diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index f5fa86a76d..a1c37bc290 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,3 +1,3 @@
-[Note]: # (Please enter the commit hash and active testmerge numbers from the "Show Server Revision" verb if you can. If you believe the issue to be caused by a testmerge, please report it in its relative PR thread. State what the issue is from a "whats wrong" prospective. Issue reports should clearly allow maintainers to understand whats wrong and how to test/reproduce if that is not obvious. Avoid ambiguity. Start your issue report below both of these lines (or remove them))
+[Note]: # (State what the issue is from a "whats wrong" perspective. Issue reports should clearly allow maintainers to understand whats wrong and how to test/reproduce if that is not obvious. Avoid ambiguity. Please enter the commit hash from the "Show Server Revision" verb if you can. Remove these notes before submitting your report.)
-[Admins]: # (If you are reporting a bug that occured AFTER you used varedit/admin buttons to alter an object out of normal operating conditions, please verify that you can re-create the bug without the varedit usage/admin buttons before reporting the issue.)
+[GameAdmins]: # (If you are reporting a bug that occurred AFTER you used varedit/admin buttons to alter an object out of normal operating conditions, please verify that you can re-create the bug without the varedit usage/admin buttons before reporting the issue.)
diff --git a/Test.txt b/Test.txt
index fc816240e4..68db24f630 100644
--- a/Test.txt
+++ b/Test.txt
@@ -1 +1 @@
-Ignore this
\ No newline at end of file
+~~
\ No newline at end of file
diff --git a/_maps/RandomRuins/SpaceRuins/deepstorage.dmm b/_maps/RandomRuins/SpaceRuins/deepstorage.dmm
new file mode 100644
index 0000000000..785d2e9456
--- /dev/null
+++ b/_maps/RandomRuins/SpaceRuins/deepstorage.dmm
@@ -0,0 +1,6741 @@
+//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/closed/wall/mineral/iron,
+/area/ruin/deepstorage)
+"ad" = (
+/obj/structure/closet/cardboard,
+/obj/item/stack/sheet/mineral/silver,
+/obj/item/stack/sheet/mineral/gold,
+/obj/item/stack/sheet/mineral/silver,
+/obj/item/stack/sheet/mineral/silver,
+/obj/item/stack/sheet/mineral/gold,
+/obj/item/stack/sheet/mineral/gold,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"ae" = (
+/obj/structure/closet/cardboard,
+/obj/item/weapon/storage/box/monkeycubes,
+/obj/item/weapon/storage/box/monkeycubes,
+/obj/item/weapon/storage/box/monkeycubes,
+/obj/item/weapon/storage/toolbox/drone,
+/obj/item/weapon/storage/toolbox/drone,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"af" = (
+/obj/structure/closet/cardboard,
+/obj/item/stack/sheet/cardboard,
+/obj/item/stack/cable_coil,
+/obj/item/stack/sheet/mineral/wood,
+/obj/item/stack/sheet/mineral/wood,
+/obj/item/stack/packageWrap,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"ag" = (
+/obj/structure/closet/cardboard,
+/obj/item/weapon/storage/box/mousetraps,
+/obj/item/weapon/storage/box/mousetraps,
+/obj/item/weapon/storage/box/drinkingglasses,
+/obj/item/weapon/storage/box/zipties,
+/obj/item/weapon/switchblade,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"ah" = (
+/obj/structure/closet/cardboard,
+/obj/item/stack/sheet/metal{
+ amount = 50;
+ pixel_x = 2;
+ pixel_y = 2
+ },
+/obj/item/stack/sheet/metal{
+ amount = 50;
+ pixel_x = 2;
+ pixel_y = 2
+ },
+/obj/item/stack/sheet/metal{
+ amount = 50;
+ pixel_x = 2;
+ pixel_y = 2
+ },
+/obj/item/stack/sheet/metal{
+ amount = 50;
+ pixel_x = 2;
+ pixel_y = 2
+ },
+/obj/item/stack/rods{
+ amount = 50
+ },
+/obj/item/stack/rods{
+ amount = 50
+ },
+/obj/item/stack/rods{
+ amount = 50
+ },
+/obj/item/stack/rods{
+ amount = 50
+ },
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"ai" = (
+/obj/structure/closet/cardboard,
+/obj/item/stack/sheet/glass{
+ amount = 50
+ },
+/obj/item/stack/sheet/glass{
+ amount = 50
+ },
+/obj/item/stack/sheet/glass{
+ amount = 50
+ },
+/obj/item/stack/sheet/glass{
+ amount = 50
+ },
+/obj/item/stack/sheet/plasteel{
+ amount = 10
+ },
+/obj/item/stack/sheet/plasteel{
+ amount = 10
+ },
+/obj/item/stack/sheet/plasteel{
+ amount = 10
+ },
+/obj/item/stack/sheet/plasteel{
+ amount = 10
+ },
+/obj/item/clothing/shoes/combat,
+/obj/item/clothing/shoes/combat,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"aj" = (
+/obj/structure/closet/cardboard,
+/obj/machinery/light{
+ icon_state = "tube1";
+ dir = 8
+ },
+/obj/item/device/flashlight/flare,
+/obj/item/device/flashlight/flare,
+/obj/item/device/flashlight/flare,
+/obj/item/device/flashlight/flare,
+/obj/item/device/flashlight/flare,
+/obj/item/device/flashlight/flare,
+/obj/item/device/flashlight,
+/obj/item/device/flashlight,
+/obj/item/device/flashlight,
+/obj/item/weapon/shovel,
+/obj/item/weapon/pickaxe/drill,
+/obj/item/weapon/pickaxe/drill,
+/obj/item/weapon/pickaxe/drill,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"ak" = (
+/obj/structure/closet/cardboard,
+/obj/item/device/flashlight/lantern,
+/obj/item/device/flashlight/lantern,
+/obj/item/device/flashlight/lantern,
+/obj/item/device/tape/random,
+/obj/item/device/tape/random,
+/obj/item/device/tape/random,
+/obj/item/weapon/storage/box/rxglasses,
+/obj/item/weapon/extinguisher,
+/obj/item/weapon/extinguisher,
+/obj/item/clothing/glasses/night,
+/obj/item/clothing/glasses/night,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"al" = (
+/obj/structure/closet/cardboard,
+/obj/item/weapon/storage/box/syringes,
+/obj/item/weapon/storage/box/syringes,
+/obj/item/weapon/storage/box/beakers,
+/obj/item/weapon/storage/box/beakers,
+/obj/item/weapon/storage/box/matches,
+/obj/item/weapon/storage/box/bodybags,
+/obj/item/clothing/glasses/meson/engine,
+/obj/item/clothing/glasses/meson/engine,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"am" = (
+/obj/structure/closet/cardboard,
+/obj/item/weapon/kitchen/knife,
+/obj/item/weapon/kitchen/knife,
+/obj/item/weapon/cultivator,
+/obj/item/weapon/hatchet,
+/obj/item/weapon/kitchen/rollingpin,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"an" = (
+/obj/structure/closet/cardboard,
+/obj/item/weapon/defibrillator,
+/obj/item/weapon/storage/box/medipens,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"ao" = (
+/obj/structure/closet/cardboard,
+/obj/machinery/light{
+ dir = 4;
+ icon_state = "tube1"
+ },
+/obj/item/ammo_box/c9mm,
+/obj/item/ammo_box/c9mm,
+/obj/item/ammo_box/c9mm,
+/obj/item/ammo_box/c9mm,
+/obj/item/ammo_box/c9mm,
+/obj/item/ammo_box/c9mm,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"ap" = (
+/obj/structure/closet/crate/freezer,
+/obj/item/weapon/reagent_containers/blood/OMinus,
+/obj/item/weapon/reagent_containers/blood/OMinus,
+/obj/item/weapon/reagent_containers/blood/OMinus,
+/obj/item/weapon/reagent_containers/blood/OMinus,
+/obj/item/weapon/reagent_containers/blood/OMinus,
+/obj/item/weapon/reagent_containers/blood/random,
+/obj/item/weapon/reagent_containers/blood/random,
+/obj/item/weapon/reagent_containers/blood/random,
+/obj/item/weapon/reagent_containers/blood/random,
+/obj/item/weapon/reagent_containers/blood/random,
+/obj/item/weapon/reagent_containers/blood/random,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"aq" = (
+/obj/machinery/iv_drip,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"ar" = (
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"as" = (
+/obj/machinery/portable_atmospherics/canister/oxygen,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"at" = (
+/obj/machinery/portable_atmospherics/canister/air,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"au" = (
+/obj/machinery/door/airlock/highsecurity{
+ name = "Bunker"
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"av" = (
+/obj/structure/toilet{
+ dir = 4
+ },
+/turf/open/floor/plasteel/freezer,
+/area/ruin/deepstorage)
+"aw" = (
+/obj/structure/mirror{
+ pixel_x = 30
+ },
+/obj/structure/sink{
+ dir = 4;
+ icon_state = "sink";
+ pixel_x = 11;
+ pixel_y = 0
+ },
+/turf/open/floor/plasteel/freezer,
+/area/ruin/deepstorage)
+"ax" = (
+/obj/structure/table,
+/obj/item/weapon/storage/toolbox/drone,
+/obj/item/device/flashlight,
+/obj/item/device/flashlight,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"ay" = (
+/obj/structure/table,
+/obj/item/weapon/gun/ballistic/automatic/wt550{
+ pixel_x = -3;
+ pixel_y = 6
+ },
+/obj/item/weapon/gun/ballistic/automatic/wt550{
+ pixel_x = 2;
+ pixel_y = 0
+ },
+/obj/structure/reagent_dispensers/peppertank{
+ pixel_y = 30
+ },
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"az" = (
+/obj/structure/table,
+/obj/item/weapon/storage/backpack/dufflebag/sec{
+ contents = newlist(/obj/item/weapon/scalpel,/obj/item/weapon/hemostat,/obj/item/weapon/retractor,/obj/item/weapon/cautery,/obj/item/weapon/circular_saw,/obj/item/weapon/surgical_drapes,/obj/item/clothing/mask/surgical);
+ desc = "A large dufflebag for holding extra supplies - this one has a material inlay with space for various sharp-looking tools.";
+ name = "dufflebag";
+ pixel_y = 5
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"aA" = (
+/obj/structure/table,
+/obj/item/device/radio{
+ pixel_x = -4
+ },
+/obj/item/device/radio,
+/obj/item/device/radio{
+ pixel_x = 4
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"aB" = (
+/obj/structure/table,
+/obj/item/stack/sheet/metal{
+ amount = 50;
+ pixel_x = 2;
+ pixel_y = 2
+ },
+/obj/item/stack/rods{
+ amount = 50
+ },
+/obj/item/stack/cable_coil,
+/obj/item/stack/cable_coil,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"aC" = (
+/obj/structure/table,
+/obj/item/weapon/storage/firstaid/brute{
+ pixel_x = 4;
+ pixel_y = 4
+ },
+/obj/item/weapon/storage/firstaid/brute,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"aD" = (
+/obj/structure/table,
+/obj/item/weapon/storage/firstaid/regular{
+ pixel_x = 4;
+ pixel_y = 4
+ },
+/obj/item/weapon/storage/firstaid/regular,
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"aE" = (
+/obj/structure/closet/crate/radiation,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"aF" = (
+/obj/structure/closet/cardboard,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"aG" = (
+/obj/structure/closet/cardboard,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/obj/machinery/light{
+ dir = 4;
+ icon_state = "tube1"
+ },
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"aH" = (
+/obj/structure/closet/cardboard,
+/obj/item/weapon/reagent_containers/glass/beaker/waterbottle/large,
+/obj/item/weapon/reagent_containers/glass/beaker/waterbottle/large,
+/obj/item/weapon/reagent_containers/glass/beaker/waterbottle/large,
+/obj/item/weapon/reagent_containers/glass/beaker/waterbottle/large,
+/obj/item/weapon/reagent_containers/glass/beaker/waterbottle/large,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"aI" = (
+/obj/machinery/vending/clothing,
+/turf/open/floor/wood,
+/area/ruin/deepstorage)
+"aJ" = (
+/turf/open/floor/wood{
+ icon_state = "wood-broken3"
+ },
+/area/ruin/deepstorage)
+"aK" = (
+/obj/structure/bed,
+/turf/open/floor/wood,
+/area/ruin/deepstorage)
+"aL" = (
+/turf/open/floor/plasteel/freezer,
+/area/ruin/deepstorage)
+"aM" = (
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/open/floor/plasteel/freezer,
+/area/ruin/deepstorage)
+"aN" = (
+/obj/structure/table,
+/obj/item/clothing/gloves/combat{
+ pixel_x = -3;
+ pixel_y = 4
+ },
+/obj/item/clothing/gloves/combat{
+ pixel_x = 3;
+ pixel_y = -2
+ },
+/obj/item/clothing/mask/gas,
+/obj/item/clothing/mask/gas,
+/obj/item/clothing/mask/gas,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"aO" = (
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"aP" = (
+/obj/structure/table,
+/obj/item/device/mass_spectrometer/adv,
+/obj/item/device/mass_spectrometer/adv,
+/obj/item/device/healthanalyzer,
+/obj/item/device/healthanalyzer,
+/obj/item/stack/medical/gauze,
+/obj/item/stack/medical/gauze,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"aQ" = (
+/obj/structure/closet/radiation,
+/obj/machinery/light{
+ icon_state = "tube1";
+ dir = 8
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"aR" = (
+/obj/structure/closet/cardboard,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"aS" = (
+/obj/structure/closet/cardboard,
+/obj/item/weapon/reagent_containers/glass/beaker/waterbottle/large,
+/obj/item/weapon/reagent_containers/glass/beaker/waterbottle/large,
+/obj/item/weapon/reagent_containers/glass/beaker/waterbottle/large,
+/obj/item/weapon/reagent_containers/glass/beaker/waterbottle/large,
+/obj/item/weapon/reagent_containers/glass/beaker/waterbottle/large,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"aT" = (
+/obj/structure/closet/wardrobe/pink,
+/turf/open/floor/wood{
+ icon_state = "wood-broken"
+ },
+/area/ruin/deepstorage)
+"aU" = (
+/turf/open/floor/wood,
+/area/ruin/deepstorage)
+"aV" = (
+/obj/structure/bed,
+/turf/open/floor/wood{
+ icon_state = "wood-broken7"
+ },
+/area/ruin/deepstorage)
+"aW" = (
+/obj/machinery/shower{
+ dir = 4
+ },
+/turf/open/floor/plasteel/freezer,
+/area/ruin/deepstorage)
+"aX" = (
+/obj/machinery/shower{
+ dir = 8
+ },
+/turf/open/floor/plasteel/freezer,
+/area/ruin/deepstorage)
+"aY" = (
+/obj/machinery/light/small{
+ dir = 8
+ },
+/obj/structure/table,
+/obj/item/weapon/storage/firstaid/toxin{
+ pixel_x = 4;
+ pixel_y = 4
+ },
+/obj/item/weapon/storage/firstaid/toxin,
+/obj/item/weapon/storage/pill_bottle/charcoal,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"aZ" = (
+/obj/structure/table,
+/obj/item/device/flashlight/flare,
+/obj/item/device/flashlight/flare,
+/obj/item/device/flashlight/flare,
+/obj/item/device/flashlight/flare{
+ pixel_y = 6
+ },
+/obj/item/device/flashlight/flare,
+/obj/item/weapon/crowbar/red,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"ba" = (
+/obj/machinery/suit_storage_unit/standard_unit,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bb" = (
+/obj/structure/closet/wardrobe/pjs,
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/open/floor/wood,
+/area/ruin/deepstorage)
+"bc" = (
+/turf/open/floor/wood{
+ icon_state = "wood-broken4"
+ },
+/area/ruin/deepstorage)
+"bd" = (
+/obj/structure/bed,
+/turf/open/floor/wood{
+ icon_state = "wood-broken3"
+ },
+/area/ruin/deepstorage)
+"be" = (
+/obj/machinery/shower{
+ dir = 4
+ },
+/obj/item/weapon/soap,
+/turf/open/floor/plasteel/freezer,
+/area/ruin/deepstorage)
+"bf" = (
+/obj/structure/grille,
+/obj/structure/window/reinforced/fulltile,
+/turf/open/floor/plating,
+/area/ruin/deepstorage)
+"bg" = (
+/obj/structure/closet/cardboard,
+/obj/item/weapon/storage/box/donkpockets,
+/obj/item/weapon/storage/box/donkpockets,
+/obj/item/weapon/storage/box/donkpockets,
+/obj/item/weapon/storage/box/donkpockets,
+/obj/item/weapon/storage/box/donkpockets,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bh" = (
+/obj/structure/closet/cardboard,
+/obj/item/weapon/storage/box/donkpockets,
+/obj/item/weapon/storage/box/donkpockets,
+/obj/item/weapon/storage/box/donkpockets,
+/obj/item/weapon/storage/box/donkpockets,
+/obj/item/weapon/storage/box/donkpockets,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bi" = (
+/obj/machinery/door/airlock/highsecurity{
+ name = "Bunker"
+ },
+/turf/open/floor/wood,
+/area/ruin/deepstorage)
+"bj" = (
+/obj/machinery/door/airlock/highsecurity{
+ name = "Bunker"
+ },
+/turf/open/floor/plasteel/freezer,
+/area/ruin/deepstorage)
+"bk" = (
+/obj/structure/fireaxecabinet{
+ pixel_y = 30
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bl" = (
+/obj/machinery/sleeper{
+ icon_state = "sleeper-open";
+ dir = 4
+ },
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bm" = (
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bn" = (
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bo" = (
+/obj/machinery/sleeper{
+ icon_state = "sleeper-open";
+ dir = 4
+ },
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bp" = (
+/obj/machinery/door/airlock/highsecurity{
+ name = "Bunker"
+ },
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bq" = (
+/obj/machinery/processor{
+ name = "processor"
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"br" = (
+/obj/structure/table,
+/obj/item/weapon/storage/box/matches,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bs" = (
+/obj/structure/table,
+/obj/machinery/reagentgrinder,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bt" = (
+/obj/structure/table,
+/obj/machinery/recharger,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bu" = (
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/machinery/hydroponics/constructable,
+/turf/open/floor/light,
+/area/ruin/deepstorage)
+"bv" = (
+/obj/machinery/hydroponics/constructable,
+/turf/open/floor/light,
+/area/ruin/deepstorage)
+"bw" = (
+/obj/machinery/blackbox_recorder,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bx" = (
+/obj/structure/cable{
+ icon_state = "0-4";
+ d2 = 4
+ },
+/obj/machinery/power/port_gen/pacman,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"by" = (
+/obj/machinery/power/smes/magical{
+ desc = "A high-capacity superconducting magnetic energy storage (SMES) unit.";
+ name = "power storage unit"
+ },
+/obj/structure/cable,
+/obj/structure/cable{
+ icon_state = "0-2";
+ pixel_y = 1;
+ d2 = 2
+ },
+/obj/structure/cable{
+ d1 = 2;
+ d2 = 8;
+ icon_state = "2-8"
+ },
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bz" = (
+/obj/machinery/telecomms/relay/preset/telecomms,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bA" = (
+/obj/machinery/light/small{
+ dir = 1
+ },
+/obj/structure/tank_dispenser/oxygen,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bB" = (
+/obj/machinery/biogenerator,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bC" = (
+/obj/machinery/light,
+/obj/machinery/hydroponics/constructable,
+/turf/open/floor/light,
+/area/ruin/deepstorage)
+"bD" = (
+/obj/machinery/autolathe,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bE" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/machinery/power/terminal{
+ icon_state = "term";
+ dir = 1
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bF" = (
+/obj/structure/reagent_dispensers/fueltank,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bG" = (
+/obj/structure/table,
+/obj/machinery/microwave,
+/turf/open/floor/plasteel/bar,
+/area/ruin/deepstorage)
+"bH" = (
+/turf/open/floor/plasteel/bar,
+/area/ruin/deepstorage)
+"bI" = (
+/obj/structure/table,
+/obj/item/weapon/storage/box/donkpockets,
+/turf/open/floor/plasteel/bar,
+/area/ruin/deepstorage)
+"bJ" = (
+/obj/structure/table,
+/obj/item/weapon/reagent_containers/food/snacks/beans,
+/turf/open/floor/plasteel/bar,
+/area/ruin/deepstorage)
+"bK" = (
+/obj/structure/chair{
+ dir = 8
+ },
+/turf/open/floor/plasteel/bar,
+/area/ruin/deepstorage)
+"bL" = (
+/obj/machinery/seed_extractor,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bM" = (
+/obj/machinery/power/apc{
+ dir = 8;
+ name = "Bunker APC";
+ pixel_x = -24;
+ pixel_y = 0
+ },
+/obj/structure/cable{
+ icon_state = "0-4";
+ d2 = 4
+ },
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bN" = (
+/obj/structure/cable{
+ d1 = 4;
+ d2 = 8;
+ icon_state = "4-8";
+ pixel_y = 0;
+ tag = ""
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bO" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 8;
+ icon_state = "1-8";
+ tag = ""
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bP" = (
+/obj/structure/reagent_dispensers/watertank,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bQ" = (
+/obj/structure/table,
+/obj/item/weapon/kitchen/knife,
+/turf/open/floor/plasteel/bar,
+/area/ruin/deepstorage)
+"bR" = (
+/obj/structure/table,
+/turf/open/floor/plasteel/bar,
+/area/ruin/deepstorage)
+"bS" = (
+/obj/structure/table,
+/obj/item/weapon/kitchen/fork,
+/turf/open/floor/plasteel/bar,
+/area/ruin/deepstorage)
+"bT" = (
+/obj/machinery/vending/hydronutrients,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bU" = (
+/obj/machinery/space_heater,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"bV" = (
+/obj/structure/chair/office/dark{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bW" = (
+/obj/structure/table/reinforced,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"bX" = (
+/obj/machinery/smartfridge,
+/turf/open/floor/plasteel/bar,
+/area/ruin/deepstorage)
+"bY" = (
+/obj/machinery/light/small,
+/turf/open/floor/plasteel/bar,
+/area/ruin/deepstorage)
+"bZ" = (
+/obj/machinery/vending/hydroseeds{
+ slogan_delay = 700
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"ca" = (
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"cb" = (
+/obj/structure/chair/office/dark,
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"cc" = (
+/obj/structure/frame/computer,
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"cd" = (
+/obj/structure/table/reinforced,
+/obj/machinery/computer/security/telescreen{
+ dir = 1;
+ name = "Bunker Entrance";
+ network = list("Bunker1");
+ pixel_x = 0;
+ pixel_y = 2
+ },
+/turf/open/floor/plasteel,
+/area/ruin/deepstorage)
+"ce" = (
+/obj/structure/table/reinforced,
+/obj/machinery/button/door{
+ id = "bunker1";
+ name = "Inner Doors";
+ pixel_y = 6
+ },
+/obj/machinery/button/door{
+ id = "bunker2";
+ name = "Outer Doors";
+ pixel_y = -4
+ },
+/turf/open/floor/plasteel/floorgrime,
+/area/ruin/deepstorage)
+"cf" = (
+/obj/machinery/door/poddoor{
+ id = "bunker1";
+ name = "Bunker Door";
+ tag = "inner"
+ },
+/turf/open/floor/plating,
+/area/ruin/deepstorage)
+"cg" = (
+/turf/open/floor/plating,
+/area/ruin/deepstorage)
+"ch" = (
+/obj/machinery/camera{
+ network = list("Bunker1")
+ },
+/turf/open/floor/plating,
+/area/ruin/deepstorage)
+"ci" = (
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/ruin/deepstorage)
+"cj" = (
+/obj/machinery/door/poddoor{
+ id = "bunker2";
+ name = "Bunker Door";
+ tag = "outer"
+ },
+/turf/open/floor/plating,
+/area/ruin/deepstorage)
+"ck" = (
+/turf/open/floor/plating/asteroid/airless,
+/area/ruin/deepstorage)
+
+(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
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+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
+aa
+"}
+(2,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+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
+ab
+ab
+ab
+ab
+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
+"}
+(3,1,1) = {"
+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
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(4,1,1) = {"
+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
+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
+"}
+(5,1,1) = {"
+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
+ab
+ab
+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
+"}
+(6,1,1) = {"
+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
+ab
+ab
+ab
+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
+"}
+(7,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(8,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(9,1,1) = {"
+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
+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
+"}
+(10,1,1) = {"
+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
+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
+"}
+(11,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+ab
+ab
+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
+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
+"}
+(12,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+"}
+(13,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(14,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(15,1,1) = {"
+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
+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
+"}
+(16,1,1) = {"
+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
+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
+"}
+(17,1,1) = {"
+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
+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
+ab
+aa
+"}
+(18,1,1) = {"
+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
+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
+ab
+ab
+ab
+"}
+(19,1,1) = {"
+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
+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
+ab
+ab
+ab
+"}
+(20,1,1) = {"
+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
+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
+ab
+ab
+ab
+"}
+(21,1,1) = {"
+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
+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
+ab
+ab
+ab
+"}
+(22,1,1) = {"
+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
+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
+ab
+ab
+ab
+"}
+(23,1,1) = {"
+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
+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
+ck
+ck
+ck
+ab
+ab
+ab
+ab
+ab
+"}
+(24,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ab
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ab
+ab
+ab
+"}
+(25,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+bl
+bo
+ac
+bw
+bD
+bM
+bU
+ca
+ar
+cf
+cg
+cg
+ac
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ab
+ab
+"}
+(26,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ar
+ar
+ac
+bx
+ar
+bN
+ar
+aO
+ar
+cf
+cg
+cg
+ac
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+"}
+(27,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+bp
+ac
+by
+bE
+bO
+aO
+ar
+aO
+ac
+cg
+cg
+ac
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+ck
+"}
+(28,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ab
+ac
+aI
+aT
+bb
+ac
+ar
+aO
+ac
+bz
+aO
+aO
+ar
+aO
+cd
+ac
+ch
+cg
+cj
+ck
+ck
+ck
+ck
+ab
+ab
+ab
+ck
+ck
+ck
+ck
+ck
+"}
+(29,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ab
+ac
+aJ
+aU
+bc
+bi
+ar
+ar
+ac
+aO
+ar
+aO
+ar
+cb
+cc
+ac
+ci
+cg
+cj
+ck
+ck
+ck
+ck
+ab
+ab
+ab
+ab
+ck
+ck
+ck
+ck
+"}
+(30,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ab
+ac
+aK
+aV
+bd
+ac
+ar
+aO
+au
+ar
+ar
+aO
+bV
+aO
+ce
+ac
+ac
+ac
+ac
+ck
+ck
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ck
+ck
+"}
+(31,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+bm
+aO
+ac
+bA
+bF
+bP
+bW
+cc
+bW
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+"}
+(32,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ac
+av
+aL
+aW
+be
+ac
+aO
+aO
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+"}
+(33,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ac
+aw
+aM
+aX
+aX
+bj
+aO
+aO
+ar
+ar
+bG
+bQ
+bX
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(34,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+aO
+aO
+aO
+ar
+bH
+bH
+bY
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(35,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ac
+ax
+aN
+aY
+ac
+bk
+ar
+bq
+ac
+ar
+bI
+bR
+bH
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(36,1,1) = {"
+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
+ab
+ab
+ab
+ac
+ay
+ar
+ar
+bf
+ar
+ar
+br
+ac
+aO
+bJ
+bS
+bH
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(37,1,1) = {"
+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
+ab
+ab
+ab
+ac
+az
+aO
+aO
+bf
+aO
+ar
+bs
+ac
+aO
+bK
+bK
+bH
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(38,1,1) = {"
+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
+ab
+ab
+ab
+ac
+aA
+ar
+aO
+au
+aO
+aO
+bt
+ac
+ar
+ar
+ar
+ar
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(39,1,1) = {"
+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
+ab
+ab
+ab
+ac
+aB
+ar
+aO
+bf
+aO
+aO
+aO
+aO
+aO
+ar
+ar
+aO
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+"}
+(40,1,1) = {"
+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
+ab
+ab
+ab
+ac
+aC
+aO
+ar
+bf
+aO
+bn
+aO
+aO
+bB
+bL
+bT
+bZ
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+"}
+(41,1,1) = {"
+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
+ac
+ac
+ac
+ac
+ac
+aD
+aP
+aZ
+ac
+au
+ac
+ac
+au
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+"}
+(42,1,1) = {"
+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
+ac
+ad
+aj
+ap
+ac
+ac
+ac
+ac
+ac
+aO
+ac
+bu
+aO
+bC
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(43,1,1) = {"
+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
+ac
+ae
+ak
+aq
+ac
+aE
+aQ
+ba
+ba
+aO
+ac
+bv
+aO
+bv
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(44,1,1) = {"
+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
+ac
+af
+al
+ar
+au
+ar
+ar
+aO
+aO
+ar
+ac
+bv
+aO
+bv
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(45,1,1) = {"
+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
+ac
+ag
+am
+ar
+ac
+aF
+aR
+aR
+bg
+bg
+ac
+bu
+aO
+bC
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(46,1,1) = {"
+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
+ac
+ah
+an
+as
+ac
+aG
+aR
+aR
+bh
+bh
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(47,1,1) = {"
+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
+ac
+ai
+ao
+at
+ac
+aH
+aS
+aH
+aH
+aH
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(48,1,1) = {"
+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
+ac
+ac
+ac
+ac
+ac
+aH
+aH
+aH
+aH
+aH
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(49,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(50,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+"}
+(51,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+"}
+(52,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+"}
+(53,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+"}
+(54,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+"}
+(55,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+"}
+(56,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+"}
+(57,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(58,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(59,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+aa
+"}
+(60,1,1) = {"
+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
+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
+ab
+ab
+ab
+aa
+aa
+"}
+(61,1,1) = {"
+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
+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
+ab
+ab
+ab
+aa
+aa
+"}
+(62,1,1) = {"
+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
+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
+ab
+ab
+ab
+aa
+aa
+"}
+(63,1,1) = {"
+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
+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
+ab
+ab
+ab
+aa
+aa
+"}
+(64,1,1) = {"
+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
+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
+ab
+ab
+aa
+aa
+aa
+"}
+(65,1,1) = {"
+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
+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
+ab
+ab
+aa
+aa
+aa
+"}
+(66,1,1) = {"
+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
+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
+ab
+ab
+ab
+aa
+aa
+aa
+"}
+(67,1,1) = {"
+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
+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
+ab
+ab
+ab
+aa
+aa
+aa
+"}
+(68,1,1) = {"
+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
+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
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+"}
+(69,1,1) = {"
+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
+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
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+"}
+(70,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+"}
+(71,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+"}
+(72,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+"}
+(73,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+"}
+(74,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+"}
+(75,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+"}
+(76,1,1) = {"
+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
+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
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+"}
+(77,1,1) = {"
+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
+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
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(78,1,1) = {"
+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
+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
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(79,1,1) = {"
+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
+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
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(80,1,1) = {"
+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
+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
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(81,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+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
+"}
+(82,1,1) = {"
+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
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+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
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(83,1,1) = {"
+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
+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
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(84,1,1) = {"
+aa
+aa
+ab
+ab
+ab
+aa
+aa
+ab
+ab
+aa
+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
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(85,1,1) = {"
+aa
+aa
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+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
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 2e275a194f..c46f6ea830 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -44697,9 +44697,7 @@
/obj/effect/turf_decal/stripes/line{
dir = 2
},
-/turf/open/floor/plating{
- icon_state = "plating_warn_side"
- },
+/turf/open/floor/plating,
/area/maintenance/starboard)
"bGN" = (
/obj/effect/decal/cleanable/dirt,
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index d841a0f335..0e3fea852f 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -72622,11 +72622,11 @@ aHl
aIi
aJs
aKz
-buW
+buX
aMR
buZ
-buZ
-buW
+bva
+bvb
aQL
aRI
aSS
@@ -72883,7 +72883,7 @@ aLP
aMS
aMS
aOC
-buW
+bvc
aQM
aRJ
aST
@@ -73911,7 +73911,7 @@ aLT
aMW
aMW
aOD
-buW
+bve
aQQ
aRN
aSX
@@ -74164,11 +74164,11 @@ aHr
aIo
aJw
aKE
-buW
+buY
aMX
aMX
aMX
-buW
+bvf
aQR
aRO
aSY
diff --git a/_maps/map_files/generic/Centcomm.dmm b/_maps/map_files/generic/Centcomm.dmm
index 6782e4cce4..9f7787b585 100644
--- a/_maps/map_files/generic/Centcomm.dmm
+++ b/_maps/map_files/generic/Centcomm.dmm
@@ -20,7 +20,7 @@
/turf/closed/indestructible/riveted,
/area/space)
"af" = (
-/turf/open/floor/holofloor/snow/cold,
+/turf/open/floor/holofloor/snow,
/area/holodeck/rec_center/winterwonderland)
"ag" = (
/obj/structure/window/reinforced{
@@ -141,7 +141,7 @@
/area/space)
"ax" = (
/obj/structure/flora/bush,
-/turf/open/floor/holofloor/snow/cold,
+/turf/open/floor/holofloor/snow,
/area/holodeck/rec_center/winterwonderland)
"ay" = (
/obj/item/toy/snowball{
@@ -155,7 +155,7 @@
/obj/item/toy/snowball{
pixel_x = -4
},
-/turf/open/floor/holofloor/snow/cold,
+/turf/open/floor/holofloor/snow,
/area/holodeck/rec_center/winterwonderland)
"az" = (
/turf/open/floor/holofloor{
@@ -216,7 +216,7 @@
/area/holodeck/rec_center/court)
"aI" = (
/obj/structure/flora/grass/brown,
-/turf/open/floor/holofloor/snow/cold,
+/turf/open/floor/holofloor/snow,
/area/holodeck/rec_center/winterwonderland)
"aJ" = (
/obj/structure/table,
@@ -268,7 +268,7 @@
/obj/structure/statue/snow/snowman{
anchored = 1
},
-/turf/open/floor/holofloor/snow/cold,
+/turf/open/floor/holofloor/snow,
/area/holodeck/rec_center/winterwonderland)
"aP" = (
/obj/structure/chair/wood/normal{
@@ -282,7 +282,7 @@
/area/holodeck/rec_center/lounge)
"aQ" = (
/obj/structure/chair/wood/wings,
-/turf/open/floor/holofloor/snow/cold,
+/turf/open/floor/holofloor/snow,
/area/holodeck/rec_center/winterwonderland)
"aR" = (
/obj/structure/window/reinforced/tinted{
@@ -303,11 +303,11 @@
/area/holodeck/rec_center/lounge)
"aT" = (
/obj/structure/flora/tree/pine,
-/turf/open/floor/holofloor/snow/cold,
+/turf/open/floor/holofloor/snow,
/area/holodeck/rec_center/winterwonderland)
"aU" = (
/obj/structure/chair/wood,
-/turf/open/floor/holofloor/snow/cold,
+/turf/open/floor/holofloor/snow,
/area/holodeck/rec_center/winterwonderland)
"aV" = (
/obj/structure/table/wood,
@@ -14883,6 +14883,20 @@
/obj/machinery/computer/emergency_shuttle,
/turf/open/floor/mineral/titanium,
/area/shuttle/escape)
+"Me" = (
+/obj/machinery/light{
+ icon_state = "tube1";
+ dir = 8
+ },
+/turf/open/floor/mineral/titanium,
+/area/shuttle/escape)
+"Mf" = (
+/obj/machinery/light{
+ icon_state = "tube1";
+ dir = 4
+ },
+/turf/open/floor/mineral/titanium,
+/area/shuttle/escape)
(1,1,1) = {"
aa
@@ -64444,7 +64458,7 @@ Fa
Fh
Fh
Fh
-Fh
+Me
Fh
Fh
Fa
@@ -65729,7 +65743,7 @@ Fa
Md
Fp
FC
-Fh
+Mf
Fh
Fh
Fa
diff --git a/bot/config.py b/bot/config.py
index 8888753ab7..c0ffc55bed 100644
--- a/bot/config.py
+++ b/bot/config.py
@@ -1,6 +1,7 @@
# Configuration for the minibot.py bot starts here
server = "irc.rizon.net"
port = 6667
+nudge_port = 45678
channels = ["#asdfgbus", "#botbus"]
defaultchannel = "#asdfgbus"
diff --git a/bot/minibot.py b/bot/minibot.py
index 82e46722f8..cc5ac1a5b4 100644
--- a/bot/minibot.py
+++ b/bot/minibot.py
@@ -73,7 +73,7 @@ def setup_irc_socket():
def setup_nudge_socket():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.bind(("", 45678)) # localhost:45678
+ s.bind(("", nudge_port)) # localhost:nudge_port
s.listen(5)
logger.info("Nudge socket up and listening")
return s
diff --git a/bot/nudge.py b/bot/nudge.py
index 7f195adae1..8a13c5636b 100644
--- a/bot/nudge.py
+++ b/bot/nudge.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python3
+from config import *
import sys
import pickle
import socket
@@ -16,7 +17,7 @@ def pack():
def nudge(data):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect(("localhost", 45678))
+ s.connect(("localhost", nudge_port))
s.send(data)
s.close()
diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm
new file mode 100644
index 0000000000..d30a2d098f
--- /dev/null
+++ b/code/__DEFINES/antagonists.dm
@@ -0,0 +1,3 @@
+#define ANTAG_DATUM_CULT /datum/antagonist/cult
+#define ANTAG_DATUM_CLOCKCULT /datum/antagonist/clockcult
+#define ANTAG_DATUM_CLOCKCULT_SILENT /datum/antagonist/clockcult/silent
\ No newline at end of file
diff --git a/code/__DEFINES/language.dm b/code/__DEFINES/language.dm
index 3f09f46817..e7818d7bf3 100644
--- a/code/__DEFINES/language.dm
+++ b/code/__DEFINES/language.dm
@@ -1,2 +1,4 @@
#define NO_STUTTER 1
#define TONGUELESS_SPEECH 2
+#define LANGUAGE_HIDE_ICON_IF_UNDERSTOOD 4
+#define LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD 8
diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm
index 004ea378da..9524fc9a43 100644
--- a/code/__DEFINES/machines.dm
+++ b/code/__DEFINES/machines.dm
@@ -23,6 +23,7 @@
#define MECHFAB 16 //Remember, objects utilising this flag should have construction_time and construction_cost vars.
#define BIOGENERATOR 32 //Uses biomass
#define LIMBGROWER 64 //Uses synthetic flesh
+#define SMELTER 128 //uses various minerals
//Note: More then one of these can be added to a design but imprinter and lathe designs are incompatable.
//Modular computer/NTNet defines
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index efb9b3addf..321bbf7b67 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -201,6 +201,21 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache)
#define BLOOD_STATE_XENO "xeno"
#define BLOOD_STATE_OIL "oil"
#define BLOOD_STATE_NOT_BLOODY "no blood whatsoever"
+
+//suit sensors: sensor_mode defines
+
+#define SENSOR_OFF 0
+#define SENSOR_LIVING 1
+#define SENSOR_VITALS 2
+#define SENSOR_COORDS 3
+
+//suit sensors: has_sensor defines
+
+#define BROKEN_SENSORS -1
+#define NO_SENSORS 0
+#define HAS_SENSORS 1
+#define LOCKED_SENSORS 2
+
//Turf wet states
#define TURF_DRY 0
#define TURF_WET_WATER 1
diff --git a/code/__DEFINES/subsystems.dm.rej b/code/__DEFINES/subsystems.dm.rej
deleted file mode 100644
index cf39977224..0000000000
--- a/code/__DEFINES/subsystems.dm.rej
+++ /dev/null
@@ -1,18 +0,0 @@
-diff a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm (rejected hunks)
-@@ -26,4 +26,13 @@
-
- #define INITIALIZE_HINT_NORMAL 0 //Nothing happens
- #define INITIALIZE_HINT_LATELOAD 1 //Call LateInitialize
--#define INITIALIZE_HINT_QDEL 2 //Call qdel on the atom
-\ No newline at end of file
-+#define INITIALIZE_HINT_QDEL 2 //Call qdel on the atom
-+
-+//type and all subtypes should always call Initialize in New()
-+#define INITIALIZE_IMMEDIATE(X) ##X/New(loc, ...){\
-+ ..();\
-+ if(!initialized) {\
-+ args[1] = TRUE;\
-+ SSatoms.InitAtom(src, args);\
-+ }\
-+}
-\ No newline at end of file
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index 6fd41f7ea1..6bc79fb7d5 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -513,7 +513,7 @@
winset(C, "mainwindow", "flash=5")
/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank)
- if(SSticker.current_state != GAME_STATE_PLAYING || !character)
+ if(!SSticker.IsRoundInProgress() || !character)
return
var/area/A = get_area(character)
var/message = "\
diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm
index 32969dd5d8..e378970225 100644
--- a/code/_globalvars/lists/mobs.dm
+++ b/code/_globalvars/lists/mobs.dm
@@ -11,6 +11,7 @@ GLOBAL_LIST_EMPTY(stealthminID) //reference list with IDs that store ckeys,
GLOBAL_LIST_EMPTY(player_list) //all mobs **with clients attached**. Excludes /mob/dead/new_player
GLOBAL_LIST_EMPTY(mob_list) //all mobs, including clientless
+GLOBAL_LIST_EMPTY(mob_directory) //mob_id -> mob
GLOBAL_LIST_EMPTY(living_mob_list) //all alive mobs, including clientless. Excludes /mob/dead/new_player
GLOBAL_LIST_EMPTY(dead_mob_list) //all dead mobs, including clientless. Excludes /mob/dead/new_player
GLOBAL_LIST_EMPTY(joined_player_list) //all clients that have joined the game at round-start or as a latejoin.
diff --git a/code/_globalvars/lists/names.dm b/code/_globalvars/lists/names.dm
index 15a0867667..5726a1501d 100644
--- a/code/_globalvars/lists/names.dm
+++ b/code/_globalvars/lists/names.dm
@@ -1,23 +1,23 @@
-GLOBAL_LIST_INIT(ai_names, world.file2list("config/names/ai.txt"))
-GLOBAL_LIST_INIT(wizard_first, world.file2list("config/names/wizardfirst.txt"))
-GLOBAL_LIST_INIT(wizard_second, world.file2list("config/names/wizardsecond.txt"))
-GLOBAL_LIST_INIT(ninja_titles, world.file2list("config/names/ninjatitle.txt"))
-GLOBAL_LIST_INIT(ninja_names, world.file2list("config/names/ninjaname.txt"))
-GLOBAL_LIST_INIT(commando_names, world.file2list("config/names/death_commando.txt"))
-GLOBAL_LIST_INIT(first_names_male, world.file2list("config/names/first_male.txt"))
-GLOBAL_LIST_INIT(first_names_female, world.file2list("config/names/first_female.txt"))
-GLOBAL_LIST_INIT(last_names, world.file2list("config/names/last.txt"))
-GLOBAL_LIST_INIT(lizard_names_male, world.file2list("config/names/lizard_male.txt"))
-GLOBAL_LIST_INIT(lizard_names_female, world.file2list("config/names/lizard_female.txt"))
-GLOBAL_LIST_INIT(clown_names, world.file2list("config/names/clown.txt"))
-GLOBAL_LIST_INIT(mime_names, world.file2list("config/names/mime.txt"))
-GLOBAL_LIST_INIT(carp_names, world.file2list("config/names/carp.txt"))
-GLOBAL_LIST_INIT(golem_names, world.file2list("config/names/golem.txt"))
-GLOBAL_LIST_INIT(plasmaman_names, world.file2list("config/names/plasmaman.txt"))
-GLOBAL_LIST_INIT(posibrain_names, list("PBU","HIU","SINA","ARMA","OSI","HBL","MSO","RR","CHRI","CDB","HG","XSI","ORNG","GUN","KOR","MET","FRE","XIS","SLI","PKP","HOG","RZH","GOOF","MRPR","JJR","FIRC","INC","PHL","BGB","ANTR","MIW","WJ","JRD","CHOC","ANCL","JLLO","JNLG","KOS","TKRG","XAL","STLP","CBOS","DUNC","FXMC","DRSD","COI"))
+GLOBAL_LIST_INIT(ai_names, world.file2list("strings/names/ai.txt"))
+GLOBAL_LIST_INIT(wizard_first, world.file2list("strings/names/wizardfirst.txt"))
+GLOBAL_LIST_INIT(wizard_second, world.file2list("strings/names/wizardsecond.txt"))
+GLOBAL_LIST_INIT(ninja_titles, world.file2list("strings/names/ninjatitle.txt"))
+GLOBAL_LIST_INIT(ninja_names, world.file2list("strings/names/ninjaname.txt"))
+GLOBAL_LIST_INIT(commando_names, world.file2list("strings/names/death_commando.txt"))
+GLOBAL_LIST_INIT(first_names_male, world.file2list("strings/names/first_male.txt"))
+GLOBAL_LIST_INIT(first_names_female, world.file2list("strings/names/first_female.txt"))
+GLOBAL_LIST_INIT(last_names, world.file2list("strings/names/last.txt"))
+GLOBAL_LIST_INIT(lizard_names_male, world.file2list("strings/names/lizard_male.txt"))
+GLOBAL_LIST_INIT(lizard_names_female, world.file2list("strings/names/lizard_female.txt"))
+GLOBAL_LIST_INIT(clown_names, world.file2list("strings/names/clown.txt"))
+GLOBAL_LIST_INIT(mime_names, world.file2list("strings/names/mime.txt"))
+GLOBAL_LIST_INIT(carp_names, world.file2list("strings/names/carp.txt"))
+GLOBAL_LIST_INIT(golem_names, world.file2list("strings/names/golem.txt"))
+GLOBAL_LIST_INIT(plasmaman_names, world.file2list("strings/names/plasmaman.txt"))
+GLOBAL_LIST_INIT(posibrain_names, world.file2list("strings/names/posibrain.txt"))
-GLOBAL_LIST_INIT(verbs, world.file2list("config/names/verbs.txt"))
-GLOBAL_LIST_INIT(adjectives, world.file2list("config/names/adjectives.txt"))
+GLOBAL_LIST_INIT(verbs, world.file2list("strings/names/verbs.txt"))
+GLOBAL_LIST_INIT(adjectives, world.file2list("strings/names/adjectives.txt"))
//loaded on startup because of "
//would include in rsc if ' was used
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index be771e0676..e82976d4a3 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -29,6 +29,7 @@ GLOBAL_LIST_EMPTY(zombie_infection_list) // A list of all zombie_infection org
GLOBAL_LIST_EMPTY(meteor_list) // List of all meteors.
GLOBAL_LIST_EMPTY(active_jammers) // List of active radio jammers
GLOBAL_LIST_EMPTY(ladders)
+GLOBAL_LIST_EMPTY(trophy_cases)
GLOBAL_LIST_EMPTY(wire_color_directory)
GLOBAL_LIST_EMPTY(wire_name_directory)
\ No newline at end of file
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index 90c953a110..8c62d68963 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -111,6 +111,10 @@
#define ui_alienplasmadisplay "EAST-1:28,CENTER-2:15"
#define ui_alien_queen_finder "EAST-1:28,CENTER-3:15"
+//constructs
+#define ui_construct_pull "EAST,CENTER-2:15"
+#define ui_construct_health "EAST,CENTER:15" //same as borgs and humans
+
// AI
#define ui_ai_core "SOUTH:6,WEST"
diff --git a/code/_onclick/hud/constructs.dm b/code/_onclick/hud/constructs.dm
new file mode 100644
index 0000000000..dc3cea7f99
--- /dev/null
+++ b/code/_onclick/hud/constructs.dm
@@ -0,0 +1,18 @@
+
+/datum/hud/construct
+ ui_style_icon = 'icons/mob/screen_construct.dmi'
+
+/datum/hud/construct/New(mob/owner)
+ ..()
+ pull_icon = new /obj/screen/pull()
+ pull_icon.icon = ui_style_icon
+ pull_icon.update_icon(mymob)
+ pull_icon.screen_loc = ui_pull_resist
+ static_inventory += pull_icon
+
+ healths = new /obj/screen/healths/construct()
+ infodisplay += healths
+
+/mob/living/simple_animal/hostile/construct/create_mob_hud()
+ if(client && !hud_used)
+ hud_used = new /datum/hud/construct(src)
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 81754efc93..bfab19ba5f 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -532,6 +532,12 @@
screen_loc = ui_health
mouse_opacity = 0
+/obj/screen/healths/construct
+ icon = 'icons/mob/screen_construct.dmi'
+ icon_state = "artificer_health0"
+ screen_loc = ui_construct_health
+ mouse_opacity = 0
+
/obj/screen/healthdoll
name = "health doll"
screen_loc = ui_healthdoll
diff --git a/code/citadel/_cit_helpers.dm b/code/citadel/_cit_helpers.dm
index 6e4ea762f1..db0626fa9c 100644
--- a/code/citadel/_cit_helpers.dm
+++ b/code/citadel/_cit_helpers.dm
@@ -117,7 +117,7 @@ GLOBAL_VAR_INIT(dlooc_allowed, 1)
prefs.chat_toggles ^= CHAT_LOOC
prefs.save_preferences()
src << "You will [(prefs.chat_toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel."
- feedback_add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/togglelooc()
set category = "Server"
@@ -126,7 +126,7 @@ GLOBAL_VAR_INIT(dlooc_allowed, 1)
toggle_looc()
log_admin("[key_name(usr)] toggled LOOC.")
message_admins("[key_name_admin(usr)] toggled LOOC.")
- feedback_add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/proc/toggle_looc(toggle = null)
if(toggle != null) //if we're specifically en/disabling ooc
@@ -146,7 +146,7 @@ GLOBAL_VAR_INIT(dlooc_allowed, 1)
log_admin("[key_name(usr)] toggled Dead LOOC.")
message_admins("[key_name_admin(usr)] toggled Dead LOOC.")
- feedback_add_details("admin_verb","TDLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.add_details("admin_verb","TDLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/mob/living/carbon/proc/has_penis()
diff --git a/code/citadel/organs/genitals.dm b/code/citadel/organs/genitals.dm
index 4066295350..c129d8e8fa 100644
--- a/code/citadel/organs/genitals.dm
+++ b/code/citadel/organs/genitals.dm
@@ -16,7 +16,8 @@
/obj/item/organ/genital/Initialize()
. = ..()
- reagents = create_reagents(fluid_max_volume)
+ if(!reagents)
+ create_reagents(fluid_max_volume)
update()
/obj/item/organ/genital/Destroy()
diff --git a/code/controllers/admin.dm b/code/controllers/admin.dm
index 2be7139a27..3565620c88 100644
--- a/code/controllers/admin.dm
+++ b/code/controllers/admin.dm
@@ -45,9 +45,9 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick)
switch(controller)
if("Master")
Recreate_MC()
- feedback_add_details("admin_verb","Restart Master Controller")
+ SSblackbox.add_details("admin_verb","Restart Master Controller")
if("Failsafe")
new /datum/controller/failsafe()
- feedback_add_details("admin_verb","Restart Failsafe Controller")
+ SSblackbox.add_details("admin_verb","Restart Failsafe Controller")
message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.")
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index ab4ff43b04..01d0ac3447 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -48,7 +48,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
var/initializations_finished_with_no_players_logged_in //I wonder what this could be?
// Has round started? (So we know what subsystems to run)
- var/round_started = 0
+ var/local_round_started = FALSE //Don't read this var, use SSticker.HasRoundStarted() instead
// The type of the last subsystem to be process()'d.
var/last_type_processed
@@ -189,7 +189,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
// Notify the MC that the round has started.
/datum/controller/master/proc/RoundStart()
- round_started = 1
+ local_round_started = TRUE
var/timer = world.time
for (var/datum/controller/subsystem/SS in subsystems)
if (SS.flags & SS_FIRE_IN_LOBBY || SS.flags & SS_TICKER)
@@ -222,7 +222,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
// local vars rock
// Schedule the first run of the Subsystems.
- round_started = world.has_round_started()
+ local_round_started = world.has_round_started()
//all this shit is here so that flag edits can be refreshed by restarting the MC. (and for speed)
var/list/tickersubsystems = list()
var/list/normalsubsystems = list()
@@ -245,7 +245,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
lobbysubsystems += SS
timer += world.tick_lag * rand(1, 5)
SS.next_fire = timer
- else if (round_started)
+ else if (local_round_started)
timer += world.tick_lag * rand(1, 5)
SS.next_fire = timer
normalsubsystems += SS
@@ -296,7 +296,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
if (!Failsafe || (Failsafe.processing_interval > 0 && (Failsafe.lasttick+(Failsafe.processing_interval*5)) < world.time))
new/datum/controller/failsafe() // (re)Start the failsafe.
if (!queue_head || !(iteration % 3))
- if (round_started)
+ if (local_round_started)
subsystems_to_check = normalsubsystems
else
subsystems_to_check = lobbysubsystems
diff --git a/code/controllers/subsystem/atoms.dm.rej b/code/controllers/subsystem/atoms.dm.rej
deleted file mode 100644
index 4d7225164f..0000000000
--- a/code/controllers/subsystem/atoms.dm.rej
+++ /dev/null
@@ -1,9 +0,0 @@
-diff a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm (rejected hunks)
-@@ -12,6 +12,7 @@ SUBSYSTEM_DEF(atoms)
- var/old_initialized
-
- var/list/late_loaders
-+ var/list/created_atoms
-
- var/list/BadInitializeCalls = list()
-
diff --git a/code/orphaned_procs/statistics.dm b/code/controllers/subsystem/blackbox.dm
similarity index 59%
rename from code/orphaned_procs/statistics.dm
rename to code/controllers/subsystem/blackbox.dm
index d6cdcda6c1..1b14b352df 100644
--- a/code/orphaned_procs/statistics.dm
+++ b/code/controllers/subsystem/blackbox.dm
@@ -1,9 +1,7 @@
-GLOBAL_DATUM_INIT(blackbox, /datum/feedback, new)
-
-//the feedback datum; stores all feedback
-/datum/feedback
- var/list/messages = list()
- var/list/messages_admin = list()
+SUBSYSTEM_DEF(blackbox)
+ name = "Blackbox"
+ wait = 6000
+ flags = SS_NO_TICK_CHECK
var/list/msg_common = list()
var/list/msg_science = list()
@@ -15,21 +13,47 @@ GLOBAL_DATUM_INIT(blackbox, /datum/feedback, new)
var/list/msg_syndicate = list()
var/list/msg_service = list()
var/list/msg_cargo = list()
+ var/list/msg_other = list()
- var/list/datum/feedback_variable/feedback = new()
+ var/list/feedback = list() //list of datum/feedback_variable
-/datum/feedback/proc/find_feedback_datum(variable)
- for (var/datum/feedback_variable/FV in feedback)
- if (FV.get_variable() == variable)
- return FV
- var/datum/feedback_variable/FV = new(variable)
- feedback += FV
- return FV
+//poll population
+/datum/controller/subsystem/blackbox/fire()
+ if(!SSdbcore.Connect())
+ return
+ var/playercount = 0
+ for(var/mob/M in GLOB.player_list)
+ if(M.client)
+ playercount += 1
+ var/admincount = GLOB.admins.len
+ var/datum/DBQuery/query_record_playercount = SSdbcore.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time, server_ip, server_port) VALUES ([playercount], [admincount], '[SQLtime()]', INET_ATON('[world.internet_address]'), '[world.port]')")
+ query_record_playercount.Execute()
-/datum/feedback/proc/get_round_feedback()
- return feedback
+/datum/controller/subsystem/blackbox/Recover()
+ msg_common = SSblackbox.msg_common
+ msg_science = SSblackbox.msg_science
+ msg_command = SSblackbox.msg_command
+ msg_medical = SSblackbox.msg_medical
+ msg_engineering = SSblackbox.msg_engineering
+ msg_security = SSblackbox.msg_security
+ msg_deathsquad = SSblackbox.msg_deathsquad
+ msg_syndicate = SSblackbox.msg_syndicate
+ msg_service = SSblackbox.msg_service
+ msg_cargo = SSblackbox.msg_cargo
+ msg_other = SSblackbox.msg_other
-/datum/feedback/proc/round_end_data_gathering()
+ feedback = SSblackbox.feedback
+
+//no touchie
+/datum/controller/subsystem/blackbox/can_vv_get(var_name)
+ if(var_name == "feedback")
+ return FALSE
+ return ..()
+
+/datum/controller/subsystem/blackbox/vv_edit_var(var_name, var_value)
+ return FALSE
+
+/datum/controller/subsystem/blackbox/Shutdown()
var/pda_msg_amt = 0
var/rc_msg_amt = 0
@@ -39,30 +63,27 @@ GLOBAL_DATUM_INIT(blackbox, /datum/feedback, new)
if (MS.rc_msgs.len > rc_msg_amt)
rc_msg_amt = MS.rc_msgs.len
- feedback_set_details("radio_usage","")
+ set_details("radio_usage","")
- feedback_add_details("radio_usage","COM-[msg_common.len]")
- feedback_add_details("radio_usage","SCI-[msg_science.len]")
- feedback_add_details("radio_usage","HEA-[msg_command.len]")
- feedback_add_details("radio_usage","MED-[msg_medical.len]")
- feedback_add_details("radio_usage","ENG-[msg_engineering.len]")
- feedback_add_details("radio_usage","SEC-[msg_security.len]")
- feedback_add_details("radio_usage","DTH-[msg_deathsquad.len]")
- feedback_add_details("radio_usage","SYN-[msg_syndicate.len]")
- feedback_add_details("radio_usage","SRV-[msg_service.len]")
- feedback_add_details("radio_usage","CAR-[msg_cargo.len]")
- feedback_add_details("radio_usage","OTH-[messages.len]")
- feedback_add_details("radio_usage","PDA-[pda_msg_amt]")
- feedback_add_details("radio_usage","RC-[rc_msg_amt]")
+ add_details("radio_usage","COM-[msg_common.len]")
+ add_details("radio_usage","SCI-[msg_science.len]")
+ add_details("radio_usage","HEA-[msg_command.len]")
+ add_details("radio_usage","MED-[msg_medical.len]")
+ add_details("radio_usage","ENG-[msg_engineering.len]")
+ add_details("radio_usage","SEC-[msg_security.len]")
+ add_details("radio_usage","DTH-[msg_deathsquad.len]")
+ add_details("radio_usage","SYN-[msg_syndicate.len]")
+ add_details("radio_usage","SRV-[msg_service.len]")
+ add_details("radio_usage","CAR-[msg_cargo.len]")
+ add_details("radio_usage","OTH-[msg_other.len]")
+ add_details("radio_usage","PDA-[pda_msg_amt]")
+ add_details("radio_usage","RC-[rc_msg_amt]")
- feedback_set_details("round_end","[time2text(world.realtime)]") //This one MUST be the last one that gets set.
+ set_details("round_end","[time2text(world.realtime)]") //This one MUST be the last one that gets set.
-//This proc is only to be called at round end.
-/datum/feedback/proc/save_all_data_to_sql()
- if (!feedback) return
+ if (!SSdbcore.Connect())
+ return
- round_end_data_gathering() //round_end time logging and some other data processing
- if (!SSdbcore.Connect()) return
var/round_id
var/datum/DBQuery/query_feedback_max_id = SSdbcore.NewQuery("SELECT MAX(round_id) AS round_id FROM [format_table_name("feedback")]")
@@ -89,69 +110,99 @@ GLOBAL_DATUM_INIT(blackbox, /datum/feedback, new)
var/datum/DBQuery/query_feedback_save = SSdbcore.NewQuery("INSERT DELAYED IGNORE INTO [format_table_name("feedback")] VALUES " + sqlrowlist)
query_feedback_save.Execute()
+/datum/controller/subsystem/blackbox/proc/LogBroadcast(blackbox_msg, freq)
+ switch(freq)
+ if(1459)
+ msg_common += blackbox_msg
+ if(1351)
+ msg_science += blackbox_msg
+ if(1353)
+ msg_command += blackbox_msg
+ if(1355)
+ msg_medical += blackbox_msg
+ if(1357)
+ msg_engineering += blackbox_msg
+ if(1359)
+ msg_security += blackbox_msg
+ if(1441)
+ msg_deathsquad += blackbox_msg
+ if(1213)
+ msg_syndicate += blackbox_msg
+ if(1349)
+ msg_service += blackbox_msg
+ if(1347)
+ msg_cargo += blackbox_msg
+ else
+ msg_other += blackbox_msg
-/proc/feedback_set(variable,value)
- if(!GLOB.blackbox)
- return
+/datum/controller/subsystem/blackbox/proc/find_feedback_datum(variable)
+ for(var/datum/feedback_variable/FV in feedback)
+ if(FV.get_variable() == variable)
+ return FV
- var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable)
-
- if(!FV)
- return
+ var/datum/feedback_variable/FV = new(variable)
+ feedback += FV
+ return FV
+/datum/controller/subsystem/blackbox/proc/set_val(variable, value)
+ var/datum/feedback_variable/FV = find_feedback_datum(variable)
FV.set_value(value)
-/proc/feedback_inc(variable,value)
- if(!GLOB.blackbox)
- return
-
- var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable)
-
- if(!FV)
- return
-
+/datum/controller/subsystem/blackbox/proc/inc(variable, value)
+ var/datum/feedback_variable/FV = find_feedback_datum(variable)
FV.inc(value)
-/proc/feedback_dec(variable,value)
- if(!GLOB.blackbox)
- return
-
- var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable)
-
- if(!FV)
- return
-
+/datum/controller/subsystem/blackbox/proc/dec(variable,value)
+ var/datum/feedback_variable/FV = find_feedback_datum(variable)
FV.dec(value)
-/proc/feedback_set_details(variable,details)
- if(!GLOB.blackbox)
- return
-
- var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable)
-
- if(!FV)
- return
-
+/datum/controller/subsystem/blackbox/proc/set_details(variable,details)
+ var/datum/feedback_variable/FV = find_feedback_datum(variable)
FV.set_details(details)
-/proc/feedback_add_details(variable,details)
- if(!GLOB.blackbox)
- return
-
- var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable)
-
- if(!FV)
- return
-
+/datum/controller/subsystem/blackbox/proc/add_details(variable,details)
+ var/datum/feedback_variable/FV = find_feedback_datum(variable)
FV.add_details(details)
+/datum/controller/subsystem/blackbox/proc/ReportDeath(mob/living/L)
+ if(!SSdbcore.Connect())
+ return
+ if(!L || !L.key || !L.mind)
+ return
+ var/turf/T = get_turf(L)
+ var/area/placeofdeath = get_area(T.loc)
+ var/sqlname = sanitizeSQL(L.real_name)
+ var/sqlkey = sanitizeSQL(L.ckey)
+ var/sqljob = sanitizeSQL(L.mind.assigned_role)
+ var/sqlspecial = sanitizeSQL(L.mind.special_role)
+ var/sqlpod = sanitizeSQL(placeofdeath.name)
+ var/laname
+ var/lakey
+ if(L.lastattacker && ismob(L.lastattacker))
+ var/mob/LA = L.lastattacker
+ laname = sanitizeSQL(LA.real_name)
+ lakey = sanitizeSQL(LA.key)
+ var/sqlgender = sanitizeSQL(L.gender)
+ var/sqlbrute = sanitizeSQL(L.getBruteLoss())
+ var/sqlfire = sanitizeSQL(L.getFireLoss())
+ var/sqlbrain = sanitizeSQL(L.getBrainLoss())
+ var/sqloxy = sanitizeSQL(L.getOxyLoss())
+ var/sqltox = sanitizeSQL(L.getStaminaLoss())
+ var/sqlclone = sanitizeSQL(L.getStaminaLoss())
+ var/sqlstamina = sanitizeSQL(L.getStaminaLoss())
+ var/coord = sanitizeSQL("[L.x], [L.y], [L.z]")
+ var/map = sanitizeSQL(SSmapping.config.map_name)
+ var/datum/DBQuery/query_report_death = SSdbcore.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, toxloss, cloneloss, staminaloss, coord, mapname, server_ip, server_port) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[SQLtime()]', '[laname]', '[lakey]', '[sqlgender]', [sqlbrute], [sqlfire], [sqlbrain], [sqloxy], [sqltox], [sqlclone], [sqlstamina], '[coord]', '[map]', INET_ATON('[world.internet_address]'), '[world.port]')")
+ query_report_death.Execute()
+
+
//feedback variable datum, for storing all kinds of data
/datum/feedback_variable
var/variable
var/value
var/details
-/datum/feedback_variable/New(var/param_variable,var/param_value = 0)
+/datum/feedback_variable/New(param_variable, param_value = 0)
variable = param_variable
value = param_value
@@ -204,50 +255,3 @@ GLOBAL_DATUM_INIT(blackbox, /datum/feedback, new)
/datum/feedback_variable/proc/get_parsed()
return list(variable,value,details)
-
-//sql reporting procs
-/proc/sql_poll_population()
- if(!config.sql_enabled)
- return
- if(!SSdbcore.Connect())
- return
- var/playercount = 0
- for(var/mob/M in GLOB.player_list)
- if(M.client)
- playercount += 1
- var/admincount = GLOB.admins.len
- var/datum/DBQuery/query_record_playercount = SSdbcore.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time, server_ip, server_port) VALUES ([playercount], [admincount], '[SQLtime()]', INET_ATON('[world.internet_address]'), '[world.port]')")
- query_record_playercount.Execute()
-
-/proc/sql_report_death(mob/living/L)
- if(!config.sql_enabled)
- return
- if(!SSdbcore.Connect())
- return
- if(!L || !L.key || !L.mind)
- return
- var/turf/T = get_turf(L)
- var/area/placeofdeath = get_area(T.loc)
- var/sqlname = sanitizeSQL(L.real_name)
- var/sqlkey = sanitizeSQL(L.ckey)
- var/sqljob = sanitizeSQL(L.mind.assigned_role)
- var/sqlspecial = sanitizeSQL(L.mind.special_role)
- var/sqlpod = sanitizeSQL(placeofdeath.name)
- var/laname
- var/lakey
- if(L.lastattacker && ismob(L.lastattacker))
- var/mob/LA = L.lastattacker
- laname = sanitizeSQL(LA.real_name)
- lakey = sanitizeSQL(LA.key)
- var/sqlgender = sanitizeSQL(L.gender)
- var/sqlbrute = sanitizeSQL(L.getBruteLoss())
- var/sqlfire = sanitizeSQL(L.getFireLoss())
- var/sqlbrain = sanitizeSQL(L.getBrainLoss())
- var/sqloxy = sanitizeSQL(L.getOxyLoss())
- var/sqltox = sanitizeSQL(L.getStaminaLoss())
- var/sqlclone = sanitizeSQL(L.getStaminaLoss())
- var/sqlstamina = sanitizeSQL(L.getStaminaLoss())
- var/coord = sanitizeSQL("[L.x], [L.y], [L.z]")
- var/map = sanitizeSQL(SSmapping.config.map_name)
- var/datum/DBQuery/query_report_death = SSdbcore.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, toxloss, cloneloss, staminaloss, coord, mapname, server_ip, server_port) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[SQLtime()]', '[laname]', '[lakey]', '[sqlgender]', [sqlbrute], [sqlfire], [sqlbrain], [sqloxy], [sqltox], [sqlclone], [sqlstamina], '[coord]', '[map]', INET_ATON('[world.internet_address]'), '[world.port]')")
- query_report_death.Execute()
diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm
index 137bd2a2c1..a3255b73e4 100644
--- a/code/controllers/subsystem/job.dm
+++ b/code/controllers/subsystem/job.dm
@@ -483,7 +483,7 @@ SUBSYSTEM_DEF(job)
else level4++ //not selected
tmp_str += "HIGH=[level1]|MEDIUM=[level2]|LOW=[level3]|NEVER=[level4]|BANNED=[level5]|YOUNG=[level6]|-"
- feedback_add_details("job_preferences",tmp_str)
+ SSblackbox.add_details("job_preferences",tmp_str)
/datum/controller/subsystem/job/proc/PopcapReached()
if(config.hard_popcap || config.extreme_popcap)
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index a27235c592..85c580f4d9 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -119,7 +119,7 @@ SUBSYSTEM_DEF(mapping)
INIT_ANNOUNCE("Loading [config.map_name]...")
TryLoadZ(config.GetFullMapPath(), FailedZs, ZLEVEL_STATION)
INIT_ANNOUNCE("Loaded station in [(REALTIMEOFDAY - start_time)/10]s!")
- feedback_add_details("map_name", config.map_name)
+ SSblackbox.add_details("map_name", config.map_name)
if(config.minetype != "lavaland")
INIT_ANNOUNCE("WARNING: A map without lavaland set as it's minetype was loaded! This is being ignored! Update the maploader code!")
diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm
index e1cf992e8b..6b3e47054c 100644
--- a/code/controllers/subsystem/persistence.dm
+++ b/code/controllers/subsystem/persistence.dm
@@ -11,10 +11,14 @@ SUBSYSTEM_DEF(persistence)
var/list/saved_messages = list()
var/savefile/chisel_messages_sav
+ var/savefile/trophy_sav
+ var/list/saved_trophies = list()
+
/datum/controller/subsystem/persistence/Initialize()
LoadSatchels()
LoadPoly()
LoadChiselMessages()
+ LoadTrophies()
..()
/datum/controller/subsystem/persistence/proc/LoadSatchels()
@@ -105,10 +109,49 @@ SUBSYSTEM_DEF(persistence)
M.persists = FALSE
qdel(M)
+/datum/controller/subsystem/persistence/proc/LoadTrophies()
+ trophy_sav = new /savefile("data/npc_saves/TrophyItems.sav")
+ var/saved_json
+ trophy_sav >> saved_json
+
+ var/decoded_json = json_decode(saved_json)
+
+ if(!islist(decoded_json))
+ return
+
+ saved_trophies = decoded_json
+
+ SetUpTrophies(saved_trophies.Copy())
+
+/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items)
+ for(var/A in GLOB.trophy_cases)
+ var/obj/structure/displaycase/trophy/T = A
+ T.added_roundstart = TRUE
+
+ var/trophy_data = pick_n_take(trophy_items)
+
+ if(!islist(trophy_data))
+ continue
+
+ var/list/chosen_trophy = trophy_data
+
+ if(!chosen_trophy || isemptylist(chosen_trophy)) //Malformed
+ continue
+
+ var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null
+ if(!path)
+ continue
+
+ T.showpiece = new /obj/item/showpiece_dummy(T, path)
+ T.trophy_message = chosen_trophy["message"]
+ T.placer_key = chosen_trophy["placer_key"]
+ T.update_icon()
+
/datum/controller/subsystem/persistence/proc/CollectData()
CollectChiselMessages()
CollectSecretSatchels()
+ CollectTrophies()
/datum/controller/subsystem/persistence/proc/CollectSecretSatchels()
for(var/A in new_secret_satchels)
@@ -135,4 +178,16 @@ SUBSYSTEM_DEF(persistence)
chisel_messages_sav[SSmapping.config.map_name] << json_encode(saved_messages)
/datum/controller/subsystem/persistence/proc/SaveChiselMessage(obj/structure/chisel_message/M)
- saved_messages += list(M.pack()) // dm eats one list.
+ saved_messages += list(M.pack()) // dm eats one list
+
+
+/datum/controller/subsystem/persistence/proc/CollectTrophies()
+ trophy_sav << json_encode(saved_trophies)
+
+/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T)
+ if(!T.added_roundstart && T.showpiece)
+ var/list/data = list()
+ data["path"] = T.showpiece.type
+ data["message"] = T.trophy_message
+ data["placer_key"] = T.placer_key
+ saved_trophies += list(data)
\ No newline at end of file
diff --git a/code/controllers/subsystem/ping.dm b/code/controllers/subsystem/ping.dm
index 0829766174..a6b444c4e7 100644
--- a/code/controllers/subsystem/ping.dm
+++ b/code/controllers/subsystem/ping.dm
@@ -3,14 +3,20 @@
SUBSYSTEM_DEF(ping)
name = "Ping"
wait = 6
- flags = SS_NO_INIT|SS_POST_FIRE_TIMING|SS_FIRE_IN_LOBBY
+ flags = SS_POST_FIRE_TIMING|SS_FIRE_IN_LOBBY
priority = 10
var/list/currentrun
+/datum/controller/subsystem/ping/Initialize()
+ if (config.hub)
+ world.visibility = 1
+ ..()
+
/datum/controller/subsystem/ping/fire(resumed = FALSE)
if (!resumed)
src.currentrun = GLOB.clients.Copy()
+ var/round_started = Master.round_started
var/list/currentrun = src.currentrun
while (length(currentrun))
var/client/C = currentrun[currentrun.len]
@@ -19,7 +25,15 @@ SUBSYSTEM_DEF(ping)
if (MC_TICK_CHECK)
return
continue
+
+ if(round_started && C.is_afk(INACTIVITY_KICK))
+ if(!istype(C.mob, /mob/dead))
+ log_access("AFK: [key_name(C)]")
+ to_chat(C, "You have been inactive for more than 10 minutes and have been disconnected.")
+ qdel(C)
+
winset(C, null, "command=.update_ping+[world.time+world.tick_lag*world.tick_usage/100]")
+
if (MC_TICK_CHECK) //one day, when ss13 has 1000 people per server, you guys are gonna be glad I added this tick check
return
diff --git a/code/controllers/subsystem/server_maint.dm b/code/controllers/subsystem/server_maint.dm
index 3ef088b328..08f60d23e6 100644
--- a/code/controllers/subsystem/server_maint.dm
+++ b/code/controllers/subsystem/server_maint.dm
@@ -1,17 +1,28 @@
+#define PING_BUFFER_TIME 25
+
SUBSYSTEM_DEF(server_maint)
name = "Server Tasks"
- wait = 6000
- flags = SS_NO_TICK_CHECK
+ wait = 6
+ flags = SS_POST_FIRE_TIMING|SS_FIRE_IN_LOBBY
+ priority = 10
+ var/list/currentrun
/datum/controller/subsystem/server_maint/Initialize(timeofday)
if (config.hub)
world.visibility = 1
..()
-/datum/controller/subsystem/server_maint/fire()
- //handle kicking inactive players
- if(config.kick_inactive)
- for(var/client/C in GLOB.clients)
+/datum/controller/subsystem/server_maint/fire(resumed = FALSE)
+ if(!resumed)
+ src.currentrun = GLOB.clients.Copy()
+
+ var/list/currentrun = src.currentrun
+ var/round_started = SSticker.HasRoundStarted()
+
+ for(var/I in currentrun)
+ var/client/C = I
+ //handle kicking inactive players
+ if(round_started && config.kick_inactive)
if(C.is_afk(config.afk_period))
var/cmob = C.mob
if(!(istype(cmob, /mob/dead/observer) || (istype(cmob, /mob/dead) && C.holder)))
@@ -19,5 +30,10 @@ SUBSYSTEM_DEF(server_maint)
to_chat(C, "You have been inactive for more than [config.afk_period / 600] minutes and have been disconnected.")
qdel(C)
- if(config.sql_enabled)
- sql_poll_population()
+ if (!(!C || world.time - C.connection_time < PING_BUFFER_TIME || C.inactivity >= (wait-1)))
+ winset(C, null, "command=.update_ping+[world.time+world.tick_lag*world.tick_usage/100]")
+
+ if (MC_TICK_CHECK) //one day, when ss13 has 1000 people per server, you guys are gonna be glad I added this tick check
+ return
+
+#undef PING_BUFFER_TIME
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index f701c051da..abf05aad72 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -243,7 +243,7 @@ SUBSYSTEM_DEF(ticker)
send2irc("Server", "Round of [hide_mode ? "secret":"[mode.name]"] has started[allmins.len ? ".":" with no active admins online!"]")
/datum/controller/subsystem/ticker/proc/OnRoundstart(datum/callback/cb)
- if(current_state < GAME_STATE_PLAYING)
+ if(!HasRoundStarted())
LAZYADD(round_start_events, cb)
else
cb.InvokeAsync()
@@ -625,8 +625,8 @@ SUBSYSTEM_DEF(ticker)
if(selected_tip)
m = selected_tip
else
- var/list/randomtips = world.file2list("config/tips.txt")
- var/list/memetips = world.file2list("config/sillytips.txt")
+ var/list/randomtips = world.file2list("strings/tips.txt")
+ var/list/memetips = world.file2list("strings/sillytips.txt")
if(randomtips.len && prob(95))
m = pick(randomtips)
else if(memetips.len)
@@ -672,15 +672,16 @@ SUBSYSTEM_DEF(ticker)
return
INVOKE_ASYNC(SSmapping, /datum/controller/subsystem/mapping/.proc/maprotate)
+/datum/controller/subsystem/ticker/proc/HasRoundStarted()
+ return current_state >= GAME_STATE_PLAYING
+
+/datum/controller/subsystem/ticker/proc/IsRoundInProgress()
+ return current_state == GAME_STATE_PLAYING
+
/proc/send_gamemode_vote()
SSticker.modevoted = TRUE
SSvote.initiate_vote("roundtype","server")
-/world/proc/has_round_started()
- if (SSticker && SSticker.current_state >= GAME_STATE_PLAYING)
- return TRUE
- return FALSE
-
/datum/controller/subsystem/ticker/Recover()
current_state = SSticker.current_state
force_ending = SSticker.force_ending
diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm
index b3b6dce98a..5deb0adf85 100644
--- a/code/controllers/subsystem/vote.dm
+++ b/code/controllers/subsystem/vote.dm
@@ -124,7 +124,7 @@ SUBSYSTEM_DEF(vote)
if("gamemode")
if(GLOB.master_mode != .)
world.save_mode(.)
- if(SSticker && SSticker.mode)
+ if(SSticker.HasRoundStarted())
restart = 1
else
GLOB.master_mode = .
diff --git a/code/datums/antagonists/antag_datum.dm b/code/datums/antagonists/antag_datum.dm
index cdad092087..396c185961 100644
--- a/code/datums/antagonists/antag_datum.dm
+++ b/code/datums/antagonists/antag_datum.dm
@@ -1,87 +1,62 @@
-//The Datum, Antagonist. Handles various antag things via a datum.
/datum/antagonist
- var/mob/living/owner //who's our owner and accordingly an antagonist
- var/some_flufftext = "yer an antag larry"
- var/prevented_antag_datum_type //the type of antag datum that this datum can't coexist with; should probably be a list
- var/silent_update = FALSE //if we suppress messages during on_gain, apply_innate_effects, remove_innate_effects, and on_remove
+ var/name = "Antagonist"
-/datum/antagonist/New()
- if(!prevented_antag_datum_type)
- prevented_antag_datum_type = type
+ var/datum/mind/owner //Mind that owns this datum
+
+ var/silent = FALSE //Silent will prevent the gain/lose texts to show
+
+ var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum
+ var/list/typecache_datum_blacklist = list() //List of datums this type can't coexist with
+
+/datum/antagonist/New(datum/mind/new_owner)
+ typecache_datum_blacklist = typecacheof(typecache_datum_blacklist)
+ if(new_owner)
+ owner = new_owner
/datum/antagonist/Destroy()
+ if(owner)
+ LAZYREMOVE(owner.antag_datums, src)
owner = null
return ..()
-/datum/antagonist/proc/can_be_owned(mob/living/new_body)
- return new_body && !new_body.has_antag_datum(prevented_antag_datum_type, TRUE)
+/datum/antagonist/proc/can_be_owned(datum/mind/new_owner)
+ . = TRUE
+ if(owner.has_antag_datum(type))
+ return FALSE
+ for(var/i in owner.antag_datums)
+ var/datum/antagonist/A = i
+ if(is_type_in_typecache(src, A.typecache_datum_blacklist))
+ return FALSE
-/datum/antagonist/proc/give_to_body(mob/living/new_body) //tries to give an antag datum to a mob. cancels out if it can't be owned by the new body
- if(new_body && can_be_owned(new_body))
- new_body.antag_datums += src
- owner = new_body
- on_gain()
- . = src //return the datum if successful
- else
- qdel(src)
- . = FALSE
+/datum/antagonist/proc/on_body_transfer(mob/living/old_body, mob/living/new_body)
+ remove_innate_effects(old_body)
+ apply_innate_effects(new_body)
-/datum/antagonist/proc/on_gain() //on initial gain of antag datum, do this. should only be called once per datum
- apply_innate_effects()
- if(!silent_update && some_flufftext)
- to_chat(owner, some_flufftext)
+//This handles the application of antag huds/special abilities
+/datum/antagonist/proc/apply_innate_effects(mob/living/mob_override)
+ return
-/datum/antagonist/proc/apply_innate_effects() //applies innate effects to the owner, may be called multiple times due to mind transferral, but should only be called once per mob
- //antag huds would go here if antag huds were less completely unworkable as-is
+//This handles the removal of antag huds/special abilities
+/datum/antagonist/proc/remove_innate_effects(mob/living/mob_override)
+ return
-/datum/antagonist/proc/remove_innate_effects() //removes innate effects from the owner, may be called multiple times due to mind transferral, but should only be called once per mob
- //also antag huds but see above antag huds a shit
+//Proc called when the datum is given to a mind.
+/datum/antagonist/proc/on_gain()
+ if(owner && owner.current)
+ if(!silent)
+ greet()
+ apply_innate_effects()
-/datum/antagonist/proc/on_remove() //totally removes the antag datum from the owner; can only be called once per owner
+/datum/antagonist/proc/on_removal()
remove_innate_effects()
- owner.antag_datums -= src
+ if(owner)
+ LAZYREMOVE(owner.antag_datums, src)
+ if(!silent && owner.current)
+ farewell()
qdel(src)
-/datum/antagonist/proc/transfer_to_new_body(mob/living/new_body)
- remove_innate_effects()
- if(!islist(new_body.antag_datums))
- new_body.antag_datums = list()
- new_body.antag_datums += src
- owner.antag_datums -= src
- owner = new_body
- apply_innate_effects()
+/datum/antagonist/proc/greet()
+ return
-//mob var and helper procs/Destroy override
-/mob/living
- var/list/antag_datums
-
-/mob/living/Destroy() //TODO: merge this with the living/Destroy() in code\modules\mob\living\living.dm (currently line 29)
- if(islist(antag_datums))
- for(var/i in antag_datums)
- qdel(i)
- antag_datums = null
- return ..()
-
-/mob/living/proc/can_have_antag_datum(datum_type) //if we can have this specific antagonist datum; neccessary, but requires creating a new antag datum each time.
- var/datum/antagonist/D = new datum_type()
- . = D.can_be_owned(src) //we can't exactly cache the results, either, because conditions might change. avoid use? TODO: better proc
- qdel(D)
-
-/mob/living/proc/gain_antag_datum(datum_type) //tries to give a mob a specific antagonist datum; returns the datum if successful.
- if(!islist(antag_datums))
- antag_datums = list()
- var/datum/antagonist/D = new datum_type()
- . = D.give_to_body(src)
-
-/mob/living/proc/has_antag_datum(type, check_subtypes) //checks this mob for if it has the antagonist datum. can either check specific type or subtypes
- if(!islist(antag_datums))
- return FALSE
- for(var/i in antag_datums)
- var/datum/antagonist/D = i
- if(check_subtypes)
- if(istype(D, type))
- return D //if it finds the datum, will return it so you can mess with it
- else
- if(D.type == type)
- return D
- return FALSE
+/datum/antagonist/proc/farewell()
+ return
diff --git a/code/datums/antagonists/datum_clockcult.dm b/code/datums/antagonists/datum_clockcult.dm
index 0c39b5a989..b8dfa00f23 100644
--- a/code/datums/antagonists/datum_clockcult.dm
+++ b/code/datums/antagonists/datum_clockcult.dm
@@ -1,79 +1,75 @@
//CLOCKCULT PROOF OF CONCEPT
-
-/datum/antagonist/clockcultist
- prevented_antag_datum_type = /datum/antagonist/clockcultist
- some_flufftext = null
+/datum/antagonist/clockcult
var/datum/action/innate/hierophant/hierophant_network = new()
-/datum/antagonist/clockcultist/silent
- silent_update = TRUE
+/datum/antagonist/clockcult/silent
+ silent = TRUE
-/datum/antagonist/clockcultist/Destroy()
+/datum/antagonist/clockcult/Destroy()
qdel(hierophant_network)
- ..()
+ return ..()
-/datum/antagonist/clockcultist/can_be_owned(mob/living/new_body)
+/datum/antagonist/clockcult/can_be_owned(datum/mind/new_owner)
. = ..()
if(.)
- . = is_eligible_servant(new_body)
+ if(iscyborg(new_owner.current))
+ var/mob/living/silicon/robot/R = new_owner.current
+ if(R.deployed)
+ var/mob/living/silicon/ai/AI = R.mainframe
+ R.undeploy()
+ to_chat(AI, "Anomaly Detected. Returned to core!") //The AI needs to be in its core to properly be converted
+ . = is_eligible_servant(new_owner.current)
+ if(!silent && new_owner.current)
+ if(issilicon(new_owner.current))
+ to_chat(new_owner.current, "You are unable to compute this truth. Your vision glows a brilliant yellow, and all at once it comes to you. Ratvar, the \
+ Clockwork Justiciar, lies in exile, derelict and forgotten in an unseen realm.")
+ else
+ to_chat(new_owner.current, "[iscarbon(new_owner.current) ? "Your mind is racing! Your body feels incredibly light! ":""]Your world glows a brilliant \
+ yellow! All at once it comes to you. Ratvar, the Clockwork Justiciar, lies in exile, derelict and forgotten in an unseen realm.")
+ if(!.)
+ new_owner.current.visible_message("[new_owner.current] seems to resist an unseen force!")
+ to_chat(new_owner.current, "And yet, you somehow push it all away.")
-/datum/antagonist/clockcultist/give_to_body(mob/living/new_body)
- if(iscyborg(new_body))
- var/mob/living/silicon/robot/R = new_body
- if(R.deployed)
- var/mob/living/silicon/ai/AI = R.mainframe
- R.undeploy()
- var/converted = add_servant_of_ratvar(AI, silent_update)
- to_chat(AI, "Anomaly Detected. Returned to core!") //The AI needs to be in its core to properly be converted
- return converted
- if(!silent_update)
- if(issilicon(new_body))
- to_chat(new_body, "You are unable to compute this truth. Your vision glows a brilliant yellow, and all at once it comes to you. Ratvar, the Clockwork Justiciar, \
- lies in exile, derelict and forgotten in an unseen realm.")
- else
- to_chat(new_body, "[iscarbon(new_body) ? "Your mind is racing! Your body feels incredibly light! ":""]Your world glows a brilliant yellow! All at once it comes to you. \
- Ratvar, the Clockwork Justiciar, lies in exile, derelict and forgotten in an unseen realm.")
- . = ..()
- if(!silent_update && new_body)
- if(.)
- new_body.visible_message("[new_body]'s eyes glow a blazing yellow!")
- to_chat(new_body, "Assist your new companions in their righteous efforts. Your goal is theirs, and theirs yours. You serve the Clockwork Justiciar above all else. \
- Perform his every whim without hesitation.")
- else
- new_body.visible_message("[new_body] seems to resist an unseen force!")
- to_chat(new_body, "And yet, you somehow push it all away.")
+/datum/antagonist/clockcult/greet()
+ if(!owner.current || silent)
+ return
+ owner.current.visible_message("[owner.current]'s eyes glow a blazing yellow!")
+ to_chat(owner.current, "Assist your new companions in their righteous efforts. Your goal is theirs, and theirs yours. You serve the Clockwork \
+ Justiciar above all else. Perform his every whim without hesitation.")
-/datum/antagonist/clockcultist/on_gain()
- if(SSticker && SSticker.mode && owner.mind)
- SSticker.mode.servants_of_ratvar += owner.mind
- SSticker.mode.update_servant_icons_added(owner.mind)
- if(jobban_isbanned(owner, ROLE_SERVANT_OF_RATVAR))
- INVOKE_ASYNC(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, owner, ROLE_SERVANT_OF_RATVAR, ROLE_SERVANT_OF_RATVAR)
- if(owner.mind)
- owner.mind.special_role = "Servant of Ratvar"
- owner.log_message("Has been converted to the cult of Ratvar!", INDIVIDUAL_ATTACK_LOG)
- if(issilicon(owner))
- var/mob/living/silicon/S = owner
- if(iscyborg(S) && !silent_update)
- to_chat(S, "You have been desynced from your master AI.\n\
- In addition, your onboard camera is no longer active and you have gained additional equipment, including a limited clockwork slab.")
- if(isAI(S))
- to_chat(S, "You are able to use your cameras to listen in on conversations.")
- to_chat(S, "You can communicate with other servants by using the Hierophant Network action button in the upper left.")
- else if(isbrain(owner) || isclockmob(owner))
- to_chat(owner, "You can communicate with other servants by using the Hierophant Network action button in the upper left.")
+/datum/antagonist/clockcult/on_gain()
+ var/mob/living/current = owner.current
+ SSticker.mode.servants_of_ratvar += owner
+ SSticker.mode.update_servant_icons_added(owner)
+ if(jobban_isbanned(current, ROLE_SERVANT_OF_RATVAR))
+ addtimer(CALLBACK(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, current, ROLE_SERVANT_OF_RATVAR, ROLE_SERVANT_OF_RATVAR), 0)
+ owner.special_role = "Servant of Ratvar"
+ owner.current.log_message("Has been converted to the cult of Ratvar!", INDIVIDUAL_ATTACK_LOG)
+ if(issilicon(current))
+ if(iscyborg(current) && !silent)
+ to_chat(current, "You have been desynced from your master AI.")
+ to_chat(current, "In addition, your onboard camera is no longer active and you have gained additional equipment, including a limited clockwork slab.")
+ if(isAI(current))
+ to_chat(current, "You are able to use your cameras to listen in on conversations.")
+ to_chat(current, "You can communicate with other servants by using the Hierophant Network action button in the upper left.")
+ else if(isbrain(current) || isclockmob(current))
+ to_chat(current, "You can communicate with other servants by using the Hierophant Network action button in the upper left.")
..()
if(istype(SSticker.mode, /datum/game_mode/clockwork_cult))
var/datum/game_mode/clockwork_cult/C = SSticker.mode
C.present_tasks(owner) //Memorize the objectives
-/datum/antagonist/clockcultist/apply_innate_effects()
- GLOB.all_clockwork_mobs += owner
- owner.faction |= "ratvar"
- owner.grant_language(/datum/language/ratvar)
- owner.update_action_buttons_icon() //because a few clockcult things are action buttons and we may be wearing/holding them for whatever reason, we need to update buttons
- if(issilicon(owner))
- var/mob/living/silicon/S = owner
+/datum/antagonist/clockcult/apply_innate_effects(mob/living/mob_override)
+ . = ..()
+ var/mob/living/current = owner.current
+ if(istype(mob_override))
+ current = mob_override
+ GLOB.all_clockwork_mobs += current
+ current.faction |= "ratvar"
+ current.grant_language(/datum/language/ratvar)
+ current.update_action_buttons_icon() //because a few clockcult things are action buttons and we may be wearing/holding them for whatever reason, we need to update buttons
+ if(issilicon(current))
+ var/mob/living/silicon/S = current
if(iscyborg(S))
var/mob/living/silicon/robot/R = S
if(!R.shell)
@@ -106,31 +102,33 @@
hierophant_network.title = "Silicon"
hierophant_network.span_for_name = "nezbere"
hierophant_network.span_for_message = "brass"
- else if(isbrain(owner))
- hierophant_network.Grant(owner)
+ else if(isbrain(current))
+ hierophant_network.Grant(current)
hierophant_network.title = "Vessel"
hierophant_network.span_for_name = "nezbere"
hierophant_network.span_for_message = "alloy"
- else if(isclockmob(owner))
- hierophant_network.Grant(owner)
+ else if(isclockmob(current))
+ hierophant_network.Grant(current)
hierophant_network.title = "Construct"
hierophant_network.span_for_name = "nezbere"
hierophant_network.span_for_message = "brass"
- owner.throw_alert("clockinfo", /obj/screen/alert/clockwork/infodump)
+ current.throw_alert("clockinfo", /obj/screen/alert/clockwork/infodump)
if(!GLOB.clockwork_gateway_activated)
- owner.throw_alert("scripturereq", /obj/screen/alert/clockwork/scripture_reqs)
- ..()
+ current.throw_alert("scripturereq", /obj/screen/alert/clockwork/scripture_reqs)
-/datum/antagonist/clockcultist/remove_innate_effects()
- GLOB.all_clockwork_mobs -= owner
- owner.faction -= "ratvar"
- owner.remove_language(/datum/language/ratvar)
- owner.clear_alert("clockinfo")
- owner.clear_alert("scripturereq")
- for(var/datum/action/innate/function_call/F in owner.actions) //Removes any bound Ratvarian spears
+/datum/antagonist/clockcult/remove_innate_effects(mob/living/mob_override)
+ var/mob/living/current = owner.current
+ if(istype(mob_override))
+ current = mob_override
+ GLOB.all_clockwork_mobs -= current
+ current.faction -= "ratvar"
+ current.remove_language(/datum/language/ratvar)
+ current.clear_alert("clockinfo")
+ current.clear_alert("scripturereq")
+ for(var/datum/action/innate/function_call/F in owner.current.actions) //Removes any bound Ratvarian spears
qdel(F)
- if(issilicon(owner))
- var/mob/living/silicon/S = owner
+ if(issilicon(current))
+ var/mob/living/silicon/S = current
if(isAI(S))
var/mob/living/silicon/ai/A = S
A.can_be_carded = initial(A.can_be_carded)
@@ -139,7 +137,7 @@
S.make_laws()
S.update_icons()
S.show_laws()
- var/mob/living/temp_owner = owner
+ var/mob/living/temp_owner = current
..()
if(iscyborg(temp_owner))
var/mob/living/silicon/robot/R = temp_owner
@@ -147,17 +145,15 @@
if(temp_owner)
temp_owner.update_action_buttons_icon() //because a few clockcult things are action buttons and we may be wearing/holding them, we need to update buttons
-/datum/antagonist/clockcultist/on_remove()
- if(!silent_update)
- owner.visible_message("[owner] seems to have remembered their true allegiance!", \
+/datum/antagonist/clockcult/on_removal()
+ SSticker.mode.servants_of_ratvar -= owner
+ SSticker.mode.update_servant_icons_removed(owner)
+ if(!silent)
+ owner.current.visible_message("[owner] seems to have remembered their true allegiance!", \
"A cold, cold darkness flows through your mind, extinguishing the Justiciar's light and all of your memories as his servant.")
- if(SSticker && SSticker.mode && owner.mind)
- SSticker.mode.servants_of_ratvar -= owner.mind
- SSticker.mode.update_servant_icons_removed(owner.mind)
- if(owner.mind)
- owner.mind.wipe_memory()
- owner.mind.special_role = null
- owner.log_message("Has renounced the cult of Ratvar!", INDIVIDUAL_ATTACK_LOG)
- if(iscyborg(owner))
- to_chat(owner, "Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking.")
- ..()
+ owner.current.log_message("Has renounced the cult of Ratvar!", INDIVIDUAL_ATTACK_LOG)
+ owner.wipe_memory()
+ owner.special_role = null
+ if(iscyborg(owner.current))
+ to_chat(owner.current, "Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking.")
+ . = ..()
diff --git a/code/datums/antagonists/datum_cult.dm b/code/datums/antagonists/datum_cult.dm
index 7d6806bab6..30c0aa8450 100644
--- a/code/datums/antagonists/datum_cult.dm
+++ b/code/datums/antagonists/datum_cult.dm
@@ -1,50 +1,50 @@
-/datum/antagonist/cultist
- prevented_antag_datum_type = /datum/antagonist/cultist
- some_flufftext = null
- var/datum/action/innate/cultcomm/communion = new()
+/datum/antagonist/cult
+ var/datum/action/innate/cultcomm/communion = new
-/datum/antagonist/cultist/Destroy()
+/datum/antagonist/cult/Destroy()
qdel(communion)
return ..()
-/datum/antagonist/cultist/can_be_owned(mob/living/new_body)
+/datum/antagonist/cult/can_be_owned(datum/mind/new_owner)
. = ..()
if(.)
- . = is_convertable_to_cult(new_body)
+ . = is_convertable_to_cult(new_owner.current)
-/datum/antagonist/cultist/on_gain()
- if(SSticker && SSticker.mode && owner.mind)
- SSticker.mode.cult += owner.mind
- SSticker.mode.update_cult_icons_added(owner.mind)
- if(istype(SSticker.mode, /datum/game_mode/cult))
- var/datum/game_mode/cult/C = SSticker.mode
- C.memorize_cult_objectives(owner.mind)
- if(jobban_isbanned(owner, ROLE_CULTIST))
- INVOKE_ASYNC(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, owner, ROLE_CULTIST, ROLE_CULTIST)
- if(owner.mind)
- owner.mind.special_role = "Cultist"
- owner.log_message("Has been converted to the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG)
- ..()
+/datum/antagonist/cult/on_gain()
+ . = ..()
+ SSticker.mode.cult += owner
+ SSticker.mode.update_cult_icons_added(owner)
+ if(istype(SSticker.mode, /datum/game_mode/cult))
+ var/datum/game_mode/cult/C = SSticker.mode
+ C.memorize_cult_objectives(owner)
+ if(jobban_isbanned(owner.current, ROLE_CULTIST))
+ addtimer(CALLBACK(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, owner.current, ROLE_CULTIST, ROLE_CULTIST), 0)
+ owner.current.log_message("Has been converted to the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG)
-/datum/antagonist/cultist/apply_innate_effects()
- owner.faction |= "cult"
- owner.verbs += /mob/living/proc/cult_help
- communion.Grant(owner)
- ..()
+/datum/antagonist/cult/apply_innate_effects(mob/living/mob_override)
+ . = ..()
+ var/mob/living/current = owner.current
+ if(mob_override)
+ current = mob_override
+ current.faction |= "cult"
+ current.verbs += /mob/living/proc/cult_help
+ communion.Grant(current)
-/datum/antagonist/cultist/remove_innate_effects()
- owner.faction -= "cult"
- owner.verbs -= /mob/living/proc/cult_help
- ..()
+/datum/antagonist/cult/remove_innate_effects(mob/living/mob_override)
+ . = ..()
+ var/mob/living/current = owner.current
+ if(mob_override)
+ current = mob_override
+ current.faction -= "cult"
+ current.verbs -= /mob/living/proc/cult_help
+ communion.Remove(current)
-/datum/antagonist/cultist/on_remove()
- if(owner.mind)
- owner.mind.wipe_memory()
- if(SSticker && SSticker.mode)
- SSticker.mode.cult -= owner.mind
- SSticker.mode.update_cult_icons_removed(owner.mind)
+/datum/antagonist/cult/on_removal()
+ owner.wipe_memory()
+ SSticker.mode.cult -= owner
+ SSticker.mode.update_cult_icons_removed(owner)
to_chat(owner, "An unfamiliar white light flashes through your mind, cleansing the taint of the Dark One and all your memories as its servant.")
- owner.log_message("Has renounced the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG)
- if(!silent_update)
- owner.visible_message("[owner] looks like [owner.p_they()] just reverted to their old faith!")
- ..()
+ owner.current.log_message("Has renounced the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG)
+ if(!silent)
+ owner.current.visible_message("[owner] looks like [owner.current.p_they()] just reverted to their old faith!")
+ . = ..()
diff --git a/code/datums/antagonists/datum_cult.dm.rej b/code/datums/antagonists/datum_cult.dm.rej
new file mode 100644
index 0000000000..0fc846a73c
--- /dev/null
+++ b/code/datums/antagonists/datum_cult.dm.rej
@@ -0,0 +1,25 @@
+diff a/code/datums/antagonists/datum_cult.dm b/code/datums/antagonists/datum_cult.dm (rejected hunks)
+@@ -5,13 +5,20 @@
+ qdel(communion)
+ return ..()
+
++/datum/antagonist/cult/can_be_owned(datum/mind/new_owner)
++ . = ..()
++ if(.)
++ . = is_convertable_to_cult(new_owner.current)
++
+ /datum/antagonist/cult/on_gain()
+ . = ..()
+- if(!owner)
+- return
++ SSticker.mode.cult += owner
++ SSticker.mode.update_cult_icons_added(owner)
++ if(istype(SSticker.mode, /datum/game_mode/cult))
++ var/datum/game_mode/cult/C = SSticker.mode
++ C.memorize_cult_objectives(owner)
+ if(jobban_isbanned(owner.current, ROLE_CULTIST))
+ addtimer(CALLBACK(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, owner.current, ROLE_CULTIST, ROLE_CULTIST), 0)
+- SSticker.mode.update_cult_icons_added(owner)
+ owner.current.log_message("Has been converted to the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG)
+
+ /datum/antagonist/cult/apply_innate_effects(mob/living/mob_override)
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index 7de57e4bb9..fbbf97a6ca 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -27,7 +27,7 @@
. += "---"
.["Call Proc"] = "?_src_=vars;proc_call=\ref[src]"
.["Mark Object"] = "?_src_=vars;mark_object=\ref[src]"
- .["Delete"] = "?_src_=vars;delete=\ref[src]"
+ .["Delete"] = "?_src_=vars;delete=\ref[src]"
/datum/proc/on_reagent_change()
@@ -94,7 +94,6 @@
CLONE:[M.getCloneLoss()]
BRAIN:[M.getBrainLoss()]
STAMINA:[M.getStaminaLoss()]
- AROUSAL:[M.getArousalLoss()]
"}
else
@@ -447,7 +446,7 @@
var/list/L = value
var/list/items = list()
- if (L.len > 0 && !(name == "underlays" || name == "overlays" || L.len > (IS_NORMAL_LIST(L) ? 50 : 150)))
+ if (L.len > 0 && !(name == "underlays" || name == "overlays" || L.len > (IS_NORMAL_LIST(L) ? 50 : 150)))
for (var/i in 1 to L.len)
var/key = L[i]
var/val
@@ -527,16 +526,16 @@
if(T)
callproc_datum(T)
- else if(href_list["delete"])
- if(!check_rights(R_DEBUG, 0))
- return
-
- var/datum/D = locate(href_list["delete"])
- if(!D)
- to_chat(usr, "Unable to locate item!")
- admin_delete(D)
- href_list["datumrefresh"] = href_list["delete"]
-
+ else if(href_list["delete"])
+ if(!check_rights(R_DEBUG, 0))
+ return
+
+ var/datum/D = locate(href_list["delete"])
+ if(!D)
+ to_chat(usr, "Unable to locate item!")
+ admin_delete(D)
+ href_list["datumrefresh"] = href_list["delete"]
+
else if(href_list["regenerateicons"])
if(!check_rights(0))
return
@@ -1166,8 +1165,6 @@
L.adjustCloneLoss(amount)
if("stamina")
L.adjustStaminaLoss(amount)
- if("arousal")
- L.adjustArousalLoss(amount)
else
to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]")
return
@@ -1178,3 +1175,4 @@
message_admins(msg)
admin_ticket_log(L, msg)
href_list["datumrefresh"] = href_list["mobToDamage"]
+
diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm
index 8c9d7d7704..b9358817e3 100644
--- a/code/datums/helper_datums/getrev.dm
+++ b/code/datums/helper_datums/getrev.dm
@@ -25,7 +25,7 @@
for(var/line in testmerge)
if(line)
log_world("Test merge active of PR #[line]")
- feedback_add_details("testmerged_prs","[line]")
+ SSblackbox.add_details("testmerged_prs","[line]")
log_world("Based off master commit [parentcommit]")
else
log_world(parentcommit)
@@ -89,7 +89,7 @@
to_chat(src, "Enforce Continuous Rounds: [config.continuous.len] of [config.modes.len] roundtypes")
to_chat(src, "Allow Midround Antagonists: [config.midround_antag.len] of [config.modes.len] roundtypes")
if(config.show_game_type_odds)
- if(SSticker.current_state == GAME_STATE_PLAYING)
+ if(SSticker.IsRoundInProgress())
var/prob_sum = 0
var/current_odds_differ = FALSE
var/list/probs = list()
diff --git a/code/datums/material_container.dm b/code/datums/material_container.dm
index af227212a7..76de0329cd 100644
--- a/code/datums/material_container.dm
+++ b/code/datums/material_container.dm
@@ -136,7 +136,7 @@
return FALSE
//For spawning mineral sheets; internal use only
-/datum/material_container/proc/retrieve(sheet_amt, datum/material/M)
+/datum/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null)
if(!M.sheet_type)
return 0
if(sheet_amt > 0)
@@ -149,26 +149,28 @@
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
sheet_amt -= MAX_STACK_SIZE
if(round((sheet_amt * MINERAL_MATERIAL_AMOUNT) / MINERAL_MATERIAL_AMOUNT))
- new M.sheet_type(get_turf(owner), sheet_amt)
+ var/obj/item/stack/sheet/s = new M.sheet_type(get_turf(owner), sheet_amt)
+ if(target)
+ s.forceMove(target)
count += sheet_amt
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
return count
return 0
-/datum/material_container/proc/retrieve_sheets(sheet_amt, id)
+/datum/material_container/proc/retrieve_sheets(sheet_amt, id, target = null)
if(materials[id])
- return retrieve(sheet_amt, materials[id])
+ return retrieve(sheet_amt, materials[id], target)
return 0
-/datum/material_container/proc/retrieve_amount(amt, id)
- return retrieve_sheets(amount2sheet(amt), id)
+/datum/material_container/proc/retrieve_amount(amt, id, target)
+ return retrieve_sheets(amount2sheet(amt), id, target)
-/datum/material_container/proc/retrieve_all()
+/datum/material_container/proc/retrieve_all(target = null)
var/result = 0
var/datum/material/M
for(var/MAT in materials)
M = materials[MAT]
- result += retrieve_sheets(amount2sheet(M.amount), MAT)
+ result += retrieve_sheets(amount2sheet(M.amount), MAT, target)
return result
/datum/material_container/proc/has_space(amt = 0)
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 5a6c34bcc4..e99d5bb59a 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -44,9 +44,7 @@
var/datum/job/assigned_job
var/list/datum/objective/objectives = list()
- var/list/datum/objective/special_verbs = list()
- var/list/cult_words = list()
var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button.
var/datum/faction/faction //associated faction
@@ -54,6 +52,7 @@
var/linglink
var/miming = 0 // Mime's vow of silence
+ var/list/antag_datums
var/antag_hud_icon_state = null //this mind's ANTAG_HUD should have this icon_state
var/datum/atom_hud/antag/antag_hud = null //this mind's antag HUD
var/datum/gang/gang_datum //Which gang this mind belongs to, if any
@@ -70,6 +69,10 @@
/datum/mind/Destroy()
SSticker.minds -= src
+ if(islist(antag_datums))
+ for(var/i in antag_datums)
+ qdel(i)
+ antag_datums = null
return ..()
/datum/mind/proc/transfer_to(mob/new_character, var/force_key_move = 0)
@@ -86,13 +89,13 @@
if(new_character.mind) //disassociate any mind currently in our new body's mind variable
new_character.mind.current = null
- if(istype(current) && islist(current.antag_datums)) //wow apparently current isn't always living good fucking job SOMEONE
- for(var/i in current.antag_datums)
- var/datum/antagonist/D = i
- D.transfer_to_new_body(new_character)
var/datum/atom_hud/antag/hud_to_transfer = antag_hud//we need this because leave_hud() will clear this list
+ var/mob/living/old_current = current
current = new_character //associate ourself with our new body
new_character.mind = src //and associate our new body with ourself
+ for(var/a in antag_datums) //Makes sure all antag datums effects are applied in the new body
+ var/datum/antagonist/A = a
+ A.on_body_transfer(old_current, current)
if(iscarbon(new_character))
var/mob/living/carbon/C = new_character
C.last_mind = src
@@ -108,7 +111,42 @@
/datum/mind/proc/wipe_memory()
memory = null
-
+// Datum antag mind procs
+/datum/mind/proc/add_antag_datum(datum_type)
+ if(!datum_type)
+ return
+ var/datum/antagonist/A = new datum_type(src)
+ if(!A.can_be_owned(src))
+ qdel(A)
+ return
+ LAZYADD(antag_datums, A)
+ A.on_gain()
+ return A
+
+/datum/mind/proc/remove_antag_datum(datum_type)
+ if(!datum_type)
+ return
+ var/datum/antagonist/A = has_antag_datum(datum_type)
+ if(A)
+ A.on_removal()
+ return TRUE
+
+/datum/mind/proc/remove_all_antag_datums() //For the Lazy amongst us.
+ for(var/a in antag_datums)
+ var/datum/antagonist/A = a
+ A.on_removal()
+
+/datum/mind/proc/has_antag_datum(datum_type, check_subtypes = TRUE)
+ if(!datum_type)
+ return
+ . = FALSE
+ for(var/a in antag_datums)
+ var/datum/antagonist/A = a
+ if(check_subtypes && istype(A, datum_type))
+ return A
+ else if(A.type == datum_type)
+ return A
+
/*
Removes antag type's references from a mind.
objectives, uplinks, powers etc are all handled.
@@ -255,7 +293,7 @@
to_chat(recipient, "[output]")
/datum/mind/proc/edit_memory()
- if(!SSticker || !SSticker.mode)
+ if(!SSticker.HasRoundStarted())
alert("Not before round-start!", "Alert")
return
diff --git a/code/datums/ruins/space.dm b/code/datums/ruins/space.dm
index ab55919a03..36883c59fe 100644
--- a/code/datums/ruins/space.dm
+++ b/code/datums/ruins/space.dm
@@ -43,6 +43,13 @@
name = "Asteroid 5"
description = "Oh my god, another giant rock!"
+/datum/map_template/ruin/space/deep_storage
+ id = "deep-storage"
+ suffix = "deepstorage.dmm"
+ name = "Survivalist Bunker"
+ description = "Assume the best, prepare for the worst. Generally, you should do so by digging a three man heavily fortified bunker into a giant unused asteroid. \
+ Then make it self sufficient, mask any evidence of construction, hook it covertly into the telecommunications network and hope for the best."
+
/datum/map_template/ruin/space/bigderelict1
id = "bigderelict1"
suffix = "bigderelict1.dmm"
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index d07f66609b..3f261c7991 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -72,6 +72,8 @@
add_logs(owner, null, "gained Vanguard stun immunity")
owner.add_stun_absorption("vanguard", 200, 1, "'s yellow aura momentarily intensifies!", "Your ward absorbs the stun!", " radiating with a soft yellow light!")
owner.visible_message("[owner] begins to faintly glow!", "You will absorb all stuns for the next twenty seconds.")
+ owner.SetStunned(0, FALSE)
+ owner.SetWeakened(0)
progbar = new(owner, duration, owner)
progbar.bar.color = list("#FAE48C", "#FAE48C", "#FAE48C", rgb(0,0,0))
progbar.update(duration - world.time)
diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm
index 8b6d255f1a..51b4f8fc5f 100644
--- a/code/datums/status_effects/status_effect.dm
+++ b/code/datums/status_effects/status_effect.dm
@@ -8,6 +8,7 @@
var/tick_interval = 10 //How many deciseconds between ticks, approximately. Leave at 10 for every second.
var/mob/living/owner //The mob affected by the status effect.
var/status_type = STATUS_EFFECT_UNIQUE //How many of the effect can be on one mob, and what happens when you try to add another
+ var/on_remove_on_mob_delete = FALSE //if we call on_remove() when the mob is deleted
var/alert_type = /obj/screen/alert/status_effect //the alert thrown by the status effect, contains name and description
/datum/status_effect/New(mob/living/new_owner)
@@ -21,8 +22,9 @@
STOP_PROCESSING(SSfastprocess, src)
if(owner)
owner.clear_alert(id)
- on_remove()
LAZYREMOVE(owner.status_effects, src)
+ on_remove()
+ owner = null
return ..()
/datum/status_effect/proc/start_ticking()
@@ -52,8 +54,8 @@
/datum/status_effect/proc/on_apply() //Called whenever the buff is applied.
/datum/status_effect/proc/tick() //Called every tick.
-/datum/status_effect/proc/on_remove() //Called whenever the buff expires or is removed.
-/datum/status_effect/proc/be_replaced() //Called instead of on_remove when a status effect is replaced by itself
+/datum/status_effect/proc/on_remove() //Called whenever the buff expires or is removed; do note that at the point this is called, it is out of the owner's status_effects but owner is not yet null
+/datum/status_effect/proc/be_replaced() //Called instead of on_remove when a status effect is replaced by itself or when a status effect with on_remove_on_mob_delete = FALSE has its mob deleted
owner.clear_alert(id)
LAZYREMOVE(owner.status_effects, src)
owner = null
diff --git a/code/game/area/areas/holodeck.dm b/code/game/area/areas/holodeck.dm
index c4b4e02f7b..7bf213be52 100644
--- a/code/game/area/areas/holodeck.dm
+++ b/code/game/area/areas/holodeck.dm
@@ -96,16 +96,15 @@
/area/holodeck/rec_center/kobayashi
name = "Holodeck - Kobayashi Maru"
+/area/holodeck/rec_center/winterwonderland
+ name = "Holodeck - Winter Wonderland"
+
// Bad programs
/area/holodeck/rec_center/burn
name = "Holodeck - Atmospheric Burn Test"
restricted = 1
-/area/holodeck/rec_center/winterwonderland
- name = "Holodeck - Winter Wonderland"
- restricted = 1
-
/area/holodeck/rec_center/wildlife
name = "Holodeck - Wildlife Simulation"
restricted = 1
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 5d81e1f80c..dc418cbf89 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -120,7 +120,7 @@
if(flags & CLEAN_ON_MOVE)
clean_on_move()
-
+
var/datum/proximity_monitor/proximity_monitor = src.proximity_monitor
if(proximity_monitor)
proximity_monitor.HandleMove()
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index de830c856b..2e5854509a 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -24,7 +24,7 @@
if(!istype(H)) return 0
var/obj/item/clothing/under/U = H.w_uniform
if(!istype(U)) return 0
- if(U.sensor_mode <= 2) return 0
+ if(U.sensor_mode <= SENSOR_VITALS) return 0
return 1
/datum/atom_hud/data/human/medical/basic/add_to_single_hud(mob/M, mob/living/carbon/H)
diff --git a/code/game/gamemodes/blob/blob_finish.dm b/code/game/gamemodes/blob/blob_finish.dm
index a5fc5e339a..47e2ce6a14 100644
--- a/code/game/gamemodes/blob/blob_finish.dm
+++ b/code/game/gamemodes/blob/blob_finish.dm
@@ -20,7 +20,7 @@
if(round_converted) //So badmin blobs later don't step on the dead natural blobs metaphorical toes
..()
if(blobwincount <= GLOB.blobs_legit.len)
- feedback_set_details("round_end_result","win - blob took over")
+ SSblackbox.set_details("round_end_result","win - blob took over")
to_chat(world, "The blob has taken over the station!")
to_chat(world, "The entire station was eaten by the Blob!")
log_game("Blob mode completed with a blob victory.")
@@ -28,7 +28,7 @@
SSticker.news_report = BLOB_WIN
else if(station_was_nuked)
- feedback_set_details("round_end_result","halfwin - nuke")
+ SSblackbox.set_details("round_end_result","halfwin - nuke")
to_chat(world, "Partial Win: The station has been destroyed!")
to_chat(world, "Directive 7-12 has been successfully carried out, preventing the Blob from spreading.")
log_game("Blob mode completed with a tie (station destroyed).")
@@ -36,7 +36,7 @@
SSticker.news_report = BLOB_NUKE
else if(!GLOB.blob_cores.len)
- feedback_set_details("round_end_result","loss - blob eliminated")
+ SSblackbox.set_details("round_end_result","loss - blob eliminated")
to_chat(world, "The staff has won!")
to_chat(world, "The alien organism has been eradicated from the station!")
log_game("Blob mode completed with a crew victory.")
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index fc39f2222e..9d281b5f2f 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -254,19 +254,19 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
for(var/datum/objective/objective in changeling.objectives)
if(objective.check_completion())
text += "
Objective #[count]: [objective.explanation_text] Success!"
- feedback_add_details("changeling_objective","[objective.type]|SUCCESS")
+ SSblackbox.add_details("changeling_objective","[objective.type]|SUCCESS")
else
text += "
Objective #[count]: [objective.explanation_text] Fail."
- feedback_add_details("changeling_objective","[objective.type]|FAIL")
+ SSblackbox.add_details("changeling_objective","[objective.type]|FAIL")
changelingwin = 0
count++
if(changelingwin)
text += "
The changeling was successful!"
- feedback_add_details("changeling_success","SUCCESS")
+ SSblackbox.add_details("changeling_success","SUCCESS")
else
text += "
The changeling has failed."
- feedback_add_details("changeling_success","FAIL")
+ SSblackbox.add_details("changeling_success","FAIL")
text += "
"
to_chat(world, text)
diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm
index 1673e59f49..67eb216d58 100644
--- a/code/game/gamemodes/changeling/changeling_power.dm
+++ b/code/game/gamemodes/changeling/changeling_power.dm
@@ -21,7 +21,7 @@
/obj/effect/proc_holder/changeling/proc/on_purchase(mob/user, is_respec)
if(!is_respec)
- feedback_add_details("changeling_power_purchase",name)
+ SSblackbox.add_details("changeling_power_purchase",name)
/obj/effect/proc_holder/changeling/proc/on_refund(mob/user)
return
@@ -37,7 +37,7 @@
return
var/datum/changeling/c = user.mind.changeling
if(sting_action(user, target))
- feedback_add_details("changeling_powers",name)
+ SSblackbox.add_details("changeling_powers",name)
sting_feedback(user, target)
take_chemical_cost(c)
diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm
index db1405537f..fdfec9e270 100644
--- a/code/game/gamemodes/changeling/evolution_menu.dm
+++ b/code/game/gamemodes/changeling/evolution_menu.dm
@@ -68,7 +68,7 @@
mind.changeling.purchasedpowers+=S
S.on_purchase(src, is_respec)
if(is_respec)
- feedback_add_details("changeling_power_purchase","Readapt")
+ SSblackbox.add_details("changeling_power_purchase","Readapt")
var/mob/living/carbon/C = src //only carbons have dna now, so we have to typecaste
if(ishuman(C))
diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm
index 0f1fb93071..6a52ab9312 100644
--- a/code/game/gamemodes/changeling/powers/absorb.dm
+++ b/code/game/gamemodes/changeling/powers/absorb.dm
@@ -42,13 +42,13 @@
to_chat(target, "You feel a sharp stabbing pain!")
target.take_overall_damage(40)
- feedback_add_details("changeling_powers","Absorb DNA|[i]")
+ SSblackbox.add_details("changeling_powers","Absorb DNA|[i]")
if(!do_mob(user, target, 150))
to_chat(user, "Our absorption of [target] has been interrupted!")
changeling.isabsorbing = 0
return
- feedback_add_details("changeling_powers","Absorb DNA|4")
+ SSblackbox.add_details("changeling_powers","Absorb DNA|4")
user.visible_message("[user] sucks the fluids from [target]!", "We have absorbed [target].")
to_chat(target, "You are absorbed by the changeling!")
diff --git a/code/game/gamemodes/changeling/powers/linglink.dm b/code/game/gamemodes/changeling/powers/linglink.dm
index 5a64d551b5..fc4b91b650 100644
--- a/code/game/gamemodes/changeling/powers/linglink.dm
+++ b/code/game/gamemodes/changeling/powers/linglink.dm
@@ -56,7 +56,7 @@
to_chat(target, "You can now communicate in the changeling hivemind, say \":g message\" to communicate!")
target.reagents.add_reagent("salbutamol", 40) // So they don't choke to death while you interrogate them
sleep(1800)
- feedback_add_details("changeling_powers","Hivemind Link|[i]")
+ SSblackbox.add_details("changeling_powers","Hivemind Link|[i]")
if(!do_mob(user, target, 20))
to_chat(user, "Our link with [target] has ended!")
changeling.islinking = 0
diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm
index 670e08e7a2..7fccb37d3c 100644
--- a/code/game/gamemodes/clock_cult/clock_cult.dm
+++ b/code/game/gamemodes/clock_cult/clock_cult.dm
@@ -46,7 +46,7 @@ Credit where due:
///////////
/proc/is_servant_of_ratvar(mob/living/M)
- return istype(M) && M.has_antag_datum(/datum/antagonist/clockcultist, TRUE)
+ return istype(M) && M.mind && M.mind.has_antag_datum(ANTAG_DATUM_CLOCKCULT)
/proc/is_eligible_servant(mob/living/M)
if(!istype(M))
@@ -65,17 +65,21 @@ Credit where due:
return FALSE
/proc/add_servant_of_ratvar(mob/living/L, silent = FALSE)
- var/update_type = /datum/antagonist/clockcultist
+ if(!L || !L.mind)
+ return
+ var/update_type = ANTAG_DATUM_CLOCKCULT
if(silent)
- update_type = /datum/antagonist/clockcultist/silent
- . = L.gain_antag_datum(update_type)
+ update_type = ANTAG_DATUM_CLOCKCULT_SILENT
+ . = L.mind.add_antag_datum(update_type)
/proc/remove_servant_of_ratvar(mob/living/L, silent = FALSE)
- var/datum/antagonist/clockcultist/clock_datum = L.has_antag_datum(/datum/antagonist/clockcultist, TRUE)
+ if(!L || !L.mind)
+ return
+ var/datum/antagonist/clockcult/clock_datum = L.mind.has_antag_datum(/datum/antagonist/clockcult)
if(!clock_datum)
return FALSE
- clock_datum.silent_update = silent
- clock_datum.on_remove()
+ clock_datum.silent = silent
+ clock_datum.on_removal()
return TRUE
///////////////
@@ -194,7 +198,7 @@ Credit where due:
var/datum/game_mode/clockwork_cult/C = SSticker.mode
if(C.check_clockwork_victory())
text += "Ratvar's servants have succeeded in fulfilling His goals!"
- feedback_set_details("round_end_result", "win - servants completed their objective (summon ratvar)")
+ SSblackbox.set_details("round_end_result", "win - servants completed their objective (summon ratvar)")
else
var/half_victory = FALSE
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = locate() in GLOB.all_clockwork_objects
@@ -203,10 +207,10 @@ Credit where due:
if(half_victory)
text += "The crew escaped before Ratvar could rise, but the gateway \
was successfully constructed!"
- feedback_set_details("round_end_result", "halfwin - servants constructed the gateway but their objective was not completed (summon ratvar)")
+ SSblackbox.set_details("round_end_result", "halfwin - servants constructed the gateway but their objective was not completed (summon ratvar)")
else
text += "Ratvar's servants have failed!"
- feedback_set_details("round_end_result", "loss - servants failed their objective (summon ratvar)")
+ SSblackbox.set_details("round_end_result", "loss - servants failed their objective (summon ratvar)")
text += "
The servants' objective was:
[CLOCKCULT_OBJECTIVE]"
text += "
Ratvar's servants had [GLOB.clockwork_caches] Tinkerer's Caches."
text += "
Construction Value(CV) was: [GLOB.clockwork_construction_value]"
diff --git a/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm b/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm
index f376410124..1c49d36693 100644
--- a/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm
+++ b/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm
@@ -15,9 +15,8 @@
var/obj/effect/clockwork/spatial_gateway/linked_gateway //The gateway linked to this one
var/timerid
-/obj/effect/clockwork/spatial_gateway/New()
- ..()
- update_light()
+/obj/effect/clockwork/spatial_gateway/Initialize()
+ . = ..()
addtimer(CALLBACK(src, .proc/check_setup), 1)
/obj/effect/clockwork/spatial_gateway/Destroy()
@@ -99,12 +98,12 @@
if(severity == 1 && uses)
uses = 0
visible_message("[src] is disrupted!")
- animate(src, alpha = 0, transform = matrix()*2, time = 10)
+ animate(src, alpha = 0, transform = matrix()*2, time = 10, flags = ANIMATION_END_NOW)
deltimer(timerid)
timerid = QDEL_IN(src, 10)
linked_gateway.uses = 0
linked_gateway.visible_message("[linked_gateway] is disrupted!")
- animate(linked_gateway, alpha = 0, transform = matrix()*2, time = 10)
+ animate(linked_gateway, alpha = 0, transform = matrix()*2, time = 10, flags = ANIMATION_END_NOW)
deltimer(linked_gateway.timerid)
linked_gateway.timerid = QDEL_IN(linked_gateway, 10)
return TRUE
@@ -131,9 +130,9 @@
playsound(src, 'sound/effects/EMPulse.ogg', 50, 1)
playsound(linked_gateway, 'sound/effects/EMPulse.ogg', 50, 1)
transform = matrix() * 1.5
- animate(src, transform = matrix() / 1.5, time = 10)
+ animate(src, transform = matrix() / 1.5, time = 10, flags = ANIMATION_END_NOW)
linked_gateway.transform = matrix() * 1.5
- animate(linked_gateway, transform = matrix() / 1.5, time = 10)
+ animate(linked_gateway, transform = matrix() / 1.5, time = 10, flags = ANIMATION_END_NOW)
A.forceMove(get_turf(linked_gateway))
if(!no_cost)
uses = max(0, uses - 1)
diff --git a/code/game/gamemodes/clock_cult/clock_helpers/ratvarian_language.dm b/code/game/gamemodes/clock_cult/clock_helpers/ratvarian_language.dm
index fcb30a096d..a9727017d3 100644
--- a/code/game/gamemodes/clock_cult/clock_helpers/ratvarian_language.dm
+++ b/code/game/gamemodes/clock_cult/clock_helpers/ratvarian_language.dm
@@ -106,6 +106,6 @@ List of nuances:
if(!whisper)
L.say(message, "clock", spans, language=/datum/language/common)
else
- L.whisper(message)
+ L.whisper(message, "clock", spans, language=/datum/language/common)
else
AM.say(message, language=/datum/language/common)
diff --git a/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm b/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm
index 36ff67262b..35caabab5a 100644
--- a/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm
+++ b/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm
@@ -61,7 +61,7 @@
/obj/item/clockwork/slab/cyborg/medical //five scriptures, plus a spear
quickbound = list(/datum/clockwork_scripture/ranged_ability/linked_vanguard, /datum/clockwork_scripture/ranged_ability/sentinels_compromise, \
- /datum/clockwork_scripture/create_object/vitality_matrix, /datum/clockwork_scripture/fellowship_armory, /datum/clockwork_scripture/create_object/mending_motor)
+ /datum/clockwork_scripture/create_object/vitality_matrix, /datum/clockwork_scripture/channeled/mending_mantra, /datum/clockwork_scripture/fellowship_armory)
/obj/item/clockwork/slab/cyborg/security //four scriptures, plus a spear
quickbound = list(/datum/clockwork_scripture/channeled/belligerent, /datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/channeled/taunting_tirade, \
diff --git a/code/game/gamemodes/clock_cult/clock_scripture.dm b/code/game/gamemodes/clock_cult/clock_scripture.dm
index 8e688f30aa..e8f1e8dbbc 100644
--- a/code/game/gamemodes/clock_cult/clock_scripture.dm
+++ b/code/game/gamemodes/clock_cult/clock_scripture.dm
@@ -86,7 +86,7 @@ Judgement: 12 servants, 5 caches, 300 CV, and any existing AIs are converted or
else
successful = TRUE
if(slab && !slab.no_cost && !GLOB.ratvar_awakens) //if the slab exists and isn't debug and ratvar isn't up, log the scripture as being used
- feedback_add_details("clockcult_scripture_recited", name)
+ SSblackbox.add_details("clockcult_scripture_recited", name)
if(slab)
slab.busy = null
qdel(src)
diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm
index efc479f522..25576f5710 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm
@@ -214,28 +214,6 @@
quickbind_desc = "Creates an Interdiction Lens, which drains power into nearby Sigils of Transmission."
-//Mending Motor: Creates a prism that will quickly heal mechanical servants/clockwork structures at a power cost
-/datum/clockwork_scripture/create_object/mending_motor
- descname = "Powered Structure, Repairs Other Structures"
- name = "Mending Motor"
- desc = "Creates a mechanized prism that will rapidly repair damaged clockwork constructs, converted cyborgs, and clockwork structures."
- invocations = list("May this prism...", "...mend our dents and scratches!")
- channel_time = 80
- consumed_components = list(VANGUARD_COGWHEEL = 3, GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 1)
- object_path = /obj/structure/destructible/clockwork/powered/mending_motor
- creator_message = "You form a mending motor, which will rapidly repair damaged clockwork constructs, converted cyborgs, and clockwork structures."
- observer_message = "An onyx prism forms in midair and sprouts tendrils to support itself!"
- invokers_required = 2
- multiple_invokers_used = TRUE
- usage_tip = "Powerful healing but power use is somewhat inefficient, though much better than a proselytizer."
- tier = SCRIPTURE_APPLICATION
- one_per_tile = TRUE
- primary_component = VANGUARD_COGWHEEL
- sort_priority = 7
- quickbind = TRUE
- quickbind_desc = "Creates a Mending Motor, which rapidly repairs constructs and structures at a power cost."
-
-
//Mania Motor: Creates a malevolent transmitter that will broadcast the whispers of Sevtug into the minds of nearby nonservants, causing a variety of mental effects at a power cost.
/datum/clockwork_scripture/create_object/mania_motor
descname = "Powered Structure, Area Denial"
diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm
index faab84befe..0dbd2d46e8 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm
@@ -110,7 +110,7 @@
channel_time = 150
consumed_components = list(BELLIGERENT_EYE = 3, VANGUARD_COGWHEEL = 3, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 6)
usage_tip = "Ocular wardens will become empowered, clockwork proselytizers will require no alloy, tinkerer's daemons will produce twice as quickly, \
- and interdiction lenses, mending motors, mania motors, tinkerer's daemons, and clockwork obelisks will all require no power."
+ and interdiction lenses, mania motors, tinkerer's daemons, and clockwork obelisks will all require no power."
tier = SCRIPTURE_REVENANT
primary_component = REPLICANT_ALLOY
sort_priority = 4
diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm
index 4fd4e629a1..f7fcc8c299 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm
@@ -69,6 +69,117 @@
quickbind_desc = "Creates a Vitality Matrix, which drains non-Servants on it to heal Servants that cross it."
+//Mending Mantra: Channeled for up to ten times over twenty seconds to repair structures and heal allies
+/datum/clockwork_scripture/channeled/mending_mantra
+ descname = "Channeled, Area Healing and Repair"
+ name = "Mending Mantra"
+ desc = "Repairs nearby structures and constructs. Servants wearing clockwork armor will also be healed. Channeled every two seconds for a maximum of twenty seconds."
+ chant_invocations = list("Mend our dents!", "Heal our scratches!", "Repair our gears!")
+ chant_amount = 10
+ chant_interval = 20
+ consumed_components = list(VANGUARD_COGWHEEL = 1, REPLICANT_ALLOY = 1)
+ usage_tip = "This is a very effective way to rapidly reinforce a base after an attack."
+ tier = SCRIPTURE_SCRIPT
+ primary_component = VANGUARD_COGWHEEL
+ sort_priority = 4
+ quickbind = TRUE
+ quickbind_desc = "Repairs nearby structures and constructs. Servants wearing clockwork armor will also be healed.
Maximum 10 chants."
+ var/heal_attempts = 4
+ var/heal_amount = 2.5
+ var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
+ var/static/list/heal_finish_messages = list("There, all mended!", "Try not to get too damaged.", "No more dents and scratches for you!", "Champions never die.", "All patched up.", \
+ "Ah, child, it's okay now.", "Pain is temporary.", "What you do for the Justiciar is eternal.", "Bear this for me.", "Be strong, child.", "Please, be careful!", \
+ "If you die, you will be remembered.")
+ var/static/list/heal_target_typecache = typecacheof(list(
+ /obj/structure/destructible/clockwork,
+ /obj/machinery/door/airlock/clockwork,
+ /obj/machinery/door/window/clockwork,
+ /obj/structure/window/reinforced/clockwork,
+ /obj/structure/table/reinforced/brass))
+ var/static/list/ratvarian_armor_typecache = typecacheof(list(
+ /obj/item/clothing/suit/armor/clockwork,
+ /obj/item/clothing/head/helmet/clockwork,
+ /obj/item/clothing/gloves/clockwork,
+ /obj/item/clothing/shoes/clockwork))
+
+/datum/clockwork_scripture/channeled/mending_mantra/chant_effects(chant_number)
+ var/turf/T
+ for(var/atom/movable/M in range(7, invoker))
+ if(isliving(M))
+ if(isclockmob(M) || istype(M, /mob/living/simple_animal/drone/cogscarab))
+ var/mob/living/simple_animal/S = M
+ if(S.health == S.maxHealth || S.stat == DEAD)
+ continue
+ T = get_turf(M)
+ for(var/i in 1 to heal_attempts)
+ if(S.health < S.maxHealth)
+ S.adjustHealth(-heal_amount)
+ new /obj/effect/overlay/temp/heal(T, "#1E8CE1")
+ if(i == heal_attempts && S.health >= S.maxHealth) //we finished healing on the last tick, give them the message
+ to_chat(S, "\"[text2ratvar(pick(heal_finish_messages))]\"")
+ break
+ else
+ to_chat(S, "\"[text2ratvar(pick(heal_finish_messages))]\"")
+ break
+ else if(issilicon(M))
+ var/mob/living/silicon/S = M
+ if(S.health == S.maxHealth || S.stat == DEAD || !is_servant_of_ratvar(S))
+ continue
+ T = get_turf(M)
+ for(var/i in 1 to heal_attempts)
+ if(S.health < S.maxHealth)
+ S.heal_ordered_damage(heal_amount, damage_heal_order)
+ new /obj/effect/overlay/temp/heal(T, "#1E8CE1")
+ if(i == heal_attempts && S.health >= S.maxHealth)
+ to_chat(S, "\"[text2ratvar(pick(heal_finish_messages))]\"")
+ break
+ else
+ to_chat(S, "\"[text2ratvar(pick(heal_finish_messages))]\"")
+ break
+ else if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ if(H.health == H.maxHealth || H.stat == DEAD || !is_servant_of_ratvar(H))
+ continue
+ T = get_turf(M)
+ var/heal_ticks = 0 //one heal tick for each piece of ratvarian armor worn
+ var/obj/item/I = H.get_item_by_slot(slot_wear_suit)
+ if(is_type_in_typecache(I, ratvarian_armor_typecache))
+ heal_ticks++
+ I = H.get_item_by_slot(slot_head)
+ if(is_type_in_typecache(I, ratvarian_armor_typecache))
+ heal_ticks++
+ I = H.get_item_by_slot(slot_gloves)
+ if(is_type_in_typecache(I, ratvarian_armor_typecache))
+ heal_ticks++
+ I = H.get_item_by_slot(slot_shoes)
+ if(is_type_in_typecache(I, ratvarian_armor_typecache))
+ heal_ticks++
+ if(heal_ticks)
+ for(var/i in 1 to heal_ticks)
+ if(H.health < H.maxHealth)
+ H.heal_ordered_damage(heal_amount, damage_heal_order)
+ new /obj/effect/overlay/temp/heal(T, "#1E8CE1")
+ if(i == heal_ticks && H.health >= H.maxHealth)
+ to_chat(H, "\"[text2ratvar(pick(heal_finish_messages))]\"")
+ break
+ else
+ to_chat(H, "\"[text2ratvar(pick(heal_finish_messages))]\"")
+ break
+ else if(is_type_in_typecache(M, heal_target_typecache))
+ var/obj/structure/destructible/clockwork/C = M
+ if(C.obj_integrity == C.max_integrity || (istype(C) && !C.can_be_repaired))
+ continue
+ T = get_turf(M)
+ for(var/i in 1 to heal_attempts)
+ if(C.obj_integrity < C.max_integrity)
+ C.obj_integrity = min(C.obj_integrity + 5, C.max_integrity)
+ C.update_icon()
+ new /obj/effect/overlay/temp/heal(T, "#1E8CE1")
+ else
+ break
+ return TRUE
+
+
//Sigil of Submission: Creates a sigil of submission, which converts one heretic above it after a delay.
/datum/clockwork_scripture/create_object/sigil_of_submission
descname = "Trap, Conversion"
diff --git a/code/game/gamemodes/clock_cult/clock_structures/clockwork_obelisk.dm b/code/game/gamemodes/clock_cult/clock_structures/clockwork_obelisk.dm
index c32bcb0b4b..2bebb4c9a5 100644
--- a/code/game/gamemodes/clock_cult/clock_structures/clockwork_obelisk.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures/clockwork_obelisk.dm
@@ -44,45 +44,50 @@
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/attack_hand(mob/living/user)
if(!is_servant_of_ratvar(user) || total_accessable_power() < hierophant_cost || !anchored)
- to_chat(user, "You place your hand on the obelisk, but it doesn't react.")
+ to_chat(user, "You place your hand on [src], but it doesn't react.")
return
- var/choice = alert(user,"You place your hand on the obelisk...",,"Hierophant Broadcast","Spatial Gateway","Cancel")
+ var/choice = alert(user,"You place your hand on [src]...",,"Hierophant Broadcast","Spatial Gateway","Cancel")
switch(choice)
if("Hierophant Broadcast")
if(active)
- to_chat(user, "The obelisk is sustaining a gateway and cannot broadcast!")
+ to_chat(user, "[src] is sustaining a gateway and cannot broadcast!")
return
if(!user.can_speak_vocal())
- to_chat(user, "You cannot speak through the obelisk!")
+ to_chat(user, "You cannot speak through [src]!")
return
var/input = stripped_input(usr, "Please choose a message to send over the Hierophant Network.", "Hierophant Broadcast", "")
if(!is_servant_of_ratvar(user) || !input || !user.canUseTopic(src, !issilicon(user)))
return
+ if(anchored)
+ to_chat(user, "[src] is no longer secured!")
+ return FALSE
if(active)
- to_chat(user, "The obelisk is sustaining a gateway and cannot broadcast!")
- return
- if(!try_use_power(hierophant_cost))
- to_chat(user, "The obelisk lacks the power to broadcast!")
+ to_chat(user, "[src] is sustaining a gateway and cannot broadcast!")
return
if(!user.can_speak_vocal())
- to_chat(user, "You cannot speak through the obelisk!")
+ to_chat(user, "You cannot speak through [src]!")
+ return
+ if(!try_use_power(hierophant_cost))
+ to_chat(user, "[src] lacks the power to broadcast!")
return
clockwork_say(user, text2ratvar("Hierophant Broadcast, activate! [html_decode(input)]"))
titled_hierophant_message(user, input, "big_brass", "large_brass")
if("Spatial Gateway")
if(active)
- to_chat(user, "The obelisk is already sustaining a gateway!")
- return
- if(!try_use_power(gateway_cost))
- to_chat(user, "The obelisk lacks the power to open a gateway!")
+ to_chat(user, "[src] is already sustaining a gateway!")
return
if(!user.can_speak_vocal())
to_chat(user, "You need to be able to speak to open a gateway!")
return
- if(procure_gateway(user, round(100 * get_efficiency_mod(), 1), round(5 * get_efficiency_mod(), 1), 1) && !active)
- clockwork_say(user, text2ratvar("Spatial Gateway, activate!"))
- else
- return_power(gateway_cost)
+ if(!try_use_power(gateway_cost))
+ to_chat(user, "[src] lacks the power to open a gateway!")
+ return
+ if(procure_gateway(user, round(100 * get_efficiency_mod(), 1), round(5 * get_efficiency_mod(), 1), 1))
+ process()
+ if(!active)
+ clockwork_say(user, text2ratvar("Spatial Gateway, activate!"))
+ return
+ return_power(gateway_cost) //if we didn't return above, ie, successfully create a gateway, we give the power back
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/process()
if(!anchored)
diff --git a/code/game/gamemodes/clock_cult/clock_structures/mending_motor.dm b/code/game/gamemodes/clock_cult/clock_structures/mending_motor.dm
deleted file mode 100644
index 6bd0f46e9d..0000000000
--- a/code/game/gamemodes/clock_cult/clock_structures/mending_motor.dm
+++ /dev/null
@@ -1,107 +0,0 @@
-//Mending Motor: A prism that consumes replicant alloy or power to repair nearby mechanical servants at a quick rate.
-/obj/structure/destructible/clockwork/powered/mending_motor
- name = "mending motor"
- desc = "A dark onyx prism, held in midair by spiraling tendrils of stone."
- clockwork_desc = "A powerful prism that rapidly repairs nearby mechanical servants and clockwork structures."
- icon_state = "mending_motor_inactive"
- active_icon = "mending_motor"
- inactive_icon = "mending_motor_inactive"
- unanchored_icon = "mending_motor_unwrenched"
- construction_value = 20
- max_integrity = 125
- obj_integrity = 125
- break_message = "The prism falls to the ground with a heavy thud!"
- debris = list(/obj/item/clockwork/alloy_shards/small = 3, \
- /obj/item/clockwork/alloy_shards/medium = 1, \
- /obj/item/clockwork/alloy_shards/large = 1, \
- /obj/item/clockwork/component/vanguard_cogwheel/onyx_prism = 1)
- var/heal_attempts = 4
- var/heal_cost = MIN_CLOCKCULT_POWER*2
- var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
- var/static/list/heal_finish_messages = list("There, all mended!", "Try not to get too damaged.", "No more dents and scratches for you!", "Champions never die.", "All patched up.", \
- "Ah, child, it's okay now.")
- var/static/list/heal_failure_messages = list("Pain is temporary.", "What you do for the Justiciar is eternal.", "Bear this for me.", "Be strong, child.", "Please, be careful!", \
- "If you die, you will be remembered.")
- var/static/list/mending_motor_typecache = typecacheof(list(
- /obj/structure/destructible/clockwork,
- /obj/machinery/door/airlock/clockwork,
- /obj/machinery/door/window/clockwork,
- /obj/structure/window/reinforced/clockwork,
- /obj/structure/table/reinforced/brass))
-
-/obj/structure/destructible/clockwork/powered/mending_motor/examine(mob/user)
- ..()
- if(is_servant_of_ratvar(user) || isobserver(user))
- to_chat(user, "It requires at least [heal_cost]W to attempt to repair clockwork mobs, structures, or converted silicons.")
-
-/obj/structure/destructible/clockwork/powered/mending_motor/forced_disable(bad_effects)
- if(active)
- if(bad_effects)
- try_use_power(heal_cost)
- visible_message("[src] emits an airy chuckling sound and falls dark!")
- toggle()
- return TRUE
-
-/obj/structure/destructible/clockwork/powered/mending_motor/attack_hand(mob/living/user)
- if(user.canUseTopic(src, !issilicon(user), NO_DEXTERY) && is_servant_of_ratvar(user))
- if(total_accessable_power() < MIN_CLOCKCULT_POWER)
- to_chat(user, "[src] needs more power to function!")
- return 0
- toggle(0, user)
-
-/obj/structure/destructible/clockwork/powered/mending_motor/process()
- var/efficiency = get_efficiency_mod()
- for(var/atom/movable/M in range(7, src))
- var/turf/T
- if(isclockmob(M) || istype(M, /mob/living/simple_animal/drone/cogscarab))
- T = get_turf(M)
- var/mob/living/simple_animal/S = M
- if(S.health == S.maxHealth || S.stat == DEAD)
- continue
- for(var/i in 1 to heal_attempts)
- if(S.health < S.maxHealth)
- if(try_use_power(heal_cost))
- S.adjustHealth(-(8 * efficiency))
- new /obj/effect/overlay/temp/heal(T, "#1E8CE1")
- else
- to_chat(S, "\"[text2ratvar(pick(heal_failure_messages))]\"")
- break
- else
- to_chat(S, "\"[text2ratvar(pick(heal_finish_messages))]\"")
- break
- else if(is_type_in_typecache(M, mending_motor_typecache))
- T = get_turf(M)
- var/obj/structure/destructible/clockwork/C = M
- if(C.obj_integrity == C.max_integrity || (istype(C) && !C.can_be_repaired))
- continue
- for(var/i in 1 to heal_attempts)
- if(C.obj_integrity < C.max_integrity)
- if(try_use_power(heal_cost))
- C.obj_integrity = min(C.obj_integrity + (8 * efficiency), C.max_integrity)
- if(C == src)
- efficiency = get_efficiency_mod()
- C.update_icon()
- new /obj/effect/overlay/temp/heal(T, "#1E8CE1")
- else
- break
- else
- break
- else if(issilicon(M))
- T = get_turf(M)
- var/mob/living/silicon/S = M
- if(S.health == S.maxHealth || S.stat == DEAD || !is_servant_of_ratvar(S))
- continue
- for(var/i in 1 to heal_attempts)
- if(S.health < S.maxHealth)
- if(try_use_power(heal_cost))
- S.heal_ordered_damage(8 * efficiency, damage_heal_order)
- new /obj/effect/overlay/temp/heal(T, "#1E8CE1")
- else
- to_chat(S, "\"[text2ratvar(pick(heal_failure_messages))]\"")
- break
- else
- to_chat(S, "\"[text2ratvar(pick(heal_finish_messages))]\"")
- break
- . = ..()
- if(. < heal_cost)
- forced_disable(FALSE)
diff --git a/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm b/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm
index 9b2d868730..614a22a6f5 100644
--- a/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm
@@ -40,8 +40,8 @@
/obj/structure/destructible/clockwork/massive/ratvar/attack_ghost(mob/dead/observer/O)
var/alertresult = alert(O, "Embrace the Justiciar's light? You can no longer be cloned!",,"Yes", "No")
- if(alertresult == "No" || !O)
- return 0
+ if(alertresult == "No" || QDELETED(O) || !istype(O) || !O.key)
+ return FALSE
var/mob/living/simple_animal/drone/cogscarab/ratvar/R = new/mob/living/simple_animal/drone/cogscarab/ratvar(get_turf(src))
R.visible_message("[R] forms, and its eyes blink open, glowing bright red!")
R.key = O.key
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 65dcb863eb..7780ae5db9 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -5,7 +5,7 @@
var/list/cult_objectives = list()
/proc/iscultist(mob/living/M)
- return istype(M) && M.has_antag_datum(/datum/antagonist/cultist, TRUE)
+ return istype(M) && M.mind && M.mind.has_antag_datum(ANTAG_DATUM_CULT)
/proc/is_sacrifice_target(datum/mind/mind)
if(SSticker.mode.name == "cult")
@@ -158,18 +158,18 @@
/datum/game_mode/proc/add_cultist(datum/mind/cult_mind, stun) //BASE
if (!istype(cult_mind))
return 0
- if(cult_mind.current.gain_antag_datum(/datum/antagonist/cultist))
+ if(cult_mind.add_antag_datum(ANTAG_DATUM_CULT))
if(stun)
cult_mind.current.Paralyse(5)
return 1
/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind, show_message = 1, stun)
if(cult_mind.current)
- var/datum/antagonist/cultist/cult_datum = cult_mind.current.has_antag_datum(/datum/antagonist/cultist, TRUE)
+ var/datum/antagonist/cult/cult_datum = cult_mind.has_antag_datum(ANTAG_DATUM_CULT)
if(!cult_datum)
return FALSE
- cult_datum.silent_update = show_message
- cult_datum.on_remove()
+ cult_datum.silent = show_message
+ cult_datum.on_removal()
if(stun)
cult_mind.current.Paralyse(5)
return TRUE
@@ -218,12 +218,12 @@
/datum/game_mode/cult/declare_completion()
if(!check_cult_victory())
- feedback_set_details("round_end_result","win - cult win")
- feedback_set("round_end_result",acolytes_survived)
+ SSblackbox.set_details("round_end_result","win - cult win")
+ SSblackbox.set_val("round_end_result",acolytes_survived)
to_chat(world, "The cult has succeeded! Nar-sie has snuffed out another torch in the void!")
else
- feedback_set_details("round_end_result","loss - staff stopped the cult")
- feedback_set("round_end_result",acolytes_survived)
+ SSblackbox.set_details("round_end_result","loss - staff stopped the cult")
+ SSblackbox.set_val("round_end_result",acolytes_survived)
to_chat(world, "The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!")
var/text = ""
@@ -236,31 +236,31 @@
if("survive")
if(!check_survive())
explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Success!"
- feedback_add_details("cult_objective","cult_survive|SUCCESS|[acolytes_needed]")
+ SSblackbox.add_details("cult_objective","cult_survive|SUCCESS|[acolytes_needed]")
SSticker.news_report = CULT_ESCAPE
else
explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Fail."
- feedback_add_details("cult_objective","cult_survive|FAIL|[acolytes_needed]")
+ SSblackbox.add_details("cult_objective","cult_survive|FAIL|[acolytes_needed]")
SSticker.news_report = CULT_FAILURE
if("sacrifice")
if(sacrifice_target)
if(sacrifice_target in GLOB.sacrificed)
explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Success!"
- feedback_add_details("cult_objective","cult_sacrifice|SUCCESS")
+ SSblackbox.add_details("cult_objective","cult_sacrifice|SUCCESS")
else if(sacrifice_target && sacrifice_target.current)
explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail."
- feedback_add_details("cult_objective","cult_sacrifice|FAIL")
+ SSblackbox.add_details("cult_objective","cult_sacrifice|FAIL")
else
explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail (Gibbed)."
- feedback_add_details("cult_objective","cult_sacrifice|FAIL|GIBBED")
+ SSblackbox.add_details("cult_objective","cult_sacrifice|FAIL|GIBBED")
if("eldergod")
if(!eldergod)
explanation = "Summon Nar-Sie. Success!"
- feedback_add_details("cult_objective","cult_narsie|SUCCESS")
+ SSblackbox.add_details("cult_objective","cult_narsie|SUCCESS")
SSticker.news_report = CULT_SUMMON
else
explanation = "Summon Nar-Sie. Fail."
- feedback_add_details("cult_objective","cult_narsie|FAIL")
+ SSblackbox.add_details("cult_objective","cult_narsie|FAIL")
SSticker.news_report = CULT_FAILURE
text += "
Objective #[obj_count]: [explanation]"
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index 2ed6840c91..ce4abced72 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -133,7 +133,7 @@ This file contains the arcane tome files.
text += "Talisman of Armaments
The Talisman of Arming will equip the user with armored robes, a backpack, an eldritch longsword, an empowered bola, and a pair of boots. Any items that cannot \
be equipped will not be summoned. Attacking a fellow cultist with it will instead equip them.
"
- text += "Talisman of Horrors
The Talisman of Horror must be applied directly to the victim, it will shatter your victim's mind with visions of the endtimes that may incapitate them.
"
+ text += "Talisman of Horrors
The Talisman of Horror, unlike other talismans, can be applied at range, without the victim noticing. It will cause the victim to have severe hallucinations after a short while.
"
text += "Talisman of Shackling
The Talisman of Shackling must be applied directly to the victim, it has 4 uses and cuffs victims with magic shackles that disappear when removed.
"
@@ -247,7 +247,7 @@ This file contains the arcane tome files.
var/obj/effect/rune/R = new rune_to_scribe(Turf, chosen_keyword)
R.add_mob_blood(user)
to_chat(user, "The [lowertext(R.cultist_name)] rune [R.cultist_desc]")
- feedback_add_details("cult_runes_scribed", R.cultist_name)
+ SSblackbox.add_details("cult_runes_scribed", R.cultist_name)
/obj/item/weapon/tome/proc/check_rune_turf(turf/T, mob/user)
var/area/A = get_area(T)
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 296b248938..3a80ed54b3 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -211,7 +211,7 @@ structure_check() searches for nearby cultist structures required for the invoca
log_game("Talisman Creation rune failed - already in use")
return
- for(var/I in subtypesof(/obj/item/weapon/paper/talisman) - /obj/item/weapon/paper/talisman/malformed - /obj/item/weapon/paper/talisman/supply - /obj/item/weapon/paper/talisman/supply/weak)
+ for(var/I in subtypesof(/obj/item/weapon/paper/talisman) - /obj/item/weapon/paper/talisman/malformed - /obj/item/weapon/paper/talisman/supply - /obj/item/weapon/paper/talisman/supply/weak - /obj/item/weapon/paper/talisman/summon_tome)
var/obj/item/weapon/paper/talisman/J = I
var/talisman_cult_name = initial(J.cultist_name)
if(talisman_cult_name)
@@ -633,9 +633,9 @@ structure_check() searches for nearby cultist structures required for the invoca
qdel(src) //delete before pulsing because it's a delay reee
empulse(E, 9*invokers.len, 12*invokers.len) // Scales now, from a single room to most of the station depending on # of chanters
-//Rite of Astral Communion: Separates one's spirit from their body. They will take damage while it is active.
-/obj/effect/rune/astral
- cultist_name = "Astral Communion"
+//Rite of Spirit Sight: Separates one's spirit from their body. They will take damage while it is active.
+/obj/effect/rune/spirit
+ cultist_name = "Spirit Sight"
cultist_desc = "severs the link between one's spirit and body. This effect is taxing and one's physical body will take damage while this is active."
invocation = "Fwe'sh mah erl nyag r'ya!"
icon_state = "7"
@@ -644,24 +644,24 @@ structure_check() searches for nearby cultist structures required for the invoca
construct_invoke = 0
var/mob/living/affecting = null
-/obj/effect/rune/astral/examine(mob/user)
+/obj/effect/rune/spirit/examine(mob/user)
..()
if(affecting)
to_chat(user, "A translucent field encases [user] above the rune!")
-/obj/effect/rune/astral/can_invoke(mob/living/user)
+/obj/effect/rune/spirit/can_invoke(mob/living/user)
if(rune_in_use)
to_chat(user, "[src] cannot support more than one body!")
- log_game("Astral Communion rune failed - more than one user")
+ log_game("Spirit Sight rune failed - more than one user")
return list()
var/turf/T = get_turf(src)
if(!(user in T))
to_chat(user, "You must be standing on top of [src]!")
- log_game("Astral Communion rune failed - user not standing on rune")
+ log_game("Spirit Sight rune failed - user not standing on rune")
return list()
return ..()
-/obj/effect/rune/astral/invoke(var/list/invokers)
+/obj/effect/rune/spirit/invoke(var/list/invokers)
var/mob/living/user = invokers[1]
..()
var/turf/T = get_turf(src)
@@ -898,45 +898,6 @@ structure_check() searches for nearby cultist structures required for the invoca
if(is_servant_of_ratvar(L))
L.adjustStaminaLoss(tick_damage*0.5)
-
-//Deals brute damage to all targets on the rune and heals the invoker for each target drained.
-/obj/effect/rune/leeching
- cultist_name = "Drain Life"
- cultist_desc = "drains the life of all targets on the rune, restoring life to the user."
- invocation = "Yu'gular faras desdae. Umathar uf'kal thenar!"
- icon_state = "3"
- color = "#9F1C34"
-
-/obj/effect/rune/leeching/can_invoke(mob/living/user)
- if(world.time <= user.next_move)
- return list()
- var/turf/T = get_turf(src)
- var/list/potential_targets = list()
- for(var/mob/living/carbon/M in T.contents - user)
- if(M.stat != DEAD)
- potential_targets += M
- if(!potential_targets.len)
- to_chat(user, "There must be at least one valid target on the rune!")
- log_game("Leeching rune failed - no valid targets")
- return list()
- return ..()
-
-/obj/effect/rune/leeching/invoke(var/list/invokers)
- var/mob/living/user = invokers[1]
- user.changeNext_move(CLICK_CD_CLICK_ABILITY)
- ..()
- var/turf/T = get_turf(src)
- for(var/mob/living/carbon/M in T.contents - user)
- if(M.stat != DEAD)
- var/drained_amount = rand(10,20)
- M.apply_damage(drained_amount, BRUTE, "chest")
- user.adjustBruteLoss(-drained_amount)
- to_chat(M, "You feel extremely weak.")
- user.Beam(T,icon_state="drainbeam",time=5)
- user.visible_message("Blood flows from the rune into [user]!", \
- "Blood flows into you, healing your wounds and revitalizing your spirit.")
-
-
//Rite of Spectral Manifestation: Summons a ghost on top of the rune as a cultist human with no items. User must stand on the rune at all times, and takes damage for each summoned ghost.
/obj/effect/rune/manifest
cultist_name = "Manifest Spirit"
diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm
index 2876e80373..9645b4bbce 100644
--- a/code/game/gamemodes/cult/talisman.dm
+++ b/code/game/gamemodes/cult/talisman.dm
@@ -176,7 +176,7 @@
invocation = "Kla'atu barada nikt'o!"
health_cost = 1
creation_time = 30
- uses = 2
+ uses = 6
var/revealing = FALSE //if it reveals or not
/obj/item/weapon/paper/talisman/true_sight/invoke(mob/living/user, successfuluse = 1)
@@ -186,7 +186,7 @@
"You speak the words of the talisman, hiding nearby runes.")
invocation = "Nikt'o barada kla'atu!"
revealing = TRUE
- for(var/obj/effect/rune/R in range(3,user))
+ for(var/obj/effect/rune/R in range(4,user))
R.talismanhide()
else
user.visible_message("A flash of light shines from [user]'s hand!", \
@@ -194,22 +194,6 @@
for(var/obj/effect/rune/R in range(3,user))
R.talismanreveal()
-//Rite of False Truths: Same as rune
-/obj/item/weapon/paper/talisman/make_runes_fake
- cultist_name = "Talisman of Disguising"
- cultist_desc = "A talisman that will make nearby runes appear fake."
- color = "#ff80d5" // honk
- invocation = "By'o nar'nar!"
- creation_time = 20
-
-/obj/item/weapon/paper/talisman/make_runes_fake/invoke(mob/living/user, successfuluse = 1)
- . = ..()
- user.visible_message("Dust flows from [user]s hand.", \
- "You speak the words of the talisman, making nearby runes appear fake.")
- for(var/obj/effect/rune/R in orange(6,user))
- R.desc = "A rune vandalizing the station."
-
-
//Rite of Disruption: Weaker than rune
/obj/item/weapon/paper/talisman/emp
cultist_name = "Talisman of Electromagnetic Pulse"
@@ -309,12 +293,12 @@
invocation = "Lo'Nab Na'Dm!"
creation_time = 80
-/obj/item/weapon/paper/talisman/horror/attack(mob/living/target, mob/living/user)
- if(iscultist(user))
- to_chat(user, "You disturb [target] with visons of the end!")
+/obj/item/weapon/paper/talisman/horror/afterattack(mob/living/target, mob/living/user)
+ if(iscultist(user) && (get_dist(user, target) < 7))
+ to_chat(user, "You disturb [target] with visions of madness!")
if(iscarbon(target))
var/mob/living/carbon/H = target
- H.reagents.add_reagent("mindbreaker", 25)
+ H.reagents.add_reagent("mindbreaker", 12)
if(is_servant_of_ratvar(target))
to_chat(target, "You see a brief but horrible vision of Ratvar, rusted and scrapped, being torn apart.")
target.emote("scream")
@@ -379,7 +363,7 @@
cultist_desc = "Use this talisman on a victim to handcuff them with dark bindings."
invocation = "In'totum Lig'abis!"
color = "#B27300" // burnt-orange
- uses = 4
+ uses = 6
/obj/item/weapon/paper/talisman/shackle/invoke(mob/living/user, successfuluse = 0)
if(successfuluse) //if we're forced to be successful(we normally aren't) then do the normal stuff
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 2564d1b262..a496715af2 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -80,12 +80,12 @@
report = config.intercept
addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME)
- feedback_set_details("round_start","[time2text(world.realtime)]")
+ SSblackbox.set_details("round_start","[time2text(world.realtime)]")
if(SSticker && SSticker.mode)
- feedback_set_details("game_mode","[SSticker.mode]")
+ SSblackbox.set_details("game_mode","[SSticker.mode]")
if(GLOB.revdata.commit)
- feedback_set_details("revision","[GLOB.revdata.commit]")
- feedback_set_details("server_ip","[world.internet_address]:[world.port]")
+ SSblackbox.set_details("revision","[GLOB.revdata.commit]")
+ SSblackbox.set_details("server_ip","[world.internet_address]:[world.port]")
if(report)
addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h))
generate_station_goals()
@@ -246,17 +246,17 @@
ghosts++
if(clients > 0)
- feedback_set("round_end_clients",clients)
+ SSblackbox.set_val("round_end_clients",clients)
if(ghosts > 0)
- feedback_set("round_end_ghosts",ghosts)
+ SSblackbox.set_val("round_end_ghosts",ghosts)
if(surviving_humans > 0)
- feedback_set("survived_human",surviving_humans)
+ SSblackbox.set_val("survived_human",surviving_humans)
if(surviving_total > 0)
- feedback_set("survived_total",surviving_total)
+ SSblackbox.set_val("survived_total",surviving_total)
if(escaped_humans > 0)
- feedback_set("escaped_human",escaped_humans)
+ SSblackbox.set_val("escaped_human",escaped_humans)
if(escaped_total > 0)
- feedback_set("escaped_total",escaped_total)
+ SSblackbox.set_val("escaped_total",escaped_total)
send2irc("Server", "Round just ended.")
return 0
diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm
index 22ca4b2298..9c31edf55f 100644
--- a/code/game/gamemodes/gang/gang.dm
+++ b/code/game/gamemodes/gang/gang.dm
@@ -260,12 +260,12 @@ GLOBAL_LIST_INIT(gang_colors_pool, list("red","orange","yellow","green","blue","
return
if(!winner)
to_chat(world, "The station was [station_was_nuked ? "destroyed!" : "evacuated before a gang could claim it! The station wins!"]
")
- feedback_set_details("round_end_result","loss - gangs failed takeover")
+ SSblackbox.set_details("round_end_result","loss - gangs failed takeover")
SSticker.news_report = GANG_LOSS
else
to_chat(world, "The [winner.name] Gang successfully performed a hostile takeover of the station!
")
- feedback_set_details("round_end_result","win - gang domination complete")
+ SSblackbox.set_details("round_end_result","win - gang domination complete")
SSticker.news_report = GANG_TAKEOVER
diff --git a/code/game/gamemodes/gang/gang_pen.dm b/code/game/gamemodes/gang/gang_pen.dm
index 0e01532190..621d40cc45 100644
--- a/code/game/gamemodes/gang/gang_pen.dm
+++ b/code/game/gamemodes/gang/gang_pen.dm
@@ -11,7 +11,7 @@
..()
last_used = world.time
-/obj/item/weapon/pen/gang/attack(mob/living/M, mob/user)
+/obj/item/weapon/pen/gang/attack(mob/living/M, mob/user, stealth = TRUE)
if(!istype(M))
return
if(ishuman(M) && ishuman(user) && M.stat != DEAD)
diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm
index e1a2ddf78f..400b38309b 100644
--- a/code/game/gamemodes/meteor/meteor.dm
+++ b/code/game/gamemodes/meteor/meteor.dm
@@ -50,8 +50,8 @@
else
to_chat(world, "Nobody survived the meteor storm!")
- feedback_set_details("round_end_result","end - evacuation")
- feedback_set("round_end_result",survivors)
+ SSblackbox.set_details("round_end_result","end - evacuation")
+ SSblackbox.set_val("round_end_result",survivors)
..()
return 1
diff --git a/code/game/gamemodes/miniantags/abduction/machinery/pad.dm b/code/game/gamemodes/miniantags/abduction/machinery/pad.dm
index 5f8ad3de9d..083e610587 100644
--- a/code/game/gamemodes/miniantags/abduction/machinery/pad.dm
+++ b/code/game/gamemodes/miniantags/abduction/machinery/pad.dm
@@ -47,8 +47,8 @@
icon_state = "teleport"
duration = 80
-/obj/effect/overlay/temp/teleport_abductor/New()
+/obj/effect/overlay/temp/teleport_abductor/Initialize()
+ . = ..()
var/datum/effect_system/spark_spread/S = new
S.set_up(10,0,loc)
- S.start()
- ..()
\ No newline at end of file
+ S.start()
\ No newline at end of file
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
index 6ce04bed14..c6248b03cc 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
@@ -527,9 +527,9 @@
icon_state = "disintegrate"
duration = 10
-/obj/effect/overlay/temp/swarmer/disintegration/New()
- playsound(src.loc, "sparks", 100, 1)
- ..()
+/obj/effect/overlay/temp/swarmer/disintegration/Initialize()
+ . = ..()
+ playsound(loc, "sparks", 100, 1)
/obj/effect/overlay/temp/swarmer/dismantle
icon_state = "dismantle"
diff --git a/code/game/gamemodes/miniantags/monkey/monkey.dm b/code/game/gamemodes/miniantags/monkey/monkey.dm
index ecb15bc221..f9ea8dcc2c 100644
--- a/code/game/gamemodes/miniantags/monkey/monkey.dm
+++ b/code/game/gamemodes/miniantags/monkey/monkey.dm
@@ -107,10 +107,10 @@
/datum/game_mode/monkey/declare_completion()
if(check_monkey_victory())
- feedback_set_details("round_end_result","win - monkey win")
- feedback_set("round_end_result",escaped_monkeys)
+ SSblackbox.set_details("round_end_result","win - monkey win")
+ SSblackbox.set_val("round_end_result",escaped_monkeys)
to_chat(world, "The monkeys have overthrown their captors! Eeek eeeek!!")
else
- feedback_set_details("round_end_result","loss - staff stopped the monkeys")
- feedback_set("round_end_result",escaped_monkeys)
+ SSblackbox.set_details("round_end_result","loss - staff stopped the monkeys")
+ SSblackbox.set_val("round_end_result",escaped_monkeys)
to_chat(world, "The staff managed to contain the monkey infestation!")
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index d4d788e049..b12dcc3bcc 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -199,70 +199,70 @@
if(nuke_off_station == NUKE_SYNDICATE_BASE)
- feedback_set_details("round_end_result","loss - syndicate nuked - disk secured")
+ SSblackbox.set_details("round_end_result","loss - syndicate nuked - disk secured")
to_chat(world, "Humiliating Syndicate Defeat")
to_chat(world, "The crew of [station_name()] gave [syndicate_name()] operatives back their bomb! The syndicate base was destroyed! Next time, don't lose the nuke!")
SSticker.news_report = NUKE_SYNDICATE_BASE
else if(!disk_rescued && station_was_nuked && !syndies_didnt_escape)
- feedback_set_details("round_end_result","win - syndicate nuke")
+ SSblackbox.set_details("round_end_result","win - syndicate nuke")
to_chat(world, "Syndicate Major Victory!")
to_chat(world, "[syndicate_name()] operatives have destroyed [station_name()]!")
SSticker.news_report = STATION_NUKED
else if (!disk_rescued && station_was_nuked && syndies_didnt_escape)
- feedback_set_details("round_end_result","halfwin - syndicate nuke - did not evacuate in time")
+ SSblackbox.set_details("round_end_result","halfwin - syndicate nuke - did not evacuate in time")
to_chat(world, "Total Annihilation")
to_chat(world, "[syndicate_name()] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion. Next time, don't lose the disk!")
SSticker.news_report = STATION_NUKED
else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape)
- feedback_set_details("round_end_result","halfwin - blew wrong station")
+ SSblackbox.set_details("round_end_result","halfwin - blew wrong station")
to_chat(world, "Crew Minor Victory")
to_chat(world, "[syndicate_name()] operatives secured the authentication disk but blew up something that wasn't [station_name()]. Next time, don't do that!")
SSticker.news_report = NUKE_MISS
else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape)
- feedback_set_details("round_end_result","halfwin - blew wrong station - did not evacuate in time")
+ SSblackbox.set_details("round_end_result","halfwin - blew wrong station - did not evacuate in time")
to_chat(world, "[syndicate_name()] operatives have earned Darwin Award!")
to_chat(world, "[syndicate_name()] operatives blew up something that wasn't [station_name()] and got caught in the explosion. Next time, don't do that!")
SSticker.news_report = NUKE_MISS
else if ((disk_rescued || SSshuttle.emergency.mode != SHUTTLE_ENDGAME) && are_operatives_dead())
- feedback_set_details("round_end_result","loss - evacuation - disk secured - syndi team dead")
+ SSblackbox.set_details("round_end_result","loss - evacuation - disk secured - syndi team dead")
to_chat(world, "Crew Major Victory!")
to_chat(world, "The Research Staff has saved the disk and killed the [syndicate_name()] Operatives")
SSticker.news_report = OPERATIVES_KILLED
else if (disk_rescued)
- feedback_set_details("round_end_result","loss - evacuation - disk secured")
+ SSblackbox.set_details("round_end_result","loss - evacuation - disk secured")
to_chat(world, "Crew Major Victory")
to_chat(world, "The Research Staff has saved the disk and stopped the [syndicate_name()] Operatives!")
SSticker.news_report = OPERATIVES_KILLED
else if (!disk_rescued && are_operatives_dead())
- feedback_set_details("round_end_result","halfwin - evacuation - disk not secured")
+ SSblackbox.set_details("round_end_result","halfwin - evacuation - disk not secured")
to_chat(world, "Neutral Victory!")
to_chat(world, "The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name()] Operatives!")
SSticker.news_report = OPERATIVE_SKIRMISH
else if (!disk_rescued && crew_evacuated)
- feedback_set_details("round_end_result","halfwin - detonation averted")
+ SSblackbox.set_details("round_end_result","halfwin - detonation averted")
to_chat(world, "Syndicate Minor Victory!")
to_chat(world, "[syndicate_name()] operatives survived the assault but did not achieve the destruction of [station_name()]. Next time, don't lose the disk!")
SSticker.news_report = OPERATIVE_SKIRMISH
else if (!disk_rescued && !crew_evacuated)
- feedback_set_details("round_end_result","halfwin - interrupted")
+ SSblackbox.set_details("round_end_result","halfwin - interrupted")
to_chat(world, "Neutral Victory")
to_chat(world, "Round was mysteriously interrupted!")
diff --git a/code/game/gamemodes/nuclear/nuclear_challenge.dm b/code/game/gamemodes/nuclear/nuclear_challenge.dm
index 3e47aa517d..cad958ee64 100644
--- a/code/game/gamemodes/nuclear/nuclear_challenge.dm
+++ b/code/game/gamemodes/nuclear/nuclear_challenge.dm
@@ -57,7 +57,7 @@
U.hidden_uplink.telecrystals = CHALLENGE_TELECRYSTALS
U.hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
config.shuttle_refuel_delay = max(config.shuttle_refuel_delay, CHALLENGE_SHUTTLE_DELAY)
- feedback_set("nuclear_challenge_mode",1)
+ SSblackbox.set_val("nuclear_challenge_mode",1)
qdel(src)
/obj/item/device/nuclear_challenge/proc/check_allowed(mob/living/user)
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index c082a48224..6ac0ab8c7c 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -654,7 +654,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
for(var/mob/dead/new_player/P in GLOB.player_list)
if(P.client && P.ready && P.mind!=owner)
n_p ++
- else if (SSticker.current_state == GAME_STATE_PLAYING)
+ else if (SSticker.IsRoundInProgress())
for(var/mob/living/carbon/human/P in GLOB.player_list)
if(P.client && !(P.mind in SSticker.mode.changelings) && P.mind!=owner)
n_p ++
diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm
index 634c68e89a..7a31d1f3cd 100644
--- a/code/game/gamemodes/revolution/revolution.dm
+++ b/code/game/gamemodes/revolution/revolution.dm
@@ -345,13 +345,13 @@
//////////////////////////////////////////////////////////////////////
/datum/game_mode/revolution/declare_completion()
if(finished == 1)
- feedback_set_details("round_end_result","win - heads killed")
+ SSblackbox.set_details("round_end_result","win - heads killed")
to_chat(world, "The heads of staff were killed or exiled! The revolutionaries win!")
SSticker.news_report = REVS_WIN
else if(finished == 2)
- feedback_set_details("round_end_result","loss - rev heads killed")
+ SSblackbox.set_details("round_end_result","loss - rev heads killed")
to_chat(world, "The heads of staff managed to stop the revolution!")
SSticker.news_report = REVS_LOSE
diff --git a/code/game/gamemodes/traitor/double_agents.dm b/code/game/gamemodes/traitor/double_agents.dm
index 992e10fa22..cb6609ebe6 100644
--- a/code/game/gamemodes/traitor/double_agents.dm
+++ b/code/game/gamemodes/traitor/double_agents.dm
@@ -1,22 +1,24 @@
-/datum/game_mode/traitor/double_agents
- name = "double agents"
- config_tag = "double_agents"
+/datum/game_mode/traitor/internal_affairs
+ name = "Internal Affairs"
+ config_tag = "internal_affairs"
+ employer = "Internal Affairs"
required_players = 25
required_enemies = 5
recommended_enemies = 8
reroll_friendly = 0
+ traitor_name = "Nanotrasen Internal Affairs Agent"
traitors_possible = 10 //hard limit on traitors if scaling is turned off
num_modifier = 4 // Four additional traitors
- announce_text = "There are double agents trying to kill each other!\n\
- Traitors: Eliminate your targets and protect yourself!\n\
- Crew: Stop the double agents before they can cause too much mayhem."
+ announce_text = "There are Nanotrasen Internal Affairs Agents trying to kill each other!\n\
+ IAA: Eliminate your targets and protect yourself!\n\
+ Crew: Stop the IAA agents before they can cause too much mayhem."
var/list/target_list = list()
var/list/late_joining_list = list()
-/datum/game_mode/traitor/double_agents/post_setup()
+/datum/game_mode/traitor/internal_affairs/post_setup()
var/i = 0
for(var/datum/mind/traitor in traitors)
i++
@@ -25,7 +27,7 @@
target_list[traitor] = traitors[i + 1]
..()
-/datum/game_mode/traitor/double_agents/forge_traitor_objectives(datum/mind/traitor)
+/datum/game_mode/traitor/internal_affairs/forge_traitor_objectives(datum/mind/traitor)
if(target_list.len && target_list[traitor]) // Is a double agent
@@ -58,7 +60,7 @@
..() // Give them standard objectives.
return
-/datum/game_mode/traitor/double_agents/add_latejoin_traitor(datum/mind/character)
+/datum/game_mode/traitor/internal_affairs/add_latejoin_traitor(datum/mind/character)
check_potential_agents()
@@ -87,7 +89,7 @@
late_joining_list += character
return
-/datum/game_mode/traitor/double_agents/proc/check_potential_agents()
+/datum/game_mode/traitor/internal_affairs/proc/check_potential_agents()
for(var/M in late_joining_list)
if(istype(M, /datum/mind))
@@ -100,3 +102,18 @@
// If any check fails, remove them from our list
late_joining_list -= M
+
+
+/datum/game_mode/traitor/internal_affairs/greet_traitor(datum/mind/traitor)
+ var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "recieving bribes", "malpractice", "worship of prohbited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
+ to_chat(traitor.current, "You are the [traitor_name].")
+ to_chat(traitor.current, "Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.")
+ to_chat(traitor.current, "While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.")
+ to_chat(traitor.current, "For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.")
+ to_chat(traitor.current, "Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.")
+ traitor.announce_objectives()
+
+
+
+/datum/game_mode/traitor/internal_affairs/give_codewords(mob/living/traitor_mob)
+ return
\ No newline at end of file
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index c26945801b..90a953c446 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -1,5 +1,6 @@
/datum/game_mode
var/traitor_name = "traitor"
+ var/employer = "The Syndicate"
var/list/datum/mind/traitors = list()
var/datum/mind/exchange_red
@@ -213,7 +214,7 @@
..()
return//Traitors will be checked as part of check_extra_completion. Leaving this here as a reminder.
-/proc/give_codewords(mob/living/traitor_mob)
+/datum/game_mode/proc/give_codewords(mob/living/traitor_mob)
to_chat(traitor_mob, "The Syndicate provided you with the following information on how to identify their agents:")
to_chat(traitor_mob, "Code Phrase: [GLOB.syndicate_code_phrase]")
to_chat(traitor_mob, "Code Response: [GLOB.syndicate_code_response]")
@@ -260,10 +261,10 @@
for(var/datum/objective/objective in traitor.objectives)
if(objective.check_completion())
objectives += "
Objective #[count]: [objective.explanation_text] Success!"
- feedback_add_details("traitor_objective","[objective.type]|SUCCESS")
+ SSblackbox.add_details("traitor_objective","[objective.type]|SUCCESS")
else
objectives += "
Objective #[count]: [objective.explanation_text] Fail."
- feedback_add_details("traitor_objective","[objective.type]|FAIL")
+ SSblackbox.add_details("traitor_objective","[objective.type]|FAIL")
traitorwin = 0
count++
@@ -283,10 +284,10 @@
if(traitorwin)
text += "
The [special_role_text] was successful!"
- feedback_add_details("traitor_success","SUCCESS")
+ SSblackbox.add_details("traitor_success","SUCCESS")
else
text += "
The [special_role_text] has failed!"
- feedback_add_details("traitor_success","FAIL")
+ SSblackbox.add_details("traitor_success","FAIL")
text += "
"
@@ -335,7 +336,7 @@
uplink_loc = R
if (!uplink_loc)
- to_chat(traitor_mob, "Unfortunately, the Syndicate wasn't able to get you an Uplink.")
+ to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.")
. = 0
else
var/obj/item/device/uplink/U = new(uplink_loc)
@@ -345,19 +346,19 @@
if(uplink_loc == R)
R.traitor_frequency = sanitize_frequency(rand(MIN_FREQ, MAX_FREQ))
- to_chat(traitor_mob, "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(R.traitor_frequency)] to unlock its hidden features.")
+ to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(R.traitor_frequency)] to unlock its hidden features.")
traitor_mob.mind.store_memory("Radio Frequency: [format_frequency(R.traitor_frequency)] ([R.name]).")
else if(uplink_loc == PDA)
PDA.lock_code = "[rand(100,999)] [pick("Alpha","Bravo","Charlie","Delta","Echo","Foxtrot","Golf","Hotel","India","Juliet","Kilo","Lima","Mike","November","Oscar","Papa","Quebec","Romeo","Sierra","Tango","Uniform","Victor","Whiskey","X-ray","Yankee","Zulu")]"
- to_chat(traitor_mob, "The Syndicate have cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[PDA.lock_code]\" into the ringtone select to unlock its hidden features.")
+ to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[PDA.lock_code]\" into the ringtone select to unlock its hidden features.")
traitor_mob.mind.store_memory("Uplink Passcode: [PDA.lock_code] ([PDA.name]).")
else if(uplink_loc == P)
P.traitor_unlock_degrees = rand(1, 360)
- to_chat(traitor_mob, "The Syndicate have cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [P.traitor_unlock_degrees] from its starting position to unlock its hidden features.")
+ to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [P.traitor_unlock_degrees] from its starting position to unlock its hidden features.")
traitor_mob.mind.store_memory("Uplink Degrees: [P.traitor_unlock_degrees] ([P.name]).")
if(!safety) // If they are not a rev. Can be added on to.
diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm
index c925a5cbd5..137514d1e3 100644
--- a/code/game/gamemodes/wizard/artefact.dm
+++ b/code/game/gamemodes/wizard/artefact.dm
@@ -471,7 +471,7 @@
else if(istype(I,/obj/item/weapon/bikehorn))
to_chat(target, "HONK")
target << 'sound/items/AirHorn.ogg'
- target.adjustEarDamage(0,3)
+ target.adjustEarDamage(0,3)
GiveHint(target)
cooldown = world.time +cooldown_time
return
@@ -630,6 +630,6 @@
duration = 40
pixel_x = 500
-/obj/effect/overlay/temp/tornado/New(loc)
- ..()
+/obj/effect/overlay/temp/tornado/Initialize()
+ . = ..()
animate(src, pixel_x = -500, time = 40)
diff --git a/code/game/gamemodes/wizard/raginmages.dm b/code/game/gamemodes/wizard/raginmages.dm
index 01eb8a52c4..1eb51a95b4 100644
--- a/code/game/gamemodes/wizard/raginmages.dm
+++ b/code/game/gamemodes/wizard/raginmages.dm
@@ -132,7 +132,7 @@
/datum/game_mode/wizard/raginmages/declare_completion()
if(finished)
- feedback_set_details("round_end_result","loss - wizard killed")
+ SSblackbox.set_details("round_end_result","loss - wizard killed")
to_chat(world, "The crew has managed to hold off the wizard attack! The Space Wizards Federation has been taught a lesson they will not soon forget!")
..(1)
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index e9e1a95e73..b25187195d 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -57,10 +57,10 @@
aspell.name = "Instant [aspell.name]"
if(aspell.spell_level >= aspell.level_max)
to_chat(user, "This spell cannot be strengthened any further.")
- feedback_add_details("wizard_spell_improved", "[name]|[aspell.level]")
+ SSblackbox.add_details("wizard_spell_improved", "[name]|[aspell.level]")
return 1
//No same spell found - just learn it
- feedback_add_details("wizard_spell_learned", name)
+ SSblackbox.add_details("wizard_spell_learned", name)
user.mind.AddSpell(S)
to_chat(user, "You have learned [S.name].")
return 1
@@ -253,7 +253,7 @@
/datum/spellbook_entry/the_traps
name = "The Traps!"
spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/the_traps
- category = "Offensive"
+ category = "Defensive"
cost = 1
@@ -266,7 +266,7 @@
/datum/spellbook_entry/item/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book)
new item_path(get_turf(user))
- feedback_add_details("wizard_spell_learned", name)
+ SSblackbox.add_details("wizard_spell_learned", name)
return 1
/datum/spellbook_entry/item/GetInfo()
@@ -465,7 +465,7 @@
return TRUE
/datum/spellbook_entry/summon/ghosts/Buy(mob/living/carbon/human/user, obj/item/weapon/spellbook/book)
- feedback_add_details("wizard_spell_learned", name)
+ SSblackbox.add_details("wizard_spell_learned", name)
new /datum/round_event/wizard/ghost()
active = TRUE
to_chat(user, "You have cast summon ghosts!")
@@ -482,7 +482,7 @@
return (SSticker.mode.name != "ragin' mages" && !config.no_summon_guns)
/datum/spellbook_entry/summon/guns/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book)
- feedback_add_details("wizard_spell_learned", name)
+ SSblackbox.add_details("wizard_spell_learned", name)
rightandwrong(0, user, 25)
active = 1
playsound(get_turf(user), 'sound/magic/CastSummon.ogg', 50, 1)
@@ -499,7 +499,7 @@
return (SSticker.mode.name != "ragin' mages" && !config.no_summon_magic)
/datum/spellbook_entry/summon/magic/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book)
- feedback_add_details("wizard_spell_learned", name)
+ SSblackbox.add_details("wizard_spell_learned", name)
rightandwrong(1, user, 25)
active = 1
playsound(get_turf(user), 'sound/magic/CastSummon.ogg', 50, 1)
@@ -517,7 +517,7 @@
return (SSticker.mode.name != "ragin' mages" && !config.no_summon_events)
/datum/spellbook_entry/summon/events/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book)
- feedback_add_details("wizard_spell_learned", name)
+ SSblackbox.add_details("wizard_spell_learned", name)
summonevents()
times++
playsound(get_turf(user), 'sound/magic/CastSummon.ogg', 50, 1)
diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm
index 34d148f03c..35bccb692a 100644
--- a/code/game/gamemodes/wizard/wizard.dm
+++ b/code/game/gamemodes/wizard/wizard.dm
@@ -176,7 +176,7 @@
/datum/game_mode/wizard/declare_completion()
if(finished)
- feedback_set_details("round_end_result","loss - wizard killed")
+ SSblackbox.set_details("round_end_result","loss - wizard killed")
to_chat(world, "The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!")
SSticker.news_report = WIZARD_KILLED
@@ -208,19 +208,19 @@
for(var/datum/objective/objective in wizard.objectives)
if(objective.check_completion())
text += "
Objective #[count]: [objective.explanation_text] Success!"
- feedback_add_details("wizard_objective","[objective.type]|SUCCESS")
+ SSblackbox.add_details("wizard_objective","[objective.type]|SUCCESS")
else
text += "
Objective #[count]: [objective.explanation_text] Fail."
- feedback_add_details("wizard_objective","[objective.type]|FAIL")
+ SSblackbox.add_details("wizard_objective","[objective.type]|FAIL")
wizardwin = 0
count++
if(wizard.current && wizard.current.stat!=2 && wizardwin)
text += "
The wizard was successful!"
- feedback_add_details("wizard_success","SUCCESS")
+ SSblackbox.add_details("wizard_success","SUCCESS")
else
text += "
The wizard has failed!"
- feedback_add_details("wizard_success","FAIL")
+ SSblackbox.add_details("wizard_success","FAIL")
if(wizard.spell_list.len>0)
text += "
[wizard.name] used the following spells: "
var/i = 1
diff --git a/code/game/machinery/bank_machine.dm b/code/game/machinery/bank_machine.dm
index 35f7babe1e..ace9b543d1 100644
--- a/code/game/machinery/bank_machine.dm
+++ b/code/game/machinery/bank_machine.dm
@@ -4,7 +4,21 @@
icon = 'goon/icons/obj/goon_terminals.dmi'
idle_power_usage = 100
var/siphoning = FALSE
- var/last_warning = 0
+ var/next_warning = 0
+ var/obj/item/device/radio/radio
+ var/radio_channel = "Common"
+ var/minimum_time_between_warnings = 400
+
+/obj/machinery/computer/bank_machine/Initialize(mapload)
+ ..()
+ radio = new(src)
+ radio.subspace_transmission = TRUE
+ radio.canhear_range = 0
+ radio.recalculateChannels()
+
+/obj/machinery/computer/bank_machine/Destroy()
+ QDEL_NULL(radio)
+ . = ..()
/obj/machinery/computer/bank_machine/attackby(obj/item/I, mob/user)
var/value = 0
@@ -32,18 +46,17 @@
say("Station funds depleted. Halting siphon.")
siphoning = FALSE
else
- var/obj/item/stack/spacecash/c200/on_turf = locate() in src.loc
- if(on_turf && on_turf.amount < on_turf.max_amount)
- on_turf.amount++
- else
- new /obj/item/stack/spacecash/c200(get_turf(src))
+ new /obj/item/stack/spacecash/c200(get_turf(src)) // will autostack
playsound(src.loc, 'sound/items/poster_being_created.ogg', 100, 1)
SSshuttle.points -= 200
- if(last_warning < world.time && prob(15))
+ if(next_warning < world.time && prob(15))
var/area/A = get_area(loc)
- minor_announce("Unauthorized credit withdrawal underway in [A.map_name]." , "Network Breach", TRUE)
- last_warning = world.time + 400
+ var/message = "Unauthorized credit withdrawal underway in [A.map_name]!!"
+ radio.talk_into(src, message, radio_channel, get_spans())
+ next_warning = world.time + minimum_time_between_warnings
+/obj/machinery/computer/bank_machine/get_spans()
+ . = ..() | SPAN_ROBOT
/obj/machinery/computer/bank_machine/attack_hand(mob/user)
if(..())
@@ -67,8 +80,8 @@
if(..())
return
if(href_list["siphon"])
- say("Siphon of station credits has begun!")
+ say("Siphon of station credits has begun!")
siphoning = TRUE
if(href_list["halt"])
- say("Station credit withdrawal halted.")
- siphoning = FALSE
\ No newline at end of file
+ say("Station credit withdrawal halted.")
+ siphoning = FALSE
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index eeef80ca5b..824b50b168 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -314,7 +314,7 @@
return
else
connected_message("Authorized Ejection")
- SPEAK("An authorized ejection of [occupant.real_name] has occurred.")
+ SPEAK("An authorized ejection of [clonemind.name] has occurred.")
to_chat(user, "You force an emergency ejection. ")
go_out()
else
@@ -342,7 +342,7 @@
if(mess) //Clean that mess and dump those gibs!
mess = FALSE
- new /obj/effect/gibspawner/generic(loc)
+ new /obj/effect/gibspawner/generic(loc)
audible_message("You hear a splat.")
icon_state = "pod_0"
return
@@ -355,7 +355,7 @@
to_chat(occupant, "There is a bright flash!
You feel like a new being.")
occupant.flash_act()
- var/turf/T = get_turf(src)
+ var/turf/T = get_turf(src)
occupant.forceMove(T)
icon_state = "pod_0"
occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
@@ -367,6 +367,8 @@
SPEAK("Critical error! Please contact a Thinktronic Systems \
technician, as your warranty may be affected.")
mess = TRUE
+ for(var/obj/item/O in unattached_flesh)
+ qdel(O)
icon_state = "pod_g"
if(occupant.mind != clonemind)
clonemind.transfer_to(occupant)
@@ -375,16 +377,16 @@
to_chat(occupant, "Agony blazes across your consciousness as your body is torn apart.
Is this what dying is like? Yes it is.")
playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 50, 0)
occupant << sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)
- QDEL_IN(occupant, 40)
+ QDEL_IN(occupant, 40)
/obj/machinery/clonepod/relaymove(mob/user)
if(user.stat == CONSCIOUS)
go_out()
/obj/machinery/clonepod/emp_act(severity)
- if(prob(100/(severity*efficiency)))
+ if((occupant || mess) && prob(100/(severity*efficiency)))
connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
- SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [occupant.real_name] prematurely." ,0))
+ SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [clonemind.name] prematurely." ,0))
go_out()
..()
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 514cf590af..643282ab4a 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -234,7 +234,7 @@
playsound(loc, 'sound/arcade/Win.ogg', 50, 1, extrarange = -3, falloff = 10)
if(emagged)
- feedback_inc("arcade_win_emagged")
+ SSblackbox.inc("arcade_win_emagged")
new /obj/effect/spawner/newbomb/timer/syndicate(loc)
new /obj/item/clothing/head/collectable/petehat(loc)
message_admins("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded a bomb.")
@@ -242,7 +242,7 @@
Reset()
emagged = 0
else
- feedback_inc("arcade_win_normal")
+ SSblackbox.inc("arcade_win_normal")
prizevend()
else if (emagged && (turtle >= 4))
@@ -264,10 +264,10 @@
temp = "You have been drained! GAME OVER"
playsound(loc, 'sound/arcade/Lose.ogg', 50, 1, extrarange = -3, falloff = 10)
if(emagged)
- feedback_inc("arcade_loss_mana_emagged")
+ SSblackbox.inc("arcade_loss_mana_emagged")
usr.gib()
else
- feedback_inc("arcade_loss_mana_normal")
+ SSblackbox.inc("arcade_loss_mana_normal")
else if ((enemy_hp <= 10) && (enemy_mp > 4))
temp = "[enemy_name] heals for 4 health!"
@@ -286,10 +286,10 @@
temp = "You have been crushed! GAME OVER"
playsound(loc, 'sound/arcade/Lose.ogg', 50, 1, extrarange = -3, falloff = 10)
if(emagged)
- feedback_inc("arcade_loss_hp_emagged")
+ SSblackbox.inc("arcade_loss_hp_emagged")
usr.gib()
else
- feedback_inc("arcade_loss_hp_normal")
+ SSblackbox.inc("arcade_loss_hp_normal")
blocked = FALSE
return
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 5af4f9c281..c9a448fc7b 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -115,9 +115,9 @@
message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].")
switch(GLOB.security_level)
if(SEC_LEVEL_GREEN)
- feedback_inc("alert_comms_green",1)
+ SSblackbox.inc("alert_comms_green",1)
if(SEC_LEVEL_BLUE)
- feedback_inc("alert_comms_blue",1)
+ SSblackbox.inc("alert_comms_blue",1)
tmp_alertlevel = 0
else
to_chat(usr, "You are not authorized to do this!")
@@ -176,7 +176,7 @@
SSshuttle.points -= S.credit_cost
minor_announce("[usr.name] has purchased [S.name] for [S.credit_cost] credits." , "Shuttle Purchase")
message_admins("[key_name_admin(usr)] purchased [S.name].")
- feedback_add_details("shuttle_purchase", S.name)
+ SSblackbox.add_details("shuttle_purchase", S.name)
else
to_chat(usr, "Something went wrong! The shuttle exchange system seems to be down.")
else
@@ -368,9 +368,9 @@
message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].")
switch(GLOB.security_level)
if(SEC_LEVEL_GREEN)
- feedback_inc("alert_comms_green",1)
+ SSblackbox.inc("alert_comms_green",1)
if(SEC_LEVEL_BLUE)
- feedback_inc("alert_comms_blue",1)
+ SSblackbox.inc("alert_comms_blue",1)
tmp_alertlevel = 0
src.aistate = STATE_DEFAULT
if("ai-changeseclevel")
diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm
index 1d331051e6..65fbee45f0 100644
--- a/code/game/machinery/computer/crew.dm
+++ b/code/game/machinery/computer/crew.dm
@@ -153,8 +153,8 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
U = H.w_uniform
// Are the suit sensors on?
- if (U.has_sensor && U.sensor_mode)
- pos = H.z == 0 || U.sensor_mode == 3 ? get_turf(H) : null
+ if ((U.has_sensor > 0) && U.sensor_mode)
+ pos = H.z == 0 || U.sensor_mode == SENSOR_COORDS ? get_turf(H) : null
// Special case: If the mob is inside an object confirm the z-level on turf level.
if (H.z == 0 && (!pos || pos.z != z)) continue
@@ -170,10 +170,10 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
assignment = ""
ijob = 80
- if (U.sensor_mode >= 1) life_status = (!H.stat ? "true" : "false")
+ if (U.sensor_mode >= SENSOR_LIVING) life_status = (!H.stat ? "true" : "false")
else life_status = null
- if (U.sensor_mode >= 2)
+ if (U.sensor_mode >= SENSOR_VITALS)
dam1 = round(H.getOxyLoss(),1)
dam2 = round(H.getToxLoss(),1)
dam3 = round(H.getFireLoss(),1)
@@ -184,7 +184,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
dam3 = null
dam4 = null
- if (U.sensor_mode >= 3)
+ if (U.sensor_mode >= SENSOR_COORDS)
if (!pos) pos = get_turf(H)
var/area/player_area = get_area(H)
diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm
index c97f487718..7f8eb32648 100644
--- a/code/game/machinery/computer/message.dm
+++ b/code/game/machinery/computer/message.dm
@@ -455,14 +455,16 @@
name = "monitor decryption key"
var/obj/machinery/message_server/server = null
-/obj/item/weapon/paper/monitorkey/New()
+/obj/item/weapon/paper/monitorkey/Initialize()
..()
- spawn(10)
- if(GLOB.message_servers)
- for(var/obj/machinery/message_server/server in GLOB.message_servers)
- if(!isnull(server))
- if(!isnull(server.decryptkey))
- info = "Daily Key Reset
The new message monitor key is '[server.decryptkey]'.
Please keep this a secret and away from the clown.
If necessary, change the password to a more secure one."
- info_links = info
- add_overlay("paper_words")
- break
+ return INITIALIZE_HINT_LATELOAD
+
+/obj/item/weapon/paper/monitorkey/LateInitialize()
+ if(GLOB.message_servers)
+ for(var/obj/machinery/message_server/server in GLOB.message_servers)
+ if(!isnull(server))
+ if(!isnull(server.decryptkey))
+ info = "Daily Key Reset
The new message monitor key is '[server.decryptkey]'.
Please keep this a secret and away from the clown.
If necessary, change the password to a more secure one."
+ info_links = info
+ add_overlay("paper_words")
+ break
diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm
index 8c935419a5..cf18a99875 100644
--- a/code/game/machinery/dance_machine.dm
+++ b/code/game/machinery/dance_machine.dm
@@ -13,8 +13,6 @@
var/list/rangers = list()
var/charge = 35
var/stop = 0
- var/list/available = list()
- var/list/select_name = list()
var/list/spotlights = list()
var/list/sparkles = list()
var/static/list/songs = list(
@@ -30,6 +28,7 @@
var/song_path = null
var/song_length = 0
var/song_beat = 0
+ var/GBP_required = 0
/datum/track/New(name, path, length, beat)
song_name = name
@@ -37,6 +36,19 @@
song_length = length
song_beat = beat
+/obj/machinery/disco/proc/add_track(file, name, length, beat)
+ var/sound/S = file
+ if(!istype(S))
+ return
+ if(!name)
+ name = "[file]"
+ if(!beat)
+ beat = 5
+ if(!length)
+ length = 2400 //Unless there's a way to discern via BYOND.
+ var/datum/track/T = new /datum/track(name, file, length, beat)
+ songs += T
+
/obj/machinery/disco/Initialize()
..()
selection = songs[1]
@@ -126,14 +138,14 @@
if(active)
to_chat(usr, "Error: You cannot change the song until the current one is over.")
return
- check_GBP()
- select_name = input(usr, "Choose your song", "Track:") as null|anything in available
- if (QDELETED(src))
- return
+
+ var/list/available = list()
for(var/datum/track/S in songs)
- if(select_name == S.song_name)
- selection = S
- break
+ available[S.song_name] = S
+ var/selected = input(usr, "Choose your song", "Track:") as null|anything in available
+ if(QDELETED(src) || !selected || !istype(available[selected], /datum/track))
+ return
+ selection = available[selected]
updateUsrDialog()
if("horn")
deejay('sound/items/AirHorn2.ogg')
@@ -159,13 +171,6 @@
charge -= 5
playsound(src, S,300,1)
-/obj/machinery/disco/proc/check_GBP()
- available |= "Engineering's Basic Beat"
- available |= "Engineering's Domination Dance"
- available |= "Engineering's Superiority Shimmy"
- available |= "Engineering's Ultimate High-Energy Hustle"
-
-
/obj/machinery/disco/proc/dance_setup()
stop = world.time + selection.song_length
var/turf/cen = get_turf(src)
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index a9331cd142..7ff38f53c9 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1283,8 +1283,6 @@
if(!density)
return 1
- if(!SSticker || !SSticker.mode)
- return 0
operating = 1
update_icon(AIRLOCK_OPENING, 1)
src.set_opacity(0)
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index cd587a0c44..4e076e3338 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -229,8 +229,6 @@
return 1
if(operating)
return
- if(!SSticker || !SSticker.mode)
- return 0
operating = 1
do_animate("opening")
set_opacity(0)
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 20dd6860ea..99cdc1adc3 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -129,8 +129,6 @@
/obj/machinery/door/window/open(forced=0)
if (src.operating == 1) //doors can still open when emag-disabled
return 0
- if(!SSticker || !SSticker.mode)
- return 0
if(!forced)
if(!hasPower())
return 0
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index a50a2973fc..7c3251a1be 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -535,7 +535,7 @@ GLOBAL_LIST_EMPTY(allCasters)
if(choice=="Confirm")
scan_user(usr)
GLOB.news_network.CreateFeedChannel(channel_name, scanned_user, c_locked)
- feedback_inc("newscaster_channels",1)
+ SSblackbox.inc("newscaster_channels",1)
screen=5
updateUsrDialog()
else if(href_list["set_channel_receiving"])
@@ -558,7 +558,7 @@ GLOBAL_LIST_EMPTY(allCasters)
screen=6
else
GLOB.news_network.SubmitArticle("[parsepencode(msg, usr, SIGNFONT)]", scanned_user, channel_name, photo, 0, allow_comments)
- feedback_inc("newscaster_stories",1)
+ SSblackbox.inc("newscaster_stories",1)
screen=4
msg = ""
updateUsrDialog()
@@ -850,7 +850,7 @@ GLOBAL_LIST_EMPTY(allCasters)
return
/obj/machinery/newscaster/proc/print_paper()
- feedback_inc("newscaster_newspapers_printed",1)
+ SSblackbox.inc("newscaster_newspapers_printed",1)
var/obj/item/weapon/newspaper/NEWSPAPER = new /obj/item/weapon/newspaper
for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels)
NEWSPAPER.news_content += FC
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
old mode 100644
new mode 100755
index ca398539a0..a081e3eb80
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -61,7 +61,7 @@
G.loc = src
charging = G
use_power = 2
- update_icon()
+ update_icon(scan = TRUE)
else
to_chat(user, "[src] isn't connected to anything!")
return 1
@@ -162,10 +162,13 @@
..()
-/obj/machinery/recharger/update_icon(using_power = 0) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
+/obj/machinery/recharger/update_icon(using_power = 0, scan) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
if(stat & (NOPOWER|BROKEN) || !anchored)
icon_state = "rechargeroff"
return
+ if(scan)
+ icon_state = "rechargeroff"
+ return
if(panel_open)
icon_state = "rechargeropen"
return
diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index 648b44932a..7506008e79 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -439,12 +439,12 @@ GLOBAL_LIST_EMPTY(allConsoles)
updateUsrDialog()
return
-/obj/machinery/requests_console/say_quote(input, list/spans, message_mode)
+/obj/machinery/requests_console/say_mod(input, message_mode)
var/ending = copytext(input, length(input) - 2)
if (ending == "!!!")
- return "blares, \"[attach_spans(input, spans)]\""
-
- return ..()
+ . = "blares"
+ else
+ . = ..()
/obj/machinery/requests_console/proc/clear_emergency()
emergency = null
diff --git a/code/game/machinery/telecomms/broadcasting.dm b/code/game/machinery/telecomms/broadcasting.dm
index d6c6cdc151..6c1fd431e5 100644
--- a/code/game/machinery/telecomms/broadcasting.dm
+++ b/code/game/machinery/telecomms/broadcasting.dm
@@ -144,30 +144,7 @@
// --- This following recording is intended for research and feedback in the use of department radio channels ---
var/blackbox_msg = "[AM] [AM.say_quote(message, spans)]"
- if(istype(GLOB.blackbox))
- switch(freq)
- if(1459)
- GLOB.blackbox.msg_common += blackbox_msg
- if(1351)
- GLOB.blackbox.msg_science += blackbox_msg
- if(1353)
- GLOB.blackbox.msg_command += blackbox_msg
- if(1355)
- GLOB.blackbox.msg_medical += blackbox_msg
- if(1357)
- GLOB.blackbox.msg_engineering += blackbox_msg
- if(1359)
- GLOB.blackbox.msg_security += blackbox_msg
- if(1441)
- GLOB.blackbox.msg_deathsquad += blackbox_msg
- if(1213)
- GLOB.blackbox.msg_syndicate += blackbox_msg
- if(1349)
- GLOB.blackbox.msg_service += blackbox_msg
- if(1347)
- GLOB.blackbox.msg_cargo += blackbox_msg
- else
- GLOB.blackbox.messages += blackbox_msg
+ SSblackbox.LogBroadcast(blackbox_msg, freq)
sleep(50)
if(!QDELETED(virt)) //It could happen to YOU
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index cbb4efd6b0..7d02e70671 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -297,7 +297,7 @@
to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.")
cut_overlays()
if(panel_open)
- add_overlay("[initial(icon_state)]-panel")
+ add_overlay("[initial(icon_state)]-panel")
playsound(src.loc, W.usesound, 50, 1)
updateUsrDialog()
else
@@ -528,7 +528,7 @@
if(icon_vend) //Show the vending animation if needed
flick(icon_vend,src)
new R.product_path(get_turf(src))
- feedback_add_details("vending_machine_usage","[src.type]|[R.product_path]")
+ SSblackbox.add_details("vending_machine_usage","[src.type]|[R.product_path]")
vend_ready = 1
return
@@ -732,7 +732,8 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
icon_state = "sustenance"
products = list(/obj/item/weapon/reagent_containers/food/snacks/tofu = 24,
/obj/item/weapon/reagent_containers/food/drinks/ice = 12,
- /obj/item/weapon/reagent_containers/food/snacks/candy_corn = 6)
+ /obj/item/weapon/reagent_containers/food/snacks/candy_corn = 6,
+ /obj/item/weapon/reagent_containers/glass/beaker/waterbottle = 10)
contraband = list(/obj/item/weapon/kitchen/knife = 6,
/obj/item/weapon/reagent_containers/food/drinks/coffee = 12,
/obj/item/weapon/tank/internals/emergency_oxygen = 6,
@@ -749,7 +750,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
products = list(/obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola = 10,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 10,
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb = 10,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist = 10,
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_up = 10,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/pwr_game = 10,
- /obj/item/weapon/reagent_containers/food/drinks/soda_cans/lemon_lime = 10)
+ /obj/item/weapon/reagent_containers/food/drinks/soda_cans/lemon_lime = 10,/obj/item/weapon/reagent_containers/glass/beaker/waterbottle = 10)
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/soda_cans/thirteenloko = 6,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/shamblers = 6)
premium = list(/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/filled/nuka_cola = 1,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/air = 1)
refill_canister = /obj/item/weapon/vending_refill/cola
diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm
index b065de37ca..be6e85448b 100644
--- a/code/game/mecha/mecha_construction_paths.dm
+++ b/code/game/mecha/mecha_construction_paths.dm
@@ -277,7 +277,7 @@
/datum/construction/reversible/mecha/ripley/spawn_result()
..()
- feedback_inc("mecha_ripley_created",1)
+ SSblackbox.inc("mecha_ripley_created",1)
return
@@ -564,7 +564,7 @@
var/obj/mecha/combat/gygax/M = new result(get_turf(holder))
M.CheckParts(holder.contents)
qdel(holder)
- feedback_inc("mecha_gygax_created",1)
+ SSblackbox.inc("mecha_gygax_created",1)
return
/datum/construction/mecha/firefighter_chassis
@@ -786,7 +786,7 @@
/datum/construction/reversible/mecha/firefighter/spawn_result()
..()
- feedback_inc("mecha_firefighter_created",1)
+ SSblackbox.inc("mecha_firefighter_created",1)
return
@@ -864,7 +864,7 @@
/datum/construction/mecha/honker/spawn_result()
..()
- feedback_inc("mecha_honker_created",1)
+ SSblackbox.inc("mecha_honker_created",1)
return
/datum/construction/mecha/durand_chassis
@@ -1149,7 +1149,7 @@
var/obj/mecha/combat/gygax/M = new result(get_turf(holder))
M.CheckParts(holder.contents)
qdel(holder)
- feedback_inc("mecha_durand_created",1)
+ SSblackbox.inc("mecha_durand_created",1)
return
//PHAZON
@@ -1481,7 +1481,7 @@
var/obj/mecha/combat/gygax/M = new result(get_turf(holder))
M.CheckParts(holder.contents)
qdel(holder)
- feedback_inc("mecha_phazon_created",1)
+ SSblackbox.inc("mecha_phazon_created",1)
return
//ODYSSEUS
@@ -1692,5 +1692,5 @@
/datum/construction/reversible/mecha/odysseus/spawn_result()
..()
- feedback_inc("mecha_odysseus_created",1)
+ SSblackbox.inc("mecha_odysseus_created",1)
return
diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm
index bc9251d9fc..3935b86c92 100644
--- a/code/game/objects/effects/overlays.dm
+++ b/code/game/objects/effects/overlays.dm
@@ -31,8 +31,8 @@
. = ..()
deltimer(timerid)
-/obj/effect/overlay/temp/New()
- ..()
+/obj/effect/overlay/temp/Initialize()
+ . = ..()
if(randomdir)
setDir(pick(GLOB.cardinal))
@@ -44,10 +44,10 @@
/obj/effect/overlay/temp/dir_setting
randomdir = FALSE
-/obj/effect/overlay/temp/dir_setting/New(loc, set_dir)
+/obj/effect/overlay/temp/dir_setting/Initialize(mapload, set_dir)
if(set_dir)
setDir(set_dir)
- ..()
+ . = ..()
/obj/effect/overlay/temp/dir_setting/bloodsplatter
icon = 'icons/effects/blood.dmi'
@@ -56,12 +56,12 @@
layer = BELOW_MOB_LAYER
var/splatter_type = "splatter"
-/obj/effect/overlay/temp/dir_setting/bloodsplatter/New(loc, set_dir)
+/obj/effect/overlay/temp/dir_setting/bloodsplatter/Initialize(mapload, set_dir)
if(set_dir in GLOB.diagonals)
icon_state = "[splatter_type][pick(1, 2, 6)]"
else
icon_state = "[splatter_type][pick(3, 4, 5)]"
- ..()
+ . = ..()
var/target_pixel_x = 0
var/target_pixel_y = 0
switch(set_dir)
@@ -93,6 +93,13 @@
/obj/effect/overlay/temp/dir_setting/bloodsplatter/xenosplatter
splatter_type = "xsplatter"
+/obj/effect/overlay/temp/dir_setting/speedbike_trail
+ name = "speedbike trails"
+ icon_state = "ion_fade"
+ layer = BELOW_MOB_LAYER
+ duration = 10
+ randomdir = 0
+
/obj/effect/overlay/temp/dir_setting/firing_effect
icon = 'icons/effects/effects.dmi'
icon_state = "firing_effect"
@@ -189,8 +196,8 @@
desc = "It's a decoy!"
duration = 15
-/obj/effect/overlay/temp/decoy/New(loc, atom/mimiced_atom)
- ..()
+/obj/effect/overlay/temp/decoy/Initialize(mapload, atom/mimiced_atom)
+ . = ..()
alpha = initial(alpha)
if(mimiced_atom)
name = mimiced_atom.name
@@ -198,8 +205,8 @@
setDir(mimiced_atom.dir)
mouse_opacity = 0
-/obj/effect/overlay/temp/decoy/fading/New(loc, atom/mimiced_atom)
- ..()
+/obj/effect/overlay/temp/decoy/fading/Initialize(mapload, atom/mimiced_atom)
+ . = ..()
animate(src, alpha = 0, time = duration)
/obj/effect/overlay/temp/decoy/fading/fivesecond
@@ -324,15 +331,15 @@
var/mob/user
var/damage = 20
-/obj/effect/overlay/temp/ratvar/volt_hit/New(loc, caster, multiplier)
+/obj/effect/overlay/temp/ratvar/volt_hit/Initialize(mapload, caster, multiplier)
if(multiplier)
damage *= multiplier
duration = max(round(damage * 0.2), 1)
- ..()
+ . = ..()
set_light(1.5, 2, LIGHT_COLOR_ORANGE)
-/obj/effect/overlay/temp/ratvar/volt_hit/true/New(loc, caster, multiplier)
- ..()
+/obj/effect/overlay/temp/ratvar/volt_hit/true/Initialize(mapload, caster, multiplier)
+ . = ..()
user = caster
if(user)
var/matrix/M = new
@@ -376,8 +383,8 @@
icon_state = "warden_gaze"
duration = 3
-/obj/effect/overlay/temp/ratvar/ocular_warden/New()
- ..()
+/obj/effect/overlay/temp/ratvar/ocular_warden/Initialize()
+ . = ..()
pixel_x = rand(-8, 8)
pixel_y = rand(-10, 10)
animate(src, alpha = 0, time = 3, easing = EASE_OUT)
@@ -401,8 +408,8 @@
layer = ABOVE_MOB_LAYER
duration = 10
-/obj/effect/overlay/temp/ratvar/component/New()
- ..()
+/obj/effect/overlay/temp/ratvar/component/Initialize()
+ . = ..()
transform = matrix()*0.75
pixel_x = rand(-10, 10)
pixel_y = rand(-10, -2)
@@ -432,9 +439,8 @@
light_power = 2
light_color = "#FAE48C"
-/obj/effect/overlay/temp/ratvar/sigil/transgression/New()
- ..()
- update_light()
+/obj/effect/overlay/temp/ratvar/sigil/transgression/Initialize()
+ . = ..()
var/oldtransform = transform
animate(src, transform = matrix()*2, time = 5)
animate(transform = oldtransform, alpha = 0, time = 65)
@@ -447,10 +453,6 @@
light_power = 0.5
light_color = "#1E8CE1"
-/obj/effect/overlay/temp/ratvar/sigil/vitality/New()
- ..()
- update_light()
-
/obj/effect/overlay/temp/ratvar/sigil/accession
color = "#AF0AAF"
layer = ABOVE_MOB_LAYER
@@ -493,9 +495,9 @@
icon = 'icons/mob/mob.dmi'
duration = 15
-/obj/effect/overlay/temp/gib_animation/New(loc, gib_icon)
+/obj/effect/overlay/temp/gib_animation/Initialize(mapload, gib_icon)
icon_state = gib_icon // Needs to be before ..() so icon is correct
- ..()
+ . = ..()
/obj/effect/overlay/temp/gib_animation/ex_act(severity)
return //so the overlay isn't deleted by the explosion that gibbed the mob.
@@ -507,9 +509,9 @@
icon = 'icons/mob/mob.dmi'
duration = 15
-/obj/effect/overlay/temp/dust_animation/New(loc, dust_icon)
+/obj/effect/overlay/temp/dust_animation/Initialize(mapload, dust_icon)
icon_state = dust_icon // Before ..() so the correct icon is flick()'d
- ..()
+ . = ..()
/obj/effect/overlay/temp/mummy_animation
icon = 'icons/mob/mob.dmi'
@@ -521,12 +523,12 @@
icon_state = "heal"
duration = 15
-/obj/effect/overlay/temp/heal/New(loc, colour)
- ..()
- pixel_x = rand(-12, 12)
- pixel_y = rand(-9, 0)
+/obj/effect/overlay/temp/heal/Initialize(mapload, colour)
if(colour)
color = colour
+ . = ..()
+ pixel_x = rand(-12, 12)
+ pixel_y = rand(-9, 0)
/obj/effect/overlay/temp/kinetic_blast
name = "kinetic explosion"
@@ -558,14 +560,14 @@
icon_state = "impact_bullet"
duration = 5
-/obj/effect/overlay/temp/impact_effect/New(loc, atom/target, obj/item/projectile/P)
+/obj/effect/overlay/temp/impact_effect/Initialize(mapload, atom/target, obj/item/projectile/P)
if(target == P.original) //the projectile hit the target originally clicked
pixel_x = P.p_x + target.pixel_x - 16 + rand(-4,4)
pixel_y = P.p_y + target.pixel_y - 16 + rand(-4,4)
else
pixel_x = target.pixel_x + rand(-4,4)
pixel_y = target.pixel_y + rand(-4,4)
- ..()
+ . = ..()
/obj/effect/overlay/temp/impact_effect/red_laser
icon_state = "impact_laser"
diff --git a/code/game/objects/effects/proximity.dm b/code/game/objects/effects/proximity.dm
index 8a6893c887..bfa6cd8fa9 100644
--- a/code/game/objects/effects/proximity.dm
+++ b/code/game/objects/effects/proximity.dm
@@ -9,10 +9,12 @@
host = _host
last_host_loc = _host.loc
ignore_if_not_on_turf = _ignore_if_not_on_turf
+ checkers = list()
SetRange(range)
/datum/proximity_monitor/Destroy()
host = null
+ last_host_loc = null
QDEL_LIST(checkers)
return ..()
@@ -34,46 +36,47 @@
current_range = range
- var/list/old_checkers = checkers
- var/old_checkers_len = LAZYLEN(old_checkers)
+ var/list/checkers_local = checkers
+ var/old_checkers_len = checkers_local.len
- var/atom/host_loc = host.loc
+ var/atom/_host = host
- var/atom/loc_to_use = ignore_if_not_on_turf ? host_loc : get_turf(host)
+ var/atom/loc_to_use = ignore_if_not_on_turf ? _host.loc : get_turf(_host)
if(!isturf(loc_to_use)) //only check the host's loc
if(range)
var/obj/effect/abstract/proximity_checker/pc
if(old_checkers_len)
- pc = old_checkers[old_checkers_len]
- --old_checkers.len
+ pc = checkers_local[old_checkers_len]
+ --checkers_local.len
+ QDEL_LIST(checkers_local)
else
- pc = new(host_loc, src)
+ pc = new(loc_to_use, src)
- checkers = list(pc) //only check the host's loc
+ checkers_local += pc //only check the host's loc
return
var/list/turfs = RANGE_TURFS(range, loc_to_use)
- var/old_checkers_used = min(turfs.len, old_checkers_len)
+ var/turfs_len = turfs.len
+ var/old_checkers_used = min(turfs_len, old_checkers_len)
//reuse what we can
for(var/I in 1 to old_checkers_len)
if(I <= old_checkers_used)
- var/obj/effect/abstract/proximity_checker/pc = old_checkers[I]
+ var/obj/effect/abstract/proximity_checker/pc = checkers_local[I]
pc.loc = turfs[I]
else
- qdel(old_checkers[I]) //delete the leftovers
+ qdel(checkers_local[I]) //delete the leftovers
- LAZYCLEARLIST(old_checkers)
-
- //create what we lack
- var/list/checkers_local = list()
- for(var/I in (old_checkers_used + 1) to turfs.len)
- checkers_local += new /obj/effect/abstract/proximity_checker(turfs[I], src)
-
- checkers = checkers_local
+ if(old_checkers_len < turfs_len)
+ //create what we lack
+ for(var/I in (old_checkers_used + 1) to turfs_len)
+ checkers_local += new /obj/effect/abstract/proximity_checker(turfs[I], src)
+ else
+ checkers_local.Cut(old_checkers_used + 1, old_checkers_len)
/obj/effect/abstract/proximity_checker
invisibility = INVISIBILITY_ABSTRACT
+ anchored = TRUE
var/datum/proximity_monitor/monitor
/obj/effect/abstract/proximity_checker/Initialize(mapload, datum/proximity_monitor/_monitor)
@@ -81,8 +84,8 @@
if(_monitor)
monitor = _monitor
else
- stack_trace("proximity_checker created without proximity_monitor")
- qdel(src)
+ stack_trace("proximity_checker created without host")
+ return INITIALIZE_HINT_QDEL
/obj/effect/abstract/proximity_checker/Destroy()
monitor = null
@@ -90,9 +93,6 @@
/obj/effect/abstract/proximity_checker/Crossed(atom/movable/AM)
set waitfor = FALSE
- var/datum/proximity_monitor/M = monitor
- if(!M.current_range)
- return
- var/atom/H = M.host
+ var/atom/H = monitor.host
testing("HasProx: [H] -> [AM]")
H.HasProximity(AM)
diff --git a/code/game/objects/items.dm.rej b/code/game/objects/items.dm.rej
deleted file mode 100644
index 7366e22899..0000000000
--- a/code/game/objects/items.dm.rej
+++ /dev/null
@@ -1,10 +0,0 @@
-diff a/code/game/objects/items.dm b/code/game/objects/items.dm (rejected hunks)
-@@ -102,7 +102,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
- /obj/item/Initialize()
- if (!materials)
- materials = list()
-- ..()
-+ . = ..()
- for(var/path in actions_types)
- new path(src)
- actions_types = null
diff --git a/code/game/objects/items/charter.dm b/code/game/objects/items/charter.dm
index 41a793df30..0cf73fd9ff 100644
--- a/code/game/objects/items/charter.dm
+++ b/code/game/objects/items/charter.dm
@@ -86,7 +86,7 @@
name = "station charter for [station_name()]"
desc = "An official document entrusting the governance of \
[station_name()] and surrounding space to Captain [uname]."
- feedback_set_details("station_renames","[station_name()]")
+ SSblackbox.set_details("station_renames","[station_name()]")
if(!unlimited_uses)
used = TRUE
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 496702aa4d..6955872c27 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -100,8 +100,8 @@
icon_state = "medi_holo"
duration = 30
-/obj/effect/overlay/temp/medical_holosign/New(loc, creator)
- ..()
+/obj/effect/overlay/temp/medical_holosign/Initialize(mapload, creator)
+ . = ..()
playsound(loc, 'sound/machines/ping.ogg', 50, 0) //make some noise!
if(creator)
visible_message("[creator] created a medical hologram!")
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 1028ca1429..1f923ddd5e 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -58,7 +58,7 @@
if(src.l_arm && src.r_arm)
if(src.l_leg && src.r_leg)
if(src.chest && src.head)
- feedback_inc("cyborg_frames_built",1)
+ SSblackbox.inc("cyborg_frames_built",1)
return 1
return 0
@@ -235,7 +235,7 @@
O.mmi = W //and give the real mmi to the borg.
O.updatename()
- feedback_inc("cyborg_birth",1)
+ SSblackbox.inc("cyborg_birth",1)
forceMove(O)
O.robot_suit = src
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
index 9ecd9809af..1ef83f3ac1 100644
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm
@@ -19,10 +19,10 @@
var/threatscale = 1 // Used by advanced grenades to make them slightly more worthy.
var/no_splash = FALSE //If the grenade deletes even if it has no reagents to splash with. Used for slime core reactions.
-/obj/item/weapon/grenade/chem_grenade/New()
+/obj/item/weapon/grenade/chem_grenade/Initialize()
+ . = ..()
create_reagents(1000)
stage_change() // If no argument is set, it will change the stage to the current stage, useful for stock grenades that start READY.
- ..()
/obj/item/weapon/grenade/chem_grenade/examine(mob/user)
display_timer = (stage == READY && !nadeassembly) //show/hide the timer based on assembly state
@@ -313,8 +313,8 @@
desc = "Used for emergency sealing of air breaches."
stage = READY
-/obj/item/weapon/grenade/chem_grenade/metalfoam/New()
- ..()
+/obj/item/weapon/grenade/chem_grenade/metalfoam/Initialize()
+ . = ..()
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
@@ -331,8 +331,8 @@
desc = "Used for clearing rooms of living things."
stage = READY
-/obj/item/weapon/grenade/chem_grenade/incendiary/New()
- ..()
+/obj/item/weapon/grenade/chem_grenade/incendiary/Initialize()
+ . = ..()
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
@@ -349,8 +349,8 @@
desc = "Used for purging large areas of invasive plant species. Contents under pressure. Do not directly inhale contents."
stage = READY
-/obj/item/weapon/grenade/chem_grenade/antiweed/New()
- ..()
+/obj/item/weapon/grenade/chem_grenade/antiweed/Initialize()
+ . = ..()
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
@@ -368,8 +368,8 @@
desc = "BLAM!-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas."
stage = READY
-/obj/item/weapon/grenade/chem_grenade/cleaner/New()
- ..()
+/obj/item/weapon/grenade/chem_grenade/cleaner/Initialize()
+ . = ..()
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
@@ -386,8 +386,8 @@
desc = "Waffle Co.-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas."
stage = READY
-/obj/item/weapon/grenade/chem_grenade/ez_clean/New()
- ..()
+/obj/item/weapon/grenade/chem_grenade/ez_clean/Initialize()
+ . = ..()
var/obj/item/weapon/reagent_containers/glass/beaker/large/B1 = new(src)
var/obj/item/weapon/reagent_containers/glass/beaker/large/B2 = new(src)
@@ -405,8 +405,8 @@
desc = "Used for nonlethal riot control. Contents under pressure. Do not directly inhale contents."
stage = READY
-/obj/item/weapon/grenade/chem_grenade/teargas/New()
- ..()
+/obj/item/weapon/grenade/chem_grenade/teargas/Initialize()
+ . = ..()
var/obj/item/weapon/reagent_containers/glass/beaker/large/B1 = new(src)
var/obj/item/weapon/reagent_containers/glass/beaker/large/B2 = new(src)
@@ -424,8 +424,8 @@
desc = "Used for melting armoured opponents."
stage = READY
-/obj/item/weapon/grenade/chem_grenade/facid/New()
- ..()
+/obj/item/weapon/grenade/chem_grenade/facid/Initialize()
+ . = ..()
var/obj/item/weapon/reagent_containers/glass/beaker/bluespace/B1 = new(src)
var/obj/item/weapon/reagent_containers/glass/beaker/bluespace/B2 = new(src)
@@ -444,8 +444,8 @@
desc = "Used for wide scale painting projects."
stage = READY
-/obj/item/weapon/grenade/chem_grenade/colorful/New()
- ..()
+/obj/item/weapon/grenade/chem_grenade/colorful/Initialize()
+ . = ..()
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
@@ -463,8 +463,8 @@
stage = READY
var/glitter_type = "glitter"
-/obj/item/weapon/grenade/chem_grenade/glitter/New()
- ..()
+/obj/item/weapon/grenade/chem_grenade/glitter/Initialize()
+ . = ..()
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
@@ -496,8 +496,8 @@
desc = "BURN!-brand foaming clf3. In a special applicator for rapid purging of wide areas."
stage = READY
-/obj/item/weapon/grenade/chem_grenade/clf3/New()
- ..()
+/obj/item/weapon/grenade/chem_grenade/clf3/Initialize()
+ . = ..()
var/obj/item/weapon/reagent_containers/glass/beaker/bluespace/B1 = new(src)
var/obj/item/weapon/reagent_containers/glass/beaker/bluespace/B2 = new(src)
@@ -514,8 +514,8 @@
desc = "Tiger Cooperative chemical foam grenade. Causes temporary irration, blindness, confusion, mutism, and mutations to carbon based life forms. Contains additional spore toxin"
stage = READY
-/obj/item/weapon/grenade/chem_grenade/bioterrorfoam/New()
- ..()
+/obj/item/weapon/grenade/chem_grenade/bioterrorfoam/Initialize()
+ . = ..()
var/obj/item/weapon/reagent_containers/glass/beaker/bluespace/B1 = new(src)
var/obj/item/weapon/reagent_containers/glass/beaker/bluespace/B2 = new(src)
@@ -534,8 +534,8 @@
desc = "WARNING: GRENADE WILL RELEASE DEADLY SPORES CONTAINING ACTIVE AGENTS. SEAL SUIT AND AIRFLOW BEFORE USE."
stage = READY
-/obj/item/weapon/grenade/chem_grenade/tuberculosis/New()
- ..()
+/obj/item/weapon/grenade/chem_grenade/tuberculosis/Initialize()
+ . = ..()
var/obj/item/weapon/reagent_containers/glass/beaker/bluespace/B1 = new(src)
var/obj/item/weapon/reagent_containers/glass/beaker/bluespace/B2 = new(src)
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index 49cc975546..0ab74a019d 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -45,7 +45,7 @@
if(do_mob(user, C, 30) && (C.get_num_arms() >= 2 || C.get_arm_ignore()))
apply_cuffs(C,user)
to_chat(user, "You handcuff [C].")
- feedback_add_details("handcuffs","[type]")
+ SSblackbox.add_details("handcuffs","[type]")
add_logs(user, C, "handcuffed")
else
@@ -275,7 +275,7 @@
C.legcuffed = src
src.loc = C
C.update_inv_legcuffed()
- feedback_add_details("handcuffs","[type]")
+ SSblackbox.add_details("handcuffs","[type]")
else if(isanimal(L))
var/mob/living/simple_animal/SA = L
if(SA.mob_size > MOB_SIZE_TINY)
@@ -336,7 +336,7 @@
C.legcuffed = src
src.loc = C
C.update_inv_legcuffed()
- feedback_add_details("handcuffs","[type]")
+ SSblackbox.add_details("handcuffs","[type]")
to_chat(C, "\The [src] ensnares you!")
C.Weaken(weaken)
diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm
index 571aece4c3..aa720f1979 100644
--- a/code/game/objects/items/weapons/holy_weapons.dm
+++ b/code/game/objects/items/weapons/holy_weapons.dm
@@ -39,7 +39,7 @@
SSreligion.holy_weapon_type = holy_weapon.type
- feedback_set_details("chaplain_weapon","[choice]")
+ SSblackbox.set_details("chaplain_weapon","[choice]")
if(holy_weapon)
holy_weapon.reskinned = TRUE
diff --git a/code/game/objects/items/weapons/storage/book.dm b/code/game/objects/items/weapons/storage/book.dm
index 83805d969a..7775b3692a 100644
--- a/code/game/objects/items/weapons/storage/book.dm
+++ b/code/game/objects/items/weapons/storage/book.dm
@@ -62,7 +62,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
SSreligion.bible_icon_state = B.icon_state
SSreligion.bible_item_state = B.item_state
- feedback_set_details("religion_book","[biblename]")
+ SSblackbox.set_details("religion_book","[biblename]")
usr << browse(null, "window=editicon")
/obj/item/weapon/storage/book/bible/proc/bless(mob/living/carbon/human/H, mob/living/user)
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index 0595076901..e5ffbade4c 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -116,7 +116,7 @@
var/mob/living/carbon/human/H = user
user.visible_message("[user] is putting [src]'s valve to [user.p_their()] lips! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/effects/spray.ogg', 10, 1, -3)
- if (H && !QDELETED(H))
+ if (!QDELETED(H) && air_contents && air_contents.return_pressure() >= 1000)
for(var/obj/item/W in H)
H.dropItemToGround(W)
if(prob(50))
diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm
index 3cf35daa03..7820031700 100644
--- a/code/game/objects/structures/ai_core.dm
+++ b/code/game/objects/structures/ai_core.dm
@@ -180,7 +180,7 @@
var/mob/living/silicon/ai/A = new /mob/living/silicon/ai(loc, laws, brain.brainmob)
if(brain.force_replace_ai_name)
A.fully_replace_character_name(A.name, brain.replacement_ai_name())
- feedback_inc("cyborg_ais_created",1)
+ SSblackbox.inc("cyborg_ais_created",1)
qdel(src)
else
state = AI_READY_CORE
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index be1b49074d..3817a16685 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -16,27 +16,25 @@
var/obj/item/weapon/electronics/airlock/electronics
var/start_showpiece_type = null //add type for items on display
-/obj/structure/displaycase/New()
- ..()
+/obj/structure/displaycase/Initialize()
+ . = ..()
if(start_showpiece_type)
showpiece = new start_showpiece_type (src)
update_icon()
/obj/structure/displaycase/Destroy()
if(electronics)
- qdel(electronics)
- electronics = null
+ QDEL_NULL(electronics)
if(showpiece)
- qdel(showpiece)
- showpiece = null
+ QDEL_NULL(showpiece)
return ..()
/obj/structure/displaycase/examine(mob/user)
..()
- if(showpiece)
- to_chat(user, "There's [showpiece] inside.")
if(alert)
to_chat(user, "Hooked up with an anti-theft system.")
+ if(showpiece)
+ to_chat(user, "There's [showpiece] inside.")
/obj/structure/displaycase/proc/dump()
@@ -176,8 +174,8 @@
/obj/structure/displaycase/attack_hand(mob/user)
user.changeNext_move(CLICK_CD_MELEE)
if (showpiece && (broken || open))
- dump()
to_chat(user, "You deactivate the hover field built into the case.")
+ dump()
src.add_fingerprint(user)
update_icon()
return
@@ -249,3 +247,96 @@
desc = "A glass lab container for storing interesting creatures."
start_showpiece_type = /obj/item/clothing/mask/facehugger/lamarr
req_access = list(GLOB.access_rd)
+
+
+
+/obj/structure/displaycase/trophy
+ name = "trophy display case"
+ desc = "Store your trophies of accomplishment in here, and they will stay forever."
+ var/trophy_message = ""
+ var/placer_key = ""
+ var/added_roundstart = TRUE
+ alert = TRUE
+ integrity_failure = 0
+
+/obj/structure/displaycase/trophy/Initialize()
+ . = ..()
+ GLOB.trophy_cases += src
+
+/obj/structure/displaycase/trophy/Destroy()
+ GLOB.trophy_cases -= src
+ return ..()
+
+/obj/structure/displaycase/trophy/examine(mob/user)
+ ..()
+ if(trophy_message)
+ to_chat(user, "The plaque reads:")
+ to_chat(user, trophy_message)
+
+/obj/structure/displaycase/trophy/attackby(obj/item/weapon/W, mob/user, params)
+
+ if(!user.Adjacent(src)) //no TK museology
+ return
+
+ if(!added_roundstart)
+ to_chat(user, "You've already put something new in this case.")
+ return
+
+ if(is_type_in_typecache(W, GLOB.blacklisted_cargo_types))
+ to_chat(user, "The case rejects the [W].")
+ return
+
+ for(var/a in W.GetAllContents())
+ if(is_type_in_typecache(a, GLOB.blacklisted_cargo_types))
+ to_chat(user, "The case rejects the [W].")
+ return
+
+ if(user.drop_item())
+
+ if(showpiece)
+ to_chat(user, "You press a button, and [showpiece] descends into the floor of the case.")
+ QDEL_NULL(showpiece)
+
+ to_chat(user, "You insert [W] into the case.")
+ W.forceMove(src)
+ showpiece = W
+ added_roundstart = FALSE
+ update_icon()
+
+ placer_key = user.ckey
+
+ trophy_message = W.desc //default value
+
+ var/chosen_plaque = stripped_input(user, "What would you like the plaque to say? Default value is item's description.", "Trophy Plaque")
+ if(chosen_plaque)
+ if(user.Adjacent(src))
+ trophy_message = chosen_plaque
+ to_chat(user, "You set the plaque's text.")
+ else
+ to_chat(user, "You are too far to set the plaque's text.")
+
+ SSpersistence.SaveTrophy(src)
+
+ else
+ to_chat(user, "\The [W] is stuck to your hand, you can't put it in the [src.name]!")
+
+ return
+
+/obj/structure/displaycase/trophy/dump()
+ if (showpiece)
+ if(added_roundstart)
+ visible_message("The [showpiece] crumbles to dust!")
+ new /obj/effect/decal/cleanable/ash(loc)
+ QDEL_NULL(showpiece)
+ else
+ ..()
+
+/obj/item/showpiece_dummy
+ name = "Cheap replica"
+
+/obj/item/showpiece_dummy/Initialize(mapload, path)
+ . = ..()
+ var/obj/item/I = path
+ name = initial(I.name)
+ icon = initial(I.icon)
+ icon_state = initial(I.icon_state)
diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm
index f1a808938e..d087b14390 100644
--- a/code/game/objects/structures/ghost_role_spawners.dm
+++ b/code/game/objects/structures/ghost_role_spawners.dm
@@ -101,6 +101,7 @@
death = FALSE
anchored = 0
density = 0
+ var/can_transfer = TRUE //if golems can switch bodies to this new shell
var/mob/living/owner = null //golem's owner if it has one
flavour_text = "You are a Free Golem. Your family worships The Liberator. In his infinite and divine wisdom, he set your clan free to \
travel the stars with a single declaration: \"Yeah go do whatever.\" Though you are bound to the one who created you, it is customary in your society to repeat those same words to newborn \
@@ -119,7 +120,7 @@
Serve [creator], and assist [creator.p_them()] in completing [creator.p_their()] goals at any cost."
owner = creator
-/obj/effect/mob_spawn/human/golem/special(mob/living/new_spawn)
+/obj/effect/mob_spawn/human/golem/special(mob/living/new_spawn, name)
var/datum/species/golem/X = mob_species
to_chat(new_spawn, "[initial(X.info_text)]")
if(!owner)
@@ -132,7 +133,23 @@
if(ishuman(new_spawn))
var/mob/living/carbon/human/H = new_spawn
H.set_cloned_appearance()
- H.real_name = H.dna.species.random_name()
+ if(!name)
+ H.real_name = H.dna.species.random_name()
+ else
+ H.real_name = name
+
+/obj/effect/mob_spawn/human/golem/attack_hand(mob/user)
+ if(isgolem(user) && can_transfer)
+ var/transfer = alert("Transfer your soul to [src]? (Warning, your old body will die!)",,"Yes","No")
+ if(!transfer)
+ return
+ log_game("[user.ckey] golem-swapped into [src]")
+ user.visible_message("A faint light leaves [user], moving to [src] and animating it!","You leave your old body behind, and transfer into [src]!")
+ create(ckey = user.ckey, flavour = FALSE, name = user.real_name)
+ user.death()
+ return
+ ..()
+
/obj/effect/mob_spawn/human/golem/adamantine
name = "dust-caked golem shell"
@@ -140,6 +157,7 @@
mob_name = "a free golem"
anchored = 1
density = 1
+ can_transfer = FALSE
mob_species = /datum/species/golem/adamantine
//Malfunctioning cryostasis sleepers: Spawns in makeshift shelters in lavaland. Ghosts become hermits with knowledge of how they got to where they are now.
diff --git a/code/game/objects/structures/traps.dm b/code/game/objects/structures/traps.dm
index 90500f14db..dad4e9b53e 100644
--- a/code/game/objects/structures/traps.dm
+++ b/code/game/objects/structures/traps.dm
@@ -8,8 +8,10 @@
alpha = 30 //initially quite hidden when not "recharging"
var/last_trigger = 0
var/time_between_triggers = 600 //takes a minute to recharge
+ var/charges = INFINITY
var/list/static/ignore_typecache
+ var/list/mob/immune_minds = list()
var/datum/effect_system/spark_spread/spark_system
@@ -30,9 +32,11 @@
. = ..()
/obj/structure/trap/examine(mob/user)
- ..()
+ . = ..()
if(!isliving(user))
return
+ if(user.mind && user.mind in immune_minds)
+ return
if(get_dist(user, src) <= 1)
to_chat(user, "You reveal [src]!")
flare()
@@ -41,10 +45,15 @@
// Makes the trap visible, and starts the cooldown until it's
// able to be triggered again.
visible_message("[src] flares brightly!")
- alpha = 200
- animate(src, alpha = initial(alpha), time = time_between_triggers)
- last_trigger = world.time
spark_system.start()
+ alpha = 200
+ last_trigger = world.time
+ charges--
+ if(charges <= 0)
+ animate(src, alpha = 0, time = 10)
+ QDEL_IN(src, 10)
+ else
+ animate(src, alpha = initial(alpha), time = time_between_triggers)
/obj/structure/trap/Crossed(atom/movable/AM)
if(last_trigger + time_between_triggers > world.time)
@@ -52,6 +61,12 @@
// Don't want the traps triggered by sparks, ghosts or projectiles.
if(is_type_in_typecache(AM, ignore_typecache))
return
+ if(ismob(AM))
+ var/mob/M = AM
+ if(M.mind in immune_minds)
+ return
+ if(charges <= 0)
+ return
flare()
if(isliving(AM))
trap_effect(AM)
diff --git a/code/game/say.dm b/code/game/say.dm
index efad2f105f..deab83ad10 100644
--- a/code/game/say.dm
+++ b/code/game/say.dm
@@ -56,10 +56,16 @@ GLOBAL_LIST_INIT(freqtospan, list(
var/namepart = "[speaker.GetVoice()][speaker.get_alt_name()]"
//End name span.
var/endspanpart = ""
- //Message
- var/messagepart = " [lang_treat(speaker, message_language, raw_message, spans, message_mode)]"
- return "[spanpart1][spanpart2][freqpart][compose_track_href(speaker, namepart)][namepart][compose_job(speaker, message_language, raw_message, radio_freq)][endspanpart][messagepart]"
+ //Message
+ var/messagepart = " [lang_treat(speaker, message_language, raw_message, spans)]"
+
+ var/languageicon = ""
+ var/datum/language/D = get_language_instance(message_language)
+ if(D.display_icon(src))
+ languageicon = "[D.get_icon()] "
+
+ return "[spanpart1][spanpart2][freqpart][languageicon][compose_track_href(speaker, namepart)][namepart][compose_job(speaker, message_language, raw_message, radio_freq)][endspanpart][messagepart]"
/atom/movable/proc/compose_track_href(atom/movable/speaker, message_langs, raw_message, radio_freq)
return ""
@@ -67,33 +73,37 @@ GLOBAL_LIST_INIT(freqtospan, list(
/atom/movable/proc/compose_job(atom/movable/speaker, message_langs, raw_message, radio_freq)
return ""
-/atom/movable/proc/say_quote(input, list/spans=list(), message_mode)
- if(!input)
- return "says, \"...\"" //not the best solution, but it will stop a large number of runtimes. The cause is somewhere in the Tcomms code
+/atom/movable/proc/say_mod(input, message_mode)
var/ending = copytext(input, length(input))
if(copytext(input, length(input) - 1) == "!!")
- spans |= SPAN_YELL
- return "[verb_yell], \"[attach_spans(input, spans)]\""
- input = attach_spans(input, spans)
- if(ending == "?")
- return "[verb_ask], \"[input]\""
- if(ending == "!")
- return "[verb_exclaim], \"[input]\""
+ return verb_yell
+ else if(ending == "?")
+ return verb_ask
+ else if(ending == "!")
+ return verb_exclaim
+ else
+ return verb_say
- return "[verb_say], \"[input]\""
+/atom/movable/proc/say_quote(input, list/spans=list(), message_mode)
+ if(!input)
+ input = "..."
+
+ if(copytext(input, length(input) - 1) == "!!")
+ spans |= SPAN_YELL
+
+ var/spanned = attach_spans(input, spans)
+ return "[say_mod(input, message_mode)], \"[spanned]\""
/atom/movable/proc/lang_treat(atom/movable/speaker, datum/language/language, raw_message, list/spans, message_mode)
if(has_language(language))
var/atom/movable/AM = speaker.GetSource()
if(AM) //Basically means "if the speaker is virtual"
- if(AM.verb_say != speaker.verb_say || AM.verb_ask != speaker.verb_ask || AM.verb_exclaim != speaker.verb_exclaim || AM.verb_yell != speaker.verb_yell) //If the saymod was changed
- return speaker.say_quote(raw_message, spans, message_mode)
return AM.say_quote(raw_message, spans, message_mode)
else
return speaker.say_quote(raw_message, spans, message_mode)
else if(language)
var/atom/movable/AM = speaker.GetSource()
- var/datum/language/D = new language
+ var/datum/language/D = get_language_instance(language)
raw_message = D.scramble(raw_message)
if(AM)
return AM.say_quote(raw_message, spans, message_mode)
diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm
index a17fcf2ca8..f4a3403ee5 100644
--- a/code/game/turfs/simulated/floor/plating/asteroid.dm
+++ b/code/game/turfs/simulated/floor/plating/asteroid.dm
@@ -63,7 +63,7 @@
if(istype(src, /turf/open/floor/plating/asteroid))
to_chat(user, "You dig a hole.")
gets_dug()
- feedback_add_details("pick_used_mining","[W.type]")
+ SSblackbox.add_details("pick_used_mining","[W.type]")
if(istype(W,/obj/item/weapon/storage/bag/ore))
var/obj/item/weapon/storage/bag/ore/S = W
diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm
index 5805d75e56..398ff190f2 100644
--- a/code/game/turfs/simulated/minerals.dm
+++ b/code/game/turfs/simulated/minerals.dm
@@ -63,7 +63,7 @@
if(ismineralturf(src))
to_chat(user, "You finish cutting into the rock.")
gets_drilled(user)
- feedback_add_details("pick_used_mining","[P.type]")
+ SSblackbox.add_details("pick_used_mining","[P.type]")
else
return attack_hand(user)
@@ -72,7 +72,7 @@
var/i
for(i in 1 to mineralAmt)
new mineralType(src)
- feedback_add_details("ore_mined",mineralType)
+ SSblackbox.add_details("ore_mined",mineralType)
ChangeTurf(turf_type, defer_change)
addtimer(CALLBACK(src, .proc/AfterChange), 1, TIMER_UNIQUE)
playsound(src, 'sound/effects/break_stone.ogg', 50, 1) //beautiful destruction
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 1c2d65355e..4c29d87dfa 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -398,7 +398,7 @@
/turf/proc/add_blueprints_preround(atom/movable/AM)
- if(!SSticker || SSticker.current_state != GAME_STATE_PLAYING)
+ if(!SSticker.HasRoundStarted())
add_blueprints(AM)
/turf/proc/empty(turf_type=/turf/open/space)
diff --git a/code/modules/VR/vr_sleeper.dm b/code/modules/VR/vr_sleeper.dm
index 41f3bbc001..9411917c39 100644
--- a/code/modules/VR/vr_sleeper.dm
+++ b/code/modules/VR/vr_sleeper.dm
@@ -17,8 +17,8 @@
var/allow_creating_vr_humans = TRUE //So you can have vr_sleepers that always spawn you as a specific person or 1 life/chance vr games
var/outfit = /datum/outfit/vr_basic
-/obj/machinery/vr_sleeper/New()
- ..()
+/obj/machinery/vr_sleeper/Initialize()
+ . = ..()
sparks = new /datum/effect_system/spark_spread()
sparks.set_up(2,0)
sparks.attach(src)
diff --git a/code/modules/admin/NewBan.dm b/code/modules/admin/NewBan.dm
index aa8c8db2db..fabda7fc4d 100644
--- a/code/modules/admin/NewBan.dm
+++ b/code/modules/admin/NewBan.dm
@@ -141,7 +141,7 @@ GLOBAL_PROTECT(Banlist)
ban_unban_log_save("[key_name(usr)] unbanned [key]")
log_admin_private("[key_name(usr)] unbanned [key]")
message_admins("[key_name_admin(usr)] unbanned: [key]")
- feedback_inc("ban_unban",1)
+ SSblackbox.inc("ban_unban",1)
usr.client.holder.DB_ban_unban( ckey(key), BANTYPE_ANY_FULLBAN)
for (var/A in GLOB.Banlist.dir)
GLOB.Banlist.cd = "/base/[A]"
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 25b7deba9b..0e7986ec18 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -42,8 +42,8 @@
body += "TP - "
body += "PM - "
body += "SM - "
- body += "FLW - "
- body += "LOGS\]
"
+ body += "FLW - "
+ body += "LOGS\]
"
body += "Mob type = [M.type]
"
@@ -166,7 +166,7 @@
body += "