diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm
index fd2e56a53f..945ea515c7 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm
@@ -274,8 +274,7 @@
/area/ruin/powered/seedvault)
"Z" = (
/obj/item/disk/design_disk/plant_disk,
-/obj/machinery/autolathe{
- hacked = TRUE;
+/obj/machinery/autolathe/hacked{
desc = "This autolathe seems to have its safety light off."
},
/turf/open/floor/plasteel/freezer,
diff --git a/_maps/RandomRuins/SpaceRuins/originalcontent.dmm b/_maps/RandomRuins/SpaceRuins/originalcontent.dmm
index 5f0dd0434a..2945a06b25 100644
--- a/_maps/RandomRuins/SpaceRuins/originalcontent.dmm
+++ b/_maps/RandomRuins/SpaceRuins/originalcontent.dmm
@@ -913,6 +913,10 @@
},
/turf/open/indestructible/paper,
/area/ruin/powered)
+"Ns" = (
+/obj/item/paper/secretrecipe,
+/turf/open/indestructible/paper,
+/area/ruin/powered)
(1,1,1) = {"
aa
@@ -2247,7 +2251,7 @@ ap
az
af
al
-aA
+Ns
bW
ca
af
diff --git a/_maps/RandomRuins/SpaceRuins/spacehermit.dmm b/_maps/RandomRuins/SpaceRuins/spacehermit.dmm
new file mode 100644
index 0000000000..341dcf7b99
--- /dev/null
+++ b/_maps/RandomRuins/SpaceRuins/spacehermit.dmm
@@ -0,0 +1,2941 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"aa" = (
+/turf/template_noop,
+/area/template_noop)
+"ab" = (
+/turf/closed/mineral/random/low_chance,
+/area/ruin/unpowered)
+"ac" = (
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"ad" = (
+/obj/machinery/hydroponics/soil,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"ae" = (
+/turf/closed/wall/mineral/titanium,
+/area/ruin/powered)
+"af" = (
+/obj/effect/spawner/structure/window/shuttle,
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"ag" = (
+/obj/structure/shuttle/engine/propulsion/right{
+ dir = 4
+ },
+/turf/closed/wall/mineral/titanium,
+/area/ruin/powered)
+"ah" = (
+/obj/structure/table/wood,
+/obj/item/shovel,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"ai" = (
+/obj/structure/lattice,
+/turf/template_noop,
+/area/template_noop)
+"aj" = (
+/obj/machinery/computer/cryopod,
+/turf/closed/wall/mineral/titanium,
+/area/ruin/powered)
+"ak" = (
+/obj/structure/fluff/empty_cryostasis_sleeper,
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"al" = (
+/obj/machinery/status_display/shuttle,
+/turf/closed/wall/mineral/titanium,
+/area/ruin/powered)
+"am" = (
+/obj/item/circuitboard/computer/rdconsole,
+/obj/item/circuitboard/machine/protolathe/department/science,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"an" = (
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"ao" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 8
+ },
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"ap" = (
+/obj/machinery/light{
+ dir = 1
+ },
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"aq" = (
+/obj/machinery/computer{
+ desc = "A computer long since rendered non-functional due to lack of maintenance. Spitting out error messages.";
+ dir = 4;
+ name = "Broken Computer"
+ },
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"ar" = (
+/obj/machinery/door/airlock/titanium{
+ name = "Escape Pod Airlock"
+ },
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"as" = (
+/obj/machinery/light,
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"at" = (
+/obj/structure/shuttle/engine/propulsion/left{
+ dir = 4
+ },
+/turf/closed/wall/mineral/titanium,
+/area/ruin/powered)
+"au" = (
+/obj/item/seeds/tower,
+/obj/item/seeds/tower,
+/obj/item/seeds/tower,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"av" = (
+/obj/structure/table/wood,
+/obj/item/paper/crumpled{
+ info = "
So this is it, I guess.. Always thought I'd go out doing something stupid, but.. not like this.
Should anyone find this note, tell Jeremy Clarke he can kiss my ass. Launching the pod unprepared like that..
Well. Now that I'm keeling over here, I guess I should write how I came to be the last one standing here.
Four of us took this pod.. only three of us woke up though.. fourth pod is locked from the inside, we couldn't figure out how to get it open.
Me and the clown set up a farm s'we can survive at least a while.. though, he didn't seem to understand that man cannot live on banana alone.
Had a bunch of circuits on him for some reason when he eventually passed, whispered to me something about a chem dispenser.. I.. don't know what he meant by that. I was never good with machinary. Maybe he wanted space lube?
The assistant that we gave the space suit to go out and find help never came back.. I'm betting he found salvation and left us behind.. never can trust those grubby greytiders."
+ },
+/obj/item/pen,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aw" = (
+/obj/item/stack/sheet/mineral/wood,
+/obj/item/stack/sheet/mineral/wood,
+/obj/item/stack/sheet/mineral/wood,
+/obj/item/stack/sheet/mineral/wood,
+/obj/item/stack/sheet/mineral/wood,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"ax" = (
+/obj/item/twohanded/spear,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"ay" = (
+/obj/item/grown/log,
+/obj/item/grown/log,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"az" = (
+/obj/structure/table/wood,
+/obj/item/storage/bag/plants/portaseeder,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aA" = (
+/turf/open/floor/plating/asteroid/airless,
+/area/ruin/unpowered)
+"aB" = (
+/obj/item/seeds/banana,
+/obj/item/seeds/banana,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aC" = (
+/obj/effect/mob_spawn/human/clown/corpse,
+/obj/structure/fans/tiny/invisible,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aD" = (
+/obj/item/mining_scanner,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aE" = (
+/obj/machinery/status_display/shuttle,
+/turf/closed/wall/mineral/titanium,
+/area/ruin/unpowered)
+"aF" = (
+/obj/item/pickaxe/emergency,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aG" = (
+/obj/structure/sink/puddle,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aH" = (
+/obj/structure/table/wood,
+/obj/item/storage/firstaid/regular,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aI" = (
+/obj/effect/mob_spawn/human/corpse/assistant,
+/turf/template_noop,
+/area/template_noop)
+"aJ" = (
+/obj/structure/table/wood,
+/obj/item/storage/bag/ore,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aK" = (
+/obj/structure/reagent_dispensers/fueltank,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aL" = (
+/obj/structure/table/wood,
+/obj/item/storage/toolbox/mechanical,
+/obj/item/clothing/head/welding,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aM" = (
+/mob/living/simple_animal/hostile/carp,
+/turf/template_noop,
+/area/template_noop)
+"aN" = (
+/obj/structure/mineral_door/sandstone,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aO" = (
+/mob/living/simple_animal/hostile/carp,
+/turf/open/floor/plating/asteroid/airless,
+/area/ruin/unpowered)
+"aP" = (
+/obj/item/stack/ore/gold,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aQ" = (
+/obj/item/stack/ore/gold,
+/obj/item/stack/ore/gold,
+/obj/item/stack/ore/gold,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aR" = (
+/obj/item/stack/ore/iron,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aS" = (
+/turf/closed/wall/mineral/iron,
+/area/ruin/unpowered)
+"aT" = (
+/obj/item/stack/ore/iron,
+/obj/item/stack/ore/iron,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aU" = (
+/obj/item/flashlight/lamp,
+/obj/structure/table/wood,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aV" = (
+/obj/item/clothing/suit/space/orange,
+/turf/template_noop,
+/area/template_noop)
+"aW" = (
+/obj/item/clothing/head/helmet/space/orange,
+/turf/template_noop,
+/area/template_noop)
+"aX" = (
+/mob/living/simple_animal/hostile/carp/megacarp,
+/turf/template_noop,
+/area/template_noop)
+"aY" = (
+/obj/effect/mob_spawn/human/hermit{
+ flavour_text = "You've been late to awaken from your cryo slumber. Blasted machine, you set it to 10 days not 10 weeks! Where have the others gone while we were out? Did they manage to survive? These thoughts are dispelled by yet another recollection of how you got here... ";
+ job_description = "Space Hermit"
+ },
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"aZ" = (
+/turf/closed/wall/mineral/titanium,
+/area/ruin/unpowered)
+"ba" = (
+/obj/effect/spawner/structure/window/shuttle,
+/turf/open/floor/mineral/titanium,
+/area/ruin/unpowered)
+"bb" = (
+/obj/structure/shuttle/engine/propulsion/left{
+ dir = 4
+ },
+/turf/closed/wall/mineral/titanium,
+/area/ruin/unpowered)
+"bc" = (
+/obj/item/circuitboard/machine/circuit_imprinter,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bd" = (
+/obj/item/grown/bananapeel,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"be" = (
+/obj/effect/mob_spawn/human/corpse/cargo_tech,
+/obj/structure/fans/tiny/invisible,
+/obj/effect/decal/cleanable/vomit,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bf" = (
+/obj/item/clothing/glasses/meson,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bg" = (
+/obj/item/stock_parts/matter_bin,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bh" = (
+/obj/item/circuitboard/machine/autolathe,
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"bi" = (
+/obj/item/stock_parts/manipulator,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bj" = (
+/obj/item/holosign_creator/atmos,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bk" = (
+/obj/structure/holosign/barrier/atmos,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bl" = (
+/obj/machinery/power/floodlight,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bm" = (
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bn" = (
+/obj/structure/cable{
+ icon_state = "2-8"
+ },
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bo" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bp" = (
+/obj/item/stack/ore/iron,
+/obj/item/stack/ore/iron,
+/obj/item/stack/ore/iron,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bq" = (
+/obj/structure/cable,
+/obj/machinery/power/port_gen/pacman{
+ active = 1;
+ anchored = 1;
+ sheets = 10
+ },
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"br" = (
+/obj/item/stack/ore/iron,
+/obj/item/stack/sheet/mineral/plasma,
+/obj/item/stack/sheet/mineral/plasma,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bs" = (
+/obj/item/flashlight/lamp/bananalamp,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+
+(1,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ac
+aO
+aA
+aA
+aA
+aA
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(2,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aA
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aA
+aA
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+"}
+(3,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aA
+aa
+aa
+aa
+aa
+aW
+aa
+aM
+aa
+"}
+(4,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aV
+aI
+aX
+aa
+aa
+"}
+(5,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aA
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(6,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aM
+aa
+aa
+aa
+"}
+(7,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+"}
+(8,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ae
+af
+ae
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+"}
+(9,1,1) = {"
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+af
+aq
+af
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+"}
+(10,1,1) = {"
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ae
+ae
+ao
+ae
+ae
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+"}
+(11,1,1) = {"
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+af
+an
+an
+an
+af
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(12,1,1) = {"
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ae
+ae
+bh
+an
+an
+ae
+aZ
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(13,1,1) = {"
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+af
+aY
+ao
+ao
+ao
+ak
+ba
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(14,1,1) = {"
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+al
+aj
+ap
+an
+as
+aj
+aE
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(15,1,1) = {"
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+aA
+aa
+aa
+aa
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+af
+ak
+ao
+ao
+ao
+ak
+ba
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(16,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ah
+az
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aR
+ae
+ae
+an
+an
+an
+ae
+aZ
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aM
+"}
+(17,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aR
+ag
+ag
+af
+ar
+af
+at
+bb
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(18,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ad
+ac
+ac
+ac
+ac
+ab
+aH
+aJ
+aL
+ab
+ab
+aT
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+aR
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(19,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ad
+au
+ac
+aB
+am
+ac
+ac
+ac
+ac
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+bg
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(20,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ad
+aw
+bs
+aC
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(21,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ad
+ax
+ac
+aD
+aF
+ac
+ac
+ac
+ab
+ab
+ab
+aU
+bd
+ac
+ac
+bl
+bm
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(22,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ad
+ay
+ac
+ac
+ac
+aG
+ac
+ac
+ab
+ab
+ab
+av
+be
+ac
+ac
+ac
+bn
+bo
+bo
+bq
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(23,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+bc
+bf
+ac
+ac
+ac
+ac
+ac
+ac
+br
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+"}
+(24,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ab
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+"}
+(25,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+aN
+ac
+ac
+ac
+ac
+aR
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+"}
+(26,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+"}
+(27,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aK
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+bp
+ac
+ac
+aR
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+aM
+"}
+(28,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aP
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+aR
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+"}
+(29,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aQ
+aP
+ac
+ac
+aR
+ac
+ac
+ac
+ac
+ab
+ac
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+"}
+(30,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+aP
+ac
+bg
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+"}
+(31,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+aS
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+ab
+aA
+"}
+(32,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+bg
+ac
+ac
+ac
+ac
+ac
+aS
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aO
+ab
+ab
+"}
+(33,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+bj
+ac
+ac
+ac
+aS
+ab
+ab
+ab
+ab
+aA
+aa
+aA
+ab
+ab
+ab
+"}
+(34,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aS
+bi
+ac
+ac
+ac
+aS
+aS
+ab
+ab
+ab
+ab
+aA
+aa
+aA
+ab
+ab
+aA
+"}
+(35,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aa
+aa
+aa
+aa
+aM
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aS
+ac
+ac
+ac
+ac
+aS
+aS
+ab
+ab
+ab
+aA
+aa
+aa
+aA
+ab
+ab
+ab
+"}
+(36,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aS
+aS
+aS
+bk
+bk
+aS
+aS
+aS
+aS
+ab
+ab
+aA
+aa
+aa
+aa
+ab
+ab
+ab
+"}
+(37,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aA
+aA
+aS
+aS
+aS
+bk
+aS
+aS
+aS
+aA
+aA
+ab
+aA
+aa
+aa
+aa
+aa
+aA
+aA
+"}
+(38,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aA
+ai
+ai
+ai
+ai
+ai
+ai
+ai
+ai
+aA
+aA
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(39,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+ai
+ai
+ai
+aa
+ai
+aa
+aa
+aA
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(40,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+ai
+aa
+aa
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(41,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(42,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aA
+aA
+aA
+aA
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+"}
+(43,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aA
+aA
+aA
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(44,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ac
+aa
+aa
+aa
+"}
+(45,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+ac
+ab
+ac
+aa
+aa
+"}
+(46,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+aa
+aa
+"}
+(47,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+aa
+aa
+"}
+(48,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ac
+ab
+ac
+aa
+aa
+"}
+(49,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ac
+aa
+aa
+aa
+aa
+"}
+(50,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+aa
+aa
+aa
+aa
+"}
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index f9792a736e..0dc0afcd0c 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -35713,13 +35713,13 @@
/obj/structure/extinguisher_cabinet{
pixel_x = -26
},
-/obj/machinery/rnd/production/protolathe/department/medical,
/obj/effect/turf_decal/tile/blue{
dir = 1
},
/obj/effect/turf_decal/tile/blue{
dir = 4
},
+/obj/machinery/rnd/production/techfab/department/medical,
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"bEw" = (
diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm
index dbe8cfbb62..210bdf57a6 100644
--- a/code/__DEFINES/components.dm
+++ b/code/__DEFINES/components.dm
@@ -130,6 +130,7 @@
#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters)
#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" //from base of mob/RangedAttack(): (atom/A, params)
#define COMSIG_MOB_THROW "mob_throw" //from base of /mob/throw_item(): (atom/target)
+#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" //from base of /mob/update_sight(): ()
// /mob/living signals
#define COMSIG_LIVING_RESIST "living_resist" //from base of mob/living/resist() (/mob/living)
diff --git a/code/__DEFINES/food.dm b/code/__DEFINES/food.dm
index 2c7a66ce40..15c7af5749 100644
--- a/code/__DEFINES/food.dm
+++ b/code/__DEFINES/food.dm
@@ -16,3 +16,4 @@
#define DRINK_GOOD 2
#define DRINK_VERYGOOD 3
#define DRINK_FANTASTIC 4
+#define FOOD_AMAZING 5
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 19710a89fe..175f3d45ab 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -114,8 +114,9 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define TRANSITIONEDGE 7 //Distance from edge to move to another z-level
-#define BE_CLOSE 1 //in the case of a silicon, to select if they need to be next to the atom
-#define NO_DEXTERY 1 //if other mobs (monkeys, aliens, etc) can use this
+#define BE_CLOSE TRUE //in the case of a silicon, to select if they need to be next to the atom
+#define NO_DEXTERY TRUE //if other mobs (monkeys, aliens, etc) can use this
+#define NO_TK TRUE
//used by canUseTopic()
//singularity defines
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index f54a0542f4..ecd1ef1e21 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -102,7 +102,6 @@
#define FIRE_PRIORITY_SPACEDRIFT 30
#define FIRE_PRIORITY_FIELDS 30
#define FIRE_PRIOTITY_SMOOTHING 35
-#define FIRE_PRIORITY_ORBIT 35
#define FIRE_PRIORITY_NETWORKS 40
#define FIRE_PRIORITY_OBJ 40
#define FIRE_PRIORITY_ACID 40
diff --git a/code/__HELPERS/matrices.dm b/code/__HELPERS/matrices.dm
index 8b77b170e0..d96ec76a7c 100644
--- a/code/__HELPERS/matrices.dm
+++ b/code/__HELPERS/matrices.dm
@@ -2,7 +2,7 @@
. = new_angle - old_angle
Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
-/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3)
+/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3, parallel = TRUE)
if(!segments)
return
var/segment = 360/segments
@@ -18,7 +18,11 @@
speed /= segments
- animate(src, transform = matrices[1], time = speed, loops)
+ if(parallel)
+ animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL)
+ else
+ animate(src, transform = matrices[1], time = speed, loops)
+
for(var/i in 2 to segments) //2 because 1 is covered above
animate(transform = matrices[i], time = speed)
//doesn't have an object argument because this is "Stacking" with the animate call above
diff --git a/code/__HELPERS/reagents.dm b/code/__HELPERS/reagents.dm
new file mode 100644
index 0000000000..f1208abdd3
--- /dev/null
+++ b/code/__HELPERS/reagents.dm
@@ -0,0 +1,74 @@
+/proc/chem_recipes_do_conflict(datum/chemical_reaction/r1, datum/chemical_reaction/r2)
+ //do the non-list tests first, because they are cheaper
+ if(r1.required_container != r2.required_container)
+ return FALSE
+ if(r1.is_cold_recipe == r2.is_cold_recipe)
+ if(r1.required_temp != r2.required_temp)
+ //one reaction requires a more extreme temperature than the other, so there is no conflict
+ return FALSE
+ else
+ var/datum/chemical_reaction/cold_one = r1.is_cold_recipe ? r1 : r2
+ var/datum/chemical_reaction/warm_one = r1.is_cold_recipe ? r2 : r1
+ if(cold_one.required_temp < warm_one.required_temp)
+ //the range of temperatures does not overlap, so there is no conflict
+ return FALSE
+
+ //find the reactions with the shorter and longer required_reagents list
+ var/datum/chemical_reaction/long_req
+ var/datum/chemical_reaction/short_req
+ if(r1.required_reagents.len > r2.required_reagents.len)
+ long_req = r1
+ short_req = r2
+ else if(r1.required_reagents.len < r2.required_reagents.len)
+ long_req = r2
+ short_req = r1
+ else
+ //if they are the same length, sort instead by the length of the catalyst list
+ //this is important if the required_reagents lists are the same
+ if(r1.required_catalysts.len > r2.required_catalysts.len)
+ long_req = r1
+ short_req = r2
+ else
+ long_req = r2
+ short_req = r1
+
+
+ //check if the shorter reaction list is a subset of the longer one
+ var/list/overlap = r1.required_reagents & r2.required_reagents
+ if(overlap.len != short_req.required_reagents.len)
+ //there is at least one reagent in the short list that is not in the long list, so there is no conflict
+ return FALSE
+
+ //check to see if the shorter reaction's catalyst list is also a subset of the longer reaction's catalyst list
+ //if the longer reaction's catalyst list is a subset of the shorter ones, that is fine
+ //if the reaction lists are the same, the short reaction will have the shorter required_catalysts list, so it will register as a conflict
+ var/list/short_minus_long_catalysts = short_req.required_catalysts - long_req.required_catalysts
+ if(short_minus_long_catalysts.len)
+ //there is at least one unique catalyst for the short reaction, so there is no conflict
+ return FALSE
+
+ //if we got this far, the longer reaction will be impossible to create if the shorter one is earlier in GLOB.chemical_reactions_list, and will require the reagents to be added in a particular order otherwise
+ return TRUE
+
+/proc/get_chemical_reaction(id)
+ if(!GLOB.chemical_reactions_list)
+ return
+ for(var/reagent in GLOB.chemical_reactions_list)
+ for(var/datum/chemical_reaction/R in GLOB.chemical_reactions_list[reagent])
+ if(R.id == id)
+ return R
+
+/proc/remove_chemical_reaction(datum/chemical_reaction/R)
+ if(!GLOB.chemical_reactions_list || !R)
+ return
+ for(var/rid in R.required_reagents)
+ GLOB.chemical_reactions_list[rid] -= R
+
+//see build_chemical_reactions_list in holder.dm for explanations
+/proc/add_chemical_reaction(datum/chemical_reaction/R)
+ if(!GLOB.chemical_reactions_list || !R.id || !R.required_reagents || !R.required_reagents.len)
+ return
+ var/primary_reagent = R.required_reagents[1]
+ if(!GLOB.chemical_reactions_list[primary_reagent])
+ GLOB.chemical_reactions_list[primary_reagent] = list()
+ GLOB.chemical_reactions_list[primary_reagent] += R
diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm
index 200e1f907f..b28e7b5807 100644
--- a/code/__HELPERS/time.dm
+++ b/code/__HELPERS/time.dm
@@ -70,3 +70,6 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
if(hour)
hourT = " and [hour] hour[(hour != 1)? "s":""]"
return "[day] day[(day != 1)? "s":""][hourT][minuteT][secondT]"
+
+/proc/daysSince(realtimev)
+ return round((world.realtime - realtimev) / (24 HOURS))
diff --git a/code/controllers/subsystem/augury.dm b/code/controllers/subsystem/augury.dm
index 875f1ee7d3..1b1c7bc3b7 100644
--- a/code/controllers/subsystem/augury.dm
+++ b/code/controllers/subsystem/augury.dm
@@ -50,7 +50,7 @@ SUBSYSTEM_DEF(augury)
watchers -= w
continue
var/mob/dead/observer/O = w
- if(biggest_doom && (!O.orbiting || O.orbiting.orbiting != biggest_doom))
+ if(biggest_doom && (!O.orbiting || O.orbiting.parent != biggest_doom))
O.ManualFollow(biggest_doom)
/datum/action/innate/augury
diff --git a/code/controllers/subsystem/orbit.dm b/code/controllers/subsystem/orbit.dm
deleted file mode 100644
index 45d280b601..0000000000
--- a/code/controllers/subsystem/orbit.dm
+++ /dev/null
@@ -1,44 +0,0 @@
-SUBSYSTEM_DEF(orbit)
- name = "Orbits"
- priority = FIRE_PRIORITY_ORBIT
- wait = 2
- flags = SS_NO_INIT|SS_TICKER
-
- var/list/currentrun = list()
- var/list/processing = list()
-
-/datum/controller/subsystem/orbit/stat_entry()
- ..("P:[processing.len]")
-
-
-/datum/controller/subsystem/orbit/fire(resumed = 0)
- if (!resumed)
- src.currentrun = processing.Copy()
-
- //cache for sanic speed (lists are references anyways)
- var/list/currentrun = src.currentrun
-
- while (currentrun.len)
- var/datum/orbit/O = currentrun[currentrun.len]
- currentrun.len--
- if (!O)
- processing -= O
- if (MC_TICK_CHECK)
- return
- continue
- if (!O.orbiter)
- qdel(O)
- if (MC_TICK_CHECK)
- return
- continue
- if (O.lastprocess >= world.time) //we already checked recently
- if (MC_TICK_CHECK)
- return
- continue
- var/targetloc = get_turf(O.orbiting)
- if (targetloc != O.lastloc || O.orbiter.loc != targetloc)
- O.Check(targetloc)
- if (MC_TICK_CHECK)
- return
-
-
diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm
index 978eedb62f..455b53b1df 100644
--- a/code/controllers/subsystem/persistence.dm
+++ b/code/controllers/subsystem/persistence.dm
@@ -28,6 +28,7 @@ SUBSYSTEM_DEF(persistence)
LoadPhotoPersistence()
if(CONFIG_GET(flag/use_antag_rep))
LoadAntagReputation()
+ LoadRandomizedRecipes()
return ..()
/datum/controller/subsystem/persistence/proc/LoadSatchels()
@@ -206,6 +207,7 @@ SUBSYSTEM_DEF(persistence)
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
if(CONFIG_GET(flag/use_antag_rep))
CollectAntagReputation()
+ SaveRandomizedRecipes()
/datum/controller/subsystem/persistence/proc/GetPhotoAlbums()
var/album_path = file("data/photo_albums.json")
@@ -371,3 +373,43 @@ SUBSYSTEM_DEF(persistence)
fdel(FILE_ANTAG_REP)
text2file(json_encode(antag_rep), FILE_ANTAG_REP)
+/datum/controller/subsystem/persistence/proc/LoadRandomizedRecipes()
+ var/json_file = file("data/RandomizedChemRecipes.json")
+ var/json
+ if(fexists(json_file))
+ json = json_decode(file2text(json_file))
+
+ for(var/randomized_type in subtypesof(/datum/chemical_reaction/randomized))
+ var/datum/chemical_reaction/randomized/R = new randomized_type
+ var/loaded = FALSE
+ if(R.persistent && json)
+ var/list/recipe_data = json[R.id]
+ if(recipe_data && R.LoadOldRecipe(recipe_data) && (daysSince(R.created) <= R.persistence_period))
+ loaded = TRUE
+ if(!loaded) //We do not have information for whatever reason, just generate new one
+ R.GenerateRecipe()
+
+ if(!R.HasConflicts()) //Might want to try again if conflicts happened in the future.
+ add_chemical_reaction(R)
+
+/datum/controller/subsystem/persistence/proc/SaveRandomizedRecipes()
+ var/json_file = file("data/RandomizedChemRecipes.json")
+ var/list/file_data = list()
+
+ //asert globchems done
+ for(var/randomized_type in subtypesof(/datum/chemical_reaction/randomized))
+ var/datum/chemical_reaction/randomized/R = randomized_type
+ R = get_chemical_reaction(initial(R.id)) //ew, would be nice to add some simple tracking
+ if(R && R.persistent && R.id)
+ var/recipe_data = list()
+ recipe_data["timestamp"] = R.created
+ recipe_data["required_reagents"] = R.required_reagents
+ recipe_data["required_catalysts"] = R.required_catalysts
+ recipe_data["required_temp"] = R.required_temp
+ recipe_data["is_cold_recipe"] = R.is_cold_recipe
+ recipe_data["results"] = R.results
+ recipe_data["required_container"] = "[R.required_container]"
+ file_data["[R.id]"] = recipe_data
+
+ fdel(json_file)
+ WRITE_FILE(json_file, json_encode(file_data))
diff --git a/code/datums/components/orbiter.dm b/code/datums/components/orbiter.dm
new file mode 100644
index 0000000000..301e50dc42
--- /dev/null
+++ b/code/datums/components/orbiter.dm
@@ -0,0 +1,156 @@
+/datum/component/orbiter
+ dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+ var/list/orbiters
+ var/datum/callback/orbiter_spy
+ var/datum/callback/orbited_spy
+
+//radius: range to orbit at, radius of the circle formed by orbiting (in pixels)
+//clockwise: whether you orbit clockwise or anti clockwise
+//rotation_speed: how fast to rotate (how many ds should it take for a rotation to complete)
+//rotation_segments: the resolution of the orbit circle, less = a more block circle, this can be used to produce hexagons (6 segments) triangles (3 segments), and so on, 36 is the best default.
+//pre_rotation: Chooses to rotate src 90 degress towards the orbit dir (clockwise/anticlockwise), useful for things to go "head first" like ghosts
+/datum/component/orbiter/Initialize(atom/movable/orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
+ if(!istype(orbiter) || !isatom(parent) || isarea(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ orbiters = list()
+ orbiter_spy = CALLBACK(src, .proc/orbiter_move_react)
+ orbited_spy = CALLBACK(src, .proc/move_react)
+
+ var/atom/master = parent
+ master.orbiters = src
+
+ begin_orbit(orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
+
+/datum/component/orbiter/RegisterWithParent()
+ var/atom/target = parent
+ while(ismovableatom(target))
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, orbited_spy)
+ target = target.loc
+
+/datum/component/orbiter/UnregisterFromParent()
+ var/atom/target = parent
+ while(ismovableatom(target))
+ UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
+ target = target.loc
+
+/datum/component/orbiter/Destroy()
+ var/atom/master = parent
+ master.orbiters = null
+ for(var/i in orbiters)
+ end_orbit(i)
+ orbiters = null
+ QDEL_NULL(orbiter_spy)
+ QDEL_NULL(orbited_spy)
+ return ..()
+
+/datum/component/orbiter/InheritComponent(datum/component/orbiter/newcomp, original, list/arguments)
+ if(arguments)
+ begin_orbit(arglist(arguments))
+ return
+ // The following only happens on component transfers
+ orbiters += newcomp.orbiters
+
+/datum/component/orbiter/PostTransfer()
+ if(!isatom(parent) || isarea(parent) || !get_turf(parent))
+ return COMPONENT_INCOMPATIBLE
+ move_react()
+
+/datum/component/orbiter/proc/begin_orbit(atom/movable/orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
+ if(orbiter.orbiting)
+ if(orbiter.orbiting == src)
+ orbiter.orbiting.end_orbit(orbiter, TRUE)
+ else
+ orbiter.orbiting.end_orbit(orbiter)
+ orbiters[orbiter] = TRUE
+ orbiter.orbiting = src
+ RegisterSignal(orbiter, COMSIG_MOVABLE_MOVED, orbiter_spy)
+ var/matrix/initial_transform = matrix(orbiter.transform)
+
+ // Head first!
+ if(pre_rotation)
+ var/matrix/M = matrix(orbiter.transform)
+ var/pre_rot = 90
+ if(!clockwise)
+ pre_rot = -90
+ M.Turn(pre_rot)
+ orbiter.transform = M
+
+ var/matrix/shift = matrix(orbiter.transform)
+ shift.Translate(0, radius)
+ orbiter.transform = shift
+
+ orbiter.SpinAnimation(rotation_speed, -1, clockwise, rotation_segments, parallel = FALSE)
+
+ //we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
+ orbiter.transform = initial_transform
+ orbiter.forceMove(get_turf(parent))
+ to_chat(orbiter, "Now orbiting [parent].")
+
+/datum/component/orbiter/proc/end_orbit(atom/movable/orbiter, refreshing=FALSE)
+ if(!orbiters[orbiter])
+ return
+ UnregisterSignal(orbiter, COMSIG_MOVABLE_MOVED)
+ orbiter.SpinAnimation(0, 0)
+ orbiters -= orbiter
+ orbiter.stop_orbit(src)
+ orbiter.orbiting = null
+ if(!refreshing && !length(orbiters) && !QDELING(src))
+ qdel(src)
+
+// This proc can receive signals by either the thing being directly orbited or anything holding it
+/datum/component/orbiter/proc/move_react(atom/orbited, atom/oldloc, direction)
+ set waitfor = FALSE // Transfer calls this directly and it doesnt care if the ghosts arent done moving
+
+ var/atom/movable/master = parent
+ if(master.loc == oldloc)
+ return
+
+ var/turf/newturf = get_turf(master)
+ if(!newturf)
+ qdel(src)
+
+ // Handling the signals of stuff holding us (or not anymore)
+ // These are prety rarely activated, how often are you following something in a bag?
+ if(oldloc && !isturf(oldloc)) // We used to be registered to it, probably
+ var/atom/target = oldloc
+ while(ismovableatom(target))
+ UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
+ target = target.loc
+ if(orbited?.loc && orbited.loc != newturf) // We want to know when anything holding us moves too
+ var/atom/target = orbited.loc
+ while(ismovableatom(target))
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, orbited_spy, TRUE)
+ target = target.loc
+
+ var/atom/curloc = master.loc
+ for(var/i in orbiters)
+ var/atom/movable/thing = i
+ if(QDELETED(thing) || thing.loc == newturf)
+ continue
+ thing.forceMove(newturf)
+ if(CHECK_TICK && master.loc != curloc)
+ // We moved again during the checktick, cancel current operation
+ break
+
+
+/datum/component/orbiter/proc/orbiter_move_react(atom/movable/orbiter, atom/oldloc, direction)
+ if(orbiter.loc == get_turf(parent))
+ return
+ end_orbit(orbiter)
+
+/////////////////////
+
+/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = FALSE, rotation_speed = 20, rotation_segments = 36, pre_rotation = TRUE)
+ if(!istype(A) || !get_turf(A) || A == src)
+ return
+
+ return A.AddComponent(/datum/component/orbiter, src, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
+
+/atom/movable/proc/stop_orbit(datum/component/orbiter/orbits)
+ return // We're just a simple hook
+
+/atom/proc/transfer_observers_to(atom/target)
+ if(!orbiters || !istype(target) || !get_turf(target) || target == src)
+ return
+ target.TakeComponent(orbiters)
diff --git a/code/datums/mood_events/drink_events.dm b/code/datums/mood_events/drink_events.dm
index db5a91009e..5d0eb0e0cb 100644
--- a/code/datums/mood_events/drink_events.dm
+++ b/code/datums/mood_events/drink_events.dm
@@ -22,3 +22,8 @@
description = "That drink was amazing!\n"
mood_change = 4
timeout = 1200
+
+/datum/mood_event/amazingtaste
+ description = "Amazing taste!\n"
+ mood_change = 50
+ timeout = 10 MINUTES
diff --git a/code/datums/ruins/space.dm b/code/datums/ruins/space.dm
index e66673d4f5..22fca23902 100644
--- a/code/datums/ruins/space.dm
+++ b/code/datums/ruins/space.dm
@@ -299,3 +299,9 @@
suffix = "arcade.dmm"
name = "Space Arcade"
description = "A lonely arcade in the depths of space."
+
+/datum/map_template/ruin/space/hermit
+ id = "spacehermit"
+ suffix = "spacehermit.dmm"
+ name = "Space Hermit"
+ description = "A late awakening cryo pod in a crashed escape pod wakes up to find what befell of his fellow survivors. Contains all the necessary resources to actually make it out alive. Good luck."
diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm
index bbf38c822a..36c6733cf7 100644
--- a/code/datums/traits/negative.dm
+++ b/code/datums/traits/negative.dm
@@ -38,13 +38,13 @@
var/obj/item/heirloom_type
switch(quirk_holder.mind.assigned_role)
if("Clown")
- heirloom_type = /obj/item/paint/anycolor
- heirloom_type = /obj/item/bikehorn/golden
+ heirloom_type = pick(/obj/item/paint/anycolor, /obj/item/bikehorn/golden)
if("Mime")
- heirloom_type = /obj/item/paint/anycolor
- heirloom_type = /obj/item/toy/dummy
+ heirloom_type = pick(/obj/item/paint/anycolor, /obj/item/toy/dummy)
if("Cook")
heirloom_type = /obj/item/kitchen/knife/scimitar
+ if("Botanist")
+ heirloom_type = pick(/obj/item/cultivator, /obj/item/reagent_containers/glass/bucket, /obj/item/storage/bag/plants, /obj/item/toy/plush/beeplushie)
if("Medical Doctor")
heirloom_type = /obj/item/healthanalyzer/advanced
if("Station Engineer")
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 81e2371f9a..f2eb23808e 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -31,6 +31,8 @@
var/list/filter_data //For handling persistent filters
+ var/datum/component/orbiter/orbiters
+
var/rad_flags = NONE // Will move to flags_1 when i can be arsed to
var/rad_insulation = RAD_NO_INSULATION
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index c37c120b93..f88f4f8e41 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -31,6 +31,7 @@
var/atom/movable/pulling
var/grab_state = 0
var/throwforce = 0
+ var/datum/component/orbiter/orbiting
var/can_be_z_moved = TRUE
/atom/movable/vv_edit_var(var_name, var_value)
@@ -296,14 +297,7 @@
if (length(client_mobs_in_contents))
update_parallax_contents()
- if (orbiters)
- for (var/thing in orbiters)
- var/datum/orbit/O = thing
- O.Check()
- if (orbiting)
- orbiting.Check()
-
- return 1
+ return TRUE
/atom/movable/Destroy(force)
QDEL_NULL(proximity_monitor)
@@ -325,6 +319,10 @@
if(pulledby)
pulledby.stop_pulling()
+ if(orbiting)
+ orbiting.end_orbit(src)
+ orbiting = null
+
// Make sure you know what you're doing if you call this, this is intended to only be called by byond directly.
// You probably want CanPass()
/atom/movable/Cross(atom/movable/AM)
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index efbbe36228..7f2fef18ac 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -1,7 +1,7 @@
#define ARCADE_WEIGHT_TRICK 4
#define ARCADE_WEIGHT_USELESS 2
#define ARCADE_WEIGHT_RARE 1
-#define ARCADE_WEIGHT_PLUSH 3
+#define ARCADE_WEIGHT_PLUSH 65
/obj/machinery/computer/arcade
@@ -32,7 +32,6 @@
/obj/item/toy/spinningtoy = ARCADE_WEIGHT_TRICK,
/obj/item/toy/sword = ARCADE_WEIGHT_TRICK,
/obj/item/toy/sword/cx = ARCADE_WEIGHT_TRICK,
- /obj/item/toy/sword/darksabre = ARCADE_WEIGHT_TRICK,
/obj/item/toy/talking/AI = ARCADE_WEIGHT_USELESS,
/obj/item/toy/talking/codex_gigas = ARCADE_WEIGHT_USELESS,
/obj/item/toy/talking/griffin = ARCADE_WEIGHT_USELESS,
diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm
index 7beb32eebb..1c6d713437 100644
--- a/code/game/machinery/dance_machine.dm
+++ b/code/game/machinery/dance_machine.dm
@@ -214,11 +214,11 @@
sparkles += S
switch(i)
if(1 to 8)
- S.orbit(src, 30, TRUE, 60, 36, TRUE, FALSE)
+ S.orbit(src, 30, TRUE, 60, 36, TRUE)
if(9 to 16)
- S.orbit(src, 62, TRUE, 60, 36, TRUE, FALSE)
+ S.orbit(src, 62, TRUE, 60, 36, TRUE)
if(17 to 24)
- S.orbit(src, 95, TRUE, 60, 36, TRUE, FALSE)
+ S.orbit(src, 95, TRUE, 60, 36, TRUE)
if(25)
S.pixel_y = 7
S.forceMove(get_turf(src))
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 48b21d58bd..5d4984b321 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -171,12 +171,16 @@ GLOBAL_LIST_EMPTY(PDAs)
overlay.icon_state = "pai_off_overlay"
add_overlay(new /mutable_appearance(overlay))
-/obj/item/pda/MouseDrop(obj/over_object, src_location, over_location)
+/obj/item/pda/MouseDrop(mob/over, src_location, over_location)
var/mob/M = usr
- if((!istype(over_object, /obj/screen)) && usr.canUseTopic(src))
+ if((M == over) && usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return attack_self(M)
return ..()
+/obj/item/pda/attack_self_tk(mob/user)
+ to_chat(user, "The PDA's capacitive touch screen doesn't seem to respond!")
+ return
+
/obj/item/pda/interact(mob/user)
if(!user.IsAdvancedToolUser())
to_chat(user, "You don't have the dexterity to do this!")
@@ -382,7 +386,7 @@ GLOBAL_LIST_EMPTY(PDAs)
var/mob/living/U = usr
//Looking for master was kind of pointless since PDAs don't appear to have one.
- if(usr.canUseTopic(src) && !href_list["close"])
+ if(usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK) && !href_list["close"])
add_fingerprint(U)
U.set_machine(src)
@@ -636,7 +640,7 @@ GLOBAL_LIST_EMPTY(PDAs)
/obj/item/pda/proc/remove_id()
- if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE))
+ if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if (id)
@@ -802,7 +806,7 @@ GLOBAL_LIST_EMPTY(PDAs)
/obj/item/pda/proc/remove_pen()
- if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE))
+ if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(inserted_item)
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 40f2059d25..d8b539ac27 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -13,7 +13,8 @@
actions_types = list(/datum/action/item_action/toggle_light)
var/on = FALSE
var/brightness_on = 4 //range of light when on
- var/flashlight_power = 1 //strength of the light when on
+ var/flashlight_power = 0.8 //strength of the light when on
+ light_color = "#FFCC66"
/obj/item/flashlight/Initialize()
. = ..()
@@ -63,7 +64,7 @@
to_chat(user, "[M] doesn't have a head!")
return
- if(flashlight_power < 1)
+ if(flashlight_power < 0.3)
to_chat(user, "\The [src] isn't bright enough to see anything! ")
return
@@ -168,6 +169,8 @@
item_state = ""
flags_1 = CONDUCT_1
brightness_on = 2
+ light_color = "#FFDDCC"
+ flashlight_power = 0.3
var/holo_cooldown = 0
/obj/item/flashlight/pen/afterattack(atom/target, mob/user, proximity_flag)
@@ -204,6 +207,8 @@
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
force = 9 // Not as good as a stun baton.
brightness_on = 5 // A little better than the standard flashlight.
+ light_color = "#CDDDFF"
+ flashlight_power = 0.9
hitsound = 'sound/weapons/genhit1.ogg'
// the desk lamps are a bit special
@@ -216,6 +221,7 @@
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
force = 10
brightness_on = 5
+ light_color = "#FFDDBB"
w_class = WEIGHT_CLASS_BULKY
flags_1 = CONDUCT_1
materials = list()
@@ -252,6 +258,7 @@
desc = "A red Nanotrasen issued flare. There are instructions on the side, it reads 'pull cord, make light'."
w_class = WEIGHT_CLASS_SMALL
brightness_on = 7 // Pretty bright.
+ light_color = "#FA421A"
icon_state = "flare"
item_state = "flare"
actions_types = list()
@@ -325,6 +332,7 @@
desc = "A torch fashioned from some leaves and a log."
w_class = WEIGHT_CLASS_BULKY
brightness_on = 4
+ light_color = "#FAA44B"
icon_state = "torch"
item_state = "torch"
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
@@ -341,6 +349,8 @@
righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi'
desc = "A mining lantern."
brightness_on = 6 // luminosity when on
+ light_color = "#FFAA44"
+ flashlight_power = 0.75
/obj/item/flashlight/slime
@@ -354,6 +364,8 @@
slot_flags = ITEM_SLOT_BELT
materials = list()
brightness_on = 6 //luminosity when on
+ light_color = "#FFEEAA"
+ flashlight_power = 0.6
/obj/item/flashlight/emp
var/emp_max_charges = 4
@@ -517,6 +529,7 @@
icon_state = null
light_color = null
brightness_on = 0
+ flashlight_power = 1
light_range = 0
light_power = 10
alpha = 0
@@ -538,7 +551,6 @@
name = "eyelight"
desc = "This shouldn't exist outside of someone's head, how are you seeing this?"
brightness_on = 15
- flashlight_power = 1
flags_1 = CONDUCT_1
item_flags = DROPDEL
actions_types = list()
diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm
index 9528bf94ba..12de29c76e 100644
--- a/code/game/objects/items/plushes.dm
+++ b/code/game/objects/items/plushes.dm
@@ -613,6 +613,20 @@
icon_state = "plushie_awake"
item_state = "plushie_awake"
+/obj/item/toy/plush/awakenedplushie/ComponentInitialize()
+ . = ..()
+ AddComponent(/datum/component/edit_complainer)
+
+
+/obj/item/toy/plush/beeplushie
+ name = "bee plushie"
+ desc = "A cute toy that resembles an even cuter bee."
+ icon_state = "plushie_h"
+ item_state = "plushie_h"
+ attack_verb = list("stung")
+ gender = FEMALE
+ squeak_override = list('modular_citadel/sound/voice/scream_moth.ogg' = 1)
+
/obj/item/toy/plush/mothplushie
name = "insect plushie"
desc = "An adorable stuffed toy that resembles some kind of insect"
@@ -904,7 +918,3 @@
item_state = "fermis"
attack_verb = list("cuddled", "petpatted", "wigglepurred")
squeak_override = list('modular_citadel/sound/voice/merowr.ogg' = 1)
-
-/obj/item/toy/plush/awakenedplushie/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/edit_complainer)
diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm
index e70e8553ed..a9f0e038df 100644
--- a/code/game/objects/items/shields.dm
+++ b/code/game/objects/items/shields.dm
@@ -170,7 +170,7 @@
name = "tower shield"
desc = "A massive shield that can block a lot of attacks, can take a lot of abuse before braking."
armor = list("melee" = 95, "bullet" = 95, "laser" = 75, "energy" = 60, "bomb" = 90, "bio" = 90, "rad" = 0, "fire" = 90, "acid" = 10) //Armor for the item, dosnt transfer to user
- icon_state = "metal"
+ item_state = "metal"
block_chance = 75 //1/4 shots will hit*
force = 10
slowdown = 2
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index 8178f0390a..c2929dafbd 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -589,3 +589,16 @@
new /obj/item/clothing/mask/gas/clown_hat(src)
new /obj/item/bikehorn(src)
new /obj/item/implanter/sad_trombone(src)
+
+obj/item/storage/backpack/duffelbag/syndie/shredderbundle
+ desc = "A large duffel bag containing two CX Shredders, some magazines, an elite hardsuit, and a chest rig."
+
+/obj/item/storage/backpack/duffelbag/syndie/shredderbundle/PopulateContents()
+ new /obj/item/ammo_box/magazine/flechette/shredder(src)
+ new /obj/item/ammo_box/magazine/flechette/shredder(src)
+ new /obj/item/ammo_box/magazine/flechette/shredder(src)
+ new /obj/item/ammo_box/magazine/flechette/shredder(src)
+ new /obj/item/gun/ballistic/automatic/flechette/shredder(src)
+ new /obj/item/gun/ballistic/automatic/flechette/shredder(src)
+ new /obj/item/storage/belt/military(src)
+ new /obj/item/clothing/suit/space/hardsuit/syndi/elite(src)
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index 57c77e5983..beb62d0ed1 100755
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -541,6 +541,25 @@
/obj/item/ammo_casing/shotgun
))
+/obj/item/storage/belt/medolier
+ name = "medolier"
+ desc = "A medical bandolier for holding smartdarts."
+ icon_state = "medolier"
+ item_state = "medolier"
+
+/obj/item/storage/belt/medolier/ComponentInitialize()
+ . = ..()
+ GET_COMPONENT(STR, /datum/component/storage)
+ STR.max_items = 15
+ STR.display_numerical_stacking = FALSE
+ STR.can_hold = typecacheof(list(
+ /obj/item/reagent_containers/syringe/dart
+ ))
+
+/obj/item/storage/belt/medolier/full/PopulateContents()
+ for(var/i in 1 to 16)
+ new /obj/item/reagent_containers/syringe/dart/(src)
+
/obj/item/storage/belt/holster
name = "shoulder holster"
desc = "A holster to carry a handgun and ammo. WARNING: Badasses only."
diff --git a/code/game/objects/items/storage/briefcase.dm b/code/game/objects/items/storage/briefcase.dm
index 1f80cec0f5..46676b5adb 100644
--- a/code/game/objects/items/storage/briefcase.dm
+++ b/code/game/objects/items/storage/briefcase.dm
@@ -80,6 +80,21 @@
new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src)
new /obj/item/suppressor/specialoffer(src)
+
+/obj/item/storage/briefcase/modularbundle
+ desc = "It's label reads genuine hardened Captain leather, but suspiciously has no other tags or branding."
+ force = 10
+
+/obj/item/storage/briefcase/modularbundle/PopulateContents()
+ new /obj/item/gun/ballistic/automatic/pistol/modular(src)
+ new /obj/item/suppressor(src)
+ new /obj/item/ammo_box/magazine/m10mm(src)
+ new /obj/item/ammo_box/magazine/m10mm/soporific(src)
+ new /obj/item/ammo_box/c10mm/soporific(src)
+ new /obj/item/clothing/under/lawyer/blacksuit(src)
+ new /obj/item/clothing/accessory/waistcoat(src)
+ new /obj/item/clothing/suit/toggle/lawyer/black/syndie(src)
+
/obj/item/storage/briefcase/medical
name = "medical briefcase"
icon_state = "medbriefcase"
@@ -89,3 +104,4 @@
new /obj/item/clothing/neck/stethoscope(src)
new /obj/item/healthanalyzer(src)
..() //In case of paperwork
+
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index ea2e99d371..b15d686b7b 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -24,15 +24,13 @@
if(ishuman(user))
var/mob/living/carbon/human/H = user
- var/userloc = H.loc
-
//see code/modules/mob/dead/new_player/preferences.dm at approx line 545 for comments!
//this is largely copypasted from there.
//handle facial hair (if necessary)
if(H.gender == MALE)
var/new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in GLOB.facial_hair_styles_list
- if(userloc != H.loc)
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return //no tele-grooming
if(new_style)
H.facial_hair_style = new_style
@@ -41,7 +39,7 @@
//handle normal hair
var/new_style = input(user, "Select a hair style", "Grooming") as null|anything in GLOB.hair_styles_list
- if(userloc != H.loc)
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return //no tele-grooming
if(new_style)
H.hair_style = new_style
@@ -90,9 +88,9 @@
/obj/structure/mirror/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
if(BRUTE)
- playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
if(BURN)
- playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
/obj/structure/mirror/magic
@@ -131,7 +129,7 @@
var/choice = input(user, "Something to change?", "Magical Grooming") as null|anything in list("name", "race", "gender", "hair", "eyes")
- if(!Adjacent(user))
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
switch(choice)
@@ -140,7 +138,7 @@
if(!newname)
return
- if(!Adjacent(user))
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
H.real_name = newname
H.name = newname
@@ -156,7 +154,7 @@
if(!newrace)
return
- if(!Adjacent(user))
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
H.set_species(newrace, icon_update=0)
@@ -186,7 +184,7 @@
if("gender")
if(!(H.gender in list("male", "female"))) //blame the patriarchy
return
- if(!Adjacent(user))
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(H.gender == "male")
if(alert(H, "Become a Witch?", "Confirmation", "Yes", "No") == "Yes")
@@ -207,7 +205,7 @@
if("hair")
var/hairchoice = alert(H, "Hair style or hair color?", "Change Hair", "Style", "Color")
- if(!Adjacent(user))
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(hairchoice == "Style") //So you just want to use a mirror then?
..()
@@ -225,7 +223,7 @@
if(BODY_ZONE_PRECISE_EYES)
var/new_eye_color = input(H, "Choose your eye color", "Eye Color","#"+H.eye_color) as color|null
- if(!Adjacent(user))
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(new_eye_color)
H.eye_color = sanitize_hexcolor(new_eye_color)
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 57dc357859..e15613c43d 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -29,69 +29,62 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/callproc()
set category = "Debug"
set name = "Advanced ProcCall"
- set waitfor = 0
+ set waitfor = FALSE
if(!check_rights(R_DEBUG))
return
var/datum/target = null
- var/targetselected = 0
+ var/targetselected = FALSE
var/returnval = null
- switch(alert("Proc owned by something?",,"Yes","No"))
- if("Yes")
- targetselected = 1
- var/list/value = vv_get_value(default_class = VV_ATOM_REFERENCE, classes = list(VV_ATOM_REFERENCE, VV_DATUM_REFERENCE, VV_MOB_REFERENCE, VV_CLIENT))
- if (!value["class"] || !value["value"])
- return
- target = value["value"]
- if("No")
- target = null
- targetselected = 0
-
- var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
- if(!procname)
- return
-
- //hascall() doesn't support proc paths (eg: /proc/gib(), it only supports "gib")
- var/testname = procname
- if(targetselected)
- //Find one of the 3 possible ways they could have written /proc/PROCNAME
- if(findtext(procname, "/proc/"))
- testname = replacetext(procname, "/proc/", "")
- else if(findtext(procname, "/proc"))
- testname = replacetext(procname, "/proc", "")
- else if(findtext(procname, "proc/"))
- testname = replacetext(procname, "proc/", "")
- //Clear out any parenthesis if they're a dummy
- testname = replacetext(testname, "()", "")
-
- if(targetselected && !hascall(target,testname))
- to_chat(usr, "Error: callproc(): type [target.type] has no proc named [procname].")
- return
- else
- var/procpath = text2path(procname)
- if (!procpath)
- to_chat(usr, "Error: callproc(): proc [procname] does not exist. (Did you forget the /proc/ part?)")
+ if(alert("Proc owned by something?",,"Yes","No") == "Yes")
+ targetselected = TRUE
+ var/list/value = vv_get_value(default_class = VV_ATOM_REFERENCE, classes = list(VV_ATOM_REFERENCE, VV_DATUM_REFERENCE, VV_MOB_REFERENCE, VV_CLIENT))
+ if (!value["class"] || !value["value"])
return
+ target = value["value"]
+
+ var/procpath = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
+ if(!procpath)
+ return
+
+ //strip away everything but the proc name
+ var/list/proclist = splittext(procpath, "/")
+ if (!length(proclist))
+ return
+
+ var/procname = proclist[proclist.len]
+ var/proctype = ("verb" in proclist) ? "verb" :"proc"
+
+ if(targetselected)
+ if(!hascall(target, procname))
+ to_chat(usr, "Error: callproc(): type [target.type] has no [proctype] named [procpath].")
+ return
+ else
+ procpath = "/[proctype]/[procname]"
+ if(!text2path(procpath))
+ to_chat(usr, "Error: callproc(): [procpath] does not exist.")
+ return
+
var/list/lst = get_callproc_args()
if(!lst)
return
if(targetselected)
if(!target)
- to_chat(usr, "Error: callproc(): owner of proc no longer exists.")
+ to_chat(usr, "Error: callproc(): owner of proc no longer exists.")
return
- var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
+ var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no argument"]."
log_admin(msg)
message_admins(msg)
admin_ticket_log(target, msg)
- returnval = WrapAdminProcCall(target, procname, lst) // Pass the lst as an argument list to the proc
+ returnval = WrapAdminProcCall(target, procname, lst)
else
- //this currently has no hascall protection. wasn't able to get it working.
- log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
- message_admins("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
- returnval = WrapAdminProcCall(GLOBAL_PROC, procname, lst) // Pass the lst as an argument list to the proc
+ var/msg = "[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no argument"]."
+ log_admin(msg)
+ message_admins(msg)
+ returnval = WrapAdminProcCall(GLOBAL_PROC, procpath, lst) //calling globals needs full qualified name (e.g /proc/foo)
. = get_callproc_returnval(returnval, procname)
if(.)
to_chat(usr, .)
@@ -111,8 +104,8 @@ GLOBAL_LIST_EMPTY(AdminProcCallSpamPrevention)
GLOBAL_PROTECT(AdminProcCallSpamPrevention)
/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
- if(target && procname == "Del")
- to_chat(usr, "Calling Del() is not allowed")
+ if(target != GLOBAL_PROC && procname == "Del")
+ to_chat(usr, "Calling Del() is not allowed")
return
if(target != GLOBAL_PROC && !target.CanProcCall(procname))
@@ -159,7 +152,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
/client/proc/callproc_datum(datum/A as null|area|mob|obj|turf)
set category = "Debug"
set name = "Atom ProcCall"
- set waitfor = 0
+ set waitfor = FALSE
if(!check_rights(R_DEBUG))
return
@@ -168,7 +161,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(!procname)
return
if(!hascall(A,procname))
- to_chat(usr, "Error: callproc_datum(): type [A.type] has no proc named [procname].")
+ to_chat(usr, "Error: callproc_datum(): type [A.type] has no proc named [procname].")
return
var/list/lst = get_callproc_args()
if(!lst)
@@ -177,8 +170,8 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(!A || !IsValidSrc(A))
to_chat(usr, "Error: callproc_datum(): owner of proc no longer exists.")
return
- log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
var/msg = "[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
+ log_admin(msg)
message_admins(msg)
admin_ticket_log(A, msg)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Atom ProcCall") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -188,8 +181,6 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(.)
to_chat(usr, .)
-
-
/client/proc/get_callproc_args()
var/argnum = input("Number of arguments","Number:",0) as num|null
if(isnull(argnum))
@@ -213,7 +204,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
. = ""
if(islist(returnval))
var/list/returnedlist = returnval
- . = ""
+ . = ""
if(returnedlist.len)
var/assoc_check = returnedlist[1]
if(istext(assoc_check) && (returnedlist[assoc_check] != null))
@@ -227,11 +218,10 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
. += "\n[elem]"
else
. = "[procname] returned an empty list"
- . += ""
+ . += ""
else
- . = "[procname] returned: [!isnull(returnval) ? returnval : "null"]"
-
+ . = "[procname] returned: [!isnull(returnval) ? returnval : "null"]"
/client/proc/Cell()
set category = "Debug"
diff --git a/code/modules/antagonists/abductor/machinery/console.dm b/code/modules/antagonists/abductor/machinery/console.dm
index a14b667069..52bda50b86 100644
--- a/code/modules/antagonists/abductor/machinery/console.dm
+++ b/code/modules/antagonists/abductor/machinery/console.dm
@@ -126,8 +126,20 @@
if(vest)
vest.flip_mode()
-/obj/machinery/abductor/console/proc/SelectDisguise(remote = 0)
- var/entry_name = input( "Choose Disguise", "Disguise") as null|anything in disguises
+/obj/machinery/abductor/console/proc/SelectDisguise(remote = FALSE)
+ var/list/disguises2 = list()
+ for(var/name in disguises)
+ var/datum/icon_snapshot/snap = disguises[name]
+ var/image/dummy = image(snap.icon, src, snap.icon_state)
+ dummy.overlays = snap.overlays
+ disguises2[name] = dummy
+
+ var/entry_name
+ if(remote)
+ entry_name = show_radial_menu(usr, camera.eyeobj, disguises2)
+ else
+ entry_name = show_radial_menu(usr, src, disguises2)
+
var/datum/icon_snapshot/chosen = disguises[entry_name]
if(chosen && vest && (remote || in_range(usr,src)))
vest.SetDisguise(chosen)
diff --git a/code/modules/antagonists/changeling/powers/panacea.dm b/code/modules/antagonists/changeling/powers/panacea.dm
index 9f7a36f214..8d571d21e3 100644
--- a/code/modules/antagonists/changeling/powers/panacea.dm
+++ b/code/modules/antagonists/changeling/powers/panacea.dm
@@ -29,7 +29,7 @@
O.forceMove(get_turf(user))
user.reagents.add_reagent("mutadone", 10)
- user.reagents.add_reagent("pen_acid", 20)
+ user.reagents.add_reagent("pen_jelly", 20)
user.reagents.add_reagent("antihol", 10)
user.reagents.add_reagent("mannitol", 25)
diff --git a/code/modules/antagonists/cult/cult_comms.dm b/code/modules/antagonists/cult/cult_comms.dm
index 8452f78ed3..761412e9f8 100644
--- a/code/modules/antagonists/cult/cult_comms.dm
+++ b/code/modules/antagonists/cult/cult_comms.dm
@@ -342,10 +342,7 @@
if(cooldown>world.time)
to_chat(owner, "You aren't ready to place another blood mark yet!")
return
- if(owner.orbiting && owner.orbiting.orbiting)
- target = owner.orbiting.orbiting
- else
- target = get_turf(owner)
+ target = owner.orbiting?.parent || get_turf(owner)
if(!target)
return
C.cult_team.blood_target = target
diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm
index 923a224b81..1df81a797b 100644
--- a/code/modules/antagonists/devil/true_devil/_true_devil.dm
+++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm
@@ -94,7 +94,7 @@
visible_message("[src] easily breaks out of [p_their()] handcuffs!", \
"With just a thought your handcuffs fall off.")
-/mob/living/carbon/true_devil/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/carbon/true_devil/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated())
to_chat(src, "You can't do that right now!")
return FALSE
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 746d5da60d..767b700051 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -216,6 +216,34 @@ BLIND // can't see anything
..()
+/obj/item/clothing/under/CtrlClick(mob/user)
+ . = ..()
+
+ if (!(item_flags & IN_INVENTORY))
+ return
+
+ if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ return
+
+ if(has_sensor == LOCKED_SENSORS)
+ to_chat(user, "The controls are locked.")
+ return
+ if(has_sensor == BROKEN_SENSORS)
+ to_chat(user, "The sensors have shorted out!")
+ return
+ if(has_sensor <= NO_SENSORS)
+ to_chat(user, "This suit does not have any sensors.")
+ return
+
+ sensor_mode = SENSOR_COORDS
+
+ to_chat(user, "Your suit will now report your exact vital lifesigns as well as your coordinate position.")
+
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(H.w_uniform == src)
+ H.update_suit_sensors()
+
/obj/item/clothing/under/AltClick(mob/user)
if(..())
return 1
diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm
index deaedfec18..bf11d40caf 100644
--- a/code/modules/clothing/suits/jobs.dm
+++ b/code/modules/clothing/suits/jobs.dm
@@ -124,6 +124,9 @@
icon_state = "suitjacket_black"
item_state = "ro_suit"
+/obj/item/clothing/suit/toggle/lawyer/black/syndie
+ desc = "A snappy dress jacket. Suspiciously has no tags or branding."
+ armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 10, "rad" = 10, "fire" = 40, "acid" = 40)
//Mime
/obj/item/clothing/suit/suspenders
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index 97e9a8f8ca..91fde0dbd0 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -1,759 +1,758 @@
-/obj/item/clothing/under/pj/red
- name = "red pj's"
- desc = "Sleepwear."
- icon_state = "red_pyjamas"
- item_color = "red_pyjamas"
- item_state = "w_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/pj/blue
- name = "blue pj's"
- desc = "Sleepwear."
- icon_state = "blue_pyjamas"
- item_color = "blue_pyjamas"
- item_state = "w_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/patriotsuit
- name = "Patriotic Suit"
- desc = "Motorcycle not included."
- icon_state = "ek"
- item_state = "ek"
- item_color = "ek"
- can_adjust = FALSE
-
-/obj/item/clothing/under/scratch
- name = "white suit"
- desc = "A white suit, suitable for an excellent host."
- icon_state = "scratch"
- item_state = "scratch"
- item_color = "scratch"
- can_adjust = FALSE
-
-/obj/item/clothing/under/sl_suit
- desc = "It's a very amish looking suit."
- name = "amish suit"
- icon_state = "sl_suit"
- item_color = "sl_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/roman
- name = "\improper Roman armor"
- desc = "Ancient Roman armor. Made of metallic and leather straps."
- icon_state = "roman"
- item_color = "roman"
- item_state = "armor"
- can_adjust = FALSE
- strip_delay = 100
- resistance_flags = NONE
-
-/obj/item/clothing/under/waiter
- name = "waiter's outfit"
- desc = "It's a very smart uniform with a special pocket for tip."
- icon_state = "waiter"
- item_state = "waiter"
- item_color = "waiter"
- can_adjust = FALSE
-
-/obj/item/clothing/under/rank/prisoner
- name = "prison jumpsuit"
- desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position."
- icon_state = "prisoner"
- item_state = "o_suit"
- item_color = "prisoner"
- has_sensor = LOCKED_SENSORS
- sensor_mode = SENSOR_COORDS
- random_sensor = FALSE
-
-/obj/item/clothing/under/rank/mailman
- name = "mailman's jumpsuit"
- desc = "'Special delivery!'"
- icon_state = "mailman"
- item_state = "b_suit"
- item_color = "mailman"
-
-/obj/item/clothing/under/rank/psyche
- name = "psychedelic jumpsuit"
- desc = "Groovy!"
- icon_state = "psyche"
- item_state = "p_suit"
- item_color = "psyche"
-
-/obj/item/clothing/under/rank/clown/sexy
- name = "sexy-clown suit"
- desc = "It makes you look HONKable!"
- icon_state = "sexyclown"
- item_state = "sexyclown"
- item_color = "sexyclown"
- can_adjust = FALSE
-
-/obj/item/clothing/under/jabroni
- name = "Jabroni Outfit"
- desc = "The leather club is two sectors down."
- icon_state = "darkholme"
- item_state = "darkholme"
- item_color = "darkholme"
- can_adjust = FALSE
-
-/obj/item/clothing/under/rank/vice
- name = "vice officer's jumpsuit"
- desc = "It's the standard issue pretty-boy outfit, as seen on Holo-Vision."
- icon_state = "vice"
- item_state = "gy_suit"
- item_color = "vice"
- can_adjust = FALSE
-
-/obj/item/clothing/under/rank/centcom_officer
- desc = "It's a jumpsuit worn by CentCom Officers."
- name = "\improper CentCom officer's jumpsuit"
- icon_state = "officer"
- item_state = "g_suit"
- item_color = "officer"
- alt_covers_chest = TRUE
-
-/obj/item/clothing/under/rank/centcom_commander
- desc = "It's a jumpsuit worn by CentCom's highest-tier Commanders."
- name = "\improper CentCom officer's jumpsuit"
- icon_state = "centcom"
- item_state = "dg_suit"
- item_color = "centcom"
-
-/obj/item/clothing/under/space
- name = "\improper NASA jumpsuit"
- desc = "It has a NASA logo on it and is made of space-proofed materials."
- icon_state = "black"
- item_state = "bl_suit"
- item_color = "black"
- w_class = WEIGHT_CLASS_BULKY
- gas_transfer_coefficient = 0.01
- permeability_coefficient = 0.02
- body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- cold_protection = CHEST | GROIN | LEGS | ARMS //Needs gloves and shoes with cold protection to be fully protected.
- min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
- heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
- can_adjust = FALSE
- resistance_flags = NONE
-
-/obj/item/clothing/under/acj
- name = "administrative cybernetic jumpsuit"
- icon_state = "syndicate"
- item_state = "bl_suit"
- item_color = "syndicate"
- desc = "A cybernetically enhanced jumpsuit used for administrative duties."
- gas_transfer_coefficient = 0.01
- permeability_coefficient = 0.01
- body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- armor = list("melee" = 100, "bullet" = 100, "laser" = 100,"energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
- cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS
- min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
- heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
- can_adjust = FALSE
- resistance_flags = FIRE_PROOF | ACID_PROOF
-
-/obj/item/clothing/under/owl
- name = "owl uniform"
- desc = "A soft brown jumpsuit made of synthetic feathers and strong conviction."
- icon_state = "owl"
- item_color = "owl"
- can_adjust = FALSE
-
-/obj/item/clothing/under/griffin
- name = "griffon uniform"
- desc = "A soft brown jumpsuit with a white feather collar made of synthetic feathers and a lust for mayhem."
- icon_state = "griffin"
- item_color = "griffin"
- can_adjust = FALSE
-
-/obj/item/clothing/under/cloud
- name = "cloud"
- desc = "cloud"
- icon_state = "cloud"
- item_color = "cloud"
- can_adjust = FALSE
-
-/obj/item/clothing/under/gimmick/rank/captain/suit
- name = "captain's suit"
- desc = "A green suit and yellow necktie. Exemplifies authority."
- icon_state = "green_suit"
- item_state = "dg_suit"
- item_color = "green_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/gimmick/rank/head_of_personnel/suit
- name = "head of personnel's suit"
- desc = "A teal suit and yellow necktie. An authoritative yet tacky ensemble."
- icon_state = "teal_suit"
- item_state = "g_suit"
- item_color = "teal_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/suit_jacket
- name = "black suit"
- desc = "A black suit and red tie. Very formal."
- icon_state = "black_suit"
- item_state = "bl_suit"
- item_color = "black_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/suit_jacket/really_black
- name = "executive suit"
- desc = "A formal black suit and red tie, intended for the station's finest."
- icon_state = "really_black_suit"
- item_state = "bl_suit"
- item_color = "black_suit"
-
-/obj/item/clothing/under/suit_jacket/female
- name = "executive suit"
- desc = "A formal trouser suit for women, intended for the station's finest."
- icon_state = "black_suit_fem"
- item_state = "black_suit_fem"
- item_color = "black_suit_fem"
-
-/obj/item/clothing/under/suit_jacket/green
- name = "green suit"
- desc = "A green suit and yellow necktie. Baller."
- icon_state = "green_suit"
- item_state = "dg_suit"
- item_color = "green_suit"
- can_adjust = FALSE
-
-/obj/item/clothing/under/suit_jacket/red
- name = "red suit"
- desc = "A red suit and blue tie. Somewhat formal."
- icon_state = "red_suit"
- item_state = "r_suit"
- item_color = "red_suit"
-
-/obj/item/clothing/under/suit_jacket/charcoal
- name = "charcoal suit"
- desc = "A charcoal suit and red tie. Very professional."
- icon_state = "charcoal_suit"
- item_state = "charcoal_suit"
- item_color = "charcoal_suit"
-
-/obj/item/clothing/under/suit_jacket/navy
- name = "navy suit"
- desc = "A navy suit and red tie, intended for the station's finest."
- icon_state = "navy_suit"
- item_state = "navy_suit"
- item_color = "navy_suit"
-
-/obj/item/clothing/under/suit_jacket/burgundy
- name = "burgundy suit"
- desc = "A burgundy suit and black tie. Somewhat formal."
- icon_state = "burgundy_suit"
- item_state = "burgundy_suit"
- item_color = "burgundy_suit"
-
-/obj/item/clothing/under/suit_jacket/checkered
- name = "checkered suit"
- desc = "That's a very nice suit you have there. Shame if something were to happen to it, eh?"
- icon_state = "checkered_suit"
- item_state = "checkered_suit"
- item_color = "checkered_suit"
-
-/obj/item/clothing/under/suit_jacket/tan
- name = "tan suit"
- desc = "A tan suit with a yellow tie. Smart, but casual."
- icon_state = "tan_suit"
- item_state = "tan_suit"
- item_color = "tan_suit"
-
-/obj/item/clothing/under/suit_jacket/white
- name = "white suit"
- desc = "A white suit and jacket with a blue shirt. You wanna play rough? OKAY!"
- icon_state = "white_suit"
- item_state = "white_suit"
- item_color = "white_suit"
-
-/obj/item/clothing/under/burial
- name = "burial garments"
- desc = "Traditional burial garments from the early 22nd century."
- icon_state = "burial"
- item_state = "burial"
- item_color = "burial"
- has_sensor = NO_SENSORS
-
-/obj/item/clothing/under/skirt/black
- name = "black skirt"
- desc = "A black skirt, very fancy!"
- icon_state = "blackskirt"
- item_color = "blackskirt"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/skirt/blue
- name = "blue skirt"
- desc = "A blue, casual skirt."
- icon_state = "blueskirt"
- item_color = "blueskirt"
- item_state = "b_suit"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/skirt/red
- name = "red skirt"
- desc = "A red, casual skirt."
- icon_state = "redskirt"
- item_color = "redskirt"
- item_state = "r_suit"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/skirt/purple
- name = "purple skirt"
- desc = "A purple, casual skirt."
- icon_state = "purpleskirt"
- item_color = "purpleskirt"
- item_state = "p_suit"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-
-/obj/item/clothing/under/schoolgirl
- name = "blue schoolgirl uniform"
- desc = "It's just like one of my Japanese animes!"
- icon_state = "schoolgirl"
- item_state = "schoolgirl"
- item_color = "schoolgirl"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/schoolgirl/red
- name = "red schoolgirl uniform"
- icon_state = "schoolgirlred"
- item_state = "schoolgirlred"
- item_color = "schoolgirlred"
-
-/obj/item/clothing/under/schoolgirl/green
- name = "green schoolgirl uniform"
- icon_state = "schoolgirlgreen"
- item_state = "schoolgirlgreen"
- item_color = "schoolgirlgreen"
-
-/obj/item/clothing/under/schoolgirl/orange
- name = "orange schoolgirl uniform"
- icon_state = "schoolgirlorange"
- item_state = "schoolgirlorange"
- item_color = "schoolgirlorange"
-
-/obj/item/clothing/under/overalls
- name = "laborer's overalls"
- desc = "A set of durable overalls for getting the job done."
- icon_state = "overalls"
- item_state = "lb_suit"
- item_color = "overalls"
- can_adjust = FALSE
-
-/obj/item/clothing/under/pirate
- name = "pirate outfit"
- desc = "Yarr."
- icon_state = "pirate"
- item_state = "pirate"
- item_color = "pirate"
- can_adjust = FALSE
-
-/obj/item/clothing/under/soviet
- name = "soviet uniform"
- desc = "For the Motherland!"
- icon_state = "soviet"
- item_state = "soviet"
- item_color = "soviet"
- can_adjust = FALSE
-
-/obj/item/clothing/under/redcoat
- name = "redcoat uniform"
- desc = "Looks old."
- icon_state = "redcoat"
- item_state = "redcoat"
- item_color = "redcoat"
- can_adjust = FALSE
-
-/obj/item/clothing/under/kilt
- name = "kilt"
- desc = "Includes shoes and plaid."
- icon_state = "kilt"
- item_state = "kilt"
- item_color = "kilt"
- body_parts_covered = CHEST|GROIN|LEGS|FEET
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/kilt/highlander
- desc = "You're the only one worthy of this kilt."
- item_flags = NODROP
-
-/obj/item/clothing/under/sexymime
- name = "sexy mime outfit"
- desc = "The only time when you DON'T enjoy looking at someone's rack."
- icon_state = "sexymime"
- item_state = "sexymime"
- item_color = "sexymime"
- body_parts_covered = CHEST|GROIN|LEGS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/gladiator
- name = "gladiator uniform"
- desc = "Are you not entertained? Is that not why you are here?"
- icon_state = "gladiator"
- item_state = "gladiator"
- item_color = "gladiator"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = NO_FEMALE_UNIFORM
- can_adjust = FALSE
- resistance_flags = NONE
-
-/obj/item/clothing/under/gladiator/ash_walker
- desc = "This gladiator uniform appears to be covered in ash and fairly dated."
- has_sensor = NO_SENSORS
-
-/obj/item/clothing/under/sundress
- name = "sundress"
- desc = "Makes you want to frolic in a field of daisies."
- icon_state = "sundress"
- item_state = "sundress"
- item_color = "sundress"
- body_parts_covered = CHEST|GROIN
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/captainparade
- name = "captain's parade uniform"
- desc = "A captain's luxury-wear, for special occasions."
- icon_state = "captain_parade"
- item_state = "by_suit"
- item_color = "captain_parade"
- can_adjust = FALSE
-
-/obj/item/clothing/under/hosparademale
- name = "head of security's parade uniform"
- desc = "A male head of security's luxury-wear, for special occasions."
- icon_state = "hos_parade_male"
- item_state = "r_suit"
- item_color = "hos_parade_male"
- can_adjust = FALSE
-
-/obj/item/clothing/under/hosparadefem
- name = "head of security's parade uniform"
- desc = "A female head of security's luxury-wear, for special occasions."
- icon_state = "hos_parade_fem"
- item_state = "r_suit"
- item_color = "hos_parade_fem"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/assistantformal
- name = "assistant's formal uniform"
- desc = "An assistant's formal-wear. Why an assistant needs formal-wear is still unknown."
- icon_state = "assistant_formal"
- item_state = "gy_suit"
- item_color = "assistant_formal"
- can_adjust = FALSE
-
-/obj/item/clothing/under/blacktango
- name = "black tango dress"
- desc = "Filled with Latin fire."
- icon_state = "black_tango"
- item_state = "wcoat"
- item_color = "black_tango"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
- body_parts_covered = CHEST|GROIN
-
-/obj/item/clothing/under/stripeddress
- name = "striped dress"
- desc = "Fashion in space."
- icon_state = "striped_dress"
- item_state = "stripeddress"
- item_color = "striped_dress"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_FULL
- can_adjust = FALSE
-
-/obj/item/clothing/under/sailordress
- name = "sailor dress"
- desc = "Formal wear for a leading lady."
- icon_state = "sailor_dress"
- item_state = "sailordress"
- item_color = "sailor_dress"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/redeveninggown
- name = "red evening gown"
- desc = "Fancy dress for space bar singers."
- icon_state = "red_evening_gown"
- item_state = "redeveninggown"
- item_color = "red_evening_gown"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/maid
- name = "maid costume"
- desc = "Maid in China."
- icon_state = "maid"
- item_state = "maid"
- item_color = "maid"
- body_parts_covered = CHEST|GROIN
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/maid/Initialize()
- . = ..()
- var/obj/item/clothing/accessory/maidapron/A = new (src)
- attach_accessory(A)
-
-/obj/item/clothing/under/janimaid
- name = "maid uniform"
- desc = "A simple maid uniform for housekeeping."
- icon_state = "janimaid"
- item_state = "janimaid"
- item_color = "janimaid"
- body_parts_covered = CHEST|GROIN
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/plaid_skirt
- name = "red plaid skirt"
- desc = "A preppy red skirt with a white blouse."
- icon_state = "plaid_red"
- item_state = "plaid_red"
- item_color = "plaid_red"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = TRUE
- alt_covers_chest = TRUE
-
-/obj/item/clothing/under/plaid_skirt/blue
- name = "blue plaid skirt"
- desc = "A preppy blue skirt with a white blouse."
- icon_state = "plaid_blue"
- item_state = "plaid_blue"
- item_color = "plaid_blue"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = TRUE
- alt_covers_chest = TRUE
-
-/obj/item/clothing/under/plaid_skirt/purple
- name = "purple plaid skirt"
- desc = "A preppy purple skirt with a white blouse."
- icon_state = "plaid_purple"
- item_state = "plaid_purple"
- item_color = "plaid_purple"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = TRUE
- alt_covers_chest = TRUE
-
-/obj/item/clothing/under/singery
- name = "yellow performer's outfit"
- desc = "Just looking at this makes you want to sing."
- icon_state = "ysing"
- item_state = "ysing"
- item_color = "ysing"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = NO_FEMALE_UNIFORM
- alternate_worn_layer = ABOVE_SHOES_LAYER
- can_adjust = FALSE
-
-/obj/item/clothing/under/singerb
- name = "blue performer's outfit"
- desc = "Just looking at this makes you want to sing."
- icon_state = "bsing"
- item_state = "bsing"
- item_color = "bsing"
- body_parts_covered = CHEST|GROIN|ARMS
- alternate_worn_layer = ABOVE_SHOES_LAYER
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
-
-/obj/item/clothing/under/plaid_skirt/green
- name = "green plaid skirt"
- desc = "A preppy green skirt with a white blouse."
- icon_state = "plaid_green"
- item_state = "plaid_green"
- item_color = "plaid_green"
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = TRUE
- alt_covers_chest = TRUE
-
-/obj/item/clothing/under/jester
- name = "jester suit"
- desc = "A jolly dress, well suited to entertain your master, nuncle."
- icon_state = "jester"
- item_color = "jester"
- can_adjust = FALSE
-
-/obj/item/clothing/under/jester/alt
- icon_state = "jester2"
-
-/obj/item/clothing/under/geisha
- name = "geisha suit"
- desc = "Cute space ninja senpai not included."
- icon_state = "geisha"
- item_color = "geisha"
- body_parts_covered = CHEST|GROIN|ARMS
- can_adjust = FALSE
-
-/obj/item/clothing/under/villain
- name = "villain suit"
- desc = "A change of wardrobe is necessary if you ever want to catch a real superhero."
- icon_state = "villain"
- item_color = "villain"
- can_adjust = FALSE
-
-/obj/item/clothing/under/sailor
- name = "sailor suit"
- desc = "Skipper's in the wardroom drinkin gin'."
- icon_state = "sailor"
- item_state = "b_suit"
- item_color = "sailor"
- can_adjust = FALSE
-
-/obj/item/clothing/under/plasmaman
- name = "plasma envirosuit"
- desc = "A special containment suit that allows plasma-based lifeforms to exist safely in an oxygenated environment, and automatically extinguishes them in a crisis. Despite being airtight, it's not spaceworthy."
- icon_state = "plasmaman"
- item_state = "plasmaman"
- item_color = "plasmaman"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95)
- body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- can_adjust = FALSE
- strip_delay = 80
- var/next_extinguish = 0
- var/extinguish_cooldown = 100
- var/extinguishes_left = 5
-
-
-/obj/item/clothing/under/plasmaman/examine(mob/user)
- ..()
- to_chat(user, "There are [extinguishes_left] extinguisher charges left in this suit.")
-
-
-/obj/item/clothing/under/plasmaman/proc/Extinguish(mob/living/carbon/human/H)
- if(!istype(H))
- return
-
- if(H.on_fire)
- if(extinguishes_left)
- if(next_extinguish > world.time)
- return
- next_extinguish = world.time + extinguish_cooldown
- extinguishes_left--
- H.visible_message("[H]'s suit automatically extinguishes [H.p_them()]!","Your suit automatically extinguishes you.")
- H.ExtinguishMob()
- new /obj/effect/particle_effect/water(get_turf(H))
- return 0
-
-/obj/item/clothing/under/plasmaman/attackby(obj/item/E, mob/user, params)
- ..()
- if (istype(E, /obj/item/extinguisher_refill))
- if (extinguishes_left == 5)
- to_chat(user, "The inbuilt extinguisher is full.")
- return
- else
- extinguishes_left = 5
- to_chat(user, "You refill the suit's built-in extinguisher, using up the cartridge.")
- qdel(E)
- return
- return
- return
-
-/obj/item/extinguisher_refill
- name = "envirosuit extinguisher cartridge"
- desc = "A cartridge loaded with a compressed extinguisher mix, used to refill the automatic extinguisher on plasma envirosuits."
- icon_state = "plasmarefill"
- icon = 'icons/obj/device.dmi'
-
-/obj/item/clothing/under/rank/security/navyblue/russian
- name = "\improper Russian officer's uniform"
- desc = "The latest in fashionable russian outfits."
- icon_state = "hostanclothes"
- item_state = "hostanclothes"
- item_color = "hostanclothes"
-
-/obj/item/clothing/under/mummy
- name = "mummy wrapping"
- desc = "Return the slab or suffer my stale references."
- icon_state = "mummy"
- item_state = "mummy"
- item_color = "mummy"
- body_parts_covered = CHEST|GROIN|ARMS|LEGS
- fitted = NO_FEMALE_UNIFORM
- can_adjust = FALSE
- resistance_flags = NONE
-
-/obj/item/clothing/under/scarecrow
- name = "scarecrow clothes"
- desc = "Perfect camouflage for hiding in botany."
- icon_state = "scarecrow"
- item_state = "scarecrow"
- item_color = "scarecrow"
- body_parts_covered = CHEST|GROIN|ARMS|LEGS
- fitted = NO_FEMALE_UNIFORM
- can_adjust = FALSE
- resistance_flags = NONE
-
-/obj/item/clothing/under/draculass
- name = "draculass coat"
- desc = "A dress inspired by the ancient \"Victorian\" era."
- icon_state = "draculass"
- item_state = "draculass"
- item_color = "draculass"
- body_parts_covered = CHEST|GROIN|ARMS
- fitted = FEMALE_UNIFORM_TOP
- can_adjust = FALSE
- mutantrace_variation = NO_MUTANTRACE_VARIATION
-
-/obj/item/clothing/under/drfreeze
- name = "doctor freeze's jumpsuit"
- desc = "A modified scientist jumpsuit to look extra cool."
- icon_state = "drfreeze"
- item_state = "drfreeze"
- item_color = "drfreeze"
- can_adjust = FALSE
- mutantrace_variation = NO_MUTANTRACE_VARIATION
-
-/obj/item/clothing/under/lobster
- name = "foam lobster suit"
- desc = "Who beheaded the college mascot?"
- icon_state = "lobster"
- item_state = "lobster"
- item_color = "lobster"
- fitted = NO_FEMALE_UNIFORM
- can_adjust = FALSE
- mutantrace_variation = NO_MUTANTRACE_VARIATION
-
-/obj/item/clothing/under/gondola
- name = "gondola hide suit"
- desc = "Now you're cooking."
- icon_state = "gondola"
- item_state = "lb_suit"
- item_color = "gondola"
- can_adjust = FALSE
-
-/obj/item/clothing/under/skeleton
- name = "skeleton jumpsuit"
- desc = "A black jumpsuit with a white bone pattern printed on it. Spooky!"
- icon_state = "skeleton"
- item_state = "skeleton"
- item_color = "skeleton"
- body_parts_covered = CHEST|GROIN|ARMS|LEGS
- fitted = NO_FEMALE_UNIFORM
- can_adjust = FALSE
- resistance_flags = NONE
-
-/obj/item/clothing/under/permit
- name = "public nudity permit"
- desc = "This permit entitles the bearer to conduct their duties without a uniform. Normally issued to furred crewmembers or those with nothing to hide."
- icon = 'icons/obj/card.dmi'
- icon_state = "fingerprint1"
- item_state = "golem" //This is dumb and hacky but was here when I got here.//No, it really isn't. Why make a new blank clothing sprite if we already have one?
- body_parts_covered = CHEST|GROIN
+/obj/item/clothing/under/pj/red
+ name = "red pj's"
+ desc = "Sleepwear."
+ icon_state = "red_pyjamas"
+ item_color = "red_pyjamas"
+ item_state = "w_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/pj/blue
+ name = "blue pj's"
+ desc = "Sleepwear."
+ icon_state = "blue_pyjamas"
+ item_color = "blue_pyjamas"
+ item_state = "w_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/patriotsuit
+ name = "Patriotic Suit"
+ desc = "Motorcycle not included."
+ icon_state = "ek"
+ item_state = "ek"
+ item_color = "ek"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/scratch
+ name = "white suit"
+ desc = "A white suit, suitable for an excellent host."
+ icon_state = "scratch"
+ item_state = "scratch"
+ item_color = "scratch"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/sl_suit
+ desc = "It's a very amish looking suit."
+ name = "amish suit"
+ icon_state = "sl_suit"
+ item_color = "sl_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/roman
+ name = "\improper Roman armor"
+ desc = "Ancient Roman armor. Made of metallic and leather straps."
+ icon_state = "roman"
+ item_color = "roman"
+ item_state = "armor"
+ can_adjust = FALSE
+ strip_delay = 100
+ resistance_flags = NONE
+
+/obj/item/clothing/under/waiter
+ name = "waiter's outfit"
+ desc = "It's a very smart uniform with a special pocket for tip."
+ icon_state = "waiter"
+ item_state = "waiter"
+ item_color = "waiter"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/rank/prisoner
+ name = "prison jumpsuit"
+ desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position."
+ icon_state = "prisoner"
+ item_state = "o_suit"
+ item_color = "prisoner"
+ has_sensor = LOCKED_SENSORS
+ sensor_mode = SENSOR_COORDS
+ random_sensor = FALSE
+
+/obj/item/clothing/under/rank/mailman
+ name = "mailman's jumpsuit"
+ desc = "'Special delivery!'"
+ icon_state = "mailman"
+ item_state = "b_suit"
+ item_color = "mailman"
+
+/obj/item/clothing/under/rank/psyche
+ name = "psychedelic jumpsuit"
+ desc = "Groovy!"
+ icon_state = "psyche"
+ item_state = "p_suit"
+ item_color = "psyche"
+
+/obj/item/clothing/under/rank/clown/sexy
+ name = "sexy-clown suit"
+ desc = "It makes you look HONKable!"
+ icon_state = "sexyclown"
+ item_state = "sexyclown"
+ item_color = "sexyclown"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/jabroni
+ name = "Jabroni Outfit"
+ desc = "The leather club is two sectors down."
+ icon_state = "darkholme"
+ item_state = "darkholme"
+ item_color = "darkholme"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/rank/vice
+ name = "vice officer's jumpsuit"
+ desc = "It's the standard issue pretty-boy outfit, as seen on Holo-Vision."
+ icon_state = "vice"
+ item_state = "gy_suit"
+ item_color = "vice"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/rank/centcom_officer
+ desc = "It's a jumpsuit worn by CentCom Officers."
+ name = "\improper CentCom officer's jumpsuit"
+ icon_state = "officer"
+ item_state = "g_suit"
+ item_color = "officer"
+ alt_covers_chest = TRUE
+
+/obj/item/clothing/under/rank/centcom_commander
+ desc = "It's a jumpsuit worn by CentCom's highest-tier Commanders."
+ name = "\improper CentCom officer's jumpsuit"
+ icon_state = "centcom"
+ item_state = "dg_suit"
+ item_color = "centcom"
+
+/obj/item/clothing/under/space
+ name = "\improper NASA jumpsuit"
+ desc = "It has a NASA logo on it and is made of space-proofed materials."
+ icon_state = "black"
+ item_state = "bl_suit"
+ item_color = "black"
+ w_class = WEIGHT_CLASS_BULKY
+ gas_transfer_coefficient = 0.01
+ permeability_coefficient = 0.02
+ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ cold_protection = CHEST | GROIN | LEGS | ARMS //Needs gloves and shoes with cold protection to be fully protected.
+ min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
+ heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
+ can_adjust = FALSE
+ resistance_flags = NONE
+
+/obj/item/clothing/under/acj
+ name = "administrative cybernetic jumpsuit"
+ icon_state = "syndicate"
+ item_state = "bl_suit"
+ item_color = "syndicate"
+ desc = "A cybernetically enhanced jumpsuit used for administrative duties."
+ gas_transfer_coefficient = 0.01
+ permeability_coefficient = 0.01
+ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ armor = list("melee" = 100, "bullet" = 100, "laser" = 100,"energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
+ cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS
+ min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
+ heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
+ can_adjust = FALSE
+ resistance_flags = FIRE_PROOF | ACID_PROOF
+
+/obj/item/clothing/under/owl
+ name = "owl uniform"
+ desc = "A soft brown jumpsuit made of synthetic feathers and strong conviction."
+ icon_state = "owl"
+ item_color = "owl"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/griffin
+ name = "griffon uniform"
+ desc = "A soft brown jumpsuit with a white feather collar made of synthetic feathers and a lust for mayhem."
+ icon_state = "griffin"
+ item_color = "griffin"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/cloud
+ name = "cloud"
+ desc = "cloud"
+ icon_state = "cloud"
+ item_color = "cloud"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/gimmick/rank/captain/suit
+ name = "captain's suit"
+ desc = "A green suit and yellow necktie. Exemplifies authority."
+ icon_state = "green_suit"
+ item_state = "dg_suit"
+ item_color = "green_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/gimmick/rank/head_of_personnel/suit
+ name = "head of personnel's suit"
+ desc = "A teal suit and yellow necktie. An authoritative yet tacky ensemble."
+ icon_state = "teal_suit"
+ item_state = "g_suit"
+ item_color = "teal_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/suit_jacket
+ name = "black suit"
+ desc = "A black suit and red tie. Very formal."
+ icon_state = "black_suit"
+ item_state = "bl_suit"
+ item_color = "black_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/suit_jacket/really_black
+ name = "executive suit"
+ desc = "A formal black suit and red tie, intended for the station's finest."
+ icon_state = "really_black_suit"
+ item_state = "bl_suit"
+ item_color = "black_suit"
+
+/obj/item/clothing/under/suit_jacket/female
+ name = "executive suit"
+ desc = "A formal trouser suit for women, intended for the station's finest."
+ icon_state = "black_suit_fem"
+ item_state = "black_suit_fem"
+ item_color = "black_suit_fem"
+
+/obj/item/clothing/under/suit_jacket/green
+ name = "green suit"
+ desc = "A green suit and yellow necktie. Baller."
+ icon_state = "green_suit"
+ item_state = "dg_suit"
+ item_color = "green_suit"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/suit_jacket/red
+ name = "red suit"
+ desc = "A red suit and blue tie. Somewhat formal."
+ icon_state = "red_suit"
+ item_state = "r_suit"
+ item_color = "red_suit"
+
+/obj/item/clothing/under/suit_jacket/charcoal
+ name = "charcoal suit"
+ desc = "A charcoal suit and red tie. Very professional."
+ icon_state = "charcoal_suit"
+ item_state = "charcoal_suit"
+ item_color = "charcoal_suit"
+
+/obj/item/clothing/under/suit_jacket/navy
+ name = "navy suit"
+ desc = "A navy suit and red tie, intended for the station's finest."
+ icon_state = "navy_suit"
+ item_state = "navy_suit"
+ item_color = "navy_suit"
+
+/obj/item/clothing/under/suit_jacket/burgundy
+ name = "burgundy suit"
+ desc = "A burgundy suit and black tie. Somewhat formal."
+ icon_state = "burgundy_suit"
+ item_state = "burgundy_suit"
+ item_color = "burgundy_suit"
+
+/obj/item/clothing/under/suit_jacket/checkered
+ name = "checkered suit"
+ desc = "That's a very nice suit you have there. Shame if something were to happen to it, eh?"
+ icon_state = "checkered_suit"
+ item_state = "checkered_suit"
+ item_color = "checkered_suit"
+
+/obj/item/clothing/under/suit_jacket/tan
+ name = "tan suit"
+ desc = "A tan suit with a yellow tie. Smart, but casual."
+ icon_state = "tan_suit"
+ item_state = "tan_suit"
+ item_color = "tan_suit"
+
+/obj/item/clothing/under/suit_jacket/white
+ name = "white suit"
+ desc = "A white suit and jacket with a blue shirt. You wanna play rough? OKAY!"
+ icon_state = "white_suit"
+ item_state = "white_suit"
+ item_color = "white_suit"
+
+/obj/item/clothing/under/burial
+ name = "burial garments"
+ desc = "Traditional burial garments from the early 22nd century."
+ icon_state = "burial"
+ item_state = "burial"
+ item_color = "burial"
+ has_sensor = NO_SENSORS
+
+/obj/item/clothing/under/skirt/black
+ name = "black skirt"
+ desc = "A black skirt, very fancy!"
+ icon_state = "blackskirt"
+ item_color = "blackskirt"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/skirt/blue
+ name = "blue skirt"
+ desc = "A blue, casual skirt."
+ icon_state = "blueskirt"
+ item_color = "blueskirt"
+ item_state = "b_suit"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/skirt/red
+ name = "red skirt"
+ desc = "A red, casual skirt."
+ icon_state = "redskirt"
+ item_color = "redskirt"
+ item_state = "r_suit"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/skirt/purple
+ name = "purple skirt"
+ desc = "A purple, casual skirt."
+ icon_state = "purpleskirt"
+ item_color = "purpleskirt"
+ item_state = "p_suit"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+
+/obj/item/clothing/under/schoolgirl
+ name = "blue schoolgirl uniform"
+ desc = "It's just like one of my Japanese animes!"
+ icon_state = "schoolgirl"
+ item_state = "schoolgirl"
+ item_color = "schoolgirl"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/schoolgirl/red
+ name = "red schoolgirl uniform"
+ icon_state = "schoolgirlred"
+ item_state = "schoolgirlred"
+ item_color = "schoolgirlred"
+
+/obj/item/clothing/under/schoolgirl/green
+ name = "green schoolgirl uniform"
+ icon_state = "schoolgirlgreen"
+ item_state = "schoolgirlgreen"
+ item_color = "schoolgirlgreen"
+
+/obj/item/clothing/under/schoolgirl/orange
+ name = "orange schoolgirl uniform"
+ icon_state = "schoolgirlorange"
+ item_state = "schoolgirlorange"
+ item_color = "schoolgirlorange"
+
+/obj/item/clothing/under/overalls
+ name = "laborer's overalls"
+ desc = "A set of durable overalls for getting the job done."
+ icon_state = "overalls"
+ item_state = "lb_suit"
+ item_color = "overalls"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/pirate
+ name = "pirate outfit"
+ desc = "Yarr."
+ icon_state = "pirate"
+ item_state = "pirate"
+ item_color = "pirate"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/soviet
+ name = "soviet uniform"
+ desc = "For the Motherland!"
+ icon_state = "soviet"
+ item_state = "soviet"
+ item_color = "soviet"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/redcoat
+ name = "redcoat uniform"
+ desc = "Looks old."
+ icon_state = "redcoat"
+ item_state = "redcoat"
+ item_color = "redcoat"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/kilt
+ name = "kilt"
+ desc = "Includes shoes and plaid."
+ icon_state = "kilt"
+ item_state = "kilt"
+ item_color = "kilt"
+ body_parts_covered = CHEST|GROIN|LEGS|FEET
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/kilt/highlander
+ desc = "You're the only one worthy of this kilt."
+ item_flags = NODROP
+
+/obj/item/clothing/under/sexymime
+ name = "sexy mime outfit"
+ desc = "The only time when you DON'T enjoy looking at someone's rack."
+ icon_state = "sexymime"
+ item_state = "sexymime"
+ item_color = "sexymime"
+ body_parts_covered = CHEST|GROIN|LEGS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/gladiator
+ name = "gladiator uniform"
+ desc = "Are you not entertained? Is that not why you are here?"
+ icon_state = "gladiator"
+ item_state = "gladiator"
+ item_color = "gladiator"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = NO_FEMALE_UNIFORM
+ can_adjust = FALSE
+ resistance_flags = NONE
+
+/obj/item/clothing/under/gladiator/ash_walker
+ desc = "This gladiator uniform appears to be covered in ash and fairly dated."
+ has_sensor = NO_SENSORS
+
+/obj/item/clothing/under/sundress
+ name = "sundress"
+ desc = "Makes you want to frolic in a field of daisies."
+ icon_state = "sundress"
+ item_state = "sundress"
+ item_color = "sundress"
+ body_parts_covered = CHEST|GROIN
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/captainparade
+ name = "captain's parade uniform"
+ desc = "A captain's luxury-wear, for special occasions."
+ icon_state = "captain_parade"
+ item_state = "by_suit"
+ item_color = "captain_parade"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/hosparademale
+ name = "head of security's parade uniform"
+ desc = "A male head of security's luxury-wear, for special occasions."
+ icon_state = "hos_parade_male"
+ item_state = "r_suit"
+ item_color = "hos_parade_male"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/hosparadefem
+ name = "head of security's parade uniform"
+ desc = "A female head of security's luxury-wear, for special occasions."
+ icon_state = "hos_parade_fem"
+ item_state = "r_suit"
+ item_color = "hos_parade_fem"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/assistantformal
+ name = "assistant's formal uniform"
+ desc = "An assistant's formal-wear. Why an assistant needs formal-wear is still unknown."
+ icon_state = "assistant_formal"
+ item_state = "gy_suit"
+ item_color = "assistant_formal"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/blacktango
+ name = "black tango dress"
+ desc = "Filled with Latin fire."
+ icon_state = "black_tango"
+ item_state = "wcoat"
+ item_color = "black_tango"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+ body_parts_covered = CHEST|GROIN
+
+/obj/item/clothing/under/stripeddress
+ name = "striped dress"
+ desc = "Fashion in space."
+ icon_state = "striped_dress"
+ item_state = "stripeddress"
+ item_color = "striped_dress"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_FULL
+ can_adjust = FALSE
+
+/obj/item/clothing/under/sailordress
+ name = "sailor dress"
+ desc = "Formal wear for a leading lady."
+ icon_state = "sailor_dress"
+ item_state = "sailordress"
+ item_color = "sailor_dress"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/redeveninggown
+ name = "red evening gown"
+ desc = "Fancy dress for space bar singers."
+ icon_state = "red_evening_gown"
+ item_state = "redeveninggown"
+ item_color = "red_evening_gown"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/maid
+ name = "maid costume"
+ desc = "Maid in China."
+ icon_state = "maid"
+ item_state = "maid"
+ item_color = "maid"
+ body_parts_covered = CHEST|GROIN
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/maid/Initialize()
+ . = ..()
+ var/obj/item/clothing/accessory/maidapron/A = new (src)
+ attach_accessory(A)
+
+/obj/item/clothing/under/janimaid
+ name = "maid uniform"
+ desc = "A simple maid uniform for housekeeping."
+ icon_state = "janimaid"
+ item_state = "janimaid"
+ item_color = "janimaid"
+ body_parts_covered = CHEST|GROIN
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/plaid_skirt
+ name = "red plaid skirt"
+ desc = "A preppy red skirt with a white blouse."
+ icon_state = "plaid_red"
+ item_state = "plaid_red"
+ item_color = "plaid_red"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = TRUE
+ alt_covers_chest = TRUE
+
+/obj/item/clothing/under/plaid_skirt/blue
+ name = "blue plaid skirt"
+ desc = "A preppy blue skirt with a white blouse."
+ icon_state = "plaid_blue"
+ item_state = "plaid_blue"
+ item_color = "plaid_blue"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = TRUE
+ alt_covers_chest = TRUE
+
+/obj/item/clothing/under/plaid_skirt/purple
+ name = "purple plaid skirt"
+ desc = "A preppy purple skirt with a white blouse."
+ icon_state = "plaid_purple"
+ item_state = "plaid_purple"
+ item_color = "plaid_purple"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = TRUE
+ alt_covers_chest = TRUE
+
+/obj/item/clothing/under/singery
+ name = "yellow performer's outfit"
+ desc = "Just looking at this makes you want to sing."
+ icon_state = "ysing"
+ item_state = "ysing"
+ item_color = "ysing"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = NO_FEMALE_UNIFORM
+ alternate_worn_layer = ABOVE_SHOES_LAYER
+ can_adjust = FALSE
+
+/obj/item/clothing/under/singerb
+ name = "blue performer's outfit"
+ desc = "Just looking at this makes you want to sing."
+ icon_state = "bsing"
+ item_state = "bsing"
+ item_color = "bsing"
+ body_parts_covered = CHEST|GROIN|ARMS
+ alternate_worn_layer = ABOVE_SHOES_LAYER
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+
+/obj/item/clothing/under/plaid_skirt/green
+ name = "green plaid skirt"
+ desc = "A preppy green skirt with a white blouse."
+ icon_state = "plaid_green"
+ item_state = "plaid_green"
+ item_color = "plaid_green"
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = TRUE
+ alt_covers_chest = TRUE
+
+/obj/item/clothing/under/jester
+ name = "jester suit"
+ desc = "A jolly dress, well suited to entertain your master, nuncle."
+ icon_state = "jester"
+ item_color = "jester"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/jester/alt
+ icon_state = "jester2"
+
+/obj/item/clothing/under/geisha
+ name = "geisha suit"
+ desc = "Cute space ninja senpai not included."
+ icon_state = "geisha"
+ item_color = "geisha"
+ body_parts_covered = CHEST|GROIN|ARMS
+ can_adjust = FALSE
+
+/obj/item/clothing/under/villain
+ name = "villain suit"
+ desc = "A change of wardrobe is necessary if you ever want to catch a real superhero."
+ icon_state = "villain"
+ item_color = "villain"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/sailor
+ name = "sailor suit"
+ desc = "Skipper's in the wardroom drinkin gin'."
+ icon_state = "sailor"
+ item_state = "b_suit"
+ item_color = "sailor"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/plasmaman
+ name = "plasma envirosuit"
+ desc = "A special containment suit that allows plasma-based lifeforms to exist safely in an oxygenated environment, and automatically extinguishes them in a crisis. Despite being airtight, it's not spaceworthy."
+ icon_state = "plasmaman"
+ item_state = "plasmaman"
+ item_color = "plasmaman"
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95)
+ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ can_adjust = FALSE
+ strip_delay = 80
+ var/next_extinguish = 0
+ var/extinguish_cooldown = 100
+ var/extinguishes_left = 5
+
+
+/obj/item/clothing/under/plasmaman/examine(mob/user)
+ ..()
+ to_chat(user, "There are [extinguishes_left] extinguisher charges left in this suit.")
+
+
+/obj/item/clothing/under/plasmaman/proc/Extinguish(mob/living/carbon/human/H)
+ if(!istype(H))
+ return
+
+ if(H.on_fire)
+ if(extinguishes_left)
+ if(next_extinguish > world.time)
+ return
+ next_extinguish = world.time + extinguish_cooldown
+ extinguishes_left--
+ H.visible_message("[H]'s suit automatically extinguishes [H.p_them()]!","Your suit automatically extinguishes you.")
+ H.ExtinguishMob()
+ new /obj/effect/particle_effect/water(get_turf(H))
+ return 0
+
+/obj/item/clothing/under/plasmaman/attackby(obj/item/E, mob/user, params)
+ ..()
+ if (istype(E, /obj/item/extinguisher_refill))
+ if (extinguishes_left == 5)
+ to_chat(user, "The inbuilt extinguisher is full.")
+ return
+ else
+ extinguishes_left = 5
+ to_chat(user, "You refill the suit's built-in extinguisher, using up the cartridge.")
+ qdel(E)
+ return
+ return
+ return
+
+/obj/item/extinguisher_refill
+ name = "envirosuit extinguisher cartridge"
+ desc = "A cartridge loaded with a compressed extinguisher mix, used to refill the automatic extinguisher on plasma envirosuits."
+ icon_state = "plasmarefill"
+ icon = 'icons/obj/device.dmi'
+
+/obj/item/clothing/under/rank/security/navyblue/russian
+ name = "\improper Russian officer's uniform"
+ desc = "The latest in fashionable russian outfits."
+ icon_state = "hostanclothes"
+ item_state = "hostanclothes"
+ item_color = "hostanclothes"
+
+/obj/item/clothing/under/mummy
+ name = "mummy wrapping"
+ desc = "Return the slab or suffer my stale references."
+ icon_state = "mummy"
+ item_state = "mummy"
+ item_color = "mummy"
+ body_parts_covered = CHEST|GROIN|ARMS|LEGS
+ fitted = NO_FEMALE_UNIFORM
+ can_adjust = FALSE
+ resistance_flags = NONE
+
+/obj/item/clothing/under/scarecrow
+ name = "scarecrow clothes"
+ desc = "Perfect camouflage for hiding in botany."
+ icon_state = "scarecrow"
+ item_state = "scarecrow"
+ item_color = "scarecrow"
+ body_parts_covered = CHEST|GROIN|ARMS|LEGS
+ fitted = NO_FEMALE_UNIFORM
+ can_adjust = FALSE
+ resistance_flags = NONE
+
+/obj/item/clothing/under/draculass
+ name = "draculass coat"
+ desc = "A dress inspired by the ancient \"Victorian\" era."
+ icon_state = "draculass"
+ item_state = "draculass"
+ item_color = "draculass"
+ body_parts_covered = CHEST|GROIN|ARMS
+ fitted = FEMALE_UNIFORM_TOP
+ can_adjust = FALSE
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
+
+/obj/item/clothing/under/drfreeze
+ name = "doctor freeze's jumpsuit"
+ desc = "A modified scientist jumpsuit to look extra cool."
+ icon_state = "drfreeze"
+ item_state = "drfreeze"
+ item_color = "drfreeze"
+ can_adjust = FALSE
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
+
+/obj/item/clothing/under/lobster
+ name = "foam lobster suit"
+ desc = "Who beheaded the college mascot?"
+ icon_state = "lobster"
+ item_state = "lobster"
+ item_color = "lobster"
+ fitted = NO_FEMALE_UNIFORM
+ can_adjust = FALSE
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
+
+/obj/item/clothing/under/gondola
+ name = "gondola hide suit"
+ desc = "Now you're cooking."
+ icon_state = "gondola"
+ item_state = "lb_suit"
+ item_color = "gondola"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/skeleton
+ name = "skeleton jumpsuit"
+ desc = "A black jumpsuit with a white bone pattern printed on it. Spooky!"
+ icon_state = "skeleton"
+ item_state = "skeleton"
+ item_color = "skeleton"
+ body_parts_covered = CHEST|GROIN|ARMS|LEGS
+ fitted = NO_FEMALE_UNIFORM
+ can_adjust = FALSE
+ resistance_flags = NONE
+
+/obj/item/clothing/under/gear_harness
+ name = "gear harness"
+ desc = "A simple, inconspicuous harness replacement for a jumpsuit."
+ icon_state = "gear_harness"
+ item_state = "gear_harness" //We dont use golem do to being a item, item without faces making it default to error suit sprites.
+ body_parts_covered = CHEST|GROIN
\ No newline at end of file
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
index c1cc6d856e..a76be1ff45 100644
--- a/code/modules/crafting/recipes.dm
+++ b/code/modules/crafting/recipes.dm
@@ -790,3 +790,36 @@
/datum/reagent/water = 15)
time = 40
category = CAT_MISC
+
+/datum/crafting_recipe/smartdart
+ name = "Medical smartdart"
+ result = /obj/item/reagent_containers/syringe/dart
+ reqs = list(/obj/item/stack/sheet/metal = 1,
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/stack/sheet/plastic = 1)
+ time = 10
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
+
+/datum/crafting_recipe/medolier
+ name = "Medolier"
+ result = /obj/item/storage/belt/medolier
+ reqs = list(/obj/item/stack/sheet/metal = 2,
+ /obj/item/stack/sheet/cloth = 3,
+ /obj/item/stack/sheet/plastic = 4)
+ time = 30
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
+
+/datum/crafting_recipe/smartdartgun
+ name = "Smart dartgun"
+ result = /obj/item/gun/syringe/dart
+ reqs = list(/obj/item/stack/sheet/metal = 15,
+ /obj/item/stack/sheet/glass = 10,
+ /obj/item/tank/internals = 1,
+ /obj/item/reagent_containers/glass/beaker = 1,
+ /obj/item/stack/sheet/plastic = 10,
+ /obj/item/stack/cable_coil = 2)
+ time = 150 //It's a gun
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
index deba080ca2..483055cb0d 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
@@ -15,6 +15,7 @@
var/max_n_of_items = 1500
var/allow_ai_retrieve = FALSE
var/list/initial_contents
+ var/visible_contents = TRUE
/obj/machinery/smartfridge/Initialize()
. = ..()
@@ -37,11 +38,21 @@
update_icon()
/obj/machinery/smartfridge/update_icon()
- var/startstate = initial(icon_state)
if(!stat)
- icon_state = startstate
+ if(visible_contents)
+ switch(contents.len)
+ if(0)
+ icon_state = "[initial(icon_state)]"
+ if(1 to 25)
+ icon_state = "[initial(icon_state)]1"
+ if(26 to 75)
+ icon_state = "[initial(icon_state)]2"
+ if(76 to INFINITY)
+ icon_state = "[initial(icon_state)]3"
+ else
+ icon_state = "[initial(icon_state)]"
else
- icon_state = "[startstate]-off"
+ icon_state = "[initial(icon_state)]-off"
@@ -50,7 +61,14 @@
********************/
/obj/machinery/smartfridge/attackby(obj/item/O, mob/user, params)
- if(default_deconstruction_screwdriver(user, "smartfridge_open", "smartfridge", O))
+ if(user.a_intent == INTENT_HARM)
+ return ..()
+
+ if(default_deconstruction_screwdriver(user, icon_state, icon_state, O))
+ cut_overlays()
+ if(panel_open)
+ add_overlay("[initial(icon_state)]-panel")
+ updateUsrDialog()
return
if(default_pry_open(O))
@@ -64,49 +82,46 @@
updateUsrDialog()
return
- if(!stat)
-
- if(contents.len >= max_n_of_items)
- to_chat(user, "\The [src] is full!")
- return FALSE
-
- if(accept_check(O))
- load(O)
- user.visible_message("[user] has added \the [O] to \the [src].", "You add \the [O] to \the [src].")
- updateUsrDialog()
- return TRUE
-
- if(istype(O, /obj/item/storage/bag))
- var/obj/item/storage/P = O
- var/loaded = 0
- for(var/obj/G in P.contents)
- if(contents.len >= max_n_of_items)
- break
- if(accept_check(G))
- load(G)
- loaded++
- updateUsrDialog()
-
- if(loaded)
- if(contents.len >= max_n_of_items)
- user.visible_message("[user] loads \the [src] with \the [O].", \
- "You fill \the [src] with \the [O].")
- else
- user.visible_message("[user] loads \the [src] with \the [O].", \
- "You load \the [src] with \the [O].")
- if(O.contents.len > 0)
- to_chat(user, "Some items are refused.")
- return TRUE
- else
- to_chat(user, "There is nothing in [O] to put in [src]!")
- return FALSE
-
- if(user.a_intent != INTENT_HARM)
- to_chat(user, "\The [src] smartly refuses [O].")
+ if(stat)
updateUsrDialog()
return FALSE
- else
- return ..()
+
+ if(contents.len >= max_n_of_items)
+ to_chat(user, "\The [src] is full!")
+ return FALSE
+
+ if(accept_check(O))
+ load(O)
+ user.visible_message("[user] has added \the [O] to \the [src].", "You add \the [O] to \the [src].")
+ updateUsrDialog()
+ if (visible_contents)
+ update_icon()
+ return TRUE
+
+ if(istype(O, /obj/item/storage/bag))
+ var/obj/item/storage/P = O
+ var/loaded = 0
+ for(var/obj/G in P.contents)
+ if(contents.len >= max_n_of_items)
+ break
+ if(accept_check(G))
+ load(G)
+ loaded++
+ updateUsrDialog()
+
+ if(loaded)
+ user.visible_message("[user] loads \the [src] with \the [O].", \
+ "You [contents.len >= max_n_of_items ? "fill" : "load"] \the [src] with \the [O].")
+ if(O.contents.len > 0)
+ to_chat(user, "Some items are refused.")
+ return TRUE
+ else
+ to_chat(user, "There is nothing in [O] to put in [src]!")
+ return FALSE
+
+ to_chat(user, "\The [src] smartly refuses [O].")
+ updateUsrDialog()
+ return FALSE
@@ -186,6 +201,8 @@
O.forceMove(drop_location())
adjust_item_drop_location(O)
break
+ if (visible_contents)
+ update_icon()
return TRUE
for(var/obj/item/O in src)
@@ -195,6 +212,8 @@
O.forceMove(drop_location())
adjust_item_drop_location(O)
desired--
+ if (visible_contents)
+ update_icon()
return TRUE
return FALSE
@@ -210,6 +229,7 @@
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 200
+ visible_contents = FALSE
var/drying = FALSE
/obj/machinery/smartfridge/drying_rack/Initialize()
@@ -414,6 +434,7 @@
name = "disk compartmentalizer"
desc = "A machine capable of storing a variety of disks. Denoted by most as the DSU (disk storage unit)."
icon_state = "disktoaster"
+ visible_contents = FALSE
pass_flags = PASSTABLE
/obj/machinery/smartfridge/disks/accept_check(obj/item/O)
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
index ba6c0120e1..2246d12df4 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
@@ -104,7 +104,7 @@ datum/crafting_recipe/food/donut/meat
/datum/crafting_recipe/food/rofflewaffles
name = "Roffle waffles"
reqs = list(
- /datum/reagent/mushroomhallucinogen = 5,
+ /datum/reagent/drug/mushroomhallucinogen = 5,
/obj/item/reagent_containers/food/snacks/pastrybase = 2
)
result = /obj/item/reagent_containers/food/snacks/rofflewaffles
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 0990ca961a..eaac1984e3 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -273,23 +273,12 @@
to_chat(user, "You release the wisp. It begins to bob around your head.")
icon_state = "lantern"
wisp.orbit(user, 20)
- user.update_sight()
SSblackbox.record_feedback("tally", "wisp_lantern", 1, "Freed")
else
to_chat(user, "You return the wisp to the lantern.")
-
- var/mob/target
- if(wisp.orbiting)
- target = wisp.orbiting.orbiting
- wisp.stop_orbit()
- wisp.forceMove(src)
-
- if (istype(target))
- target.update_sight()
- to_chat(target, "Your vision returns to normal.")
-
icon_state = "lantern-blue"
+ wisp.forceMove(src)
SSblackbox.record_feedback("tally", "wisp_lantern", 1, "Returned")
/obj/item/wisp_lantern/Initialize()
@@ -302,7 +291,7 @@
qdel(wisp)
else
wisp.visible_message("[wisp] has a sad feeling for a moment, then it passes.")
- ..()
+ return ..()
/obj/effect/wisp
name = "friendly wisp"
@@ -314,6 +303,25 @@
var/sight_flags = SEE_MOBS
var/lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
+/obj/effect/wisp/orbit(atom/thing, radius, clockwise, rotation_speed, rotation_segments, pre_rotation, lockinorbit)
+ . = ..()
+ if(ismob(thing))
+ RegisterSignal(thing, COMSIG_MOB_UPDATE_SIGHT, .proc/update_user_sight)
+ var/mob/being = thing
+ being.update_sight()
+ to_chat(thing, "The wisp enhances your vision.")
+
+/obj/effect/wisp/stop_orbit(datum/component/orbiter/orbits)
+ . = ..()
+ if(ismob(orbits.parent))
+ UnregisterSignal(orbits.parent, COMSIG_MOB_UPDATE_SIGHT)
+ to_chat(orbits.parent, "Your vision returns to normal.")
+
+/obj/effect/wisp/proc/update_user_sight(mob/user)
+ user.sight |= sight_flags
+ if(!isnull(lighting_alpha))
+ user.lighting_alpha = min(user.lighting_alpha, lighting_alpha)
+
//Red/Blue Cubes
/obj/item/warp_cube
name = "blue cube"
@@ -781,19 +789,17 @@
var/turf/T = get_turf(src)
var/list/contents = T.GetAllContents()
var/mob/dead/observer/current_spirits = list()
- var/list/orbiters = list()
for(var/thing in contents)
var/atom/A = thing
- if (A.orbiters)
- orbiters += A.orbiters
+ A.transfer_observers_to(src)
- for(var/thing in orbiters)
- var/datum/orbit/O = thing
- if (isobserver(O.orbiter))
- var/mob/dead/observer/G = O.orbiter
- ghost_counter++
- G.invisibility = 0
- current_spirits |= G
+ for(var/i in orbiters?.orbiters)
+ if(!isobserver(i))
+ continue
+ var/mob/dead/observer/G = i
+ ghost_counter++
+ G.invisibility = 0
+ current_spirits |= G
for(var/mob/dead/observer/G in spirits - current_spirits)
G.invisibility = GLOB.observer_default_invisibility
diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm
index 883f5a034f..c780d57810 100644
--- a/code/modules/mob/camera/camera.dm
+++ b/code/modules/mob/camera/camera.dm
@@ -26,7 +26,9 @@
return
/mob/camera/forceMove(atom/destination)
+ var/oldloc = loc
loc = destination
+ Moved(oldloc, NONE, TRUE)
/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE)
return
diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm
index d886a41b0f..381dc131e7 100644
--- a/code/modules/mob/dead/dead.dm
+++ b/code/modules/mob/dead/dead.dm
@@ -34,7 +34,9 @@ INITIALIZE_IMMEDIATE(/mob/dead)
var/turf/new_turf = get_turf(destination)
if (old_turf?.z != new_turf?.z)
onTransitZ(old_turf?.z, new_turf?.z)
+ var/oldloc = loc
loc = destination
+ Moved(oldloc, NONE, TRUE)
/mob/dead/Stat()
..()
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/socks.dm b/code/modules/mob/dead/new_player/sprite_accessories/socks.dm
index 5a5d37d4e7..01a83dcc9f 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/socks.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/socks.dm
@@ -11,6 +11,10 @@
// please make sure they're sorted alphabetically and categorized
+/datum/sprite_accessory/socks/bee_knee
+ name = "Knee-high (Bee)"
+ icon_state = "bee_knee"
+
/datum/sprite_accessory/socks/black_knee
name = "Knee-high (Black)"
icon_state = "black_knee"
@@ -63,6 +67,10 @@
name = "Short (White)"
icon_state = "white_short"
+/datum/sprite_accessory/socks/bee_thigh
+ name = "Thigh-high (Bee)"
+ icon_state = "bee_thigh"
+
/datum/sprite_accessory/socks/black_thigh
name = "Thigh-high (Black)"
icon_state = "black_thigh"
@@ -93,4 +101,4 @@
/datum/sprite_accessory/socks/white_thigh
name = "Thigh-high (White)"
- icon_state = "white_thigh"
\ No newline at end of file
+ icon_state = "white_thigh"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/undershirt.dm b/code/modules/mob/dead/new_player/sprite_accessories/undershirt.dm
index 7c66ef51e3..f5af9a3849 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/undershirt.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/undershirt.dm
@@ -248,9 +248,13 @@
icon_state = "bra_commie"
/datum/sprite_accessory/undershirt/female_babyblue
- name = "Bra, Baby Blue"
+ name = "Bra - Baby Blue"
icon_state = "bra_babyblue"
+/datum/sprite_accessory/undershirt/female_beekini
+ name = "Bra - Bee-kini"
+ icon_state = "bra_bee-kini"
+
/datum/sprite_accessory/undershirt/female_black
name = "Bra - Black"
icon_state = "bra_black"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/underwear.dm b/code/modules/mob/dead/new_player/sprite_accessories/underwear.dm
index 6beed231aa..e7179eeb87 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/underwear.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/underwear.dm
@@ -90,6 +90,9 @@
name = "Boxer Briefs - Yellow"
icon_state = "boxer_briefs_yellow"
+/datum/sprite_accessory/underwear/female_beekini
+ name = "Panties - Bee-kini"
+ icon_state = "panties_bee-kini"
/datum/sprite_accessory/underwear/female_black
name = "Panties - Black"
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 55b8891534..fefa032e4f 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -429,9 +429,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/orbitsize = (I.Width()+I.Height())*0.5
orbitsize -= (orbitsize/world.icon_size)*(world.icon_size*0.25)
- if(orbiting && orbiting.orbiting != target)
- to_chat(src, "Now orbiting [target].")
-
var/rot_seg
switch(ghost_orbit)
@@ -450,10 +447,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/orbit()
setDir(2)//reset dir so the right directional sprites show up
- ..()
+ return ..()
-/mob/dead/observer/stop_orbit()
- ..()
+/mob/dead/observer/stop_orbit(datum/component/orbiter/orbits)
+ . = ..()
//restart our floating animation after orbit is done.
pixel_y = 0
animate(src, pixel_y = 2, time = 10, loop = -1)
@@ -753,7 +750,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
update_icon()
-/mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
return IsAdminGhost(usr)
/mob/dead/observer/is_literate()
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index d814893053..8550a0887f 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -294,7 +294,7 @@
if(mood.sanity <= SANITY_DISTURBED)
msg += "[t_He] seem[p_s()] distressed.\n"
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "empath", /datum/mood_event/sad_empath, src)
- if(mood.mood >= 5) //So roundstart people aren't all "happy"
+ if(mood.shown_mood >= 6) //So roundstart people aren't all "happy" and that antags don't show their true happiness.
msg += "[t_He] seem[p_s()] to have had something nice happen to them recently.\n"
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "empathH", /datum/mood_event/happy_empath, src)
if (HAS_TRAIT(src, TRAIT_BLIND))
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index c03c0fc0a9..a4fca9dd78 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -725,12 +725,12 @@
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#000000")
cut_overlay(MA)
-/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated() || lying )
to_chat(src, "You can't do that right now!")
return FALSE
if(!Adjacent(M) && (M.loc != src))
- if((be_close == 0) || (dna.check_mutation(TK) && tkMaxRangeCheck(src, M)))
+ if((be_close == 0) || (!no_tk && (dna.check_mutation(TK) && tkMaxRangeCheck(src, M))))
return TRUE
to_chat(src, "You are too far away!")
return FALSE
@@ -856,13 +856,16 @@
buckle_mob(target,TRUE,TRUE)
. = ..()
+/mob/living/carbon/human/proc/piggyback_instant(mob/living/M)
+ return buckle_mob(M, TRUE, TRUE, FALSE, TRUE)
+
//Can C try to piggyback at all.
/mob/living/carbon/human/proc/can_piggyback(mob/living/carbon/C)
if(istype(C) && C.stat == CONSCIOUS)
return TRUE
return FALSE
-/mob/living/carbon/human/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE, bypass_piggybacking = FALSE)
+/mob/living/carbon/human/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE, bypass_piggybacking = FALSE, no_delay = FALSE)
if(!force)//humans are only meant to be ridden through piggybacking and special cases
return
if(bypass_piggybacking)
@@ -879,7 +882,7 @@
if(can_piggyback(M))
riding_datum.ride_check_ridden_incapacitated = TRUE
visible_message("[M] starts to climb onto [src]...")
- if(force || do_after(M, 15, target = src))
+ if(no_delay || do_after(M, 15, target = src))
if(can_piggyback(M))
if(M.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE))
M.visible_message("[M] can't hang onto [src]!")
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 0a00bab3f4..4fb3fb0243 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -1300,7 +1300,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
. += H.physiology.speed_mod
if (H.m_intent == MOVE_INTENT_WALK && HAS_TRAIT(H, TRAIT_SPEEDY_STEP))
- . -= 1
+ . -= 1.5
if(HAS_TRAIT(H, TRAIT_IGNORESLOWDOWN))
ignoreslow = 1
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 571775d541..b2eb83d668 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -654,6 +654,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
L.damage += d
/mob/living/carbon/proc/liver_failure()
+ reagents.end_metabolization(src, keep_liverless = TRUE) //Stops trait-based effects on reagents, to prevent permanent buffs
reagents.metabolize(src, can_overdose=FALSE, liverless = TRUE)
if(HAS_TRAIT(src, TRAIT_STABLEHEART))
return
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 69168caad1..b253e27e8d 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -814,7 +814,7 @@
/mob/living/proc/harvest(mob/living/user) //used for extra objects etc. in butchering
return
-/mob/living/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated())
to_chat(src, "You can't do that right now!")
return FALSE
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 46576a357f..6d225d3913 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -779,7 +779,7 @@
return TRUE
return ..()
-/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(control_disabled || incapacitated())
to_chat(src, "You can't do that right now!")
return FALSE
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 896d8674be..7fd861bfeb 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -183,7 +183,7 @@
// See software.dm for Topic()
-/mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(be_close && !in_range(M, src))
to_chat(src, "You are too far away!")
return FALSE
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 335645b17e..e71e269222 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -910,7 +910,7 @@
if(DISCONNECT) //Tampering with the wires
to_chat(connected_ai, "
NOTICE - Remote telemetry lost with [name].
")
-/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(stat || lockcharge || low_power_mode)
to_chat(src, "You can't do that right now!")
return FALSE
diff --git a/code/modules/mob/living/simple_animal/friendly/panda.dm b/code/modules/mob/living/simple_animal/friendly/panda.dm
new file mode 100644
index 0000000000..a7b6143ef5
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/friendly/panda.dm
@@ -0,0 +1,20 @@
+/mob/living/simple_animal/pet/redpanda
+ name = "Red panda"
+ desc = "Wah't a dork."
+ icon = 'icons/mob/pets.dmi'
+ icon_state = "red_panda"
+ icon_living = "red_panda"
+ icon_dead = "dead_panda"
+ speak = list("Churip","Chuuriip","Cheep-cheep","Chiteurp","squueeaacipt")
+ speak_emote = list("chirps", "huff-quacks")
+ emote_hear = list("squeak-chrips.", "huff-squacks.")
+ emote_see = list("shakes its head.", "rolls about.")
+ speak_chance = 1
+ turns_per_move = 5
+ see_in_dark = 6
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3)
+ response_help = "pets"
+ response_disarm = "gently pushes aside"
+ response_harm = "kicks"
+ gold_core_spawnable = FRIENDLY_SPAWN
+ do_footstep = TRUE
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index 701e244f89..1a918766b6 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -596,6 +596,9 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
/obj/item/guardiancreator/tech/choose/traitor
possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
+/obj/item/guardiancreator/tech/choose/traitor/check_uplink_validity()
+ return !used
+
/obj/item/guardiancreator/tech/choose
random = FALSE
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 2517d2438d..1f81899d8a 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -392,7 +392,7 @@
if(target)
return new childspawn(target)
-/mob/living/simple_animal/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/living/simple_animal/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated())
to_chat(src, "You can't do that right now!")
return FALSE
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 7ff8fbc0b1..b098801da8 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -784,7 +784,7 @@
return 0
//Can the mob use Topic to interact with machines
-/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
return
/mob/proc/faction_check_mob(mob/target, exact_match)
@@ -871,13 +871,7 @@
return
/mob/proc/update_sight()
- for(var/O in orbiters)
- var/datum/orbit/orbit = O
- var/obj/effect/wisp/wisp = orbit.orbiter
- if (istype(wisp))
- sight |= wisp.sight_flags
- if(!isnull(wisp.lighting_alpha))
- lighting_alpha = min(lighting_alpha, wisp.lighting_alpha)
+ SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 33f1ec81c1..82e2b11f8e 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -148,7 +148,7 @@
if(INCORPOREAL_MOVE_BASIC)
var/T = get_step(L,direct)
if(T)
- L.loc = T
+ L.forceMove(T)
L.setDir(direct)
if(INCORPOREAL_MOVE_SHADOW)
if(prob(50))
@@ -190,7 +190,7 @@
new /obj/effect/temp_visual/dir_setting/ninja/shadow(mobloc, L.dir)
var/T = get_step(L,direct)
if(T)
- L.loc = T
+ L.forceMove(T)
L.setDir(direct)
if(INCORPOREAL_MOVE_JAUNT) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
var/turf/open/floor/stepTurf = get_step(L, direct)
@@ -209,7 +209,7 @@
to_chat(L, "Holy energies block your path!")
return
- L.loc = get_step(L, direct)
+ L.forceMove(stepTurf)
L.setDir(direct)
return TRUE
diff --git a/code/modules/modular_computers/computers/item/processor.dm b/code/modules/modular_computers/computers/item/processor.dm
index 20ad2214cf..99d648d02b 100644
--- a/code/modules/modular_computers/computers/item/processor.dm
+++ b/code/modules/modular_computers/computers/item/processor.dm
@@ -44,7 +44,7 @@
return machinery_computer.update_icon()
// This thing is not meant to be used on it's own, get topic data from our machinery owner.
-//obj/item/modular_computer/processor/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
+//obj/item/modular_computer/processor/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
// if(!machinery_computer)
// return 0
diff --git a/code/modules/orbit/orbit.dm b/code/modules/orbit/orbit.dm
deleted file mode 100644
index 79685b9104..0000000000
--- a/code/modules/orbit/orbit.dm
+++ /dev/null
@@ -1,135 +0,0 @@
-/datum/orbit
- var/atom/movable/orbiter
- var/atom/orbiting
- var/lock = TRUE
- var/turf/lastloc
- var/lastprocess
-
-/datum/orbit/New(_orbiter, _orbiting, _lock)
- orbiter = _orbiter
- orbiting = _orbiting
- SSorbit.processing += src
- if (!orbiting.orbiters)
- orbiting.orbiters = list()
- orbiting.orbiters += src
-
- if (orbiter.orbiting)
- orbiter.stop_orbit()
- orbiter.orbiting = src
- Check()
- lock = _lock
-
-//do not qdel directly, use stop_orbit on the orbiter. (This way the orbiter can bind to the orbit stopping)
-/datum/orbit/Destroy(force = FALSE)
- SSorbit.processing -= src
- if (orbiter)
- orbiter.orbiting = null
- orbiter = null
- if (orbiting)
- if (orbiting.orbiters)
- orbiting.orbiters -= src
- if (!orbiting.orbiters.len)//we are the last orbit, delete the list
- orbiting.orbiters = null
- orbiting = null
- return ..()
-
-/datum/orbit/proc/Check(turf/targetloc, list/checked_already = list())
- //Avoid infinite loops for people who end up orbiting themself through another orbiter
- checked_already[src] = TRUE
- if (!orbiter)
- qdel(src)
- return
- if (!orbiting)
- orbiter.stop_orbit()
- return
- if (!orbiter.orbiting) //admin wants to stop the orbit.
- orbiter.orbiting = src //set it back to us first
- orbiter.stop_orbit()
- var/atom/movable/AM = orbiting
- if(istype(AM) && AM.orbiting && AM.orbiting.orbiting == orbiter)
- orbiter.stop_orbit()
- return
- lastprocess = world.time
- if (!targetloc)
- targetloc = get_turf(orbiting)
- if (!targetloc || (!lock && orbiter.loc != lastloc && orbiter.loc != targetloc))
- orbiter.stop_orbit()
- return
- var/turf/old_turf = get_turf(orbiter)
- var/turf/new_turf = get_turf(targetloc)
- if (old_turf?.z != new_turf?.z)
- orbiter.onTransitZ(old_turf?.z, new_turf?.z)
- // DO NOT PORT TO FORCEMOVE - MEMECODE WILL KILL MC
- orbiter.loc = targetloc
- orbiter.update_parallax_contents()
- orbiter.update_light()
- lastloc = orbiter.loc
- for(var/other_orbit in orbiter.orbiters)
- var/datum/orbit/OO = other_orbit
- //Skip if checked already
- if(checked_already[OO])
- continue
- OO.Check(targetloc, checked_already)
-
-/atom/movable/var/datum/orbit/orbiting = null
-/atom/var/list/orbiters = null
-
-//A: atom to orbit
-//radius: range to orbit at, radius of the circle formed by orbiting (in pixels)
-//clockwise: whether you orbit clockwise or anti clockwise
-//rotation_speed: how fast to rotate (how many ds should it take for a rotation to complete)
-//rotation_segments: the resolution of the orbit circle, less = a more block circle, this can be used to produce hexagons (6 segments) triangles (3 segments), and so on, 36 is the best default.
-//pre_rotation: Chooses to rotate src 90 degress towards the orbit dir (clockwise/anticlockwise), useful for things to go "head first" like ghosts
-//lockinorbit: Forces src to always be on A's turf, otherwise the orbit cancels when src gets too far away (eg: ghosts)
-
-/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = FALSE, rotation_speed = 20, rotation_segments = 36, pre_rotation = TRUE, lockinorbit = FALSE)
- if (!istype(A))
- return
-
- new/datum/orbit(src, A, lockinorbit)
- if (!orbiting) //something failed, and our orbit datum deleted itself
- return
- var/matrix/initial_transform = matrix(transform)
-
- //Head first!
- if (pre_rotation)
- var/matrix/M = matrix(transform)
- var/pre_rot = 90
- if(!clockwise)
- pre_rot = -90
- M.Turn(pre_rot)
- transform = M
-
- var/matrix/shift = matrix(transform)
- shift.Translate(0,radius)
- transform = shift
-
- SpinAnimation(rotation_speed, -1, clockwise, rotation_segments)
-
- //we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
- transform = initial_transform
-
-/atom/movable/proc/stop_orbit()
- SpinAnimation(0,0)
- qdel(orbiting)
-
-/atom/Destroy(force = FALSE)
- . = ..()
- if (orbiters)
- for (var/thing in orbiters)
- var/datum/orbit/O = thing
- if (O.orbiter)
- O.orbiter.stop_orbit()
-
-/atom/movable/Destroy(force = FALSE)
- . = ..()
- if (orbiting)
- stop_orbit()
-
-/atom/movable/proc/transfer_observers_to(atom/movable/target)
- if(orbiters)
- for(var/thing in orbiters)
- var/datum/orbit/O = thing
- if(O.orbiter && isobserver(O.orbiter))
- var/mob/dead/observer/D = O.orbiter
- D.ManualFollow(target)
diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm
index 0a54bcab33..bbad3e08b0 100644
--- a/code/modules/power/tesla/energy_ball.dm
+++ b/code/modules/power/tesla/energy_ball.dm
@@ -33,8 +33,8 @@
return
/obj/singularity/energy_ball/Destroy()
- if(orbiting && istype(orbiting.orbiting, /obj/singularity/energy_ball))
- var/obj/singularity/energy_ball/EB = orbiting.orbiting
+ if(orbiting && istype(orbiting.parent, /obj/singularity/energy_ball))
+ var/obj/singularity/energy_ball/EB = orbiting.parent
EB.orbiting_balls -= src
for(var/ball in orbiting_balls)
@@ -146,12 +146,12 @@
. = ..()
/obj/singularity/energy_ball/stop_orbit()
- if (orbiting && istype(orbiting.orbiting, /obj/singularity/energy_ball))
- var/obj/singularity/energy_ball/orbitingball = orbiting.orbiting
+ if (orbiting && istype(orbiting.parent, /obj/singularity/energy_ball))
+ var/obj/singularity/energy_ball/orbitingball = orbiting.parent
orbitingball.orbiting_balls -= src
orbitingball.dissipate_strength = orbitingball.orbiting_balls.len
- ..()
- if (!loc && !QDELETED(src))
+ . = ..()
+ if (!QDELETED(src))
qdel(src)
diff --git a/code/modules/projectiles/ammunition/special/syringe.dm b/code/modules/projectiles/ammunition/special/syringe.dm
index 4a2a354ca6..d5cba6936f 100644
--- a/code/modules/projectiles/ammunition/special/syringe.dm
+++ b/code/modules/projectiles/ammunition/special/syringe.dm
@@ -59,3 +59,20 @@
S.forceMove(D)
D.injector = S
..()
+
+/obj/item/ammo_casing/syringegun/dart
+ name = "used air canister"
+ desc = "A small canister of compressed gas."
+ projectile_type = /obj/item/projectile/bullet/dart/syringe/dart
+ firing_effect_type = null
+ harmful = FALSE
+
+/obj/item/ammo_casing/syringegun/dart/ready_proj(atom/target, mob/living/user, quiet, zone_override = "")
+ ..()
+ var/obj/item/gun/syringe/SG = loc
+ if(!SG.syringes.len)
+ return
+ var/obj/item/reagent_containers/syringe/dart/S = SG.syringes[1]
+ if(S.emptrig == TRUE)
+ var/obj/item/projectile/bullet/dart/syringe/dart/D = BB
+ D.emptrig = TRUE
diff --git a/code/modules/projectiles/guns/misc/medbeam.dm b/code/modules/projectiles/guns/misc/medbeam.dm
index 17c0f63955..7bdefe5e91 100644
--- a/code/modules/projectiles/guns/misc/medbeam.dm
+++ b/code/modules/projectiles/guns/misc/medbeam.dm
@@ -116,7 +116,7 @@
new /obj/effect/temp_visual/heal(get_turf(target), "#80F5FF")
target.adjustBruteLoss(-4)
target.adjustFireLoss(-4)
- target.adjustToxLoss(-1)
+ target.adjustToxLoss(-1, forced = TRUE)
target.adjustOxyLoss(-1)
return
diff --git a/code/modules/projectiles/guns/misc/syringe_gun.dm b/code/modules/projectiles/guns/misc/syringe_gun.dm
index cc1b321e3a..26e66b1987 100644
--- a/code/modules/projectiles/guns/misc/syringe_gun.dm
+++ b/code/modules/projectiles/guns/misc/syringe_gun.dm
@@ -102,3 +102,23 @@
else
to_chat(user, "[src] cannot hold more syringes!")
return FALSE
+
+/obj/item/gun/syringe/dart
+ name = "dart gun"
+ desc = "A compressed air gun, designed to fit medicinal darts for application of medicine for those patients just out of reach."
+ icon_state = "dartgun"
+ item_state = "dartgun"
+ materials = list(MAT_METAL=2000, MAT_GLASS=500)
+ suppressed = TRUE //Softer fire sound
+ can_unsuppress = FALSE
+
+/obj/item/gun/syringe/dart/Initialize()
+ ..()
+ chambered = new /obj/item/ammo_casing/syringegun/dart(src)
+
+/obj/item/gun/syringe/dart/attackby(obj/item/A, mob/user, params, show_msg = TRUE)
+ if(istype(A, /obj/item/reagent_containers/syringe/dart))
+ ..()
+ else
+ to_chat(user, "You can't put the [A] into \the [src]!")
+ return FALSE
diff --git a/code/modules/projectiles/projectile/bullets/dart_syringe.dm b/code/modules/projectiles/projectile/bullets/dart_syringe.dm
index 94d075c789..bdbf706448 100644
--- a/code/modules/projectiles/projectile/bullets/dart_syringe.dm
+++ b/code/modules/projectiles/projectile/bullets/dart_syringe.dm
@@ -8,12 +8,14 @@
. = ..()
create_reagents(50, NO_REACT)
-/obj/item/projectile/bullet/dart/on_hit(atom/target, blocked = FALSE)
+/obj/item/projectile/bullet/dart/on_hit(atom/target, blocked = FALSE, skip = FALSE)
if(iscarbon(target))
var/mob/living/carbon/M = target
if(blocked != 100) // not completely blocked
if(M.can_inject(null, FALSE, def_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body.
..()
+ if(skip == TRUE)
+ return
reagents.reaction(M, INJECT)
reagents.trans_to(M, reagents.total_volume)
return TRUE
@@ -36,3 +38,44 @@
/obj/item/projectile/bullet/dart/syringe
name = "syringe"
icon_state = "syringeproj"
+
+//I am in a mess of my own making
+/obj/item/projectile/bullet/dart/syringe/dart
+ name = "Smartdart"
+ icon_state = "dartproj"
+ damage = 0
+ var/emptrig = FALSE
+
+/obj/item/projectile/bullet/dart/syringe/dart/on_hit(atom/target, blocked = FALSE)
+ if(iscarbon(target))
+ var/mob/living/carbon/M = target
+ if(blocked != 100)
+ if(M.can_inject(null, FALSE, def_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body.
+ ..(target, blocked, TRUE)
+ for(var/datum/reagent/R in reagents.reagent_list) //OD prevention time!
+ if(istype(R, /datum/reagent/medicine)) //Is this a medicine?
+ if(M.reagents.has_reagent(R.id))
+ if(R.overdose_threshold == 0 || emptrig == TRUE) //Is there a possible OD?
+ M.reagents.add_reagent(R.id, R.volume)
+ else
+ var/transVol = CLAMP(R.volume, 0, (R.overdose_threshold - M.reagents.get_reagent_amount(R.id)) -1)
+ M.reagents.add_reagent(R.id, transVol)
+ else
+ if(!R.overdose_threshold == 0)
+ var/transVol = CLAMP(R.volume, 0, R.overdose_threshold-1)
+ M.reagents.add_reagent(R.id, transVol)
+ else
+ M.reagents.add_reagent(R.id, R.volume)
+
+
+
+ target.visible_message("\The [src] beeps!")
+ to_chat("You feel a tiny prick as a smartdart embeds itself in you with a beep.")
+ return TRUE
+ else
+ blocked = 100
+ target.visible_message("\The [src] was deflected!", \
+ "You see a [src] bounce off you, booping sadly!")
+
+ target.visible_message("\The [src] fails to land on target!")
+ return TRUE
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index 58c29f351b..dc86ab4e6c 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -21,7 +21,9 @@
if(GLOB.chemical_reactions_list)
return
- var/paths = subtypesof(/datum/chemical_reaction)
+
+ //Randomized need to go last since they need to check against conflicts with normal recipes
+ var/paths = subtypesof(/datum/chemical_reaction) - typesof(/datum/chemical_reaction/randomized) + subtypesof(/datum/chemical_reaction/randomized)
GLOB.chemical_reactions_list = list()
for(var/path in paths)
@@ -29,6 +31,9 @@
var/datum/chemical_reaction/D = new path()
var/list/reaction_ids = list()
+ if(!D.id)
+ continue
+
if(D.required_reagents && D.required_reagents.len)
for(var/reaction in D.required_reagents)
reaction_ids += reaction
@@ -267,6 +272,9 @@
continue
if(!C)
C = R.holder.my_atom
+ if(!R.metabolizing)
+ R.metabolizing = TRUE
+ R.on_mob_metabolize(C)
if(C && R)
if(C.reagent_check(R) != 1)
if(can_overdose)
@@ -313,6 +321,21 @@
C.update_stamina()
update_total()
+//Signals that metabolization has stopped, triggering the end of trait-based effects
+/datum/reagents/proc/end_metabolization(mob/living/carbon/C, keep_liverless = TRUE)
+ var/list/cached_reagents = reagent_list
+ for(var/reagent in cached_reagents)
+ var/datum/reagent/R = reagent
+ if(QDELETED(R.holder))
+ continue
+ if(keep_liverless && R.self_consuming) //Will keep working without a liver
+ continue
+ if(!C)
+ C = R.holder.my_atom
+ if(R.metabolizing)
+ R.metabolizing = FALSE
+ R.on_mob_end_metabolize(C)
+
/datum/reagents/proc/conditional_update_move(atom/A, Running = 0)
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
@@ -466,6 +489,9 @@
if(R.id == reagent)
if(my_atom && isliving(my_atom))
var/mob/living/M = my_atom
+ if(R.metabolizing)
+ R.metabolizing = FALSE
+ R.on_mob_end_metabolize(M)
R.on_mob_delete(M)
qdel(R)
reagent_list -= R
diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm
index a52bb1ecfe..9bfbffd330 100644
--- a/code/modules/reagents/chemistry/reagents.dm
+++ b/code/modules/reagents/chemistry/reagents.dm
@@ -33,6 +33,10 @@
var/addiction_stage4_end = 40
var/overdosed = 0 // You fucked up and this is now triggering its overdose effects, purge that shit quick.
var/self_consuming = FALSE
+ var/metabolizing = FALSE
+
+
+
/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references
. = ..()
@@ -68,6 +72,14 @@
/datum/reagent/proc/on_mob_delete(mob/living/L)
return
+// Called when this reagent first starts being metabolized by a liver
+/datum/reagent/proc/on_mob_metabolize(mob/living/L)
+ return
+
+// Called when this reagent stops being metabolized by a liver
+/datum/reagent/proc/on_mob_end_metabolize(mob/living/L)
+ return
+
/datum/reagent/proc/on_move(mob/M)
return
diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
index 14963a6689..80e195d5ac 100644
--- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
@@ -111,7 +111,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
M.add_atom_colour(color, TEMPORARY_COLOUR_PRIORITY)
return ..()
-/datum/reagent/consumable/ethanol/beer/green/on_mob_delete(mob/living/M)
+/datum/reagent/consumable/ethanol/beer/green/on_mob_end_metabolize(mob/living/M)
M.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, color)
/datum/reagent/consumable/ethanol/kahlua
@@ -569,13 +569,13 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "Tequila and Coffee liqueur, brought together in a mouthwatering mixture. Drink up."
var/tough_text
-/datum/reagent/consumable/ethanol/brave_bull/on_mob_add(mob/living/M)
+/datum/reagent/consumable/ethanol/brave_bull/on_mob_metabolize(mob/living/M)
tough_text = pick("brawny", "tenacious", "tough", "hardy", "sturdy") //Tuff stuff
to_chat(M, "You feel [tough_text]!")
M.maxHealth += 10 //Brave Bull makes you sturdier, and thus capable of withstanding a tiny bit more punishment.
M.health += 10
-/datum/reagent/consumable/ethanol/brave_bull/on_mob_delete(mob/living/M)
+/datum/reagent/consumable/ethanol/brave_bull/on_mob_end_metabolize(mob/living/M)
to_chat(M, "You no longer feel [tough_text].")
M.maxHealth -= 10
M.health = min(M.health - 10, M.maxHealth) //This can indeed crit you if you're alive solely based on alchol ingestion
@@ -593,7 +593,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "Oh great, now you feel nostalgic about sunrises back on Terra..."
var/obj/effect/light_holder
-/datum/reagent/consumable/ethanol/tequila_sunrise/on_mob_add(mob/living/M)
+/datum/reagent/consumable/ethanol/tequila_sunrise/on_mob_metabolize(mob/living/M)
to_chat(M, "You feel gentle warmth spread through your body!")
light_holder = new(M)
light_holder.set_light(3, 0.7, "#FFCC00") //Tequila Sunrise makes you radiate dim light, like a sunrise!
@@ -605,7 +605,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
light_holder.forceMove(M)
return ..()
-/datum/reagent/consumable/ethanol/tequila_sunrise/on_mob_delete(mob/living/M)
+/datum/reagent/consumable/ethanol/tequila_sunrise/on_mob_end_metabolize(mob/living/M)
to_chat(M, "The warmth in your body fades.")
QDEL_NULL(light_holder)
@@ -671,7 +671,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "A manly concoction made from Ale and Beer. Intended for true men only."
var/dorf_mode
-/datum/reagent/consumable/ethanol/manly_dorf/on_mob_add(mob/living/M)
+/datum/reagent/consumable/ethanol/manly_dorf/on_mob_metabolize(mob/living/M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.dna.check_mutation(DWARFISM) || HAS_TRAIT(H, TRAIT_ALCOHOL_TOLERANCE))
@@ -722,7 +722,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "Kahlua, Irish Cream, and cognac. You will get bombed."
shot_glass_icon_state = "b52glass"
-/datum/reagent/consumable/ethanol/b52/on_mob_add(mob/living/M)
+/datum/reagent/consumable/ethanol/b52/on_mob_metabolize(mob/living/M)
playsound(M, 'sound/effects/explosion_distant.ogg', 100, FALSE)
/datum/reagent/consumable/ethanol/irishcoffee
@@ -1534,7 +1534,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "If you're feeling low, count on the buttery flavor of our own bastion bourbon."
shot_glass_icon_state = "shotglassgreen"
-/datum/reagent/consumable/ethanol/bastion_bourbon/on_mob_add(mob/living/L)
+/datum/reagent/consumable/ethanol/bastion_bourbon/on_mob_metabolize(mob/living/L)
var/heal_points = 10
if(L.health <= 0)
heal_points = 20 //heal more if we're in softcrit
@@ -1618,7 +1618,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "Crevice Spike"
glass_desc = "It'll either knock the drunkenness out of you or knock you out cold. Both, probably."
-/datum/reagent/consumable/ethanol/crevice_spike/on_mob_add(mob/living/L) //damage only applies when drink first enters system and won't again until drink metabolizes out
+/datum/reagent/consumable/ethanol/crevice_spike/on_mob_metabolize(mob/living/L) //damage only applies when drink first enters system and won't again until drink metabolizes out
L.adjustBruteLoss(3 * min(5,volume)) //minimum 3 brute damage on ingestion to limit non-drink means of injury - a full 5 unit gulp of the drink trucks you for the full 15
/datum/reagent/consumable/ethanol/sake
@@ -1661,7 +1661,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "A creamy, indulgent delight that is stronger than it seems."
var/obj/item/shield/mighty_shield
-/datum/reagent/consumable/ethanol/alexander/on_mob_add(mob/living/L)
+/datum/reagent/consumable/ethanol/alexander/on_mob_metabolize(mob/living/L)
if(ishuman(L))
var/mob/living/carbon/human/thehuman = L
for(var/obj/item/shield/theshield in thehuman.contents)
@@ -1675,7 +1675,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
if(mighty_shield && !(mighty_shield in L.contents)) //If you had a shield and lose it, you lose the reagent as well. Otherwise this is just a normal drink.
L.reagents.del_reagent("alexander")
-/datum/reagent/consumable/ethanol/alexander/on_mob_delete(mob/living/L)
+/datum/reagent/consumable/ethanol/alexander/on_mob_end_metabolize(mob/living/L)
if(mighty_shield)
mighty_shield.block_chance -= 10
to_chat(L,"You notice [mighty_shield] looks worn again. Weird.")
@@ -1796,7 +1796,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
M.overeatduration = 0
return ..()
-/datum/reagent/consumable/ethanol/fanciulli/on_mob_add(mob/living/M)
+/datum/reagent/consumable/ethanol/fanciulli/on_mob_metabolize(mob/living/M)
if(M.health > 0)
M.adjustStaminaLoss(20)
. = TRUE
@@ -1820,7 +1820,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
M.adjust_bodytemperature(-20 * TEMPERATURE_DAMAGE_COEFFICIENT, T0C)
return ..()
-/datum/reagent/consumable/ethanol/branca_menta/on_mob_add(mob/living/M)
+/datum/reagent/consumable/ethanol/branca_menta/on_mob_metabolize(mob/living/M)
if(M.health > 0)
M.adjustStaminaLoss(35)
. = TRUE
diff --git a/code/modules/reagents/chemistry/reagents/blob_reagents.dm b/code/modules/reagents/chemistry/reagents/blob_reagents.dm
index 8ee9449468..af85b6b35f 100644
--- a/code/modules/reagents/chemistry/reagents/blob_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/blob_reagents.dm
@@ -204,7 +204,7 @@
C.hal_screwyhud = SCREWYHUD_HEALTHY //fully healed, honest
..()
-/datum/reagent/blob/regenerative_materia/on_mob_delete(mob/living/M)
+/datum/reagent/blob/regenerative_materia/on_mob_end_metabolize(mob/living/M)
if(iscarbon(M))
var/mob/living/carbon/N = M
N.hal_screwyhud = 0
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index ac15eb6b01..6d0d1e13c6 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -390,11 +390,11 @@
glass_name = "glass of Nuka Cola"
glass_desc = "Don't cry, Don't raise your eye, It's only nuclear wasteland."
-/datum/reagent/consumable/nuka_cola/on_mob_add(mob/living/L)
+/datum/reagent/consumable/nuka_cola/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
-/datum/reagent/consumable/nuka_cola/on_mob_delete(mob/living/L)
+/datum/reagent/consumable/nuka_cola/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
..()
diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
index 04dad3a065..a4586dd997 100644
--- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
@@ -5,7 +5,7 @@
taste_description = "bitterness"
var/trippy = TRUE //Does this drug make you trip?
-/datum/reagent/drug/on_mob_delete(mob/living/M)
+/datum/reagent/drug/on_mob_end_metabolize(mob/living/M)
if(trippy)
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "[id]_high")
@@ -168,11 +168,11 @@
var/jitter = TRUE
var/confusion = TRUE
-/datum/reagent/drug/methamphetamine/on_mob_add(mob/living/L)
+/datum/reagent/drug/methamphetamine/on_mob_metabolize(mob/living/L)
..()
L.ignore_slowdown(id)
-/datum/reagent/drug/methamphetamine/on_mob_delete(mob/living/L)
+/datum/reagent/drug/methamphetamine/on_mob_end_metabolize(mob/living/L)
L.unignore_slowdown(id)
..()
@@ -262,7 +262,7 @@
taste_description = "salt" // because they're bathsalts?
var/datum/brain_trauma/special/psychotic_brawling/bath_salts/rage
-/datum/reagent/drug/bath_salts/on_mob_add(mob/living/L)
+/datum/reagent/drug/bath_salts/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_STUNIMMUNE, id)
ADD_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
@@ -271,7 +271,7 @@
rage = new()
C.gain_trauma(rage, TRAUMA_RESILIENCE_ABSOLUTE)
-/datum/reagent/drug/bath_salts/on_mob_delete(mob/living/L)
+/datum/reagent/drug/bath_salts/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_STUNIMMUNE, id)
REMOVE_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
if(rage)
@@ -381,7 +381,7 @@
addiction_stage3_end = 40
addiction_stage4_end = 240
-/datum/reagent/drug/skooma/on_mob_add(mob/living/L)
+/datum/reagent/drug/skooma/on_mob_metabolize(mob/living/L)
. = ..()
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
L.next_move_modifier *= 2
@@ -392,7 +392,7 @@
if(H.dna && H.dna.species)
H.dna.species.punchdamagehigh *= 5
-/datum/reagent/drug/skooma/on_mob_delete(mob/living/L)
+/datum/reagent/drug/skooma/on_mob_end_metabolize(mob/living/L)
. = ..()
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
L.next_move_modifier *= 0.5
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index afa469706a..38db62fd2a 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -32,6 +32,8 @@
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_verygood)
if (DRINK_FANTASTIC)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_fantastic)
+ if (FOOD_AMAZING)
+ SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_food", /datum/mood_event/amazingtaste)
return ..()
/datum/reagent/consumable/nutriment
@@ -401,7 +403,7 @@
metabolization_rate = 0.2 * REAGENTS_METABOLISM
taste_description = "mushroom"
-/datum/reagent/mushroomhallucinogen/on_mob_life(mob/living/carbon/M)
+/datum/reagent/drug/mushroomhallucinogen/on_mob_life(mob/living/carbon/M)
M.slurring = max(M.slurring,50)
switch(current_cycle)
if(1 to 5)
@@ -686,7 +688,7 @@
/datum/reagent/consumable/tinlux/reaction_mob(mob/living/M)
M.set_light(2)
-/datum/reagent/consumable/tinlux/on_mob_delete(mob/living/M)
+/datum/reagent/consumable/tinlux/on_mob_end_metabolize(mob/living/M)
M.set_light(-2)
/datum/reagent/consumable/vitfro
@@ -711,3 +713,14 @@
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#eef442" // rgb: 238, 244, 66
taste_description = "mournful honking"
+
+/datum/reagent/consumable/secretsauce
+ name = "secret sauce"
+ id = "secret_sauce"
+ description = "What could it be."
+ nutriment_factor = 2 * REAGENTS_METABOLISM
+ color = "#792300"
+ taste_description = "indescribable"
+ quality = FOOD_AMAZING
+ taste_mult = 100
+ can_synth = FALSE
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 07a2a9c02a..ed441504a5 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -366,7 +366,7 @@
to_chat(M, "You feel your wounds fade away to nothing!" )
..()
-/datum/reagent/medicine/mine_salve/on_mob_delete(mob/living/M)
+/datum/reagent/medicine/mine_salve/on_mob_end_metabolize(mob/living/M)
if(iscarbon(M))
var/mob/living/carbon/N = M
N.hal_screwyhud = SCREWYHUD_NONE
@@ -483,16 +483,24 @@
reagent_state = LIQUID
color = "#E6FFF0"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
+ var/healtoxinlover = FALSE
/datum/reagent/medicine/pen_acid/on_mob_life(mob/living/carbon/M)
M.radiation -= max(M.radiation-RAD_MOB_SAFE, 0)/50
- M.adjustToxLoss(-2*REM, 0)
+ M.adjustToxLoss(-2*REM, 0, healtoxinlover)
for(var/datum/reagent/R in M.reagents.reagent_list)
if(R != src)
M.reagents.remove_reagent(R.id,2)
..()
. = 1
+/datum/reagent/medicine/pen_acid/pen_jelly
+ name = "Pentetic Jelly"
+ id = "pen_jelly"
+ description = "Reduces massive amounts of radiation and toxin damage while purging other chemicals from the body. Slimepeople friendly!"
+ color = "#91D865"
+ healtoxinlover = TRUE
+
/datum/reagent/medicine/sal_acid
name = "Salicyclic Acid"
id = "sal_acid"
@@ -630,11 +638,11 @@
overdose_threshold = 30
addiction_threshold = 25
-/datum/reagent/medicine/morphine/on_mob_add(mob/living/L)
+/datum/reagent/medicine/morphine/on_mob_metabolize(mob/living/L)
..()
L.ignore_slowdown(id)
-/datum/reagent/medicine/morphine/on_mob_delete(mob/living/L)
+/datum/reagent/medicine/morphine/on_mob_end_metabolize(mob/living/L)
L.unignore_slowdown(id)
..()
@@ -875,11 +883,11 @@
metabolization_rate = 0.5 * REAGENTS_METABOLISM
overdose_threshold = 60
-/datum/reagent/medicine/stimulants/on_mob_add(mob/living/L)
+/datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
-/datum/reagent/medicine/stimulants/on_mob_delete(mob/living/L)
+/datum/reagent/medicine/stimulants/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
..()
@@ -1102,7 +1110,7 @@
M.adjustBruteLoss(-3 * REM, 0)
M.adjustFireLoss(-3 * REM, 0)
M.adjustOxyLoss(-15 * REM, 0)
- M.adjustToxLoss(-3 * REM, 0)
+ M.adjustToxLoss(-3 * REM, 0, TRUE) //Heals TOXINLOVERS
M.adjustBrainLoss(2 * REM, 150) //This does, after all, come from ambrosia, and the most powerful ambrosia in existence, at that!
M.adjustCloneLoss(-1 * REM, 0)
M.adjustStaminaLoss(-30 * REM, 0)
@@ -1113,7 +1121,7 @@
/datum/reagent/medicine/earthsblood/overdose_process(mob/living/M)
M.hallucination = min(max(0, M.hallucination + 5), 60)
- M.adjustToxLoss(5 * REM, 0)
+ M.adjustToxLoss(8 * REM, 0, TRUE) //Hurts TOXINLOVERS
..()
. = 1
@@ -1188,11 +1196,11 @@
color = "#C8A5DC"
metabolization_rate = 1
-/datum/reagent/medicine/changelinghaste/on_mob_add(mob/living/L)
+/datum/reagent/medicine/changelinghaste/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_GOTTAGOREALLYFAST, id)
-/datum/reagent/medicine/changelinghaste/on_mob_delete(mob/living/L)
+/datum/reagent/medicine/changelinghaste/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_GOTTAGOREALLYFAST, id)
..()
@@ -1210,11 +1218,11 @@
color = "#F5F5F5"
self_consuming = TRUE
-/datum/reagent/medicine/corazone/on_mob_add(mob/living/M)
+/datum/reagent/medicine/corazone/on_mob_metabolize(mob/living/M)
..()
ADD_TRAIT(M, TRAIT_STABLEHEART, id)
-/datum/reagent/medicine/corazone/on_mob_delete(mob/living/M)
+/datum/reagent/medicine/corazone/on_mob_end_metabolize(mob/living/M)
REMOVE_TRAIT(M, TRAIT_STABLEHEART, id)
..()
@@ -1223,11 +1231,11 @@
id = "muscle_stimulant"
description = "A potent chemical that allows someone under its influence to be at full physical ability even when under massive amounts of pain."
-/datum/reagent/medicine/muscle_stimulant/on_mob_add(mob/living/M)
+/datum/reagent/medicine/muscle_stimulant/on_mob_metabolize(mob/living/M)
. = ..()
M.ignore_slowdown(id)
-/datum/reagent/medicine/muscle_stimulant/on_mob_delete(mob/living/M)
+/datum/reagent/medicine/muscle_stimulant/on_mob_end_metabolize(mob/living/M)
. = ..()
M.unignore_slowdown(id)
@@ -1242,11 +1250,11 @@
taste_description = "salt" // it actually does taste salty
var/overdose_progress = 0 // to track overdose progress
-/datum/reagent/medicine/modafinil/on_mob_add(mob/living/M)
+/datum/reagent/medicine/modafinil/on_mob_metabolize(mob/living/M)
ADD_TRAIT(M, TRAIT_SLEEPIMMUNE, id)
..()
-/datum/reagent/medicine/modafinil/on_mob_delete(mob/living/M)
+/datum/reagent/medicine/modafinil/on_mob_end_metabolize(mob/living/M)
REMOVE_TRAIT(M, TRAIT_SLEEPIMMUNE, id)
..()
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 40242909de..890403691e 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -196,11 +196,11 @@
glass_name = "glass of holy water"
glass_desc = "A glass of holy water."
-/datum/reagent/water/holywater/on_mob_add(mob/living/L)
+/datum/reagent/water/holywater/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_HOLY, id)
-/datum/reagent/water/holywater/on_mob_delete(mob/living/L)
+/datum/reagent/water/holywater/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_HOLY, id)
..()
@@ -1241,12 +1241,12 @@
color = "E1A116"
taste_description = "sourness"
-/datum/reagent/stimulum/on_mob_add(mob/living/L)
+/datum/reagent/stimulum/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_STUNIMMUNE, id)
ADD_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
-/datum/reagent/stimulum/on_mob_delete(mob/living/L)
+/datum/reagent/stimulum/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_STUNIMMUNE, id)
REMOVE_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
..()
@@ -1266,11 +1266,11 @@
color = "90560B"
taste_description = "burning"
-/datum/reagent/nitryl/on_mob_add(mob/living/L)
+/datum/reagent/nitryl/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
-/datum/reagent/nitryl/on_mob_delete(mob/living/L)
+/datum/reagent/nitryl/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
..()
@@ -1723,7 +1723,7 @@
H.update_transform()
..()
-/datum/reagent/growthserum/on_mob_delete(mob/living/M)
+/datum/reagent/growthserum/on_mob_end_metabolize(mob/living/M)
M.resize = 1/current_size
M.update_transform()
..()
@@ -1777,11 +1777,11 @@
taste_description = "water"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
-/datum/reagent/pax/on_mob_add(mob/living/L)
+/datum/reagent/pax/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_PACIFISM, id)
-/datum/reagent/pax/on_mob_delete(mob/living/L)
+/datum/reagent/pax/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_PACIFISM, id)
..()
@@ -1793,11 +1793,11 @@
taste_description = "acrid cinnamon"
metabolization_rate = 0.2 * REAGENTS_METABOLISM
-/datum/reagent/bz_metabolites/on_mob_add(mob/living/L)
+/datum/reagent/bz_metabolites/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, CHANGELING_HIVEMIND_MUTE, id)
-/datum/reagent/bz_metabolites/on_mob_delete(mob/living/L)
+/datum/reagent/bz_metabolites/on_mob_end_metabolize(mob/living/L)
..()
REMOVE_TRAIT(L, CHANGELING_HIVEMIND_MUTE, id)
@@ -1814,14 +1814,14 @@
description = "A colorless liquid that suppresses violence on the subjects. Cheaper to synthetize, but wears out faster than normal Pax."
metabolization_rate = 1.5 * REAGENTS_METABOLISM
-/datum/reagent/peaceborg/confuse
+/datum/reagent/peaceborg_confuse
name = "Dizzying Solution"
id = "dizzysolution"
description = "Makes the target off balance and dizzy"
metabolization_rate = 1.5 * REAGENTS_METABOLISM
taste_description = "dizziness"
-/datum/reagent/peaceborg/confuse/on_mob_life(mob/living/carbon/M)
+/datum/reagent/peaceborg_confuse/on_mob_life(mob/living/carbon/M)
if(M.confused < 6)
M.confused = CLAMP(M.confused + 3, 0, 5)
if(M.dizziness < 6)
@@ -1830,14 +1830,14 @@
to_chat(M, "You feel confused and disorientated.")
..()
-/datum/reagent/peaceborg/tire
+/datum/reagent/peaceborg_tire
name = "Tiring Solution"
id = "tiresolution"
description = "An extremely weak stamina-toxin that tires out the target. Completely harmless."
metabolization_rate = 1.5 * REAGENTS_METABOLISM
taste_description = "tiredness"
-/datum/reagent/peaceborg/tire/on_mob_life(mob/living/carbon/M)
+/datum/reagent/peaceborg_tire/on_mob_life(mob/living/carbon/M)
var/healthcomp = (100 - M.health) //DOES NOT ACCOUNT FOR ADMINBUS THINGS THAT MAKE YOU HAVE MORE THAN 200/210 HEALTH, OR SOMETHING OTHER THAN A HUMAN PROCESSING THIS.
if(M.getStaminaLoss() < (45 - healthcomp)) //At 50 health you would have 200 - 150 health meaning 50 compensation. 60 - 50 = 10, so would only do 10-19 stamina.)
M.adjustStaminaLoss(10)
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 8be95efb83..d9a4e3a843 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -156,11 +156,11 @@
toxpwr = 0.5
taste_description = "death"
-/datum/reagent/toxin/zombiepowder/on_mob_add(mob/living/L)
+/datum/reagent/toxin/zombiepowder/on_mob_metabolize(mob/living/L)
..()
L.fakedeath(id)
-/datum/reagent/toxin/zombiepowder/on_mob_delete(mob/living/L)
+/datum/reagent/toxin/zombiepowder/on_mob_end_metabolize(mob/living/L)
L.cure_fakedeath(id)
..()
@@ -178,11 +178,11 @@
toxpwr = 0.8
taste_description = "death"
-/datum/reagent/toxin/ghoulpowder/on_mob_add(mob/living/L)
+/datum/reagent/toxin/ghoulpowder/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_FAKEDEATH, id)
-/datum/reagent/toxin/ghoulpowder/on_mob_delete(mob/living/L)
+/datum/reagent/toxin/ghoulpowder/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_FAKEDEATH, id)
..()
@@ -626,7 +626,7 @@
toxpwr = 0
metabolization_rate = 0.5 * REAGENTS_METABOLISM
-/datum/reagent/toxin/amanitin/on_mob_delete(mob/living/M)
+/datum/reagent/toxin/amanitin/on_mob_end_metabolize(mob/living/M)
var/toxdamage = current_cycle*3*REM
M.log_message("has taken [toxdamage] toxin damage from amanitin toxin", LOG_ATTACK)
M.adjustToxLoss(toxdamage)
@@ -742,7 +742,7 @@
animate(transform = matrix(-rotation, MATRIX_ROTATE), time = 5, easing = QUAD_EASING)
return ..()
-/datum/reagent/toxin/rotatium/on_mob_delete(mob/living/M)
+/datum/reagent/toxin/rotatium/on_mob_end_metabolize(mob/living/M)
if(M && M.hud_used)
var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
for(var/whole_screen in screens)
@@ -779,7 +779,7 @@
*/
return ..()
-/datum/reagent/toxin/skewium/on_mob_delete(mob/living/M)
+/datum/reagent/toxin/skewium/on_mob_end_metabolize(mob/living/M)
if(M && M.hud_used)
var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
for(var/whole_screen in screens)
@@ -798,7 +798,7 @@
/datum/reagent/toxin/anacea/on_mob_life(mob/living/carbon/M)
var/remove_amt = 5
- if(holder.has_reagent("calomel") || holder.has_reagent("pen_acid"))
+ if(holder.has_reagent("calomel") || holder.has_reagent("pen_acid") || holder.has_reagent("pen_jelly"))
remove_amt = 0.5
for(var/datum/reagent/medicine/R in M.reagents.reagent_list)
M.reagents.remove_reagent(R.id,remove_amt)
@@ -882,8 +882,8 @@
toxpwr = 0
taste_description = "stillness"
-/datum/reagent/toxin/mimesbane/on_mob_add(mob/living/L)
+/datum/reagent/toxin/mimesbane/on_mob_metabolize(mob/living/L)
ADD_TRAIT(L, TRAIT_EMOTEMUTE, id)
-/datum/reagent/toxin/mimesbane/on_mob_delete(mob/living/L)
+/datum/reagent/toxin/mimesbane/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_EMOTEMUTE, id)
diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm
index dc7c32d925..727048a12c 100644
--- a/code/modules/reagents/chemistry/recipes/medicine.dm
+++ b/code/modules/reagents/chemistry/recipes/medicine.dm
@@ -94,6 +94,12 @@
results = list("pen_acid" = 6)
required_reagents = list("welding_fuel" = 1, "chlorine" = 1, "ammonia" = 1, "formaldehyde" = 1, "sodium" = 1, "cyanide" = 1)
+/datum/chemical_reaction/pen_jelly
+ name = "Pentetic Jelly"
+ id = "pen_jelly"
+ results = list("pen_jelly" = 2)
+ required_reagents = list("pen_acid" = 1, "slimejelly" = 1)
+
/datum/chemical_reaction/sal_acid
name = "Salicyclic Acid"
id = "sal_acid"
diff --git a/code/modules/reagents/chemistry/recipes/special.dm b/code/modules/reagents/chemistry/recipes/special.dm
new file mode 100644
index 0000000000..153372101e
--- /dev/null
+++ b/code/modules/reagents/chemistry/recipes/special.dm
@@ -0,0 +1,212 @@
+GLOBAL_LIST_INIT(food_reagents, build_reagents_to_food()) //reagentid = related food types
+
+/proc/build_reagents_to_food()
+ . = list()
+ for (var/type in subtypesof(/obj/item/reagent_containers/food))
+ var/obj/item/reagent_containers/food/item = new type()
+ for(var/r in item.list_reagents)
+ if (!.[r])
+ .[r] = list()
+ .[r] += type
+ qdel(item)
+ //dang plant snowflake
+ for (var/type in subtypesof(/obj/item/seeds))
+ var/obj/item/seeds/item = new type()
+ for(var/r in item.reagents_add)
+ if (!.[r])
+ .[r] = list()
+ .[r] += type
+ qdel(item)
+
+
+#define RNGCHEM_INPUT "input"
+#define RNGCHEM_CATALYSTS "catalysts"
+#define RNGCHEM_OUTPUT "output"
+
+/datum/chemical_reaction/randomized
+ name = "semi randomized reaction"
+
+ var/persistent = FALSE
+ var/persistence_period = 7 //Will reset every x days
+ var/created //creation timestamp
+
+ var/randomize_container = FALSE
+ var/list/possible_containers = list()
+
+ var/randomize_req_temperature = TRUE
+ var/min_temp = 1
+ var/max_temp = 600
+
+ var/randomize_inputs = TRUE
+ var/min_input_reagent_amount = 1
+ var/max_input_reagent_amount = 10
+ var/min_input_reagents = 2
+ var/max_input_reagents = 5
+ var/list/possible_reagents = list()
+ var/min_catalysts = 0
+ var/max_catalysts = 2
+ var/list/possible_catalysts = list()
+
+ var/randomize_results = FALSE
+ var/min_output_reagent_amount = 1
+ var/max_output_reagent_amount = 5
+ var/min_result_reagents = 1
+ var/max_result_reagents = 1
+ var/list/possible_results = list()
+
+/datum/chemical_reaction/randomized/proc/GenerateRecipe()
+ created = world.time
+ if(randomize_container)
+ required_container = pick(possible_containers)
+ if(randomize_req_temperature)
+ required_temp = rand(min_temp,max_temp)
+ is_cold_recipe = pick(TRUE,FALSE)
+
+ if(randomize_results)
+ results = list()
+ var/list/remaining_possible_results = GetPossibleReagents(RNGCHEM_OUTPUT)
+ var/out_reagent_count = min(rand(min_result_reagents,max_result_reagents),remaining_possible_results.len)
+ for(var/i in 1 to out_reagent_count)
+ var/r_id = pick_n_take(remaining_possible_results)
+ results[r_id] = rand(min_output_reagent_amount,max_output_reagent_amount)
+
+ if(randomize_inputs)
+ var/list/remaining_possible_reagents = GetPossibleReagents(RNGCHEM_INPUT)
+ var/list/remaining_possible_catalysts = GetPossibleReagents(RNGCHEM_CATALYSTS)
+
+ //We're going to assume we're not doing any weird partial reactions for now.
+ for(var/reagent_type in results)
+ remaining_possible_catalysts -= reagent_type
+ remaining_possible_reagents -= reagent_type
+
+ var/in_reagent_count = min(rand(min_input_reagents,max_input_reagents),remaining_possible_reagents.len)
+ if(in_reagent_count <= 0)
+ return FALSE
+
+ required_reagents = list()
+ for(var/i in 1 to in_reagent_count)
+ var/r_id = pick_n_take(remaining_possible_reagents)
+ required_reagents[r_id] = rand(min_input_reagent_amount,max_input_reagent_amount)
+ remaining_possible_catalysts -= r_id //Can't have same reagents both as catalyst and reagent. Or can we ?
+
+ required_catalysts = list()
+ var/in_catalyst_count = min(rand(min_catalysts,max_catalysts),remaining_possible_catalysts.len)
+ for(var/i in 1 to in_catalyst_count)
+ var/r_id = pick_n_take(remaining_possible_catalysts)
+ required_catalysts[r_id] = rand(min_input_reagent_amount,max_input_reagent_amount)
+
+ return TRUE
+
+/datum/chemical_reaction/randomized/proc/GetPossibleReagents(kind)
+ switch(kind)
+ if(RNGCHEM_INPUT)
+ return possible_reagents.Copy()
+ if(RNGCHEM_CATALYSTS)
+ return possible_catalysts.Copy()
+ if(RNGCHEM_OUTPUT)
+ return possible_results.Copy()
+
+/datum/chemical_reaction/randomized/proc/HasConflicts()
+ for(var/x in required_reagents)
+ for(var/datum/chemical_reaction/R in GLOB.chemical_reactions_list[x])
+ if(chem_recipes_do_conflict(R,src))
+ return TRUE
+ return FALSE
+
+/datum/chemical_reaction/randomized/proc/unwrap_reagent_list(list/textreagents)
+ . = list()
+ for(var/R in textreagents)
+ var/pathR = text2path(R)
+ if(!pathR)
+ return null
+ .[pathR] = textreagents[R]
+
+/datum/chemical_reaction/randomized/proc/LoadOldRecipe(recipe_data)
+ created = text2num(recipe_data["timestamp"])
+
+ var/req_reag = unwrap_reagent_list(recipe_data["required_reagents"])
+ if(!req_reag)
+ return FALSE
+ required_reagents = req_reag
+
+ var/req_catalysts = unwrap_reagent_list(recipe_data["required_catalysts"])
+ if(!req_catalysts)
+ return FALSE
+ required_catalysts = req_catalysts
+
+ required_temp = recipe_data["required_temp"]
+ is_cold_recipe = recipe_data["is_cold_recipe"]
+
+ var/temp_results = unwrap_reagent_list(recipe_data["results"])
+ if(!temp_results)
+ return FALSE
+ results = temp_results
+ var/containerpath = text2path(recipe_data["required_container"])
+ if(!containerpath)
+ return FALSE
+ required_container = containerpath
+ return TRUE
+
+/datum/chemical_reaction/randomized/secret_sauce
+ name = "secret sauce creation"
+ id = "secretsauce"
+ persistent = TRUE
+ persistence_period = 7 //Reset every week
+ randomize_container = TRUE
+ possible_containers = list(/obj/item/reagent_containers/glass/bucket) //easy way to ensure no common conflicts
+ randomize_req_temperature = TRUE
+ results = list("secret_sauce" =1)
+
+/datum/chemical_reaction/randomized/secret_sauce/GetPossibleReagents(kind)
+ switch(kind)
+ if(RNGCHEM_INPUT,RNGCHEM_CATALYSTS)
+ var/food_reagent_ids = list()
+ for(var/key in GLOB.food_reagents)
+ food_reagent_ids += key
+ return food_reagent_ids
+ return ..()
+
+
+/obj/item/paper/secretrecipe
+ name = "old recipe"
+ var/recipe_id = "secretsauce"
+
+/obj/item/paper/secretrecipe/examine(mob/user) //Extra secret
+ if(isobserver(user))
+ return
+ . = ..()
+
+/obj/item/paper/secretrecipe/Initialize()
+ . = ..()
+ if(SSpersistence.initialized)
+ UpdateInfo()
+ else
+ SSticker.OnRoundstart(CALLBACK(src,.proc/UpdateInfo))
+
+/obj/item/paper/secretrecipe/proc/UpdateInfo()
+ var/datum/chemical_reaction/recipe = get_chemical_reaction(recipe_id)
+ if(!recipe)
+ info = "This recipe is illegible."
+ var/list/dat = list("")
+ for(var/rid in recipe.required_reagents)
+ var/datum/reagent/R = GLOB.chemical_reagents_list[rid]
+ dat += "- [recipe.required_reagents[rid]]u of [R.name]
"
+ dat += "
"
+ if(recipe.required_catalysts.len)
+ dat += "With following present: "
+ for(var/rid in recipe.required_catalysts)
+ var/datum/reagent/R = GLOB.chemical_reagents_list[rid]
+ dat += "- [recipe.required_catalysts[rid]]u of [R.name]
"
+ dat += "
"
+ dat += "Mix slowly"
+ if(recipe.required_container)
+ var/obj/item/I = recipe.required_container
+ dat += " in [initial(I.name)]"
+ if(recipe.required_temp != 0)
+ if(recipe.is_cold_recipe)
+ dat += " below [recipe.required_temp] degrees"
+ else
+ dat += " above [recipe.required_temp] degrees"
+ dat += "."
+ info = dat.Join("")
+ update_icon()
\ No newline at end of file
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 4947ddde6f..cc83eb28f6 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -259,3 +259,92 @@
/obj/item/reagent_containers/syringe/get_belt_overlay()
return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "pouch")
+
+/obj/item/reagent_containers/syringe/dart
+ name = "medicinal smartdart"
+ desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented."
+ volume = 20
+ amount_per_transfer_from_this = 20
+ icon_state = "empty"
+ item_state = "syringe_empty"
+ var/emptrig = FALSE
+
+/obj/item/reagent_containers/syringe/dart/afterattack(atom/target, mob/user , proximity)
+
+ if(busy)
+ return
+ if(!proximity)
+ return
+ if(!target.reagents)
+ return
+
+ var/mob/living/L
+ if(isliving(target))
+ L = target
+ if(!L.can_inject(user, 1))
+ return
+
+ switch(mode)
+ if(SYRINGE_DRAW)
+
+ if(reagents.total_volume >= reagents.maximum_volume)
+ to_chat(user, "The dart is full!")
+ return
+
+ if(L) //living mob
+ to_chat(user, "You can't draw blood using a dart!")
+ return
+
+ else //if not mob
+ if(!target.reagents.total_volume)
+ to_chat(user, "[target] is empty!")
+ return
+
+ if(!target.is_drawable())
+ to_chat(user, "You cannot directly remove reagents from [target]!")
+ return
+
+ var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
+
+ to_chat(user, "You soak the [src] with [trans] units of the solution. It now contains [reagents.total_volume] units.")
+ if (reagents.total_volume >= reagents.maximum_volume)
+ mode=!mode
+ update_icon()
+
+ if(SYRINGE_INJECT)
+ src.visible_message("The smartdart gives a frustrated boop! It's fully saturated; You need to shoot someone with it!")
+
+/obj/item/reagent_containers/syringe/dart/attack_self(mob/user)
+ return
+
+/obj/item/reagent_containers/syringe/dart/update_icon()
+ cut_overlays()
+ var/rounded_vol
+
+ rounded_vol = "empty"
+ if(reagents && reagents.total_volume)
+ if(volume/reagents.total_volume == 1)
+ rounded_vol="full"
+
+ icon_state = "[rounded_vol]"
+ item_state = "syringe_[rounded_vol]"
+ if(ismob(loc))
+ var/mob/M = loc
+ var/injoverlay
+ switch(mode)
+ if (SYRINGE_DRAW)
+ injoverlay = "draw"
+ if (SYRINGE_INJECT)
+ injoverlay = "ready"
+ add_overlay(injoverlay)
+ M.update_inv_hands()
+
+/obj/item/reagent_containers/syringe/dart/emp_act(severity)
+ emptrig = TRUE
+ ..()
+
+/obj/item/reagent_containers/syringe/dart/bluespace
+ name = "bluespace smartdart"
+ desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented. Has an extended volume capacity thanks to bluespace foam."
+ amount_per_transfer_from_this = 50
+ volume = 50
diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm
index 8a8377601a..3a7ef68903 100644
--- a/code/modules/research/designs/medical_designs.dm
+++ b/code/modules/research/designs/medical_designs.dm
@@ -92,6 +92,36 @@
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+/datum/design/medicinalsmartdart
+ name = "Medicinal Smartdart"
+ desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented."
+ id = "medicinalsmartdart"
+ build_type = PROTOLATHE
+ materials = list(MAT_GLASS = 100, MAT_PLASTIC = 100, MAT_METAL = 100)
+ build_path = /obj/item/reagent_containers/syringe/dart
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+
+/datum/design/bluespacesmartdart
+ name = "bluespace smartdart"
+ desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented. Has an extended volume capacity thanks to bluespace foam."
+ id = "bluespacesmartdart"
+ build_type = PROTOLATHE
+ materials = list(MAT_GLASS = 250, MAT_PLASTIC = 250, MAT_METAL = 250, MAT_BLUESPACE = 250)
+ build_path = /obj/item/reagent_containers/syringe/dart/bluespace
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+
+/datum/design/smartdartgun
+ name = "dart gun"
+ desc = "A compressed air gun, designed to fit medicinal darts for application of medicine for those patients just out of reach."
+ id = "smartdartgun"
+ build_type = PROTOLATHE
+ materials = list(MAT_GLASS = 500, MAT_PLASTIC = 1000, MAT_METAL = 500)
+ build_path = /obj/item/gun/syringe/dart
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+
/datum/design/bluespacebodybag
name = "Bluespace Body Bag"
desc = "A bluespace body bag, powered by experimental bluespace technology. It can hold loads of bodies and the largest of creatures."
diff --git a/code/modules/research/nanites/nanite_programs.dm b/code/modules/research/nanites/nanite_programs.dm
index f691c828c9..a06311f26f 100644
--- a/code/modules/research/nanites/nanite_programs.dm
+++ b/code/modules/research/nanites/nanite_programs.dm
@@ -57,6 +57,7 @@
deactivate()
if(passive_enabled)
disable_passive_effect()
+ on_mob_remove()
if(nanites)
nanites.programs -= src
return ..()
@@ -107,6 +108,9 @@
if(activated) //apply activation effects if it starts active
activate()
+datum/nanite_program/proc/on_mob_remove()
+ return
+
/datum/nanite_program/proc/toggle()
if(!activated)
activate()
@@ -115,6 +119,7 @@
/datum/nanite_program/proc/activate()
activated = TRUE
+ timer_counter = activation_delay
/datum/nanite_program/proc/deactivate()
if(passive_enabled)
@@ -135,8 +140,10 @@
if(timer && timer_counter > timer)
if(timer_type == NANITE_TIMER_DEACTIVATE)
deactivate()
+ return
else if(timer_type == NANITE_TIMER_SELFDELETE)
qdel(src)
+ return
else if(can_trigger && timer_type == NANITE_TIMER_TRIGGER)
trigger()
timer_counter = activation_delay
@@ -251,4 +258,3 @@
return "Trigger"
if(NANITE_TIMER_RESET)
return "Reset Activation Timer"
-
diff --git a/code/modules/research/nanites/nanite_programs/utility.dm b/code/modules/research/nanites/nanite_programs/utility.dm
index 4405401cec..77fb4e1005 100644
--- a/code/modules/research/nanites/nanite_programs/utility.dm
+++ b/code/modules/research/nanites/nanite_programs/utility.dm
@@ -237,7 +237,11 @@
if(prob(10))
var/list/mob/living/target_hosts = list()
for(var/mob/living/L in oview(5, host_mob))
+ if(!(MOB_ORGANIC in L.mob_biotypes) && !(MOB_UNDEAD in L.mob_biotypes))
+ continue
target_hosts += L
+ if(!target_hosts.len)
+ return
var/mob/living/infectee = pick(target_hosts)
if(prob(100 - (infectee.get_permeability_protection() * 100)))
//this will potentially take over existing nanites!
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index c1124efe2d..4331d8858b 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -69,7 +69,7 @@
display_name = "Advanced Biotechnology"
description = "Advanced Biotechnology"
prereq_ids = list("biotech")
- design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "defibrillator", "meta_beaker", "healthanalyzer_advanced","harvester","holobarrier_med")
+ design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "defibrillator", "meta_beaker", "healthanalyzer_advanced","harvester","holobarrier_med","smartdartgun","medicinalsmartdart")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -246,7 +246,7 @@
display_name = "Applied Bluespace Research"
description = "Using bluespace to make things faster and better."
prereq_ids = list("bluespace_basic", "engineering")
- design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "roastingstick", "ore_silo")
+ design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "roastingstick", "ore_silo", "bluespacesmartdart")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500)
export_price = 5000
diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm
index 28ea849782..161ea3ac62 100644
--- a/code/modules/ruins/lavaland_ruin_code.dm
+++ b/code/modules/ruins/lavaland_ruin_code.dm
@@ -22,7 +22,7 @@
icon_state = "datadisk1"
max_blueprints = 1
-/obj/item/disk/design_disk/golem_shell/Initialize()
+/obj/item/disk/design_disk/plant_disk/Initialize()
. = ..()
var/datum/design/diskplantgene/P = new
blueprints[1] = P
diff --git a/code/modules/spells/spell_types/construct_spells.dm b/code/modules/spells/spell_types/construct_spells.dm
index 39066ae4a9..bb3cc1f7e3 100644
--- a/code/modules/spells/spell_types/construct_spells.dm
+++ b/code/modules/spells/spell_types/construct_spells.dm
@@ -146,11 +146,14 @@
clothes_req = 0
invocation = "none"
invocation_type = "none"
+ proj_type = /obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile/lesser
proj_lifespan = 10
max_targets = 6
action_icon_state = "magicm"
action_background_icon_state = "bg_demon"
+/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile/lesser
+ amt_knockdown = 84
/obj/effect/proc_holder/spell/targeted/smoke/disable
name = "Paralysing Smoke"
@@ -304,7 +307,8 @@
name = "Gauntlet Echo"
alpha = 180
amt_dam_brute = 30
- amt_knockdown = 50
+ amt_knockdown = 84
+ amt_dam_stam = 30
sound = 'sound/weapons/punch3.ogg'
/obj/effect/proc_holder/spell/targeted/inflict_handler/juggernaut/cast(list/targets,mob/user = usr)
diff --git a/code/modules/spells/spell_types/inflict_handler.dm b/code/modules/spells/spell_types/inflict_handler.dm
index da0af7a601..25bdc7c9d2 100644
--- a/code/modules/spells/spell_types/inflict_handler.dm
+++ b/code/modules/spells/spell_types/inflict_handler.dm
@@ -3,10 +3,12 @@
desc = "This spell blinds and/or destroys/damages/heals and/or knockdowns/stuns the target."
var/amt_knockdown = 0
+ var/amt_hardstun
var/amt_unconscious = 0
var/amt_stun = 0
//set to negatives for healing
+ var/amt_dam_stam
var/amt_dam_fire = 0
var/amt_dam_brute = 0
var/amt_dam_oxy = 0
@@ -41,7 +43,10 @@
target.adjustToxLoss(amt_dam_tox)
target.adjustOxyLoss(amt_dam_oxy)
//disabling
- target.Knockdown(amt_knockdown)
+ if(!amt_knockdown && amt_dam_stam)
+ target.adjustStaminaLoss(amt_dam_stam)
+ else
+ target.Knockdown(amt_knockdown, override_hardstun = amt_hardstun, amt_dam_stam)
target.Unconscious(amt_unconscious)
target.Stun(amt_stun)
diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm
index aec0e7806b..c4d2c34a71 100644
--- a/code/modules/spells/spell_types/wizard.dm
+++ b/code/modules/spells/spell_types/wizard.dm
@@ -28,7 +28,8 @@
sound = 'sound/magic/magic_missile.ogg'
/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile
- amt_knockdown = 60
+ amt_knockdown = 120
+ amt_hardstun = 5
sound = 'sound/magic/mm_hit.ogg'
/obj/effect/proc_holder/spell/targeted/genetic/mutate
@@ -262,7 +263,7 @@
action_icon_state = "repulse"
-/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets,mob/user = usr, var/stun_amt = 40)
+/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets,mob/user = usr, stun_amt = 50)
var/list/thrownatoms = list()
var/atom/throwtarget
var/distfromcaster
@@ -286,14 +287,14 @@
if(distfromcaster == 0)
if(isliving(AM))
var/mob/living/M = AM
- M.Knockdown(100)
+ M.Knockdown(100, override_hardstun = 20)
M.adjustBruteLoss(5)
to_chat(M, "You're slammed into the floor by [user]!")
else
new sparkle_path(get_turf(AM), get_dir(user, AM)) //created sparkles will disappear on their own
if(isliving(AM))
var/mob/living/M = AM
- M.Knockdown(stun_amt)
+ M.Knockdown(stun_amt, override_hardstun = stun_amt * 0.2)
to_chat(M, "You're thrown back by [user]!")
AM.throw_at(throwtarget, ((CLAMP((maxthrow - (CLAMP(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time.
diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm
index 3c80737b31..a97a133685 100644
--- a/code/modules/surgery/bodyparts/bodyparts.dm
+++ b/code/modules/surgery/bodyparts/bodyparts.dm
@@ -564,6 +564,11 @@
max_stamina_damage = 200
var/obj/item/cavity_item
+/obj/item/bodypart/chest/can_dismember(obj/item/I)
+ if(!((owner.stat == DEAD) || owner.InFullCritical()))
+ return FALSE
+ return ..()
+
/obj/item/bodypart/chest/Destroy()
if(cavity_item)
qdel(cavity_item)
diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm
index ad07ce7238..f09258f19f 100644
--- a/code/modules/surgery/organs/augments_arms.dm
+++ b/code/modules/surgery/organs/augments_arms.dm
@@ -129,11 +129,14 @@
holder = null
if(contents.len == 1)
Extend(contents[1])
- else // TODO: make it similar to borg's storage-like module selection
- var/obj/item/choise = input("Activate which item?", "Arm Implant", null, null) as null|anything in items_list
- if(owner && owner == usr && owner.stat != DEAD && (src in owner.internal_organs) && !holder && istype(choise) && (choise in contents))
- // This monster sanity check is a nice example of how bad input() is.
- Extend(choise)
+ else
+ var/list/choice_list = list()
+ for(var/obj/item/I in items_list)
+ choice_list[I] = getFlatIcon(I)
+ var/obj/item/choice = show_radial_menu(owner, owner, choice_list)
+ if(owner && owner == usr && owner.stat != DEAD && (src in owner.internal_organs) && !holder && (choice in contents))
+ // This monster sanity check is a nice example of how bad input is.
+ Extend(choice)
else
Retract()
diff --git a/code/modules/unit_tests/reagent_recipe_collisions.dm b/code/modules/unit_tests/reagent_recipe_collisions.dm
index 31027c2cd3..20e875422f 100644
--- a/code/modules/unit_tests/reagent_recipe_collisions.dm
+++ b/code/modules/unit_tests/reagent_recipe_collisions.dm
@@ -11,57 +11,5 @@
for(var/i2 in (i+1) to reactions.len)
var/datum/chemical_reaction/r1 = reactions[i]
var/datum/chemical_reaction/r2 = reactions[i2]
- if(recipes_do_conflict(r1, r2))
+ if(chem_recipes_do_conflict(r1, r2))
Fail("Chemical recipe conflict between [r1.type] and [r2.type]")
-
-/datum/unit_test/reagent_recipe_collisions/proc/recipes_do_conflict(datum/chemical_reaction/r1, datum/chemical_reaction/r2)
- //do the non-list tests first, because they are cheaper
- if(r1.required_container != r2.required_container)
- return FALSE
- if(r1.is_cold_recipe == r2.is_cold_recipe)
- if(r1.required_temp != r2.required_temp)
- //one reaction requires a more extreme temperature than the other, so there is no conflict
- return FALSE
- else
- var/datum/chemical_reaction/cold_one = r1.is_cold_recipe ? r1 : r2
- var/datum/chemical_reaction/warm_one = r1.is_cold_recipe ? r2 : r1
- if(cold_one.required_temp < warm_one.required_temp)
- //the range of temperatures does not overlap, so there is no conflict
- return FALSE
-
- //find the reactions with the shorter and longer required_reagents list
- var/datum/chemical_reaction/long_req
- var/datum/chemical_reaction/short_req
- if(r1.required_reagents.len > r2.required_reagents.len)
- long_req = r1
- short_req = r2
- else if(r1.required_reagents.len < r2.required_reagents.len)
- long_req = r2
- short_req = r1
- else
- //if they are the same length, sort instead by the length of the catalyst list
- //this is important if the required_reagents lists are the same
- if(r1.required_catalysts.len > r2.required_catalysts.len)
- long_req = r1
- short_req = r2
- else
- long_req = r2
- short_req = r1
-
-
- //check if the shorter reaction list is a subset of the longer one
- var/list/overlap = r1.required_reagents & r2.required_reagents
- if(overlap.len != short_req.required_reagents.len)
- //there is at least one reagent in the short list that is not in the long list, so there is no conflict
- return FALSE
-
- //check to see if the shorter reaction's catalyst list is also a subset of the longer reaction's catalyst list
- //if the longer reaction's catalyst list is a subset of the shorter ones, that is fine
- //if the reaction lists are the same, the short reaction will have the shorter required_catalysts list, so it will register as a conflict
- var/list/short_minus_long_catalysts = short_req.required_catalysts - long_req.required_catalysts
- if(short_minus_long_catalysts.len)
- //there is at least one unique catalyst for the short reaction, so there is no conflict
- return FALSE
-
- //if we got this far, the longer reaction will be impossible to create if the shorter one is earlier in GLOB.chemical_reactions_list, and will require the reagents to be added in a particular order otherwise
- return TRUE
\ No newline at end of file
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index 2bda7956da..af1c954c5b 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -109,72 +109,194 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/discounts
category = "Discounted Gear"
-// Nuclear Operative (Special Offers)
-/datum/uplink_item/nukeoffer
- category = "Special Offers"
+//All bundles and telecrystals
+/datum/uplink_item/bundles_TC
+ category = "Bundles and Telecrystals"
surplus = 0
- include_modes = list(/datum/game_mode/nuclear)
cant_discount = TRUE
-/datum/uplink_item/nukeoffer/c20r
- name = "C-20r bundle"
- desc = "Old faithful: The classic C-20r, bundled with two magazines, and a (surplus) suppressor at discount price."
- item = /obj/item/storage/backpack/duffelbag/syndie/c20rbundle
- cost = 14 // normally 16
-
-/datum/uplink_item/nukeoffer/bulldog
- name = "Bulldog bundle"
- desc = "Lean and mean: Optimised for people that want to get up close and personal. Contains the popular \
- Bulldog shotgun, two 12g drums, and a pair of Thermal imaging goggles."
- item = /obj/item/storage/backpack/duffelbag/syndie/bulldogbundle
- cost = 13 // normally 16
-
-/datum/uplink_item/nukeoffer/medical
- name = "Medical bundle"
- desc = "The support specialist: Aid your fellow operatives with this medical bundle. Contains a Donksoft machine gun, \
- a box of ammo, and a pair of magboots to rescue your friends in no-gravity environments."
- item = /obj/item/storage/backpack/duffelbag/syndie/med/medicalbundle
- cost = 15 // normally 20
-
-/datum/uplink_item/nukeoffer/sniper
- name = "Sniper bundle"
- desc = "Elegant and refined: Contains a collapsed sniper rifle in an expensive carrying case, a hollow-point \
- a soporific knockout magazine, a free surplus supressor, and a worn out suit and tie."
- item = /obj/item/storage/briefcase/sniperbundle
- cost = 20 // normally 26
-
-/datum/uplink_item/nukeoffer/chemical
+/datum/uplink_item/bundles_TC/chemical
name = "Bioterror bundle"
desc = "For the madman: Contains Bioterror spray, Bioterror grenade, chemicals, syringe gun, box of syringes,\
Donksoft assault rifle, and some darts. Remember: Seal suit and equip internals before use."
item = /obj/item/storage/backpack/duffelbag/syndie/med/bioterrorbundle
cost = 30 // normally 42
+ include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/nukeoffer/firestarter
+/datum/uplink_item/bundles_TC/bulldog
+ name = "Bulldog bundle"
+ desc = "Lean and mean: Optimised for people that want to get up close and personal. Contains the popular \
+ Bulldog shotgun, two 12g drums, and a pair of Thermal imaging goggles."
+ item = /obj/item/storage/backpack/duffelbag/syndie/bulldogbundle
+ cost = 13 // normally 16
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/c20r
+ name = "C-20r bundle"
+ desc = "Old faithful: The classic C-20r, bundled with two magazines, and a (surplus) suppressor at discount price."
+ item = /obj/item/storage/backpack/duffelbag/syndie/c20rbundle
+ cost = 14 // normally 16
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/cybernetics_bundle
+ name = "Cybernetic Implants Bundle"
+ desc = "A random selection of cybernetic implants. Guaranteed 5 high quality implants. Comes with an autosurgeon."
+ item = /obj/item/storage/box/cyber_implants
+ cost = 40
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/medical
+ name = "Medical bundle"
+ desc = "The support specialist: Aid your fellow operatives with this medical bundle. Contains a Donksoft machine gun, \
+ a box of ammo, and a pair of magboots to rescue your friends in no-gravity environments."
+ item = /obj/item/storage/backpack/duffelbag/syndie/med/medicalbundle
+ cost = 15 // normally 20
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/modular
+ name = "Modular Pistol Kit"
+ desc = "A heavy briefcase containing one modular pistol (chambered in 10mm), one supressor, and spare ammunition, including a box of soporific ammo. \
+ Includes a suit jacket that is padded with a robust liner."
+ item = /obj/item/storage/briefcase/modularbundle
+ cost = 12
+
+/datum/uplink_item/bundles_TC/shredder
+ name = "Shredder bundle"
+ desc = "A truly horrific weapon designed simply to maim its victim, the CX Shredder is banned by several intergalactic treaties. \
+ You'll get two of them with this. And spare ammo to boot. And we'll throw in an extra elite hardsuit and chest rig to hold them all!"
+ item = /obj/item/storage/backpack/duffelbag/syndie/shredderbundle
+ cost = 30 // normally 41
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/sniper
+ name = "Sniper bundle"
+ desc = "Elegant and refined: Contains a collapsed sniper rifle in an expensive carrying case, a hollow-point \
+ a soporific knockout magazine, a free surplus supressor, and a worn out suit and tie."
+ item = /obj/item/storage/briefcase/sniperbundle
+ cost = 20 // normally 26
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/firestarter
name = "Spetsnaz Pyro bundle"
desc = "For systematic suppression of carbon lifeforms in close range: Contains a specialist Pyrotechnic equipment, foreign pistol, two magazines, a pipebomb, and a stimulant syringe."
item = /obj/item/storage/backpack/duffelbag/syndie/firestarter
cost = 30
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/bundles_TC/bundle
+ name = "Syndicate Bundle"
+ desc = "Syndicate Bundles are specialized groups of items that arrive in a plain box. \
+ These items are collectively worth more than 20 telecrystals, but you do not know which specialization \
+ you will receive."
+ item = /obj/item/storage/box/syndicate
+ cost = 20
+ exclude_modes = list(/datum/game_mode/nuclear)
+ cant_discount = TRUE
+
+/datum/uplink_item/bundles_TC/surplus
+ name = "Syndicate Surplus Crate"
+ desc = "A dusty crate from the back of the Syndicate warehouse. Rumored to contain a valuable assortment of items, \
+ but you never know. Contents are sorted to always be worth 50 TC."
+ item = /obj/structure/closet/crate
+ cost = 20
+ player_minimum = 25
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+ cant_discount = TRUE
+ var/starting_crate_value = 50
+
+/datum/uplink_item/bundles_TC/surplus/super
+ name = "Super Surplus Crate"
+ desc = "A dusty SUPER-SIZED from the back of the Syndicate warehouse. Rumored to contain a valuable assortment of items, \
+ but you never know. Contents are sorted to always be worth 125 TC."
+ cost = 40
+ player_minimum = 40
+ starting_crate_value = 125
+
+/datum/uplink_item/bundles_TC/surplus/purchase(mob/user, datum/component/uplink/U)
+ var/list/uplink_items = get_uplink_items(SSticker && SSticker.mode? SSticker.mode : null, FALSE)
+
+ var/crate_value = starting_crate_value
+ var/obj/structure/closet/crate/C = spawn_item(/obj/structure/closet/crate, user)
+ if(U.purchase_log)
+ U.purchase_log.LogPurchase(C, src, cost)
+ while(crate_value)
+ var/category = pick(uplink_items)
+ var/item = pick(uplink_items[category])
+ var/datum/uplink_item/I = uplink_items[category][item]
+
+ if(!I.surplus || prob(100 - I.surplus))
+ continue
+ if(crate_value < I.cost)
+ continue
+ crate_value -= I.cost
+ var/obj/goods = new I.item(C)
+ if(U.purchase_log)
+ U.purchase_log.LogPurchase(goods, I, 0)
+ return C
+
+/datum/uplink_item/bundles_TC/random
+ name = "Random Item"
+ desc = "Picking this will purchase a random item. Useful if you have some TC to spare or if you haven't decided on a strategy yet."
+ item = /obj/effect/gibspawner/generic // non-tangible item because techwebs use this path to determine illegal tech
+ cost = 0
+ cant_discount = TRUE
+
+/datum/uplink_item/bundles_TC/random/purchase(mob/user, datum/component/uplink/U)
+ var/list/uplink_items = U.uplink_items
+ var/list/possible_items = list()
+ for(var/category in uplink_items)
+ for(var/item in uplink_items[category])
+ var/datum/uplink_item/I = uplink_items[category][item]
+ if(src == I || !I.item)
+ continue
+ if(U.telecrystals < I.cost)
+ continue
+ if(I.limited_stock == 0)
+ continue
+ possible_items += I
+
+ if(possible_items.len)
+ var/datum/uplink_item/I = pick(possible_items)
+ SSblackbox.record_feedback("tally", "traitor_random_uplink_items_gotten", 1, initial(I.name))
+ U.MakePurchase(user, I)
+
+/datum/uplink_item/bundles_TC/telecrystal
+ name = "1 Raw Telecrystal"
+ desc = "A telecrystal in its rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
+ item = /obj/item/stack/telecrystal
+ cost = 1
+ surplus = 0
+ cant_discount = TRUE
+ // Don't add telecrystals to the purchase_log since
+ // it's just used to buy more items (including itself!)
+ purchase_log_vis = FALSE
+
+/datum/uplink_item/bundles_TC/telecrystal/five
+ name = "5 Raw Telecrystals"
+ desc = "Five telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
+ item = /obj/item/stack/telecrystal/five
+ cost = 5
+
+/datum/uplink_item/bundles_TC/telecrystal/twenty
+ name = "20 Raw Telecrystals"
+ desc = "Twenty telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
+ item = /obj/item/stack/telecrystal/twenty
+ cost = 20
// Dangerous Items
/datum/uplink_item/dangerous
category = "Conspicuous and Dangerous Weapons"
-/datum/uplink_item/dangerous/pistol
- name = "Stechkin Pistol"
- desc = "A small, easily concealable handgun that uses 10mm auto rounds in 8-round magazines and is compatible \
- with suppressors."
- item = /obj/item/gun/ballistic/automatic/pistol
- cost = 7
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/dangerous/revolver
- name = "Syndicate Revolver"
- desc = "A brutally simple syndicate revolver that fires .357 Magnum rounds and has 7 chambers."
- item = /obj/item/gun/ballistic/revolver
- cost = 13
- surplus = 50
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/dangerous/antitank
+ name = "Anti Tank Pistol"
+ desc = "Essentially amounting to a sniper rifle with no stock and barrel (or indeed, any rifling at all), \
+ this extremely dubious pistol is guaranteed to dislocate your wrists and hit the broad side of a barn! \
+ Uses sniper ammo. \
+ Bullets tend to veer off-course. We are not responsible for any unintentional damage or injury resulting from inaacuracy."
+ item = /obj/item/gun/ballistic/automatic/pistol/antitank/syndicate
+ cost = 14
+ surplus = 25
+ include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/dangerous/pie_cannon
name = "Banana Cream Pie Cannon"
@@ -184,6 +306,42 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
surplus = 0
include_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/dangerous/bananashield
+ name = "Bananium Energy Shield"
+ desc = "A clown's most powerful defensive weapon, this personal shield provides near immunity to ranged energy attacks \
+ by bouncing them back at the ones who fired them. It can also be thrown to bounce off of people, slipping them, \
+ and returning to you even if you miss. WARNING: DO NOT ATTEMPT TO STAND ON SHIELD WHILE DEPLOYED, EVEN IF WEARING ANTI-SLIP SHOES."
+ item = /obj/item/shield/energy/bananium
+ cost = 16
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/dangerous/clownsword
+ name = "Bananium Energy Sword"
+ desc = "An energy sword that deals no damage, but will slip anyone it contacts, be it by melee attack, thrown \
+ impact, or just stepping on it. Beware friendly fire, as even anti-slip shoes will not protect against it."
+ item = /obj/item/melee/transforming/energy/sword/bananium
+ cost = 3
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/dangerous/bioterror
+ name = "Biohazardous Chemical Sprayer"
+ desc = "A chemical sprayer that allows a wide dispersal of selected chemicals. Especially tailored by the Tiger \
+ Cooperative, the deadly blend it comes stocked with will disorient, damage, and disable your foes... \
+ Use with extreme caution, to prevent exposure to yourself and your fellow operatives."
+ item = /obj/item/reagent_containers/spray/chemsprayer/bioterror
+ cost = 20
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/dangerous/throwingweapons
+ name = "Box of Throwing Weapons"
+ desc = "A box of shurikens and reinforced bolas from ancient Earth martial arts. They are highly effective \
+ throwing weapons. The bolas can knock a target down and the shurikens will embed into limbs."
+ item = /obj/item/storage/box/syndie_kit/throwing_weapons
+ cost = 3
+
/datum/uplink_item/dangerous/shotgun
name = "Bulldog Shotgun"
desc = "A fully-loaded semi-automatic drum-fed shotgun. Compatible with all 12g rounds. Designed for close \
@@ -202,86 +360,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
surplus = 40
include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/dangerous/carbine
- name = "M-90gl Carbine"
- desc = "A fully-loaded, specialized three-round burst carbine that fires 5.56mm ammunition from a 30 round magazine \
- with a togglable 40mm under-barrel grenade launcher."
- item = /obj/item/gun/ballistic/automatic/m90
- cost = 18
- surplus = 50
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/dangerous/machinegun
- name = "L6 Squad Automatic Weapon"
- desc = "A fully-loaded Aussec Armoury belt-fed machine gun. \
- This deadly weapon has a massive 50-round magazine of devastating 1.95x129mm ammunition."
- item = /obj/item/gun/ballistic/automatic/l6_saw
- cost = 18
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/dangerous/grenadier
- name = "Grenadier's belt"
- desc = "A belt of a large variety of lethally dangerous and destructive grenades."
- item = /obj/item/storage/belt/grenade/full
- include_modes = list(/datum/game_mode/nuclear)
- cost = 22
- surplus = 0
-
-/datum/uplink_item/dangerous/sniper
- name = "Sniper Rifle"
- desc = "Ranged fury, Syndicate style. Guaranteed to cause shock and awe or your TC back!"
- item = /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate
- cost = 16
- surplus = 25
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/dangerous/bolt_action
- name = "Surplus Rifle"
- desc = "A horribly outdated bolt action weapon. You've got to be desperate to use this."
- item = /obj/item/gun/ballistic/shotgun/boltaction
- cost = 2
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/dangerous/crossbow
- name = "Miniature Energy Crossbow"
- desc = "A short bow mounted across a tiller in miniature. Small enough to \
- fit into a pocket or slip into a bag unnoticed. It will synthesize \
- and fire bolts tipped with a paralyzing toxin that will briefly stun \
- targets and cause them to slur as if inebriated. It can produce an \
- infinite number of bolts, but takes time to automatically recharge \
- after each shot."
- item = /obj/item/gun/energy/kinetic_accelerator/crossbow
- cost = 12
- surplus = 50
- exclude_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/dangerous/flamethrower
- name = "Flamethrower"
- desc = "A flamethrower, fueled by a portion of highly flammable biotoxins stolen previously from Nanotrasen \
- stations. Make a statement by roasting the filth in their own greed. Use with caution."
- item = /obj/item/flamethrower/full/tank
- cost = 4
- surplus = 40
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/dangerous/sword
- name = "Energy Sword"
- desc = "The energy sword is an edged weapon with a blade of pure energy. The sword is small enough to be \
- pocketed when inactive. Activating it produces a loud, distinctive noise."
- item = /obj/item/melee/transforming/energy/sword/saber
- cost = 8
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/dangerous/clownsword
- name = "Bananium Energy Sword"
- desc = "An energy sword that deals no damage, but will slip anyone it contacts, be it by melee attack, thrown \
- impact, or just stepping on it. Beware friendly fire, as even anti-slip shoes will not protect against it."
- item = /obj/item/melee/transforming/energy/sword/bananium
- cost = 3
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
-
/datum/uplink_item/dangerous/doublesword
name = "Double-Bladed Energy Sword"
desc = "The double-bladed energy sword does slightly more damage than a standard energy sword and will deflect \
@@ -294,6 +372,90 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/dangerous/doublesword/get_discount()
return pick(4;0.8,2;0.65,1;0.5)
+/datum/uplink_item/dangerous/cxneb
+ name = "Dragon's Tooth Non-Eutactic Blade"
+ desc = "An illegal modification of a weapon that is functionally identical to the energy sword, \
+ the Non-Eutactic Blade (NEB) forges a hardlight blade on-demand, \
+ generating an extremely sharp, unbreakable edge that is guaranteed to satisfy your every need. \
+ This particular model has a polychromic hardlight generator, allowing you to murder in style! \
+ The illegal modifications bring this weapon up to par with the classic energy sword, and also gives it the energy sword's distinctive sounds."
+ item = /obj/item/melee/transforming/energy/sword/cx/traitor
+ cost = 8
+
+/datum/uplink_item/dangerous/sword
+ name = "Energy Sword"
+ desc = "The energy sword is an edged weapon with a blade of pure energy. The sword is small enough to be \
+ pocketed when inactive. Activating it produces a loud, distinctive noise."
+ item = /obj/item/melee/transforming/energy/sword/saber
+ cost = 8
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/dangerous/shield
+ name = "Energy Shield"
+ desc = "An incredibly useful personal shield projector, capable of reflecting energy projectiles and defending \
+ against other attacks. Pair with an Energy Sword for a killer combination."
+ item = /obj/item/shield/energy
+ cost = 16
+ surplus = 20
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/dangerous/flamethrower
+ name = "Flamethrower"
+ desc = "A flamethrower, fueled by a portion of highly flammable biotoxins stolen previously from Nanotrasen \
+ stations. Make a statement by roasting the filth in their own greed. Use with caution."
+ item = /obj/item/flamethrower/full/tank
+ cost = 4
+ surplus = 40
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/dangerous/flechettegun
+ name = "Flechette Launcher"
+ desc = "A compact bullpup that fires micro-flechettes.\
+ Flechettes have very poor performance idividually, but can be very deadly in numbers. \
+ Pre-loaded with armor piercing flechettes that are capable of puncturing most kinds of armor."
+ item = /obj/item/gun/ballistic/automatic/flechette
+ cost = 12
+ surplus = 30
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/badass/rapid
+ name = "Gloves of the North Star"
+ desc = "These gloves let the user punch people very fast. Does not improve weapon attack speed or the meaty fists of a hulk."
+ item = /obj/item/clothing/gloves/rapid
+ cost = 8
+
+/datum/uplink_item/dangerous/guardian
+ name = "Holoparasites"
+ 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."
+ item = /obj/item/storage/box/syndie_kit/guardian
+ cost = 15
+ refundable = TRUE
+ cant_discount = TRUE
+ surplus = 0
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+ player_minimum = 25
+ restricted = TRUE
+ refund_path = /obj/item/guardiancreator/tech/choose/traitor
+
+/datum/uplink_item/dangerous/machinegun
+ name = "L6 Squad Automatic Weapon"
+ desc = "A fully-loaded Aussec Armoury belt-fed machine gun. \
+ This deadly weapon has a massive 50-round magazine of devastating 1.95x129mm ammunition."
+ item = /obj/item/gun/ballistic/automatic/l6_saw
+ cost = 18
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/dangerous/carbine
+ name = "M-90gl Carbine"
+ desc = "A fully-loaded, specialized three-round burst carbine that fires 5.56mm ammunition from a 30 round magazine \
+ with a togglable 40mm under-barrel grenade launcher."
+ item = /obj/item/gun/ballistic/automatic/m90
+ cost = 18
+ surplus = 50
+ include_modes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/dangerous/powerfist
name = "Power Fist"
desc = "The power-fist is a metal gauntlet with a built-in piston-ram powered by an external gas supply.\
@@ -303,46 +465,36 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/melee/powerfist
cost = 8
-/datum/uplink_item/badass/combatglovesplus
- name = "Combat Gloves Plus"
- desc = "A pair of gloves that are fireproof and shock resistant, however unlike the regular Combat Gloves this one uses nanotechnology \
- to learn the abilities of krav maga to the wearer."
- item = /obj/item/clothing/gloves/krav_maga/combatglovesplus
- cost = 5
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/dangerous/sniper
+ name = "Sniper Rifle"
+ desc = "Ranged fury, Syndicate style. Guaranteed to cause shock and awe or your TC back!"
+ item = /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate
+ cost = 16
+ surplus = 25
+ include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/dangerous/emp
- name = "EMP Grenades and Implanter Kit"
- desc = "A box that contains two EMP grenades and an EMP implant. Useful to disrupt communication, \
- security's energy weapons, and silicon lifeforms when you're in a tight spot."
- item = /obj/item/storage/box/syndie_kit/emp
- cost = 2
-
-/datum/uplink_item/dangerous/syndicate_minibomb
- name = "Syndicate Minibomb"
- desc = "The minibomb is a grenade with a five-second fuse. Upon detonation, it will create a small hull breach \
- in addition to dealing high amounts of damage to nearby personnel."
- item = /obj/item/grenade/syndieminibomb
- cost = 6
+/datum/uplink_item/dangerous/pistol
+ name = "Stechkin Pistol"
+ desc = "A small, easily concealable handgun that uses 10mm auto rounds in 8-round magazines and is compatible \
+ with suppressors."
+ item = /obj/item/gun/ballistic/automatic/pistol
+ cost = 7
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/dangerous/bombanana
- name = "Bombanana"
- desc = "A banana with an explosive taste! discard the peel quickly, as it will explode with the force of a syndicate minibomb \
- a few seconds after the banana is eaten."
- item = /obj/item/reagent_containers/food/snacks/grown/banana/bombanana
- cost = 4 //it is a bit cheaper than a minibomb because you have to take off your helmet to eat it, which is how you arm it
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/dangerous/bolt_action
+ name = "Surplus Rifle"
+ desc = "A horribly outdated bolt action weapon. You've got to be desperate to use this."
+ item = /obj/item/gun/ballistic/shotgun/boltaction
+ cost = 2
+ include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/dangerous/tearstache
- name = "Teachstache Grenade"
- desc = "A teargas grenade that launches sticky moustaches onto the face of anyone not wearing a clown or mime mask. The moustaches will \
- remain attached to the face of all targets for one minute, preventing the use of breath masks and other such devices."
- item = /obj/item/grenade/chem_grenade/teargas/moustache
- cost = 3
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/dangerous/revolver
+ name = "Syndicate Revolver"
+ desc = "A brutally simple syndicate revolver that fires .357 Magnum rounds and has 7 chambers."
+ item = /obj/item/gun/ballistic/revolver/syndie
+ cost = 13
+ surplus = 50
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
/datum/uplink_item/dangerous/foamsmg
name = "Toy Submachine Gun"
@@ -361,65 +513,132 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
surplus = 0
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/dangerous/viscerators
- name = "Viscerator Delivery Grenade"
- desc = "A unique grenade that deploys a swarm of viscerators upon activation, which will chase down and shred \
- any non-operatives in the area."
- item = /obj/item/grenade/spawnergrenade/manhacks
- cost = 5
- surplus = 35
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/dangerous/foampistol
+ name = "Toy Gun with Riot Darts"
+ desc = "An innocent-looking toy pistol designed to fire foam darts. Comes loaded with riot-grade \
+ darts effective at incapacitating a target."
+ item = /obj/item/gun/ballistic/automatic/toy/pistol/riot
+ cost = 3
+ surplus = 10
-/datum/uplink_item/dangerous/bioterrorfoam
- name = "Chemical Foam Grenade"
- desc = "A powerful chemical foam grenade which creates a deadly torrent of foam that will mute, blind, confuse, \
- mutate, and irritate carbon lifeforms. Specially brewed by Tiger Cooperative chemical weapons specialists \
- using additional spore toxin. Ensure suit is sealed before use."
- item = /obj/item/grenade/chem_grenade/bioterrorfoam
- cost = 5
- surplus = 35
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+// Stealthy Weapons
+/datum/uplink_item/stealthy_weapons
+ category = "Stealthy and Inconspicuous Weapons"
-/datum/uplink_item/dangerous/bioterror
- name = "Biohazardous Chemical Sprayer"
- desc = "A chemical sprayer that allows a wide dispersal of selected chemicals. Especially tailored by the Tiger \
- Cooperative, the deadly blend it comes stocked with will disorient, damage, and disable your foes... \
- Use with extreme caution, to prevent exposure to yourself and your fellow operatives."
- item = /obj/item/reagent_containers/spray/chemsprayer/bioterror
- cost = 20
+/datum/uplink_item/stealthy_weapons/combatglovesplus
+ name = "Combat Gloves Plus"
+ desc = "A pair of gloves that are fireproof and shock resistant, however unlike the regular Combat Gloves this one uses nanotechnology \
+ to learn the abilities of krav maga to the wearer."
+ item = /obj/item/clothing/gloves/krav_maga/combatglovesplus
+ cost = 5
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
surplus = 0
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/stealthy_weapons/virus_grenade
- name = "Fungal Tuberculosis Grenade"
- desc = "A primed bio-grenade packed into a compact box. Comes with five Bio Virus Antidote Kit (BVAK) \
- autoinjectors for rapid application on up to two targets each, a syringe, and a bottle containing \
- the BVAK solution."
- item = /obj/item/storage/box/syndie_kit/tuberculosisgrenade
- cost = 8
- surplus = 35
+/datum/uplink_item/stealthy_weapons/cqc
+ name = "CQC Manual"
+ desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing."
+ item = /obj/item/book/granter/martial/cqc
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
- restricted = TRUE
+ cost = 13
+ surplus = 0
-/datum/uplink_item/dangerous/guardian
- name = "Holoparasites"
- 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."
- item = /obj/item/storage/box/syndie_kit/guardian
- cost = 18
+/datum/uplink_item/stealthy_weapons/dart_pistol
+ name = "Dart Pistol"
+ desc = "A miniaturized version of a normal syringe gun. It is very quiet when fired and can fit into any \
+ space a small item can."
+ item = /obj/item/gun/syringe/syndicate
+ cost = 4
+ surplus = 50
+
+/datum/uplink_item/stealthy_weapons/dehy_carp
+ name = "Dehydrated Space Carp"
+ desc = "Looks like a plush toy carp, but just add water and it becomes a real-life space carp! Activate in \
+ your hand before use so it knows not to kill you."
+ item = /obj/item/toy/plush/carpplushie/dehy_carp
+ cost = 1
+
+/datum/uplink_item/stealthy_weapons/edagger
+ name = "Energy Dagger"
+ desc = "A dagger made of energy that looks and functions as a pen when off."
+ item = /obj/item/pen/edagger
+ cost = 2
+
+/datum/uplink_item/stealthy_weapons/martialarts
+ name = "Martial Arts Scroll"
+ desc = "This scroll contains the secrets of an ancient martial arts technique. You will master unarmed combat, \
+ deflecting all ranged weapon fire, but you also refuse to use dishonorable ranged weaponry."
+ item = /obj/item/book/granter/martial/carp
+ cost = 17
surplus = 0
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
- player_minimum = 25
- restricted = TRUE
-/datum/uplink_item/dangerous/buzzkill
- name = "Buzzkill Grenade Box"
- desc = "A box with three grenades that release a swarm of angry bees upon activation. These bees indiscriminately attack friend or foe \
- with random toxins. Courtesy of the BLF and Tiger Cooperative."
- item = /obj/item/storage/box/syndie_kit/bee_grenades
- cost = 15
- surplus = 35
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/stealthy_weapons/crossbow
+ name = "Miniature Energy Crossbow"
+ desc = "A short bow mounted across a tiller in miniature. Small enough to \
+ fit into a pocket or slip into a bag unnoticed. It will synthesize \
+ and fire bolts tipped with a paralyzing toxin that will briefly stun \
+ targets and cause them to slur as if inebriated. It can produce an \
+ infinite number of bolts, but takes time to automatically recharge \
+ after each shot."
+ item = /obj/item/gun/energy/kinetic_accelerator/crossbow
+ cost = 12
+ surplus = 50
+ exclude_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/stealthy_weapons/traitor_chem_bottle
+ name = "Poison Kit"
+ desc = "An assortment of deadly chemicals packed into a compact box. Comes with a syringe for more precise application."
+ item = /obj/item/storage/box/syndie_kit/chemical
+ cost = 6
+ surplus = 50
+
+/datum/uplink_item/stealthy_weapons/romerol_kit
+ name = "Romerol"
+ 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
+ exclude_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/stealthy_weapons/sleepy_pen
+ name = "Sleepy Pen"
+ desc = "A syringe disguised as a functional pen, filled with a potent mix of drugs, including a \
+ strong anesthetic and a chemical that prevents the target from speaking. \
+ The pen holds one dose of the mixture, and can be refilled. Note that before the target \
+ falls asleep, they will be able to move and act."
+ item = /obj/item/pen/sleepy
+ cost = 4
+ exclude_modes = list(/datum/game_mode/nuclear)
+
+datum/uplink_item/stealthy_weapons/taeclowndo_shoes
+ name = "Tae-clown-do Shoes"
+ desc = "A pair of shoes for the most elite agents of the honkmotherland. They grant the mastery of taeclowndo with some honk-fu moves as long as they're worn."
+ cost = 12
+ item = /obj/item/clothing/shoes/clown_shoes/taeclowndo
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/stealthy_weapons/suppressor
+ name = "Universal Suppressor"
+ desc = "Fitted for use on any small caliber weapon with a threaded barrel, this suppressor will silence the \
+ shots of the weapon for increased stealth and superior ambushing capability."
+ item = /obj/item/suppressor
+ cost = 1
+ surplus = 10
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/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."
+ item = /obj/item/soap/syndie
+ cost = 1
+ surplus = 50
+
+/datum/uplink_item/stealthy_weapons/soap_clusterbang
+ name = "Slipocalypse Clusterbang"
+ desc = "A traditional clusterbang grenade with a payload consisting entirely of Syndicate soap. Useful in any scenario!"
+ item = /obj/item/grenade/clusterbuster/soap
+ cost = 6
// Ammunition
/datum/uplink_item/ammo
@@ -441,13 +660,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 2
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/ammo/pistolfire
- name = "10mm Incendiary Magazine"
- desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. Loaded with incendiary rounds which ignite the target."
- item = /obj/item/ammo_box/magazine/m10mm/fire
- cost = 2
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-
/datum/uplink_item/ammo/pistolhp
name = "10mm Hollow Point Magazine"
desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. These rounds are more damaging but ineffective against armour."
@@ -455,51 +667,35 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 3
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/ammo/pistolaps
- name = "9mm Handgun Magazine"
- desc = "An additional 15-round 9mm magazine, compatible with the Stetchkin APS pistol, found in the Spetsnaz Pyro bundle."
- item = /obj/item/ammo_box/magazine/pistolm9mm
+/datum/uplink_item/ammo/pistolfire
+ name = "10mm Incendiary Magazine"
+ desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. Loaded with incendiary rounds which ignite the target."
+ item = /obj/item/ammo_box/magazine/m10mm/fire
cost = 2
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/ammo/bolt_action
- name = "Surplus Rifle Clip"
- desc = "A stripper clip used to quickly load bolt action rifles. Contains 5 rounds."
- item = /obj/item/ammo_box/a762
- cost = 1
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/ammo/revolver
- name = ".357 Speed Loader"
- desc = "A speed loader that contains seven additional .357 Magnum rounds; usable with the Syndicate revolver. \
- For when you really need a lot of things dead."
- item = /obj/item/ammo_box/a357
- cost = 4
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/ammo/pistolzzz
+ name = "10mm Soporific Magazine"
+ desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. Loaded with soporific rounds that put the target to sleep. \
+ NOTE: Soporific is not instant acting due to the constraints of the round's scale. Will usually require three shots to take effect."
+ item = /obj/item/ammo_box/magazine/m10mm/soporific
+ cost = 2
+
/datum/uplink_item/ammo/shotgun
cost = 2
include_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/ammo/shotgun/bag
+ name = "12g Ammo Duffel Bag"
+ desc = "A duffel bag filled with enough 12g ammo to supply an entire team, at a discounted price."
+ item = /obj/item/storage/backpack/duffelbag/syndie/ammo/shotgun
+ cost = 12
+
/datum/uplink_item/ammo/shotgun/buck
name = "12g Buckshot Drum"
desc = "An additional 8-round buckshot magazine for use with the Bulldog shotgun. Front towards enemy."
item = /obj/item/ammo_box/magazine/m12g
-/datum/uplink_item/ammo/shotgun/slug
- name = "12g Slug Drum"
- desc = "An additional 8-round slug magazine for use with the Bulldog shotgun. \
- Now 8 times less likely to shoot your pals."
- cost = 3
- item = /obj/item/ammo_box/magazine/m12g/slug
-
-/datum/uplink_item/ammo/shotgun/stun
- name = "12g Stun Slug Drum"
- desc = "An alternative 8-round stun slug magazine for use with the Bulldog shotgun. \
- Saying that they're completely non-lethal would be lying."
- item = /obj/item/ammo_box/magazine/m12g/stun
- include_modes = list(/datum/game_mode/nuclear)
-
/datum/uplink_item/ammo/shotgun/dragon
name = "12g Dragon's Breath Drum"
desc = "An alternative 8-round dragon's breath magazine for use in the Bulldog shotgun. \
@@ -520,18 +716,34 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/ammo_box/magazine/m12g/scatter
cost = 4 // most armor has less laser protection then bullet
-/datum/uplink_item/ammo/shotgun/bag
- name = "12g Ammo Duffel Bag"
- desc = "A duffel bag filled with enough 12g ammo to supply an entire team, at a discounted price."
- item = /obj/item/storage/backpack/duffelbag/syndie/ammo/shotgun
- cost = 12
-
-/datum/uplink_item/ammo/smg
- name = ".45 SMG Magazine"
- desc = "An additional 24-round .45 magazine suitable for use with the C-20r submachine gun. \
- These bullets pack a lot of punch that can knock most targets down, but do limited overall damage."
- item = /obj/item/ammo_box/magazine/smgm45
+/datum/uplink_item/ammo/shotgun/slug
+ name = "12g Slug Drum"
+ desc = "An additional 8-round slug magazine for use with the Bulldog shotgun. \
+ Now 8 times less likely to shoot your pals."
cost = 3
+ item = /obj/item/ammo_box/magazine/m12g/slug
+
+/datum/uplink_item/ammo/shotgun/stun
+ name = "12g Stun Slug Drum"
+ desc = "An alternative 8-round stun slug magazine for use with the Bulldog shotgun. \
+ Saying that they're completely non-lethal would be lying."
+ item = /obj/item/ammo_box/magazine/m12g/stun
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/ammo/revolver
+ name = ".357 Speed Loader"
+ desc = "A speed loader that contains seven additional .357 Magnum rounds; usable with the Syndicate revolver. \
+ For when you really need a lot of things dead."
+ item = /obj/item/ammo_box/a357
+ cost = 4
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/ammo/a40mm
+ name = "40mm Grenade"
+ desc = "A 40mm HE grenade for use with the M-90gl's under-barrel grenade launcher. \
+ Your teammates will ask you to not shoot these down small hallways."
+ item = /obj/item/ammo_casing/a40mm
+ cost = 2
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/smg/bag
@@ -541,6 +753,36 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 20
include_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/ammo/smg
+ name = ".45 SMG Magazine"
+ desc = "An additional 24-round .45 magazine suitable for use with the C-20r submachine gun. \
+ These bullets pack a lot of punch that can knock most targets down, but do limited overall damage."
+ item = /obj/item/ammo_box/magazine/smgm45
+ cost = 3
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/ammo/sniper
+ cost = 4
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/ammo/sniper/basic
+ name = ".50 Magazine"
+ desc = "An additional standard 6-round magazine for use with .50 sniper rifles."
+ item = /obj/item/ammo_box/magazine/sniper_rounds
+
+/datum/uplink_item/ammo/sniper/penetrator
+ name = ".50 Penetrator Magazine"
+ desc = "A 5-round magazine of penetrator ammo designed for use with .50 sniper rifles. \
+ Can pierce walls and multiple enemies."
+ item = /obj/item/ammo_box/magazine/sniper_rounds/penetrator
+ cost = 5
+
+/datum/uplink_item/ammo/sniper/soporific
+ name = ".50 Soporific Magazine"
+ desc = "A 3-round magazine of soporific ammo designed for use with .50 sniper rifles. Put your enemies to sleep today!"
+ item = /obj/item/ammo_box/magazine/sniper_rounds/soporific
+ cost = 6
+
/datum/uplink_item/ammo/carbine
name = "5.56mm Toploader Magazine"
desc = "An additional 30-round 5.56mm magazine; suitable for use with the M-90gl carbine. \
@@ -549,14 +791,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 4
include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/ammo/a40mm
- name = "40mm Grenade"
- desc = "A 40mm HE grenade for use with the M-90gl's under-barrel grenade launcher. \
- Your teammates will ask you to not shoot these down small hallways."
- item = /obj/item/ammo_casing/a40mm
- cost = 2
- include_modes = list(/datum/game_mode/nuclear)
-
/datum/uplink_item/ammo/machinegun
cost = 6
surplus = 0
@@ -568,12 +802,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
By the time you need to use this, you'll already be on a pile of corpses."
item = /obj/item/ammo_box/magazine/mm195x129
-/datum/uplink_item/ammo/machinegun/hollow
- name = "1.95x129mm (Hollow-Point) Box Magazine"
- desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; equipped with hollow-point tips to help \
- with the unarmored masses of crew."
- item = /obj/item/ammo_box/magazine/mm195x129/hollow
-
/datum/uplink_item/ammo/machinegun/ap
name = "1.95x129mm (Armor Penetrating) Box Magazine"
desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; equipped with special properties \
@@ -581,33 +809,41 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/ammo_box/magazine/mm195x129/ap
cost = 9
+/datum/uplink_item/ammo/machinegun/hollow
+ name = "1.95x129mm (Hollow-Point) Box Magazine"
+ desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; equipped with hollow-point tips to help \
+ with the unarmored masses of crew."
+ item = /obj/item/ammo_box/magazine/mm195x129/hollow
+
/datum/uplink_item/ammo/machinegun/incen
name = "1.95x129mm (Incendiary) Box Magazine"
desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; tipped with a special flammable \
mixture that'll ignite anyone struck by the bullet. Some men just want to watch the world burn."
item = /obj/item/ammo_box/magazine/mm195x129/incen
-/datum/uplink_item/ammo/sniper
- cost = 4
+/datum/uplink_item/ammo/pistolaps
+ name = "9mm Handgun Magazine"
+ desc = "An additional 15-round 9mm magazine, compatible with the Stetchkin APS pistol, found in the Spetsnaz Pyro bundle."
+ item = /obj/item/ammo_box/magazine/pistolm9mm
+ cost = 2
include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/ammo/sniper/basic
- name = ".50 Magazine"
- desc = "An additional standard 6-round magazine for use with .50 sniper rifles."
- item = /obj/item/ammo_box/magazine/sniper_rounds
+/datum/uplink_item/ammo/flechetteap
+ name = "Armor Piercing Flechette Magazine"
+ desc = "An additional 40-round flechette magazine; compatible with the Flechette Launcer. \
+ Loaded with armor piercing flechettes that very nearly ignore armor, but are not very effective agaisnt flesh."
+ item = /obj/item/ammo_box/magazine/flechette
+ cost = 2
+ include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/ammo/sniper/soporific
- name = ".50 Soporific Magazine"
- desc = "A 3-round magazine of soporific ammo designed for use with .50 sniper rifles. Put your enemies to sleep today!"
- item = /obj/item/ammo_box/magazine/sniper_rounds/soporific
- cost = 6
-
-/datum/uplink_item/ammo/sniper/penetrator
- name = ".50 Penetrator Magazine"
- desc = "A 5-round magazine of penetrator ammo designed for use with .50 sniper rifles. \
- Can pierce walls and multiple enemies."
- item = /obj/item/ammo_box/magazine/sniper_rounds/penetrator
- cost = 5
+/datum/uplink_item/ammo/flechettes
+ name = "Serrated Flechette Magazine"
+ desc = "An additional 40-round flechette magazine; compatible with the Flechette Launcer. \
+ Loaded with serrated flechettes that shreds flesh, but is stopped dead in its tracks by armor. \
+ These flechettes are highly likely to sever arteries, and even limbs."
+ item = /obj/item/ammo_box/magazine/flechette/s
+ cost = 2
+ include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/toydarts
name = "Box of Riot Darts"
@@ -624,12 +860,184 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 6
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/ammo/bolt_action
+ name = "Surplus Rifle Clip"
+ desc = "A stripper clip used to quickly load bolt action rifles. Contains 5 rounds."
+ item = /obj/item/ammo_box/a762
+ cost = 1
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/explosives
+ category = "Grenades and Explosives"
+
+/datum/uplink_item/explosives/bioterrorfoam
+ name = "Chemical Foam Grenade"
+ desc = "A powerful chemical foam grenade which creates a deadly torrent of foam that will mute, blind, confuse, \
+ mutate, and irritate carbon lifeforms. Specially brewed by Tiger Cooperative chemical weapons specialists \
+ using additional spore toxin. Ensure suit is sealed before use."
+ item = /obj/item/grenade/chem_grenade/bioterrorfoam
+ cost = 5
+ surplus = 35
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/bombanana
+ name = "Bombanana"
+ desc = "A banana with an explosive taste! discard the peel quickly, as it will explode with the force of a syndicate minibomb \
+ a few seconds after the banana is eaten."
+ item = /obj/item/reagent_containers/food/snacks/grown/banana/bombanana
+ cost = 4 //it is a bit cheaper than a minibomb because you have to take off your helmet to eat it, which is how you arm it
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/buzzkill
+ name = "Buzzkill Grenade Box"
+ desc = "A box with three grenades that release a swarm of angry bees upon activation. These bees indiscriminately attack friend or foe \
+ with random toxins. Courtesy of the BLF and Tiger Cooperative."
+ item = /obj/item/storage/box/syndie_kit/bee_grenades
+ cost = 15
+ surplus = 35
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/c4
+ name = "Composition C-4"
+ desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls, sabotage equipment, or connect \
+ an assembly to it in order to alter the way it detonates. It has a modifiable timer with a \
+ minimum setting of 10 seconds."
+ item = /obj/item/grenade/plastic/c4
+ cost = 1
+
+/datum/uplink_item/explosives/c4bag
+ name = "Bag of C-4 explosives"
+ desc = "Because sometimes quantity is quality. Contains 10 C-4 plastic explosives."
+ item = /obj/item/storage/backpack/duffelbag/syndie/c4
+ cost = 9 //10% discount!
+ cant_discount = TRUE
+
+/datum/uplink_item/explosives/x4bag
+ name = "Bag of X-4 explosives"
+ desc = "Contains 3 X-4 plastic explosives. Similar, but more powerful than C-4. X-4 can be placed on a solid surface, such as a wall or window, and it will \
+ blast through the wall, injuring anything on the opposite side, while being safer to the user. For when you want a wider, deeper, hole."
+ item = /obj/item/storage/backpack/duffelbag/syndie/x4
+ cost = 4 //
+ cant_discount = TRUE
+
+/datum/uplink_item/explosives/clown_bomb_clownops
+ name = "Clown Bomb"
+ desc = "The Clown bomb is a hilarious device capable of massive pranks. It has an adjustable timer, \
+ with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \
+ movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \
+ transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \
+ be defused, and some crew may attempt to do so."
+ item = /obj/item/sbeacondrop/clownbomb
+ cost = 15
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/detomatix
+ name = "Detomatix PDA Cartridge"
+ desc = "When inserted into a personal digital assistant, this cartridge gives you four opportunities to \
+ detonate PDAs of crewmembers who have their message feature enabled. \
+ The concussive effect from the explosion will knock the recipient out for a short period, and deafen \
+ them for longer. Beware, it has a chance to detonate your PDA."
+ item = /obj/item/cartridge/virus/syndicate
+ cost = 5
+ restricted = TRUE
+
+/datum/uplink_item/explosives/emp
+ name = "EMP Grenades and Implanter Kit"
+ desc = "A box that contains two EMP grenades and an EMP implant. Useful to disrupt communication, \
+ security's energy weapons, and silicon lifeforms when you're in a tight spot."
+ item = /obj/item/storage/box/syndie_kit/emp
+ cost = 2
+
+/datum/uplink_item/explosives/virus_grenade
+ name = "Fungal Tuberculosis Grenade"
+ desc = "A primed bio-grenade packed into a compact box. Comes with five Bio Virus Antidote Kit (BVAK) \
+ autoinjectors for rapid application on up to two targets each, a syringe, and a bottle containing \
+ the BVAK solution."
+ item = /obj/item/storage/box/syndie_kit/tuberculosisgrenade
+ cost = 8
+ surplus = 35
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+ restricted = TRUE
+
+/datum/uplink_item/explosives/grenadier
+ name = "Grenadier's belt"
+ desc = "A belt of a large variety of lethally dangerous and destructive grenades."
+ item = /obj/item/storage/belt/grenade/full
+ include_modes = list(/datum/game_mode/nuclear)
+ cost = 22
+ surplus = 0
+
+/datum/uplink_item/explosives/pizza_bomb
+ name = "Pizza Bomb"
+ desc = "A pizza box with a bomb cunningly attached to the lid. The timer needs to be set by opening the box; afterwards, \
+ opening the box again will trigger the detonation after the timer has elapsed. Comes with free pizza, for you or your target!"
+ item = /obj/item/pizzabox/bomb
+ cost = 6
+ surplus = 8
+
+/datum/uplink_item/explosives/syndicate_bomb
+ name = "Syndicate Bomb"
+ desc = "The Syndicate bomb is a fearsome device capable of massive destruction. It has an adjustable timer, \
+ with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \
+ movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \
+ transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \
+ be defused, and some crew may attempt to do so."
+ item = /obj/item/sbeacondrop/bomb
+ cost = 11
+
+/datum/uplink_item/explosives/syndicate_detonator
+ name = "Syndicate Detonator"
+ desc = "The Syndicate detonator is a companion device to the Syndicate bomb. Simply press the included button \
+ and an encrypted radio frequency will instruct all live Syndicate bombs to detonate. \
+ Useful for when speed matters or you wish to synchronize multiple bomb blasts. Be sure to stand clear of \
+ the blast radius before using the detonator."
+ item = /obj/item/syndicatedetonator
+ cost = 3
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/syndicate_minibomb
+ name = "Syndicate Minibomb"
+ desc = "The minibomb is a grenade with a five-second fuse. Upon detonation, it will create a small hull breach \
+ in addition to dealing high amounts of damage to nearby personnel."
+ item = /obj/item/grenade/syndieminibomb
+ cost = 6
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/tearstache
+ name = "Teachstache Grenade"
+ desc = "A teargas grenade that launches sticky moustaches onto the face of anyone not wearing a clown or mime mask. The moustaches will \
+ remain attached to the face of all targets for one minute, preventing the use of breath masks and other such devices."
+ item = /obj/item/grenade/chem_grenade/teargas/moustache
+ cost = 3
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/explosives/viscerators
+ name = "Viscerator Delivery Grenade"
+ desc = "A unique grenade that deploys a swarm of viscerators upon activation, which will chase down and shred \
+ any non-operatives in the area."
+ item = /obj/item/grenade/spawnergrenade/manhacks
+ cost = 5
+ surplus = 35
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+
//Support and Mechs
/datum/uplink_item/support
category = "Support and Mechanized Exosuits"
surplus = 0
include_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/support/clown_reinforcement
+ name = "Clown Reinforcements"
+ desc = "Call in an additional clown to share the fun, equipped with full starting gear, but no telecrystals."
+ item = /obj/item/antag_spawner/nuke_ops/clown
+ cost = 20
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+ restricted = TRUE
+
/datum/uplink_item/support/reinforcement
name = "Reinforcements"
desc = "Call in an additional team member. They won't come with any gear, so you'll have to save some telecrystals \
@@ -664,13 +1072,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/mecha/combat/gygax/dark/loaded
cost = 80
-/datum/uplink_item/support/mauler
- name = "Mauler Exosuit"
- desc = "A massive and incredibly deadly military-grade exosuit. Features long-range targeting, thrust vectoring, \
- and deployable smoke."
- item = /obj/mecha/combat/marauder/mauler/loaded
- cost = 140
-
/datum/uplink_item/support/honker
name = "Dark H.O.N.K."
desc = "A clown combat mech equipped with bombanana peel and tearstache grenade launchers, as well as the ubiquitous HoNkER BlAsT 5000."
@@ -678,141 +1079,36 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 80
include_modes = list(/datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/support/clown_reinforcement
- name = "Clown Reinforcements"
- desc = "Call in an additional clown to share the fun, equipped with full starting gear, but no telecrystals."
- item = /obj/item/antag_spawner/nuke_ops/clown
- cost = 20
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
- restricted = TRUE
-
-// Stealthy Weapons
-/datum/uplink_item/stealthy_weapons
- category = "Stealthy and Inconspicuous Weapons"
-
-/datum/uplink_item/stealthy_weapons/martialarts
- name = "Martial Arts Scroll"
- desc = "This scroll contains the secrets of an ancient martial arts technique. You will master unarmed combat, \
- deflecting all ranged weapon fire, but you also refuse to use dishonorable ranged weaponry."
- item = /obj/item/book/granter/martial/carp
- cost = 17
- surplus = 0
- exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/stealthy_weapons/cqc
- name = "CQC Manual"
- desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing."
- item = /obj/item/book/granter/martial/cqc
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
- cost = 13
- surplus = 0
-
-/datum/uplink_item/stealthy_weapons/throwingweapons
- name = "Box of Throwing Weapons"
- desc = "A box of shurikens and reinforced bolas from ancient Earth martial arts. They are highly effective \
- throwing weapons. The bolas can knock a target down and the shurikens will embed into limbs."
- item = /obj/item/storage/box/syndie_kit/throwing_weapons
- cost = 3
-
-/datum/uplink_item/stealthy_weapons/edagger
- name = "Energy Dagger"
- desc = "A dagger made of energy that looks and functions as a pen when off."
- item = /obj/item/pen/edagger
- cost = 2
-
-/datum/uplink_item/stealthy_weapons/foampistol
- name = "Toy Gun with Riot Darts"
- desc = "An innocent-looking toy pistol designed to fire foam darts. Comes loaded with riot-grade \
- darts effective at incapacitating a target."
- item = /obj/item/gun/ballistic/automatic/toy/pistol/riot
- cost = 3
- surplus = 10
-
-/datum/uplink_item/stealthy_weapons/sleepy_pen
- name = "Sleepy Pen"
- desc = "A syringe disguised as a functional pen, filled with a potent mix of drugs, including a \
- strong anesthetic and a chemical that prevents the target from speaking. \
- The pen holds one dose of the mixture, and can be refilled. Note that before the target \
- falls asleep, they will be able to move and act."
- item = /obj/item/pen/sleepy
- cost = 4
- exclude_modes = list(/datum/game_mode/nuclear)
-
-/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."
- item = /obj/item/soap/syndie
- cost = 1
- surplus = 50
-
-/datum/uplink_item/stealthy_weapons/traitor_chem_bottle
- name = "Poison Kit"
- desc = "An assortment of deadly chemicals packed into a compact box. Comes with a syringe for more precise application."
- item = /obj/item/storage/box/syndie_kit/chemical
- cost = 6
- surplus = 50
-
-/datum/uplink_item/stealthy_weapons/romerol_kit
- name = "Romerol"
- 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
- exclude_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/stealthy_weapons/dart_pistol
- name = "Dart Pistol"
- desc = "A miniaturized version of a normal syringe gun. It is very quiet when fired and can fit into any \
- space a small item can."
- item = /obj/item/gun/syringe/syndicate
- cost = 4
- surplus = 50
-
-/datum/uplink_item/stealthy_weapons/detomatix
- name = "Detomatix PDA Cartridge"
- desc = "When inserted into a personal digital assistant, this cartridge gives you four opportunities to \
- detonate PDAs of crewmembers who have their message feature enabled. \
- The concussive effect from the explosion will knock the recipient out for a short period, and deafen \
- them for longer. Beware, it has a chance to detonate your PDA."
- item = /obj/item/cartridge/virus/syndicate
- cost = 5
- restricted = TRUE
-
-/datum/uplink_item/stealthy_weapons/suppressor
- name = "Universal Suppressor"
- desc = "Fitted for use on any small caliber weapon with a threaded barrel, this suppressor will silence the \
- shots of the weapon for increased stealth and superior ambushing capability."
- item = /obj/item/suppressor
- cost = 1
- surplus = 10
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/stealthy_weapons/pizza_bomb
- name = "Pizza Bomb"
- desc = "A pizza box with a bomb cunningly attached to the lid. The timer needs to be set by opening the box; afterwards, \
- opening the box again will trigger the detonation after the timer has elapsed. Comes with free pizza, for you or your target!"
- item = /obj/item/pizzabox/bomb
- cost = 6
- surplus = 8
-
-/datum/uplink_item/stealthy_weapons/dehy_carp
- name = "Dehydrated Space Carp"
- desc = "Looks like a plush toy carp, but just add water and it becomes a real-life space carp! Activate in \
- your hand before use so it knows not to kill you."
- item = /obj/item/toy/plush/carpplushie/dehy_carp
- cost = 1
-
-/datum/uplink_item/stealthy_weapons/soap_clusterbang
- name = "Slipocalypse Clusterbang"
- desc = "A traditional clusterbang grenade with a payload consisting entirely of Syndicate soap. Useful in any scenario!"
- item = /obj/item/grenade/clusterbuster/soap
- cost = 6
+/datum/uplink_item/support/mauler
+ name = "Mauler Exosuit"
+ desc = "A massive and incredibly deadly military-grade exosuit. Features long-range targeting, thrust vectoring, \
+ and deployable smoke."
+ item = /obj/mecha/combat/marauder/mauler/loaded
+ cost = 140
// Stealth Items
/datum/uplink_item/stealthy_tools
category = "Stealth and Camouflage Items"
+/datum/uplink_item/stealthy_tools/agent_card
+ name = "Agent Identification Card"
+ desc = "Agent cards prevent artificial intelligences from tracking the wearer, and can copy access \
+ from other identification cards. The access is cumulative, so scanning one card does not erase the \
+ access gained from another. In addition, they can be forged to display a new assignment and name. \
+ This can be done an unlimited amount of times. Some Syndicate areas and devices can only be accessed \
+ with these cards."
+ item = /obj/item/card/id/syndicate
+ cost = 2
+
+/datum/uplink_item/stealthy_tools/ai_detector
+ name = "Artificial Intelligence Detector"
+ desc = "A functional multitool that turns red when it detects an artificial intelligence watching it, and can be \
+ activated to display their exact viewing location and nearby security camera blind spots. Knowing when \
+ an artificial intelligence is watching you is useful for knowing when to maintain cover, and finding nearby \
+ blind spots can help you identify escape routes."
+ item = /obj/item/multitool/ai_detect
+ cost = 1
+
/datum/uplink_item/stealthy_tools/chameleon
name = "Chameleon Kit"
desc = "A set of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more!"
@@ -820,6 +1116,46 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 2
exclude_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/stealthy_tools/chameleon_proj
+ name = "Chameleon Projector"
+ desc = "Projects an image across a user, disguising them as an object scanned with it, as long as they don't \
+ move the projector from their hand. Disguised users move slowly, and projectiles pass over them."
+ item = /obj/item/chameleon
+ cost = 7
+
+/datum/uplink_item/stealthy_tools/codespeak_manual
+ name = "Codespeak Manual"
+ desc = "Syndicate agents can be trained to use a series of codewords to convey complex information, which sounds like random concepts and drinks to anyone listening. This manual teaches you this Codespeak. You can also hit someone else with the manual in order to teach them. This is the deluxe edition, which has unlimited used."
+ item = /obj/item/codespeak_manual/unlimited
+ cost = 3
+
+/datum/uplink_item/stealthy_tools/combatbananashoes
+ name = "Combat Banana Shoes"
+ desc = "While making the wearer immune to most slipping attacks like regular combat clown shoes, these shoes \
+ can generate a large number of synthetic banana peels as the wearer walks, slipping up would-be pursuers. They also \
+ squeak significantly louder."
+ item = /obj/item/clothing/shoes/clown_shoes/banana_shoes/combat
+ cost = 6
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/stealthy_tools/emplight
+ name = "EMP Flashlight"
+ desc = "A small, self-charging, short-ranged EMP device disguised as a flashlight. \
+ Useful for disrupting headsets, cameras, and borgs during stealth operations."
+ item = /obj/item/flashlight/emp
+ cost = 2
+ surplus = 30
+
+/datum/uplink_item/stealthy_tools/mulligan
+ name = "Mulligan"
+ desc = "Screwed up and have security on your tail? This handy syringe will give you a completely new identity \
+ and appearance."
+ item = /obj/item/reagent_containers/syringe/mulligan
+ cost = 3
+ surplus = 30
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
/datum/uplink_item/stealthy_tools/syndigaloshes
name = "No-Slip Chameleon Shoes"
desc = "These shoes will allow the wearer to run on wet floors and slippery objects without falling down. \
@@ -835,57 +1171,22 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
exclude_modes = list()
include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/stealthy_tools/combatbananashoes
- name = "Combat Banana Shoes"
- desc = "While making the wearer immune to most slipping attacks like regular combat clown shoes, these shoes \
- can generate a large number of synthetic banana peels as the wearer walks, slipping up would-be pursuers. They also \
- squeak significantly louder."
- item = /obj/item/clothing/shoes/clown_shoes/banana_shoes/combat
- cost = 6
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/stealthy_tools/jammer
+ name = "Radio Jammer"
+ desc = "This device will disrupt any nearby outgoing radio communication when activated."
+ item = /obj/item/jammer
+ cost = 5
-datum/uplink_item/stealthy_tools/taeclowndo_shoes
- name = "Tae-clown-do Shoes"
- desc = "A pair of shoes for the most elite agents of the honkmotherland. They grant the mastery of taeclowndo with some honk-fu moves as long as they're worn."
- cost = 12
- item = /obj/item/clothing/shoes/clown_shoes/taeclowndo
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/stealthy_tools/frame
- name = "F.R.A.M.E. PDA Cartridge"
- desc = "When inserted into a personal digital assistant, this cartridge gives you five PDA viruses which \
- when used cause the targeted PDA to become a new uplink with zero TCs, and immediately become unlocked. \
- You will receive the unlock code upon activating the virus, and the new uplink may be charged with \
- telecrystals normally."
- item = /obj/item/cartridge/virus/frame
- cost = 2
- restricted = TRUE
-
-/datum/uplink_item/stealthy_tools/agent_card
- name = "Agent Identification Card"
- desc = "Agent cards prevent artificial intelligences from tracking the wearer, and can copy access \
- from other identification cards. The access is cumulative, so scanning one card does not erase the \
- access gained from another. In addition, they can be forged to display a new assignment and name. \
- This can be done an unlimited amount of times. Some Syndicate areas and devices can only be accessed \
- with these cards."
- item = /obj/item/card/id/syndicate
- cost = 2
-
-/datum/uplink_item/stealthy_tools/chameleon_proj
- name = "Chameleon Projector"
- desc = "Projects an image across a user, disguising them as an object scanned with it, as long as they don't \
- move the projector from their hand. Disguised users move slowly, and projectiles pass over them."
- item = /obj/item/chameleon
- cost = 7
-
-/datum/uplink_item/stealthy_tools/camera_bug
- name = "Camera Bug"
- desc = "Enables you to view all cameras on the network and track a target. Bugging cameras allows you \
- to disable them remotely."
- item = /obj/item/camera_bug
- cost = 1
- surplus = 90
+/*/datum/uplink_item/stealthy_tools/syndi_borer
+ name = "Syndicate Brain Slug"
+ desc = "A small cortical borer, modified to be completely loyal to the owner. \
+ Genetically infertile, these brain slugs can assist medically in a support role, or take direct action \
+ to assist their host."
+ item = /obj/item/antag_spawner/syndi_borer
+ refundable = TRUE
+ cost = 10
+ surplus = 20 //Let's not have this be too common
+ exclude_modes = list(/datum/game_mode/nuclear) */
/datum/uplink_item/stealthy_tools/smugglersatchel
name = "Smuggler's Satchel"
@@ -896,46 +1197,6 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
cost = 2
surplus = 30
-/datum/uplink_item/stealthy_tools/stimpack
- name = "Stimpack"
- desc = "Stimpacks, the tool of many great heroes, make you nearly immune to stuns and knockdowns for about \
- 5 minutes after injection."
- item = /obj/item/reagent_containers/syringe/stimulants
- cost = 5
- surplus = 90
-
-/datum/uplink_item/stealthy_tools/mulligan
- name = "Mulligan"
- desc = "Screwed up and have security on your tail? This handy syringe will give you a completely new identity \
- and appearance."
- item = /obj/item/reagent_containers/syringe/mulligan
- cost = 3
- surplus = 30
- exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/stealthy_tools/emplight
- name = "EMP Flashlight"
- desc = "A small, self-charging, short-ranged EMP device disguised as a flashlight. \
- Useful for disrupting headsets, cameras, and borgs during stealth operations."
- item = /obj/item/flashlight/emp
- cost = 2
- surplus = 30
-
-/datum/uplink_item/stealthy_tools/cutouts
- name = "Adaptive Cardboard Cutouts"
- desc = "These cardboard cutouts are coated with a thin material that prevents discoloration and makes the images on them appear more lifelike. This pack contains three as well as a \
- crayon for changing their appearances."
- item = /obj/item/storage/box/syndie_kit/cutouts
- cost = 1
- surplus = 20
-
-/datum/uplink_item/stealthy_tools/fakenucleardisk
- name = "Decoy Nuclear Authentication Disk"
- desc = "It's just a normal disk. Visually it's identical to the real deal, but it won't hold up under closer scrutiny by the Captain. Don't try to give this to us to complete your objective, we know better!"
- item = /obj/item/disk/nuclear/fake
- cost = 1
- surplus = 1
-
//Space Suits and Hardsuits
/datum/uplink_item/suits
category = "Space Suits and Hardsuits"
@@ -982,6 +1243,74 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
/datum/uplink_item/device_tools
category = "Devices and Tools"
+/datum/uplink_item/device_tools/cutouts
+ name = "Adaptive Cardboard Cutouts"
+ desc = "These cardboard cutouts are coated with a thin material that prevents discoloration and makes the images on them appear more lifelike. This pack contains three as well as a \
+ crayon for changing their appearances."
+ item = /obj/item/storage/box/syndie_kit/cutouts
+ cost = 1
+ surplus = 20
+
+/datum/uplink_item/device_tools/assault_pod
+ name = "Assault Pod Targeting Device"
+ desc = "Use to select the landing zone of your assault pod."
+ item = /obj/item/assault_pod
+ cost = 30
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+ restricted = TRUE
+
+/datum/uplink_item/device_tools/binary
+ name = "Binary Translator Key"
+ desc = "A key that, when inserted into a radio headset, allows you to listen to and talk with silicon-based lifeforms, \
+ such as AI units and cyborgs, over their private binary channel. Caution should \
+ be taken while doing this, as unless they are allied with you, they are programmed to report such intrusions."
+ item = /obj/item/encryptionkey/binary
+ cost = 2
+ surplus = 75
+ restricted = TRUE
+
+/datum/uplink_item/device_tools/magboots
+ name = "Blood-Red Magboots"
+ desc = "A pair of magnetic boots with a Syndicate paintjob that assist with freer movement in space or on-station \
+ during gravitational generator failures. These reverse-engineered knockoffs of Nanotrasen's \
+ 'Advanced Magboots' slow you down in simulated-gravity environments much like the standard issue variety."
+ item = /obj/item/clothing/shoes/magboots/syndie
+ cost = 2
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
+/datum/uplink_item/device_tools/compressionkit
+ name = "Bluespace Compression Kit"
+ desc = "A modified version of a BSRPED that can be used to reduce the size of most items while retaining their original functions! \
+ Does not work on storage items. \
+ Recharge using bluespace crystals. \
+ Comes with 5 charges."
+ item = /obj/item/compressionkit
+ cost = 5
+
+/datum/uplink_item/device_tools/briefcase_launchpad
+ name = "Briefcase Launchpad"
+ desc = "A briefcase containing a launchpad, a device able to teleport items and people to and from targets up to twenty tiles away from the briefcase. \
+ Also includes a remote control, disguised as an ordinary folder. Touch the briefcase with the remote to link it."
+ surplus = 0
+ item = /obj/item/storage/briefcase/launchpad
+ cost = 6
+
+/datum/uplink_item/device_tools/camera_bug
+ name = "Camera Bug"
+ desc = "Enables you to view all cameras on the network and track a target. Bugging cameras allows you \
+ to disable them remotely."
+ item = /obj/item/camera_bug
+ cost = 1
+ surplus = 90
+
+/datum/uplink_item/device_tools/military_belt
+ name = "Chest Rig"
+ desc = "A robust seven-slot set of webbing that is capable of holding all manner of tactical equipment."
+ item = /obj/item/storage/belt/military
+ cost = 1
+ exclude_modes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/device_tools/emag
name = "Cryptographic Sequencer"
desc = "The cryptographic sequencer, electromagnetic card, or emag, is a small card that unlocks hidden functions \
@@ -989,6 +1318,29 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
item = /obj/item/card/emag
cost = 6
+/datum/uplink_item/device_tools/emagrecharge
+ name = "Electromagnet Charging Device"
+ desc = "A small device intended for recharging Cryptographic Sequencers. Using it will add five extra charges to the Cryptographic Sequencer."
+ item = /obj/item/emagrecharge
+ cost = 2
+
+/datum/uplink_item/device_tools/fakenucleardisk
+ name = "Decoy Nuclear Authentication Disk"
+ desc = "It's just a normal disk. Visually it's identical to the real deal, but it won't hold up under closer scrutiny by the Captain. Don't try to give this to us to complete your objective, we know better!"
+ item = /obj/item/disk/nuclear/fake
+ cost = 1
+ surplus = 1
+
+/datum/uplink_item/device_tools/frame
+ name = "F.R.A.M.E. PDA Cartridge"
+ desc = "When inserted into a personal digital assistant, this cartridge gives you five PDA viruses which \
+ when used cause the targeted PDA to become a new uplink with zero TCs, and immediately become unlocked. \
+ You will receive the unlock code upon activating the virus, and the new uplink may be charged with \
+ telecrystals normally."
+ item = /obj/item/cartridge/virus/frame
+ cost = 2
+ restricted = TRUE
+
/datum/uplink_item/device_tools/toolbox
name = "Full Syndicate Toolbox"
desc = "The syndicate toolbox is a suspicious black and red. It comes loaded with a full tool set including a \
@@ -996,12 +1348,28 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
item = /obj/item/storage/toolbox/syndicate
cost = 1
-/datum/uplink_item/device_tools/surgerybag
- name = "Syndicate Surgery Duffel Bag"
- desc = "The Syndicate surgery duffel bag is a toolkit containing all surgery tools, surgical drapes, \
- a Syndicate brand MMI, a straitjacket, and a muzzle."
- item = /obj/item/storage/backpack/duffelbag/syndie/surgery
- cost = 3
+/datum/uplink_item/device_tools/syndie_glue
+ name = "Glue"
+ desc = "A cheap bottle of one use syndicate brand super glue. \
+ Use on any item to make it undroppable. \
+ Be careful not to glue an item you're already holding!"
+ item = /obj/item/syndie_glue
+ cost = 2
+
+/datum/uplink_item/device_tools/hacked_module
+ name = "Hacked AI Law Upload Module"
+ desc = "When used with an upload console, this module allows you to upload priority laws to an artificial intelligence. \
+ Be careful with wording, as artificial intelligences may look for loopholes to exploit."
+ item = /obj/item/aiModule/syndicate
+ cost = 9
+
+/datum/uplink_item/device_tools/medgun
+ name = "Medbeam Gun"
+ desc = "A wonder of Syndicate engineering, the Medbeam gun, or Medi-Gun enables a medic to keep his fellow \
+ operatives in the fight, even while under fire."
+ item = /obj/item/gun/medbeam
+ cost = 15
+ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
/datum/uplink_item/device_tools/nutcracker
name = "Nutcracker"
@@ -1009,19 +1377,39 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
item = /obj/item/nutcracker
cost = 1
-/datum/uplink_item/device_tools/surgerybag_adv
- name = "Advanced Syndicate Surgery Duffel Bag"
- desc = "The Syndicate surgery duffel bag is a toolkit containing all newest surgery tools, surgical drapes, \
- a Syndicate brand MMI, a straitjacket, a muzzle, and a full Syndicate Combat Medic Kit."
- item = /obj/item/storage/backpack/duffelbag/syndie/surgery_adv
- cost = 10
+/datum/uplink_item/device_tools/singularity_beacon
+ name = "Power Beacon"
+ desc = "When screwed to wiring attached to an electric grid and activated, this large device pulls any \
+ active gravitational singularities or tesla balls towards it. This will not work when the engine is still \
+ in containment. Because of its size, it cannot be carried. Ordering this \
+ sends you a small beacon that will teleport the larger beacon to your location upon activation."
+ item = /obj/item/sbeacondrop
+ cost = 14
-/datum/uplink_item/device_tools/military_belt
- name = "Chest Rig"
- desc = "A robust seven-slot set of webbing that is capable of holding all manner of tactical equipment."
- item = /obj/item/storage/belt/military
- cost = 1
- exclude_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/device_tools/powersink
+ name = "Power Sink"
+ desc = "When screwed to wiring attached to a power grid and activated, this large device places excessive \
+ load on the grid, causing a station-wide blackout. The sink is large and cannot be stored in most \
+ traditional bags and boxes."
+ item = /obj/item/powersink
+ cost = 6
+
+/datum/uplink_item/device_tools/rad_laser
+ name = "Radioactive Microlaser"
+ desc = "A radioactive microlaser disguised as a standard Nanotrasen health analyzer. When used, it emits a \
+ powerful burst of radiation, which, after a short delay, can incapacitate all but the most protected \
+ of humanoids. It has two settings: intensity, which controls the power of the radiation, \
+ and wavelength, which controls how long the radiation delay is."
+ item = /obj/item/healthanalyzer/rad_laser
+ cost = 3
+
+/datum/uplink_item/device_tools/stimpack
+ name = "Stimpack"
+ desc = "Stimpacks, the tool of many great heroes, make you nearly immune to stuns and knockdowns for about \
+ 5 minutes after injection."
+ item = /obj/item/reagent_containers/syringe/stimulants
+ cost = 5
+ surplus = 90
/datum/uplink_item/device_tools/medkit
name = "Syndicate Combat Medic Kit"
@@ -1032,6 +1420,29 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
cost = 4
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/device_tools/surgerybag
+ name = "Syndicate Surgery Duffel Bag"
+ desc = "The Syndicate surgery duffel bag is a toolkit containing all surgery tools, surgical drapes, \
+ a Syndicate brand MMI, a straitjacket, and a muzzle."
+ item = /obj/item/storage/backpack/duffelbag/syndie/surgery
+ cost = 3
+
+/datum/uplink_item/device_tools/surgerybag_adv
+ name = "Advanced Syndicate Surgery Duffel Bag"
+ desc = "The Syndicate surgery duffel bag is a toolkit containing all newest surgery tools, surgical drapes, \
+ a Syndicate brand MMI, a straitjacket, a muzzle, and a full Syndicate Combat Medic Kit."
+ item = /obj/item/storage/backpack/duffelbag/syndie/surgery_adv
+ cost = 10
+
+/datum/uplink_item/device_tools/encryptionkey
+ name = "Syndicate Encryption Key"
+ desc = "A key that, when inserted into a radio headset, allows you to listen to all station department channels \
+ as well as talk on an encrypted Syndicate channel with other agents that have the same key."
+ item = /obj/item/encryptionkey/syndicate
+ cost = 2
+ surplus = 75
+ restricted = TRUE
+
/datum/uplink_item/device_tools/syndietome
name = "Syndicate Tome"
desc = "Using rare artifacts acquired at great cost, the syndicate has reverse engineered \
@@ -1050,175 +1461,6 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
item = /obj/item/clothing/glasses/thermal/syndi
cost = 4
-/datum/uplink_item/device_tools/binary
- name = "Binary Translator Key"
- desc = "A key that, when inserted into a radio headset, allows you to listen to and talk with silicon-based lifeforms, \
- such as AI units and cyborgs, over their private binary channel. Caution should \
- be taken while doing this, as unless they are allied with you, they are programmed to report such intrusions."
- item = /obj/item/encryptionkey/binary
- cost = 2
- surplus = 75
- restricted = TRUE
-
-/datum/uplink_item/device_tools/encryptionkey
- name = "Syndicate Encryption Key"
- desc = "A key that, when inserted into a radio headset, allows you to listen to all station department channels \
- as well as talk on an encrypted Syndicate channel with other agents that have the same key."
- item = /obj/item/encryptionkey/syndicate
- cost = 2
- surplus = 75
- restricted = TRUE
-
-/datum/uplink_item/device_tools/ai_detector
- name = "Artificial Intelligence Detector"
- desc = "A functional multitool that turns red when it detects an artificial intelligence watching it, and can be \
- activated to display their exact viewing location and nearby security camera blind spots. Knowing when \
- an artificial intelligence is watching you is useful for knowing when to maintain cover, and finding nearby \
- blind spots can help you identify escape routes."
- item = /obj/item/multitool/ai_detect
- cost = 1
-
-/datum/uplink_item/device_tools/hacked_module
- name = "Hacked AI Law Upload Module"
- desc = "When used with an upload console, this module allows you to upload priority laws to an artificial intelligence. \
- Be careful with wording, as artificial intelligences may look for loopholes to exploit."
- item = /obj/item/aiModule/syndicate
- cost = 9
-
-/datum/uplink_item/device_tools/briefcase_launchpad
- name = "Briefcase Launchpad"
- desc = "A briefcase containing a launchpad, a device able to teleport items and people to and from targets up to twenty tiles away from the briefcase. \
- Also includes a remote control, disguised as an ordinary folder. Touch the briefcase with the remote to link it."
- surplus = 0
- item = /obj/item/storage/briefcase/launchpad
- cost = 6
-
-/datum/uplink_item/device_tools/magboots
- name = "Blood-Red Magboots"
- desc = "A pair of magnetic boots with a Syndicate paintjob that assist with freer movement in space or on-station \
- during gravitational generator failures. These reverse-engineered knockoffs of Nanotrasen's \
- 'Advanced Magboots' slow you down in simulated-gravity environments much like the standard issue variety."
- item = /obj/item/clothing/shoes/magboots/syndie
- cost = 2
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/device_tools/c4
- name = "Composition C-4"
- desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls, sabotage equipment, or connect \
- an assembly to it in order to alter the way it detonates. It has a modifiable timer with a \
- minimum setting of 10 seconds."
- item = /obj/item/grenade/plastic/c4
- cost = 1
-
-/datum/uplink_item/device_tools/c4bag
- name = "Bag of C-4 explosives"
- desc = "Because sometimes quantity is quality. Contains 10 C-4 plastic explosives."
- item = /obj/item/storage/backpack/duffelbag/syndie/c4
- cost = 9 //10% discount!
- cant_discount = TRUE
-
-/datum/uplink_item/device_tools/x4bag
- name = "Bag of X-4 explosives"
- desc = "Contains 3 X-4 plastic explosives. Similar, but more powerful than C-4. X-4 can be placed on a solid surface, such as a wall or window, and it will \
- blast through the wall, injuring anything on the opposite side, while being safer to the user. For when you want a wider, deeper, hole."
- item = /obj/item/storage/backpack/duffelbag/syndie/x4
- cost = 4 //
- cant_discount = TRUE
-
-/datum/uplink_item/device_tools/powersink
- name = "Power Sink"
- desc = "When screwed to wiring attached to a power grid and activated, this large device places excessive \
- load on the grid, causing a station-wide blackout. The sink is large and cannot be stored in most \
- traditional bags and boxes."
- item = /obj/item/powersink
- cost = 6
-
-/datum/uplink_item/device_tools/singularity_beacon
- name = "Power Beacon"
- desc = "When screwed to wiring attached to an electric grid and activated, this large device pulls any \
- active gravitational singularities or tesla balls towards it. This will not work when the engine is still \
- in containment. Because of its size, it cannot be carried. Ordering this \
- sends you a small beacon that will teleport the larger beacon to your location upon activation."
- item = /obj/item/sbeacondrop
- cost = 14
-
-/datum/uplink_item/device_tools/syndicate_bomb
- name = "Syndicate Bomb"
- desc = "The Syndicate bomb is a fearsome device capable of massive destruction. It has an adjustable timer, \
- with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \
- movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \
- transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \
- be defused, and some crew may attempt to do so."
- item = /obj/item/sbeacondrop/bomb
- cost = 11
-
-/datum/uplink_item/device_tools/clown_bomb_clownops
- name = "Clown Bomb"
- desc = "The Clown bomb is a hilarious device capable of massive pranks. It has an adjustable timer, \
- with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \
- movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \
- transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \
- be defused, and some crew may attempt to do so."
- item = /obj/item/sbeacondrop/clownbomb
- cost = 15
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/device_tools/syndicate_detonator
- name = "Syndicate Detonator"
- desc = "The Syndicate detonator is a companion device to the Syndicate bomb. Simply press the included button \
- and an encrypted radio frequency will instruct all live Syndicate bombs to detonate. \
- Useful for when speed matters or you wish to synchronize multiple bomb blasts. Be sure to stand clear of \
- the blast radius before using the detonator."
- item = /obj/item/syndicatedetonator
- cost = 3
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/device_tools/rad_laser
- name = "Radioactive Microlaser"
- desc = "A radioactive microlaser disguised as a standard Nanotrasen health analyzer. When used, it emits a \
- powerful burst of radiation, which, after a short delay, can incapacitate all but the most protected \
- of humanoids. It has two settings: intensity, which controls the power of the radiation, \
- and wavelength, which controls how long the radiation delay is."
- item = /obj/item/healthanalyzer/rad_laser
- cost = 3
-
-/datum/uplink_item/device_tools/assault_pod
- name = "Assault Pod Targeting Device"
- desc = "Use to select the landing zone of your assault pod."
- item = /obj/item/assault_pod
- cost = 30
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
- restricted = TRUE
-
-/datum/uplink_item/device_tools/shield
- name = "Energy Shield"
- desc = "An incredibly useful personal shield projector, capable of reflecting energy projectiles and defending \
- against other attacks. Pair with an Energy Sword for a killer combination."
- item = /obj/item/shield/energy
- cost = 16
- surplus = 20
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/device_tools/bananashield
- name = "Bananium Energy Shield"
- desc = "A clown's most powerful defensive weapon, this personal shield provides near immunity to ranged energy attacks \
- by bouncing them back at the ones who fired them. It can also be thrown to bounce off of people, slipping them, \
- and returning to you even if you miss. WARNING: DO NOT ATTEMPT TO STAND ON SHIELD WHILE DEPLOYED, EVEN IF WEARING ANTI-SLIP SHOES."
- item = /obj/item/shield/energy/bananium
- cost = 16
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear/clown_ops)
-
-/datum/uplink_item/device_tools/medgun
- name = "Medbeam Gun"
- desc = "A wonder of Syndicate engineering, the Medbeam gun, or Medi-Gun enables a medic to keep his fellow \
- operatives in the fight, even while under fire."
- item = /obj/item/gun/medbeam
- cost = 15
- include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-
/datum/uplink_item/device_tools/potion
name = "Syndicate Sentience Potion"
item = /obj/item/slimepotion/slime/sentience/nuclear
@@ -1227,79 +1469,12 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
restricted = TRUE
-/datum/uplink_item/device_tools/telecrystal
- name = "Raw Telecrystal"
- desc = "A telecrystal in its rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
- item = /obj/item/stack/telecrystal
- cost = 1
- surplus = 0
- cant_discount = TRUE
- // Don't add telecrystals to the purchase_log since
- // it's just used to buy more items (including itself!)
- purchase_log_vis = FALSE
-
-/datum/uplink_item/device_tools/telecrystal/five
- name = "5 Raw Telecrystals"
- desc = "Five telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
- item = /obj/item/stack/telecrystal/five
- cost = 5
-
-/datum/uplink_item/device_tools/telecrystal/twenty
- name = "20 Raw Telecrystals"
- desc = "Twenty telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
- item = /obj/item/stack/telecrystal/twenty
- cost = 20
-
-/datum/uplink_item/device_tools/jammer
- name = "Radio Jammer"
- desc = "This device will disrupt any nearby outgoing radio communication when activated."
- item = /obj/item/jammer
- cost = 5
-
-/datum/uplink_item/device_tools/codespeak_manual
- name = "Codespeak Manual"
- desc = "Syndicate agents can be trained to use a series of codewords to convey complex information, which sounds like random concepts and drinks to anyone listening. This manual teaches you this Codespeak. You can also hit someone else with the manual in order to teach them. This is the deluxe edition, which has unlimited used."
- item = /obj/item/codespeak_manual/unlimited
- cost = 3
-
-/datum/uplink_item/device_tools/compressionkit
- name = "Bluespace Compression Kit"
- desc = "A modified version of a BSRPED that can be used to reduce the size of most items while retaining their original functions! \
- Does not work on storage items. \
- Recharge using bluespace crystals. \
- Comes with 5 charges."
- item = /obj/item/compressionkit
- cost = 5
-
-/datum/uplink_item/device_tools/syndie_glue
- name = "Glue"
- desc = "A cheap bottle of one use syndicate brand super glue. \
- Use on any item to make it undroppable. \
- Be careful not to glue an item you're already holding!"
- item = /obj/item/syndie_glue
- cost = 2
// Implants
/datum/uplink_item/implants
category = "Implants"
surplus = 50
-/datum/uplink_item/implants/freedom
- name = "Freedom Implant"
- desc = "An implant injected into the body and later activated at the user's will. It will attempt to free the \
- user from common restraints such as handcuffs."
- item = /obj/item/storage/box/syndie_kit/imp_freedom
- cost = 5
-
-/datum/uplink_item/implants/uplink
- name = "Uplink Implant"
- desc = "An implant injected into the body, and later activated at the user's will. Has no telecrystals, must be charged by the use of physical telecrystals. Undetectable (except via surgery), and excellent for escaping confinement."
- item = /obj/item/storage/box/syndie_kit/imp_uplink
- cost = 4
- // An empty uplink is kinda useless.
- surplus = 0
- restricted = TRUE
-
/datum/uplink_item/implants/adrenal
name = "Adrenal Implant"
desc = "An implant injected into the body, and later activated at the user's will. It will inject a chemical \
@@ -1308,12 +1483,19 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
cost = 8
player_minimum = 25
-/datum/uplink_item/implants/storage
- name = "Storage Implant"
- desc = "An implant injected into the body, and later activated at the user's will. It will open a small bluespace \
- pocket capable of storing two items."
- item = /obj/item/storage/box/syndie_kit/imp_storage
- cost = 8
+/datum/uplink_item/implants/antistun
+ name = "CNS Rebooter Implant"
+ desc = "This implant will help you get back up on your feet faster after being stunned. Comes with an autosurgeon."
+ item = /obj/item/autosurgeon/anti_stun
+ cost = 12
+ include_modes = list(/datum/game_mode/nuclear)
+
+/datum/uplink_item/implants/freedom
+ name = "Freedom Implant"
+ desc = "An implant injected into the body and later activated at the user's will. It will attempt to free the \
+ user from common restraints such as handcuffs."
+ item = /obj/item/storage/box/syndie_kit/imp_freedom
+ cost = 5
/datum/uplink_item/implants/microbomb
name = "Microbomb Implant"
@@ -1340,48 +1522,49 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
cost = 4
restricted = TRUE
+/datum/uplink_item/implants/reviver
+ name = "Reviver Implant"
+ desc = "This implant will attempt to revive you if you lose consciousness. Comes with an autosurgeon."
+ item = /obj/item/autosurgeon/reviver
+ cost = 8
+ include_modes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/implants/stealthimplant
name = "Stealth Implant"
desc = "This one-of-a-kind implant will make you almost invisible if you play your cards right."
item = /obj/item/implanter/stealth
cost = 8
-// Cybernetics
-/datum/uplink_item/cyber_implants
- category = "Cybernetic Implants"
- surplus = 0
- include_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/implants/storage
+ name = "Storage Implant"
+ desc = "An implant injected into the body, and later activated at the user's will. It will open a small bluespace \
+ pocket capable of storing two items."
+ item = /obj/item/storage/box/syndie_kit/imp_storage
+ cost = 8
-/datum/uplink_item/cyber_implants/thermals
+/datum/uplink_item/implants/thermals
name = "Thermal Eyes"
desc = "These cybernetic eyes will give you thermal vision. Comes with a free autosurgeon."
item = /obj/item/autosurgeon/thermal_eyes
cost = 8
+ include_modes = list(/datum/game_mode/nuclear)
-/datum/uplink_item/cyber_implants/xray
+/datum/uplink_item/implants/uplink
+ name = "Uplink Implant"
+ desc = "An implant injected into the body, and later activated at the user's will. Has no telecrystals, must be charged by the use of physical telecrystals. Undetectable (except via surgery), and excellent for escaping confinement."
+ item = /obj/item/storage/box/syndie_kit/imp_uplink
+ cost = 4
+ // An empty uplink is kinda useless.
+ surplus = 0
+ restricted = TRUE
+
+/datum/uplink_item/implants/xray
name = "X-ray Vision Implant"
desc = "These cybernetic eyes will give you X-ray vision. Comes with an autosurgeon."
item = /obj/item/autosurgeon/xray_eyes
cost = 10
-
-/datum/uplink_item/cyber_implants/antistun
- name = "CNS Rebooter Implant"
- desc = "This implant will help you get back up on your feet faster after being stunned. Comes with an autosurgeon."
- item = /obj/item/autosurgeon/anti_stun
- cost = 12
-
-/datum/uplink_item/cyber_implants/reviver
- name = "Reviver Implant"
- desc = "This implant will attempt to revive you if you lose consciousness. Comes with an autosurgeon."
- item = /obj/item/autosurgeon/reviver
- cost = 8
-
-/datum/uplink_item/cyber_implants/bundle
- name = "Cybernetic Implants Bundle"
- desc = "A random selection of cybernetic implants. Guaranteed 5 high quality implants. Comes with an autosurgeon."
- item = /obj/item/storage/box/cyber_implants
- cost = 40
- cant_discount = TRUE
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear)
// Role-specific items
/datum/uplink_item/role_restricted
@@ -1389,23 +1572,62 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
surplus = 0
-/datum/uplink_item/role_restricted/reverse_revolver
- name = "Reverse Revolver"
- desc = "A revolver that always fires at its user. \"Accidentally\" drop your weapon, then watch as the greedy corporate pigs blow their own brains all over the wall. \
- The revolver itself is actually real. Only clumsy people, and clowns, can fire it normally. Comes in a box of hugs. Honk."
- cost = 14
- item = /obj/item/storage/box/hug/reverse_revolver
+/datum/uplink_item/role_restricted/ancient_jumpsuit
+ name = "Ancient Jumpsuit"
+ desc = "A tattered old jumpsuit that will provide absolutely no benefit to you. It fills the wearer with a strange compulsion to blurt out 'glorf'."
+ item = /obj/item/clothing/under/color/grey/glorf
+ cost = 20
+ restricted_roles = list("Assistant")
+
+/datum/uplink_item/role_restricted/pie_cannon
+ name = "Banana Cream Pie Cannon"
+ desc = "A special pie cannon for a special clown, this gadget can hold up to 20 pies and automatically fabricates one every two seconds!"
+ cost = 10
+ item = /obj/item/pneumatic_cannon/pie/selfcharge
restricted_roles = list("Clown")
-/datum/uplink_item/role_restricted/reverse_bear_trap
- name = "Reverse Bear Trap"
- desc = "An ingenious execution device worn on (or forced onto) the head. Arming it starts a 1-minute kitchen timer mounted on the bear trap. When it goes off, the trap's jaws will \
- violently open, instantly killing anyone wearing it by tearing their jaws in half. To arm, attack someone with it while they're not wearing headgear, and you will force it onto their \
- head after three seconds uninterrupted."
- cost = 5
- item = /obj/item/reverse_bear_trap
+/datum/uplink_item/role_restricted/blastcannon
+ name = "Blast Cannon"
+ desc = "A highly specialized weapon, the Blast Cannon is actually relatively simple. It contains an attachment for a tank transfer valve mounted to an angled pipe specially constructed \
+ withstand extreme pressure and temperatures, and has a mechanical trigger for triggering the transfer valve. Essentially, it turns the explosive force of a bomb into a narrow-angle \
+ blast wave \"projectile\". Aspiring scientists may find this highly useful, as forcing the pressure shockwave into a narrow angle seems to be able to bypass whatever quirk of physics \
+ disallows explosive ranges above a certain distance, allowing for the device to use the theoretical yield of a transfer valve bomb, instead of the factual yield."
+ item = /obj/item/gun/blastcannon
+ cost = 14 //High cost because of the potential for extreme damage in the hands of a skilled gas masked scientist.
+ restricted_roles = list("Research Director", "Scientist")
+
+/datum/uplink_item/role_restricted/brainwash_disk
+ name = "Brainwashing Surgery Program"
+ desc = "A disk containing the procedure to perform a brainwashing surgery, allowing you to implant an objective onto a target. \
+ Insert into an Operating Console to enable the procedure."
+ item = /obj/item/disk/surgery/brainwashing
+ restricted_roles = list("Medical Doctor")
+ cost = 3
+
+/datum/uplink_item/role_restricted/clown_bomb
+ name = "Clown Bomb"
+ desc = "The Clown bomb is a hilarious device capable of massive pranks. It has an adjustable timer, \
+ with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \
+ movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \
+ transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \
+ be defused, and some crew may attempt to do so."
+ item = /obj/item/sbeacondrop/clownbomb
+ cost = 15
restricted_roles = list("Clown")
+/*
+/datum/uplink_item/role_restricted/clowncar
+ name = "Clown Car"
+ desc = "The Clown Car is the ultimate transportation method for any worthy clown! \
+ Simply insert your bikehorn and get in, and get ready to have the funniest ride of your life! \
+ You can ram any spacemen you come across and stuff them into your car, kidnapping them and locking them inside until \
+ someone saves them or they manage to crawl out. Be sure not to ram into any walls or vending machines, as the springloaded seats \
+ are very sensetive. Now with our included lube defense mechanism which will protect you against any angry shitcurity!"
+ item = /obj/vehicle/sealed/car/clowncar
+ cost = 15
+ restricted_roles = list("Clown")
+*/
+
/datum/uplink_item/role_restricted/clumsyDNA
name = "Clumsy Clown DNA"
desc = "A DNA injector that has been loaded with the clown gene that makes people clumsy.. \
@@ -1414,19 +1636,31 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
item = /obj/item/dnainjector/clumsymut
restricted_roles = list("Clown")
-/datum/uplink_item/role_restricted/taeclowndo_shoes
- name = "Tae-clown-do Shoes"
- desc = "A pair of shoes for the most elite agents of the honkmotherland. They grant the mastery of taeclowndo with some honk-fu moves as long as they're worn."
- cost = 14
- item = /obj/item/clothing/shoes/clown_shoes/taeclowndo
- restricted_roles = list("Clown")
+/datum/uplink_item/role_restricted/haunted_magic_eightball
+ name = "Haunted Magic Eightball"
+ desc = "Most magic eightballs are toys with dice inside. Although identical in appearance to the harmless toys, this occult device reaches into the spirit world to find its answers. Be warned, that spirits are often capricious or just little assholes. To use, simply speak your question aloud, then begin shaking."
+ item = /obj/item/toy/eightball/haunted
+ cost = 2
+ restricted_roles = list("Curator")
+ limited_stock = 1 //please don't spam deadchat
-/datum/uplink_item/role_restricted/mimery
- name = "Guide to Advanced Mimery Series"
- desc = "The classical two part series on how to further hone your mime skills. Upon studying the series, the user should be able to make 3x1 invisible walls, and shoot bullets out of their fingers. Obviously only works for Mimes."
- cost = 12
- item = /obj/item/storage/box/syndie_kit/mimery
- restricted_roles = list("Mime")
+/datum/uplink_item/role_restricted/his_grace
+ name = "His Grace"
+ desc = "An incredibly dangerous weapon recovered from a station overcome by the grey tide. Once activated, He will thirst for blood and must be used to kill to sate that thirst. \
+ His Grace grants gradual regeneration and complete stun immunity to His wielder, but be wary: if He gets too hungry, He will become impossible to drop and eventually kill you if not fed. \
+ However, if left alone for long enough, He will fall back to slumber. \
+ To activate His Grace, simply unlatch Him."
+ item = /obj/item/his_grace
+ cost = 20
+ restricted_roles = list("Chaplain")
+ surplus = 5 //Very low chance to get it in a surplus crate even without being the chaplain
+
+/datum/uplink_item/role_restricted/explosive_hot_potato
+ name = "Exploding Hot Potato"
+ desc = "A potato rigged with explosives. On activation, a special mechanism is activated that prevents it from being dropped. The only way to get rid of it if you are holding it is to attack someone else with it, causing it to latch to that person instead."
+ item = /obj/item/hot_potato/syndicate
+ cost = 4
+ restricted_roles = list("Cook", "Botanist", "Clown", "Mime")
/datum/uplink_item/role_restricted/ez_clean_bundle
name = "EZ Clean Grenade Bundle"
@@ -1436,6 +1670,36 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
surplus = 20
restricted_roles = list("Janitor")
+/datum/uplink_item/role_restricted/goldenbox
+ name = "Gold Toolbox"
+ desc = "A gold planted plastitanium toolbox loaded with tools. Comes with a set of AI detection multi-tool and a pare of combat gloves."
+ item = /obj/item/storage/toolbox/gold_real
+ cost = 3 // Has syndie tools + gloves + a robust weapon
+ restricted_roles = list("Assistant", "Curator") //Curator due to this being made of gold - It fits the theme
+
+/datum/uplink_item/role_restricted/mimery
+ name = "Guide to Advanced Mimery Series"
+ desc = "The classical two part series on how to further hone your mime skills. Upon studying the series, the user should be able to make 3x1 invisible walls, and shoot bullets out of their fingers. Obviously only works for Mimes."
+ cost = 12
+ item = /obj/item/storage/box/syndie_kit/mimery
+ restricted_roles = list("Mime")
+
+/datum/uplink_item/role_restricted/ultrahonkpins
+ name = "Hilarious firing pin"
+ desc = "A single firing pin made for Clown agents, this firing pin makes any gun honk when fired if not a true clown! \
+ This firing pin also helps you fire the gun correctly. May the HonkMother HONK you agent."
+ item = /obj/item/firing_pin/clown/ultra
+ cost = 2
+ restricted_roles = list("Clown")
+
+/datum/uplink_item/role_restricted/pressure_mod
+ name = "Kinetic Accelerator Pressure Mod"
+ desc = "A modification kit which allows Kinetic Accelerators to do greatly increased damage while indoors. Occupies 35% mod capacity."
+ item = /obj/item/borg/upgrade/modkit/indoors
+ cost = 5 //you need two for full damage, so total of 10 for maximum damage
+ limited_stock = 2 //you can't use more than two!
+ restricted_roles = list("Shaft Miner")
+
/datum/uplink_item/role_restricted/kitchen_gun
name = "Kitchen Gun (TM)"
desc = "A revolutionary .45 caliber cleaning solution! Say goodbye to daily stains and dirty surfaces with Kitchen Gun (TM)! Just five shots from Kitchen Gun (TM), and it'll sparkle like new! Includes two extra ammunition clips!"
@@ -1451,60 +1715,12 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
restricted_roles = list("Cook", "Janitor")
item = /obj/item/ammo_box/magazine/m45/kitchengun
-/datum/uplink_item/role_restricted/explosive_hot_potato
- name = "Exploding Hot Potato"
- desc = "A potato rigged with explosives. On activation, a special mechanism is activated that prevents it from being dropped. The only way to get rid of it if you are holding it is to attack someone else with it, causing it to latch to that person instead."
- item = /obj/item/hot_potato/syndicate
- cost = 4
- restricted_roles = list("Cook", "Botanist", "Clown", "Mime")
-
-/datum/uplink_item/role_restricted/his_grace
- name = "His Grace"
- desc = "An incredibly dangerous weapon recovered from a station overcome by the grey tide. Once activated, He will thirst for blood and must be used to kill to sate that thirst. \
- His Grace grants gradual regeneration and complete stun immunity to His wielder, but be wary: if He gets too hungry, He will become impossible to drop and eventually kill you if not fed. \
- However, if left alone for long enough, He will fall back to slumber. \
- To activate His Grace, simply unlatch Him."
- item = /obj/item/his_grace
- cost = 20
- restricted_roles = list("Chaplain")
- surplus = 5 //Very low chance to get it in a surplus crate even without being the chaplain
-
-/datum/uplink_item/role_restricted/pie_cannon
- name = "Banana Cream Pie Cannon"
- desc = "A special pie cannon for a special clown, this gadget can hold up to 20 pies and automatically fabricates one every two seconds!"
- cost = 10
- item = /obj/item/pneumatic_cannon/pie/selfcharge
- restricted_roles = list("Clown")
-
-/datum/uplink_item/role_restricted/ancient_jumpsuit
- name = "Ancient Jumpsuit"
- desc = "A tattered old jumpsuit that will provide absolutely no benefit to you. It fills the wearer with a strange compulsion to blurt out 'glorf'."
- item = /obj/item/clothing/under/color/grey/glorf
- cost = 20
- restricted_roles = list("Assistant")
-
-/datum/uplink_item/role_restricted/goldenbox
- name = "Gold Toolbox"
- desc = "A gold planted plastitanium toolbox loaded with tools. Comes with a set of AI detection multi-tool and a pare of combat gloves."
- item = /obj/item/storage/toolbox/gold_real
- cost = 3 // Has synda tools + gloves + a robust weapon
- restricted_roles = list("Assistant", "Curator") //Curator do to being made of gold - It fits the theme
-
-/datum/uplink_item/role_restricted/brainwash_disk
- name = "Brainwashing Surgery Program"
- desc = "A disk containing the procedure to perform a brainwashing surgery, allowing you to implant an objective onto a target. \
- Insert into an Operating Console to enable the procedure."
- item = /obj/item/disk/surgery/brainwashing
- restricted_roles = list("Medical Doctor")
- cost = 3
-
-/datum/uplink_item/role_restricted/haunted_magic_eightball
- name = "Haunted Magic Eightball"
- desc = "Most magic eightballs are toys with dice inside. Although identical in appearance to the harmless toys, this occult device reaches into the spirit world to find its answers. Be warned, that spirits are often capricious or just little assholes. To use, simply speak your question aloud, then begin shaking."
- item = /obj/item/toy/eightball/haunted
- cost = 2
- restricted_roles = list("Curator")
- limited_stock = 1 //please don't spam deadchat
+/datum/uplink_item/role_restricted/magillitis_serum
+ name = "Magillitis Serum Autoinjector"
+ desc = "A single-use autoinjector which contains an experimental serum that causes rapid muscular growth in Hominidae. Side-affects may include hypertrichosis, violent outbursts, and an unending affinity for bananas."
+ item = /obj/item/reagent_containers/hypospray/magillitis
+ cost = 15
+ restricted_roles = list("Geneticist", "Chief Medical Officer")
/datum/uplink_item/role_restricted/modified_syringe_gun
name = "Modified Syringe Gun"
@@ -1520,106 +1736,41 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
cost = 12
restricted_roles = list("Chemist", "Chief Medical Officer")
-/datum/uplink_item/role_restricted/magillitis_serum
- name = "Magillitis Serum Autoinjector"
- desc = "A single-use autoinjector which contains an experimental serum that causes rapid muscular growth in Hominidae. Side-affects may include hypertrichosis, violent outbursts, and an unending affinity for bananas."
- item = /obj/item/reagent_containers/hypospray/magillitis
- cost = 15
- restricted_roles = list("Geneticist", "Chief Medical Officer")
-
-/datum/uplink_item/role_restricted/pressure_mod
- name = "Kinetic Accelerator Pressure Mod"
- desc = "A modification kit which allows Kinetic Accelerators to do greatly increased damage while indoors. Occupies 35% mod capacity."
- item = /obj/item/borg/upgrade/modkit/indoors
- cost = 5 //you need two for full damage, so total of 10 for maximum damage
- limited_stock = 2 //you can't use more than two!
- restricted_roles = list("Shaft Miner")
-
-/datum/uplink_item/role_restricted/blastcannon
- name = "Blast Cannon"
- desc = "A highly specialized weapon, the Blast Cannon is actually relatively simple. It contains an attachment for a tank transfer valve mounted to an angled pipe specially constructed \
- withstand extreme pressure and temperatures, and has a mechanical trigger for triggering the transfer valve. Essentially, it turns the explosive force of a bomb into a narrow-angle \
- blast wave \"projectile\". Aspiring scientists may find this highly useful, as forcing the pressure shockwave into a narrow angle seems to be able to bypass whatever quirk of physics \
- disallows explosive ranges above a certain distance, allowing for the device to use the theoretical yield of a transfer valve bomb, instead of the factual yield."
- item = /obj/item/gun/blastcannon
- cost = 14 //High cost because of the potential for extreme damage in the hands of a skilled gas masked scientist.
- restricted_roles = list("Research Director", "Scientist")
-
-/datum/uplink_item/device_tools/clown_bomb
- name = "Clown Bomb"
- desc = "The Clown bomb is a hilarious device capable of massive pranks. It has an adjustable timer, \
- with a minimum of 60 seconds, and can be bolted to the floor with a wrench to prevent \
- movement. The bomb is bulky and cannot be moved; upon ordering this item, a smaller beacon will be \
- transported to you that will teleport the actual bomb to it upon activation. Note that this bomb can \
- be defused, and some crew may attempt to do so."
- item = /obj/item/sbeacondrop/clownbomb
- cost = 15
+/datum/uplink_item/role_restricted/reverse_bear_trap
+ name = "Reverse Bear Trap"
+ desc = "An ingenious execution device worn on (or forced onto) the head. Arming it starts a 1-minute kitchen timer mounted on the bear trap. When it goes off, the trap's jaws will \
+ violently open, instantly killing anyone wearing it by tearing their jaws in half. To arm, attack someone with it while they're not wearing headgear, and you will force it onto their \
+ head after three seconds uninterrupted."
+ cost = 5
+ item = /obj/item/reverse_bear_trap
restricted_roles = list("Clown")
-/datum/uplink_item/device_tools/ultrahonkpins //Idealy so they can place it into their own guns without needing cargo
- name = "Hilarious firing pin"
- desc = "A single firing pin made for Clown agents, this firing pin makes any gun honk when fired if not a true clown! \
- This firing pin also helps you fire the gun correctly. May the HonkMother HONK you agent."
- item = /obj/item/firing_pin/clown/ultra
- cost = 2
+/datum/uplink_item/role_restricted/reverse_revolver
+ name = "Reverse Revolver"
+ desc = "A revolver that always fires at its user. \"Accidentally\" drop your weapon, then watch as the greedy corporate pigs blow their own brains all over the wall. \
+ The revolver itself is actually real. Only clumsy people, and clowns, can fire it normally. Comes in a box of hugs. Honk."
+ cost = 14
+ item = /obj/item/storage/box/hug/reverse_revolver
restricted_roles = list("Clown")
-/*
-/datum/uplink_item/role_restricted/clowncar
- name = "Clown Car"
- desc = "The Clown Car is the ultimate transportation method for any worthy clown! \
- Simply insert your bikehorn and get in, and get ready to have the funniest ride of your life! \
- You can ram any spacemen you come across and stuff them into your car, kidnapping them and locking them inside until \
- someone saves them or they manage to crawl out. Be sure not to ram into any walls or vending machines, as the springloaded seats \
- are very sensetive. Now with our included lube defense mechanism which will protect you against any angry shitcurity!"
- item = /obj/vehicle/sealed/car/clowncar
- cost = 15
+/datum/uplink_item/role_restricted/taeclowndo_shoes
+ name = "Tae-clown-do Shoes"
+ desc = "A pair of shoes for the most elite agents of the honkmotherland. They grant the mastery of taeclowndo with some honk-fu moves as long as they're worn."
+ cost = 14
+ item = /obj/item/clothing/shoes/clown_shoes/taeclowndo
restricted_roles = list("Clown")
-*/
+
// Pointless
/datum/uplink_item/badass
category = "(Pointless) Badassery"
surplus = 0
-/datum/uplink_item/badass/syndiecards
- name = "Syndicate Playing Cards"
- desc = "A special deck of space-grade playing cards with a mono-molecular edge and metal reinforcement, \
- making them slightly more robust than a normal deck of cards. \
- You can also play card games with them or leave them on your victims."
- item = /obj/item/toy/cards/deck/syndicate
- cost = 1
- surplus = 40
-
-/datum/uplink_item/badass/syndiecash
- name = "Syndicate Briefcase Full of Cash"
- desc = "A secure briefcase containing 5000 space credits. Useful for bribing personnel, or purchasing goods \
- and services at lucrative prices. The briefcase also feels a little heavier to hold; it has been \
- manufactured to pack a little bit more of a punch if your client needs some convincing."
- item = /obj/item/storage/secure/briefcase/syndie
- cost = 1
-
-/datum/uplink_item/badass/syndiecigs
- name = "Syndicate Smokes"
- desc = "Strong flavor, dense smoke, infused with omnizine."
- item = /obj/item/storage/fancy/cigarettes/cigpack_syndicate
- cost = 2
-
-/datum/uplink_item/badass/balloon
- name = "Syndicate Balloon"
- desc = "For showing that you are THE BOSS: A useless red balloon with the Syndicate logo on it. \
- Can blow the deepest of covers."
- item = /obj/item/toy/syndicateballoon
- cost = 20
- cant_discount = TRUE
-
-/datum/uplink_item/badass/plastitanium_toolbox
- name = "Plastitanium Toolbox"
- desc = "A very high impact toolbox. Excels at destroying stationary structures."
- item = /obj/item/storage/toolbox/plastitanium
- cost = 2 //18 damage on mobs, 50 on objects, 4.5 stam/hit
+/datum/uplink_item/badass/costumes/obvious_chameleon
+ name = "Broken Chameleon Kit"
+ desc = "A set of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more! Please note that this kit did NOT pass quality control."
+ item = /obj/item/storage/box/syndie_kit/chameleon/broken
/datum/uplink_item/badass/costumes
- surplus = 0
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
cost = 4
cant_discount = TRUE
@@ -1634,90 +1785,45 @@ datum/uplink_item/stealthy_tools/taeclowndo_shoes
desc = "Nothing is more terrifying than clowns with fully automatic weaponry."
item = /obj/item/storage/backpack/duffelbag/clown/syndie
-/datum/uplink_item/badass/costumes/obvious_chameleon
- name = "Broken Chameleon Kit"
- desc = "A set of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more! Please note that this kit did NOT pass quality control."
- item = /obj/item/storage/box/syndie_kit/chameleon/broken
+/datum/uplink_item/badass/plastitanium_toolbox
+ name = "Plastitanium Toolbox"
+ desc = "A very high impact toolbox. Excels at destroying stationary structures."
+ item = /obj/item/storage/toolbox/plastitanium
+ cost = 2 //18 damage on mobs, 50 on objects, 4.5 stam/hit
-/datum/uplink_item/badass/rapid
- name = "Gloves of the North Star"
- desc = "These gloves let the user punch people very fast. Does not improve weapon attack speed or the meaty fists of a hulk."
- item = /obj/item/clothing/gloves/rapid
- cost = 8
-
-/datum/uplink_item/badass/bundle
- name = "Syndicate Bundle"
- desc = "Syndicate Bundles are specialized groups of items that arrive in a plain box. \
- These items are collectively worth more than 20 telecrystals, but you do not know which specialization \
- you will receive."
- item = /obj/item/storage/box/syndicate
+/datum/uplink_item/badass/balloon
+ name = "Syndicate Balloon"
+ desc = "For showing that you are THE BOSS: A useless red balloon with the Syndicate logo on it. \
+ Can blow the deepest of covers."
+ item = /obj/item/toy/syndicateballoon
cost = 20
- exclude_modes = list(/datum/game_mode/nuclear)
cant_discount = TRUE
-/datum/uplink_item/badass/surplus
- name = "Syndicate Surplus Crate"
- desc = "A dusty crate from the back of the Syndicate warehouse. Rumored to contain a valuable assortment of items, \
- but you never know. Contents are sorted to always be worth 50 TC."
- item = /obj/structure/closet/crate
- cost = 20
- player_minimum = 25
- exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
- cant_discount = TRUE
- var/starting_crate_value = 50
+/datum/uplink_item/badass/syndiecash
+ name = "Syndicate Briefcase Full of Cash"
+ desc = "A secure briefcase containing 5000 space credits. Useful for bribing personnel, or purchasing goods \
+ and services at lucrative prices. The briefcase also feels a little heavier to hold; it has been \
+ manufactured to pack a little bit more of a punch if your client needs some convincing."
+ item = /obj/item/storage/secure/briefcase/syndie
+ cost = 1
-/datum/uplink_item/badass/surplus/super
- name = "Super Surplus Crate"
- desc = "A dusty SUPER-SIZED from the back of the Syndicate warehouse. Rumored to contain a valuable assortment of items, \
- but you never know. Contents are sorted to always be worth 125 TC."
- cost = 40
- player_minimum = 40
- starting_crate_value = 125
+/datum/uplink_item/badass/phantomthief
+ name = "Syndicate Mask"
+ desc = "A cheap plastic mask fitted with an adrenaline autoinjector, which can be used by simply tensing your muscles"
+ item = /obj/item/clothing/glasses/phantomthief/syndicate
+ cost = 2
-/datum/uplink_item/badass/surplus/purchase(mob/user, datum/component/uplink/U)
- var/list/uplink_items = get_uplink_items(SSticker && SSticker.mode? SSticker.mode : null, FALSE)
+/datum/uplink_item/badass/syndiecards
+ name = "Syndicate Playing Cards"
+ desc = "A special deck of space-grade playing cards with a mono-molecular edge and metal reinforcement, \
+ making them slightly more robust than a normal deck of cards. \
+ You can also play card games with them or leave them on your victims."
+ item = /obj/item/toy/cards/deck/syndicate
+ cost = 1
+ surplus = 40
- var/crate_value = starting_crate_value
- var/obj/structure/closet/crate/C = spawn_item(/obj/structure/closet/crate, user)
- if(U.purchase_log)
- U.purchase_log.LogPurchase(C, src, cost)
- while(crate_value)
- var/category = pick(uplink_items)
- var/item = pick(uplink_items[category])
- var/datum/uplink_item/I = uplink_items[category][item]
-
- if(!I.surplus || prob(100 - I.surplus))
- continue
- if(crate_value < I.cost)
- continue
- crate_value -= I.cost
- var/obj/goods = new I.item(C)
- if(U.purchase_log)
- U.purchase_log.LogPurchase(goods, I, 0)
- return C
-
-/datum/uplink_item/badass/random
- name = "Random Item"
- desc = "Picking this will purchase a random item. Useful if you have some TC to spare or if you haven't decided on a strategy yet."
- item = /obj/effect/gibspawner/generic // non-tangible item because techwebs use this path to determine illegal tech
- cost = 0
- cant_discount = TRUE
-
-/datum/uplink_item/badass/random/purchase(mob/user, datum/component/uplink/U)
- var/list/uplink_items = U.uplink_items
- var/list/possible_items = list()
- for(var/category in uplink_items)
- for(var/item in uplink_items[category])
- var/datum/uplink_item/I = uplink_items[category][item]
- if(src == I || !I.item)
- continue
- if(U.telecrystals < I.cost)
- continue
- if(I.limited_stock == 0)
- continue
- possible_items += I
-
- if(possible_items.len)
- var/datum/uplink_item/I = pick(possible_items)
- SSblackbox.record_feedback("tally", "traitor_random_uplink_items_gotten", 1, initial(I.name))
- U.MakePurchase(user, I)
+/datum/uplink_item/badass/syndiecigs
+ name = "Syndicate Smokes"
+ desc = "Strong flavor, dense smoke, infused with omnizine."
+ item = /obj/item/storage/fancy/cigarettes/cigpack_syndicate
+ cost = 2
diff --git a/code/modules/vending/medical.dm b/code/modules/vending/medical.dm
index 5eba9b6b21..523606aa6a 100644
--- a/code/modules/vending/medical.dm
+++ b/code/modules/vending/medical.dm
@@ -32,7 +32,10 @@
/obj/item/reagent_containers/hypospray/medipen = 3,
/obj/item/storage/belt/medical = 3,
/obj/item/wrench/medical = 1,
- /obj/item/storage/briefcase/medical = 2)
+ /obj/item/storage/belt/medolier/full = 2,
+ /obj/item/gun/syringe/dart = 2,
+ /obj/item/storage/briefcase/medical = 2)
+
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
refill_canister = /obj/item/vending_refill/medical
diff --git a/code/modules/vending/medical_wall.dm b/code/modules/vending/medical_wall.dm
index 018eb09d86..514bbd8730 100644
--- a/code/modules/vending/medical_wall.dm
+++ b/code/modules/vending/medical_wall.dm
@@ -10,7 +10,8 @@
/obj/item/reagent_containers/medspray/styptic = 2,
/obj/item/reagent_containers/medspray/silver_sulf = 2,
/obj/item/reagent_containers/pill/charcoal = 2,
- /obj/item/reagent_containers/medspray/sterilizine = 1)
+ /obj/item/reagent_containers/medspray/sterilizine = 1,
+ /obj/item/reagent_containers/syringe/dart = 10)
contraband = list(/obj/item/reagent_containers/pill/tox = 2,
/obj/item/reagent_containers/pill/morphine = 2)
premium = list(/obj/item/reagent_containers/medspray/synthflesh = 2)
diff --git a/config/spaceRuinBlacklist.txt b/config/spaceRuinBlacklist.txt
index 6e74857e66..cba9a01e73 100644
--- a/config/spaceRuinBlacklist.txt
+++ b/config/spaceRuinBlacklist.txt
@@ -48,3 +48,4 @@
#_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm
#_maps/RandomRuins/SpaceRuins/bigape.dmm
#_maps/RandomRuins/SpaceRuins/arcade.dmm
+#_maps/RandomRuins/SpaceRuins/spacehermit.dmm
diff --git a/html/changelogs/AutoChangeLog-pr-8659.yml b/html/changelogs/AutoChangeLog-pr-8659.yml
new file mode 100644
index 0000000000..6287f1307f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8659.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by ninjanomnom)"
+delete-after: True
+changes:
+ - bugfix: "Orbiting is a little more aggressive about staying in orbit. The wisp as a result now correctly follows you over shuttle moves."
diff --git a/html/changelogs/AutoChangeLog-pr-8665.yml b/html/changelogs/AutoChangeLog-pr-8665.yml
new file mode 100644
index 0000000000..fc34f9ac3e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8665.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - balance: "Buffed wizard and artificier's Magic Missile, wizard and xeno queen's Repulse and juggernaut's Gauntlet Echo."
diff --git a/html/changelogs/AutoChangeLog-pr-8666.yml b/html/changelogs/AutoChangeLog-pr-8666.yml
new file mode 100644
index 0000000000..df2e2e3af0
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8666.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by YPOQ)"
+delete-after: True
+changes:
+ - bugfix: "Fixing roffle waffle, mushroom halluginogen and some invalid reagents."
diff --git a/html/changelogs/AutoChangeLog-pr-8667.yml b/html/changelogs/AutoChangeLog-pr-8667.yml
new file mode 100644
index 0000000000..1f80a2917d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8667.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by Anturk)"
+delete-after: True
+changes:
+ - rscadd: "Recipe for fabled secret sauce can now be found in the deepest reaches of space."
diff --git a/html/changelogs/AutoChangeLog-pr-8669.yml b/html/changelogs/AutoChangeLog-pr-8669.yml
new file mode 100644
index 0000000000..20770e8cc2
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8669.yml
@@ -0,0 +1,5 @@
+author: "Ghommie (original PRs by Denton and Skoglol)"
+delete-after: True
+changes:
+ - tweak: "Reorganized the syndicate uplinks. Items are now mostly alphabetical, some misplaced items moved to more fitting categories. Bundles, random item and TC have been moved into a new category called \"Bundles and Telecrystals\". Gloves of the North Star and Box of Throwing Weapons have been moved to Conspicuous and Dangerous Weapons. Combat Gloves Plus have been moved to Stealthy and Inconspicuous Weapons. Moved all implants into the Implants category."
+ - tweak: "Added a new category to the uplink: Grenades and Explosives."
diff --git a/html/changelogs/AutoChangeLog-pr-8671.yml b/html/changelogs/AutoChangeLog-pr-8671.yml
new file mode 100644
index 0000000000..bb01481d5c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8671.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by wesoda25)"
+delete-after: True
+changes:
+ - balance: "disembowelment no longer works on mobs that aren't dead or in critical condition"
diff --git a/html/changelogs/AutoChangeLog-pr-8674.yml b/html/changelogs/AutoChangeLog-pr-8674.yml
new file mode 100644
index 0000000000..3277946844
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8674.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - bugfix: "fixing cat code that dosnt work, my bad"
diff --git a/html/changelogs/AutoChangeLog-pr-8675.yml b/html/changelogs/AutoChangeLog-pr-8675.yml
new file mode 100644
index 0000000000..170a44ca25
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8675.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - bugfix: "Arcades stealing from noodles"
diff --git a/html/changelogs/AutoChangeLog-pr-8677.yml b/html/changelogs/AutoChangeLog-pr-8677.yml
new file mode 100644
index 0000000000..181f6d2932
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8677.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - tweak: "speedy quirk"
diff --git a/html/changelogs/AutoChangeLog-pr-8687.yml b/html/changelogs/AutoChangeLog-pr-8687.yml
new file mode 100644
index 0000000000..65347093ef
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8687.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by monster860)"
+delete-after: True
+changes:
+ - bugfix: "fixes advanced proccall"
diff --git a/html/changelogs/AutoChangeLog-pr-8688.yml b/html/changelogs/AutoChangeLog-pr-8688.yml
new file mode 100644
index 0000000000..b22c2c52fd
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8688.yml
@@ -0,0 +1,5 @@
+author: "Ghommie (Original PR by nemvar)"
+delete-after: True
+changes:
+ - rscadd: "Botanists can now get beeplushies (or cultivator and bucket) as an heirloom."
+ - bugfix: "Clowns and mimes will now properly pick either a can of paint or their brand as heirloom now."
diff --git a/html/changelogs/AutoChangeLog-pr-8689.yml b/html/changelogs/AutoChangeLog-pr-8689.yml
new file mode 100644
index 0000000000..bf44770c76
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8689.yml
@@ -0,0 +1,4 @@
+author: "Fermis"
+delete-after: True
+changes:
+ - rscadd: "Added a panda simplemob"
diff --git a/html/changelogs/AutoChangeLog-pr-8690.yml b/html/changelogs/AutoChangeLog-pr-8690.yml
new file mode 100644
index 0000000000..3ac76333a2
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8690.yml
@@ -0,0 +1,4 @@
+author: "Fermis"
+delete-after: True
+changes:
+ - bugfix: "fixes empathy exploit."
diff --git a/html/changelogs/AutoChangeLog-pr-8691.yml b/html/changelogs/AutoChangeLog-pr-8691.yml
new file mode 100644
index 0000000000..680904cc5c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8691.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (Original PRs by nemvar and Rowell)"
+delete-after: True
+changes:
+ - rscadd: "Added beekini bras and panties, thigh-high and knee-high bee socks."
diff --git a/html/changelogs/AutoChangeLog-pr-8692.yml b/html/changelogs/AutoChangeLog-pr-8692.yml
new file mode 100644
index 0000000000..f1d87676ab
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8692.yml
@@ -0,0 +1,7 @@
+author: "Ghommie (original PRs by ShizCalev)"
+delete-after: True
+changes:
+ - bugfix: "Fixed a bug that allowed you to teleport an ID in your possession to a PDA anywhere ingame."
+ - bugfix: "Fixed an exploit allowing you to steal ID's/pens from PDA's not in your possession."
+ - bugfix: "Fixed an exploit allowing you unlimited control of a PDA's interface even if it wasn't near you/in your possession."
+ - bugfix: "Fixed Pride Mirror exploits."
diff --git a/html/changelogs/AutoChangeLog-pr-8695.yml b/html/changelogs/AutoChangeLog-pr-8695.yml
new file mode 100644
index 0000000000..671eaa519e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8695.yml
@@ -0,0 +1,6 @@
+author: "Ghommie (original PRs by grandpawalton and Mickyan)"
+delete-after: True
+changes:
+ - tweak: "the contents on the smartfridge icon now change depending on how many items it contains"
+ - bugfix: "opening the maintenance panel of smartfridges now correctly updates the icon"
+ - bugfix: "Screwing a disk compartmentalizer no longer makes it look like a smartfridge."
diff --git a/html/changelogs/AutoChangeLog-pr-8698.yml b/html/changelogs/AutoChangeLog-pr-8698.yml
new file mode 100644
index 0000000000..464f74427e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8698.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixes flashlights being unable to be used for rudimentary eyes and mouth exams."
diff --git a/html/changelogs/AutoChangeLog-pr-8711.yml b/html/changelogs/AutoChangeLog-pr-8711.yml
new file mode 100644
index 0000000000..f836783659
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8711.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - rscadd: "Adds in a grey jumpsuit to the loadout choices, restricted to Assistants."
diff --git a/html/changelogs/AutoChangeLog-pr-8715.yml b/html/changelogs/AutoChangeLog-pr-8715.yml
new file mode 100644
index 0000000000..b99309cdd9
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8715.yml
@@ -0,0 +1,5 @@
+author: "Sishen1542"
+delete-after: True
+changes:
+ - rscadd: "Pentetic Jelly, new chemical made through mixing 1:1 slime jelly and pentetic acid."
+ - tweak: "Anatomic panacea now gives pent jelly instead of pent acid. Medbeams now have TRUE tox healing to heal TOXINLOVER as well."
diff --git a/html/changelogs/AutoChangeLog-pr-8718.yml b/html/changelogs/AutoChangeLog-pr-8718.yml
new file mode 100644
index 0000000000..102fbd4f23
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8718.yml
@@ -0,0 +1,4 @@
+author: "Linzolle"
+delete-after: True
+changes:
+ - rscadd: "ability to quickly max sensors"
diff --git a/html/changelogs/AutoChangeLog-pr-8721.yml b/html/changelogs/AutoChangeLog-pr-8721.yml
new file mode 100644
index 0000000000..4b616e9923
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8721.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by XDTM)"
+delete-after: True
+changes:
+ - bugfix: "Reagents now stop their passive effects (for example, stun immunity) if the liver stops working while they're active."
diff --git a/html/changelogs/AutoChangeLog-pr-8722.yml b/html/changelogs/AutoChangeLog-pr-8722.yml
new file mode 100644
index 0000000000..fe858768af
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8722.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - bugfix: "I didn't code it right it in the first place"
diff --git a/html/changelogs/AutoChangeLog-pr-8732.yml b/html/changelogs/AutoChangeLog-pr-8732.yml
new file mode 100644
index 0000000000..69a79b93ac
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8732.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by Nicjh)"
+delete-after: True
+changes:
+ - rscadd: "Abductor console's select disguise option now uses a radial"
diff --git a/html/changelogs/AutoChangeLog-pr-8733.yml b/html/changelogs/AutoChangeLog-pr-8733.yml
new file mode 100644
index 0000000000..593c06bd90
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8733.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PR by Swindly)"
+delete-after: True
+changes:
+ - rscadd: "Arm-mounted implants that contain more than one item use a radial menu instead of a list menu."
diff --git a/html/changelogs/AutoChangeLog-pr-8736.yml b/html/changelogs/AutoChangeLog-pr-8736.yml
new file mode 100644
index 0000000000..68d64e2410
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8736.yml
@@ -0,0 +1,6 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - rscadd: "gear harness and a conflict merg"
+ - rscdel: "Nudity permits"
+ - bugfix: "nothing"
diff --git a/icons/mob/neck.dmi b/icons/mob/neck.dmi
index 3c126daba6..3463065bc7 100644
Binary files a/icons/mob/neck.dmi and b/icons/mob/neck.dmi differ
diff --git a/icons/mob/pets.dmi b/icons/mob/pets.dmi
index 45b0ab1f04..fe0146ccc4 100644
Binary files a/icons/mob/pets.dmi and b/icons/mob/pets.dmi differ
diff --git a/icons/mob/underwear.dmi b/icons/mob/underwear.dmi
index cf16eb9e32..25e7d2c6d0 100644
Binary files a/icons/mob/underwear.dmi and b/icons/mob/underwear.dmi differ
diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi
index 2ed1783941..3d281606de 100644
Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ
diff --git a/icons/obj/clothing/belts.dmi b/icons/obj/clothing/belts.dmi
index dc5dde9cb6..3e56574fbf 100644
Binary files a/icons/obj/clothing/belts.dmi and b/icons/obj/clothing/belts.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index 84155bfe43..3e3a1cefcb 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/obj/dart.dmi b/icons/obj/dart.dmi
new file mode 100644
index 0000000000..50ba4fc1ab
Binary files /dev/null and b/icons/obj/dart.dmi differ
diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi
index e4a39903b3..7d44d35f55 100644
Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ
diff --git a/icons/obj/plushes.dmi b/icons/obj/plushes.dmi
index 8e845d9710..586bca61aa 100644
Binary files a/icons/obj/plushes.dmi and b/icons/obj/plushes.dmi differ
diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi
index d276655ae8..bff1b631c3 100644
Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ
diff --git a/icons/obj/syringe.dmi b/icons/obj/syringe.dmi
index f77735fc3e..80e681399a 100644
Binary files a/icons/obj/syringe.dmi and b/icons/obj/syringe.dmi differ
diff --git a/icons/obj/vending.dmi b/icons/obj/vending.dmi
index e5d474f01d..553336115b 100644
Binary files a/icons/obj/vending.dmi and b/icons/obj/vending.dmi differ
diff --git a/modular_citadel/code/datums/uplink_items_cit.dm b/modular_citadel/code/datums/uplink_items_cit.dm
deleted file mode 100644
index 16130de96d..0000000000
--- a/modular_citadel/code/datums/uplink_items_cit.dm
+++ /dev/null
@@ -1,177 +0,0 @@
-/*/datum/uplink_item/stealthy_tools/syndi_borer
- name = "Syndicate Brain Slug"
- desc = "A small cortical borer, modified to be completely loyal to the owner. \
- Genetically infertile, these brain slugs can assist medically in a support role, or take direct action \
- to assist their host."
- item = /obj/item/antag_spawner/syndi_borer
- refundable = TRUE
- cost = 10
- surplus = 20 //Let's not have this be too common
- exclude_modes = list(/datum/game_mode/nuclear) */
-
-/datum/uplink_item/stealthy_tools/holoparasite
- name="Holoparasite Injector"
- desc="An injector containing a swarm of holographic parasites. \
- They mimic the function of the guardians employed by the Space Wizard Federation, and their form can be selected upon application \
- NOTE: The precise nature of the symbiosis required by the parasites renders them incompatible with changelings" //updated to actually describe what they do and warn traitorchans not to buy it
- item = /obj/item/storage/box/syndie_kit/holoparasite
- refundable = TRUE
- cant_discount = TRUE
- cost = 15
- surplus = 20 //Nobody needs a ton of parasites
- exclude_modes = list(/datum/game_mode/nuclear)
- refund_path = /obj/item/guardiancreator/tech/choose/traitor
-
-
-/obj/item/storage/box/syndie_kit/holoparasite
- name = "box"
-
-/obj/item/storage/box/syndie_kit/holoparasite/PopulateContents()
- new /obj/item/guardiancreator/tech/choose/traitor(src)
- new /obj/item/paper/guides/antag/guardian(src)
-
-/datum/uplink_item/dangerous/antitank
- name = "Anti Tank Pistol"
- desc = "Essentially amounting to a sniper rifle with no stock and barrel (or indeed, any rifling at all), \
- this extremely dubious pistol is guaranteed to dislocate your wrists and hit the broad side of a barn! \
- Uses sniper ammo. \
- Bullets tend to veer off-course. We are not responsible for any unintentional damage or injury resulting from inaacuracy."
- item = /obj/item/gun/ballistic/automatic/pistol/antitank/syndicate
- cost = 14
- surplus = 25
- include_modes = list(/datum/game_mode/nuclear)
-
-/* Commented out due to introduction of reskinnable stetchkins. May still have a niche if people decide it somehow has value.
-/datum/uplink_item/dangerous/stealthpistol
- name = "Stealth Pistol"
- desc = "A compact, easily concealable bullpup pistol that fires 10mm auto rounds in 8 round magazines. \
- Has an integrated suppressor."
- item = /obj/item/gun/ballistic/automatic/pistol/stealth
- cost = 10
- surplus = 30
-*/
-
-///Soporific 10mm mags///
-
-/datum/uplink_item/ammo/pistolzzz
- name = "10mm Soporific Magazine"
- desc = "An additional 8-round 10mm magazine; compatible with the Stechkin Pistol. Loaded with soporific rounds that put the target to sleep. \
- NOTE: Soporific is not instant acting due to the constraints of the round's scale. Will usually require three shots to take effect."
- item = /obj/item/ammo_box/magazine/m10mm/soporific
- cost = 2
-
-///flechette memes///
-
-/datum/uplink_item/dangerous/flechettegun
- name = "Flechette Launcher"
- desc = "A compact bullpup that fires micro-flechettes.\
- Flechettes have very poor performance idividually, but can be very deadly in numbers. \
- Pre-loaded with armor piercing flechettes that are capable of puncturing most kinds of armor."
- item = /obj/item/gun/ballistic/automatic/flechette
- cost = 12
- surplus = 30
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/ammo/flechetteap
- name = "Armor Piercing Flechette Magazine"
- desc = "An additional 40-round flechette magazine; compatible with the Flechette Launcer. \
- Loaded with armor piercing flechettes that very nearly ignore armor, but are not very effective agaisnt flesh."
- item = /obj/item/ammo_box/magazine/flechette
- cost = 2
- include_modes = list(/datum/game_mode/nuclear)
-
-/datum/uplink_item/ammo/flechettes
- name = "Serrated Flechette Magazine"
- desc = "An additional 40-round flechette magazine; compatible with the Flechette Launcer. \
- Loaded with serrated flechettes that shreds flesh, but is stopped dead in its tracks by armor. \
- These flechettes are highly likely to sever arteries, and even limbs."
- item = /obj/item/ammo_box/magazine/flechette/s
- cost = 2
- include_modes = list(/datum/game_mode/nuclear)
-
-///shredder///
-
-/datum/uplink_item/nukeoffer/shredder
- name = "Shredder bundle"
- desc = "A truly horrific weapon designed simply to maim its victim, the CX Shredder is banned by several intergalactic treaties. \
- You'll get two of them with this. And spare ammo to boot. And we'll throw in an extra elite hardsuit and chest rig to hold them all!"
- item = /obj/item/storage/backpack/duffelbag/syndie/shredderbundle
- cost = 30 // normally 41
-
-///Modular Pistols///
-
-/datum/uplink_item/bundle/modular
- name="Modular Pistol Kit"
- desc="A heavy briefcase containing one modular pistol (chambered in 10mm), one supressor, and spare ammunition, including a box of soporific ammo. \
- Includes a suit jacket that is padded with a robust liner."
- item = /obj/item/storage/briefcase/modularbundle
- cost = 12
-
-//////Bundle stuff//////
-
-///bundle category///
-
-/datum/uplink_item/bundle
- category = "Bundles"
- surplus = 0
- cant_discount = TRUE
-
-///place bundle storage items here I guess///
-
-/obj/item/storage/briefcase/modularbundle
- name = "briefcase"
- desc = "It's label reads genuine hardened Captain leather, but suspiciously has no other tags or branding."
- icon_state = "briefcase"
- flags_1 = CONDUCT_1
- force = 10
- hitsound = "swing_hit"
- throw_speed = 2
- throw_range = 4
- w_class = WEIGHT_CLASS_BULKY
- attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked")
- resistance_flags = FLAMMABLE
- max_integrity = 150
-
-/obj/item/storage/briefcase/modularbundle/PopulateContents()
- new /obj/item/gun/ballistic/automatic/pistol/modular(src)
- new /obj/item/suppressor(src)
- new /obj/item/ammo_box/magazine/m10mm(src)
- new /obj/item/ammo_box/magazine/m10mm/soporific(src)
- new /obj/item/ammo_box/c10mm/soporific(src)
- new /obj/item/clothing/under/lawyer/blacksuit(src)
- new /obj/item/clothing/accessory/waistcoat(src)
- new /obj/item/clothing/suit/toggle/lawyer/black/syndie(src)
-
-/obj/item/clothing/suit/toggle/lawyer/black/syndie
- desc = "A snappy dress jacket. Suspiciously has no tags or branding."
- armor = list(melee = 10, bullet = 10, laser = 10, energy = 10, bomb = 10)
-
-/obj/item/storage/backpack/duffelbag/syndie/shredderbundle
- desc = "A large duffel bag containing two CX Shredders, some magazines, an elite hardsuit, and a chest rig."
-
-/obj/item/storage/backpack/duffelbag/syndie/shredderbundle/PopulateContents()
- new /obj/item/ammo_box/magazine/flechette/shredder(src)
- new /obj/item/ammo_box/magazine/flechette/shredder(src)
- new /obj/item/ammo_box/magazine/flechette/shredder(src)
- new /obj/item/ammo_box/magazine/flechette/shredder(src)
- new /obj/item/gun/ballistic/automatic/flechette/shredder(src)
- new /obj/item/gun/ballistic/automatic/flechette/shredder(src)
- new /obj/item/storage/belt/military(src)
- new /obj/item/clothing/suit/space/hardsuit/syndi/elite(src)
-
-///End of Bundle stuff///
-
-
-/*/////////////////////////////////////////////////////////////////////////
-///////////// The TRUE Energy Sword ///////////////////////////
-*//////////////////////////////////////////////////////////////////////////
-
-/datum/uplink_item/dangerous/cxneb
- name = "Dragon's Tooth Non-Eutactic Blade"
- desc = "An illegal modification of a weapon that is functionally identical to the energy sword, \
- the Non-Eutactic Blade (NEB) forges a hardlight blade on-demand, \
- generating an extremely sharp, unbreakable edge that is guaranteed to satisfy your every need. \
- This particular model has a polychromic hardlight generator, allowing you to murder in style! \
- The illegal modifications bring this weapon up to par with the classic energy sword, and also gives it the energy sword's distinctive sounds."
- item = /obj/item/melee/transforming/energy/sword/cx/traitor
- cost = 8
\ No newline at end of file
diff --git a/modular_citadel/code/game/objects/items/devices/flashlight.dm b/modular_citadel/code/game/objects/items/devices/flashlight.dm
deleted file mode 100644
index 3a373c9277..0000000000
--- a/modular_citadel/code/game/objects/items/devices/flashlight.dm
+++ /dev/null
@@ -1,31 +0,0 @@
-/obj/item/flashlight
- light_color = "#FFCC66"
- flashlight_power = 0.8
-
-/obj/item/flashlight/pen
- light_color = "#FFDDCC"
- flashlight_power = 0.3
-
-/obj/item/flashlight/seclite
- light_color = "#CDDDFF"
- flashlight_power = 0.9
-
-/obj/item/flashlight/lamp
- light_color = "#FFDDBB"
- flashlight_power = 0.8
-
-/obj/item/flashlight/flare
- light_color = "#FA421A"
- flashlight_power = 0.8
-
-/obj/item/flashlight/flare/torch
- light_color = "#FAA44B"
- flashlight_power = 0.8
-
-/obj/item/flashlight/lantern
- light_color = "#FFAA44"
- flashlight_power = 0.75
-
-/obj/item/flashlight/slime
- light_color = "#FFEEAA"
- flashlight_power = 0.6
diff --git a/modular_citadel/code/modules/client/loadout/_service.dm b/modular_citadel/code/modules/client/loadout/_service.dm
index 9b508bb93f..062e22f966 100644
--- a/modular_citadel/code/modules/client/loadout/_service.dm
+++ b/modular_citadel/code/modules/client/loadout/_service.dm
@@ -1,3 +1,9 @@
+/datum/gear/greytidestationwide
+ name = "Grey jumpsuit"
+ category = SLOT_W_UNIFORM
+ path = /obj/item/clothing/under/color/grey
+ restricted_roles = list("Assistant")
+
/datum/gear/plushvar
name = "Ratvar Plushie"
category = SLOT_IN_BACKPACK
diff --git a/modular_citadel/code/modules/client/loadout/uniform.dm b/modular_citadel/code/modules/client/loadout/uniform.dm
index 4172230dbf..abdf8e3a24 100644
--- a/modular_citadel/code/modules/client/loadout/uniform.dm
+++ b/modular_citadel/code/modules/client/loadout/uniform.dm
@@ -309,8 +309,8 @@
restricted_desc = "Engineering and Security"
restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster")
-//memes
-/datum/gear/nudepermit
- name = "Nudity Permit"
+//Memes
+/datum/gear/gear_harnesses
+ name = "Gear Harness"
category = SLOT_W_UNIFORM
- path = /obj/item/clothing/under/permit
\ No newline at end of file
+ path = /obj/item/clothing/under/gear_harness
\ No newline at end of file
diff --git a/modular_citadel/code/modules/mob/cit_emotes.dm b/modular_citadel/code/modules/mob/cit_emotes.dm
index a314baa852..aff1739ae4 100644
--- a/modular_citadel/code/modules/mob/cit_emotes.dm
+++ b/modular_citadel/code/modules/mob/cit_emotes.dm
@@ -183,6 +183,7 @@
key_third_person = "suddenly hits a dab"
message = "suddenly hits a dab!"
emote_type = EMOTE_AUDIBLE
+ restraint_check = TRUE
diff --git a/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm b/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm
index e552c2cbdd..bf811b777c 100644
--- a/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm
+++ b/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm
@@ -191,6 +191,32 @@
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
+/datum/sprite_accessory/ears/human/bigwolf
+ name = "Big Wolf"
+ icon_state = "bigwolf"
+ icon = 'modular_citadel/icons/mob/mam_ears.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/ears/human/bigwolfinner
+ name = "Big Wolf (ALT)"
+ icon_state = "bigwolfinner"
+ hasinner = 1
+ icon = 'modular_citadel/icons/mob/mam_ears.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/ears/human/bigwolfdark
+ name = "Dark Big Wolf"
+ icon_state = "bigwolfdark"
+ icon = 'modular_citadel/icons/mob/mam_ears.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/ears/human/bigwolfinnerdark
+ name = "Dark Big Wolf (ALT)"
+ icon_state = "bigwolfinnerdark"
+ hasinner = 1
+ icon = 'modular_citadel/icons/mob/mam_ears.dmi'
+ color_src = MATRIXED
+
/datum/sprite_accessory/ears/human/cow
name = "Cow"
icon_state = "cow"
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 0f71a71add..00063c22d4 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -17,13 +17,13 @@
M.adjustStaminaLoss(-5*REM)
. = ..()
-/datum/reagent/syndicateadrenals/on_mob_add(mob/living/M)
+/datum/reagent/syndicateadrenals/on_mob_metabolize(mob/living/M)
. = ..()
if(istype(M))
M.next_move_modifier *= 0.5
to_chat(M, "You feel an intense surge of energy rushing through your veins.")
-/datum/reagent/syndicateadrenals/on_mob_delete(mob/living/M)
+/datum/reagent/syndicateadrenals/on_mob_end_metabolize(mob/living/M)
. = ..()
if(istype(M))
M.next_move_modifier *= 2
diff --git a/modular_citadel/code/modules/uplink/uplink_items.dm b/modular_citadel/code/modules/uplink/uplink_items.dm
deleted file mode 100644
index df076c3994..0000000000
--- a/modular_citadel/code/modules/uplink/uplink_items.dm
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-// PUT ALL YOUR NEW UPLINK STUFF HERE, OVERRIDES GO IN HERE TOO
-*/
-
-/datum/uplink_item/device_tools/emagrecharge
- name = "Electromagnet Charging Device"
- desc = "A small device intended for recharging Cryptographic Sequencers. Using it will add five extra charges to the Cryptographic Sequencer."
- item = /obj/item/emagrecharge
- cost = 2
-
-/datum/uplink_item/dangerous/revolver
- item = /obj/item/gun/ballistic/revolver/syndie
-
-/datum/uplink_item/dangerous/phantomthief
- name = "Syndicate Mask"
- desc = "A cheap plastic mask fitted with an adrenaline autoinjector, which can be used by simply tensing your muscles"
- item = /obj/item/clothing/glasses/phantomthief/syndicate
- cost = 2
diff --git a/tgstation.dme b/tgstation.dme
index 8e33f39524..c0ccbb097b 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -130,6 +130,7 @@
#include "code\__HELPERS\qdel.dm"
#include "code\__HELPERS\radiation.dm"
#include "code\__HELPERS\radio.dm"
+#include "code\__HELPERS\reagents.dm"
#include "code\__HELPERS\roundend.dm"
#include "code\__HELPERS\sanitize_values.dm"
#include "code\__HELPERS\shell.dm"
@@ -247,7 +248,6 @@
#include "code\controllers\subsystem\moods.dm"
#include "code\controllers\subsystem\nightshift.dm"
#include "code\controllers\subsystem\npcpool.dm"
-#include "code\controllers\subsystem\orbit.dm"
#include "code\controllers\subsystem\overlays.dm"
#include "code\controllers\subsystem\pai.dm"
#include "code\controllers\subsystem\parallax.dm"
@@ -360,6 +360,7 @@
#include "code\datums\components\mood.dm"
#include "code\datums\components\nanites.dm"
#include "code\datums\components\ntnet_interface.dm"
+#include "code\datums\components\orbiter.dm"
#include "code\datums\components\paintable.dm"
#include "code\datums\components\rad_insulation.dm"
#include "code\datums\components\radioactive.dm"
@@ -2103,6 +2104,7 @@
#include "code\modules\mob\living\simple_animal\friendly\gondola.dm"
#include "code\modules\mob\living\simple_animal\friendly\lizard.dm"
#include "code\modules\mob\living\simple_animal\friendly\mouse.dm"
+#include "code\modules\mob\living\simple_animal\friendly\panda.dm"
#include "code\modules\mob\living\simple_animal\friendly\penguin.dm"
#include "code\modules\mob\living\simple_animal\friendly\pet.dm"
#include "code\modules\mob\living\simple_animal\friendly\sloth.dm"
@@ -2264,7 +2266,6 @@
#include "code\modules\NTNet\network.dm"
#include "code\modules\NTNet\relays.dm"
#include "code\modules\NTNet\services\_service.dm"
-#include "code\modules\orbit\orbit.dm"
#include "code\modules\paperwork\clipboard.dm"
#include "code\modules\paperwork\contract.dm"
#include "code\modules\paperwork\filingcabinet.dm"
@@ -2480,6 +2481,7 @@
#include "code\modules\reagents\chemistry\recipes\others.dm"
#include "code\modules\reagents\chemistry\recipes\pyrotechnics.dm"
#include "code\modules\reagents\chemistry\recipes\slime_extracts.dm"
+#include "code\modules\reagents\chemistry\recipes\special.dm"
#include "code\modules\reagents\chemistry\recipes\toxins.dm"
#include "code\modules\reagents\reagent_containers\blood_pack.dm"
#include "code\modules\reagents\reagent_containers\borghydro.dm"
@@ -2825,7 +2827,6 @@
#include "modular_citadel\code\controllers\configuration\entries\general.dm"
#include "modular_citadel\code\controllers\subsystem\job.dm"
#include "modular_citadel\code\controllers\subsystem\shuttle.dm"
-#include "modular_citadel\code\datums\uplink_items_cit.dm"
#include "modular_citadel\code\datums\components\material_container.dm"
#include "modular_citadel\code\datums\components\phantomthief.dm"
#include "modular_citadel\code\datums\components\souldeath.dm"
@@ -2880,7 +2881,6 @@
#include "modular_citadel\code\game\objects\items\vending_items.dm"
#include "modular_citadel\code\game\objects\items\circuitboards\machine_circuitboards.dm"
#include "modular_citadel\code\game\objects\items\devices\aicard.dm"
-#include "modular_citadel\code\game\objects\items\devices\flashlight.dm"
#include "modular_citadel\code\game\objects\items\devices\PDA\PDA.dm"
#include "modular_citadel\code\game\objects\items\devices\radio\encryptionkey.dm"
#include "modular_citadel\code\game\objects\items\devices\radio\headset.dm"
@@ -3036,7 +3036,6 @@
#include "modular_citadel\code\modules\research\techweb\_techweb.dm"
#include "modular_citadel\code\modules\research\techweb\all_nodes.dm"
#include "modular_citadel\code\modules\research\xenobiology\xenobio_camera.dm"
-#include "modular_citadel\code\modules\uplink\uplink_items.dm"
#include "modular_citadel\code\modules\vehicles\secway.dm"
#include "modular_citadel\code\modules\vore\hook-defs_vr.dm"
#include "modular_citadel\code\modules\vore\persistence.dm"