diff --git a/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm b/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm index 051aaad259a16..61311b3f036c8 100644 --- a/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm +++ b/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm @@ -197,9 +197,6 @@ }, /turf/open/floor/wood, /area/ruin/powered/golem_ship) -"mE" = ( -/turf/open/water/jungle, -/area/ruin/powered/golem_ship) "mU" = ( /obj/machinery/power/shuttle_engine/propulsion{ dir = 4 @@ -503,6 +500,10 @@ }, /turf/open/floor/mineral/titanium, /area/ruin/powered/golem_ship) +"Cx" = ( +/obj/machinery/fishing_portal_generator, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) "CI" = ( /obj/effect/mob_spawn/ghost_role/human/golem/adamantine, /obj/structure/sink/directional/west, @@ -980,8 +981,8 @@ wN (10,1,1) = {" wN wN -mE -mE +wN +wN Df Df Df @@ -997,13 +998,13 @@ wN "} (11,1,1) = {" wN -mE -mE +wN +wN Df Df vr QX -sS +Cx sS sS At @@ -1015,8 +1016,8 @@ Df "} (12,1,1) = {" wN -mE -mE +wN +wN Df bO XR @@ -1034,7 +1035,7 @@ Df (13,1,1) = {" wN wN -mE +wN lF bO ir diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm index 218900ffdee58..79126e4fdd2e3 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm @@ -180,9 +180,6 @@ }, /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/surface/outdoors/nospawn) -"Bv" = ( -/turf/open/misc/snow, -/area/icemoon/surface/outdoors/nospawn) "Dd" = ( /turf/closed/mineral/random/snow, /area/icemoon/surface/outdoors/nospawn) @@ -265,9 +262,6 @@ /obj/structure/railing/corner, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors/nospawn) -"PT" = ( -/turf/template_noop, -/area/icemoon/surface/outdoors/nospawn) "Qi" = ( /obj/effect/turf_decal/stripes/corner, /obj/item/flashlight/glowstick/red{ @@ -414,7 +408,7 @@ fl fl "} (4,1,1) = {" -Bv +lH eu jQ vJ @@ -532,7 +526,7 @@ fl (8,1,1) = {" Dd Dd -PT +Dd nT kd yA diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm index d63d261b813c5..ebb62bff3750a 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm @@ -61,10 +61,11 @@ /turf/closed/indestructible/riveted/boss, /area/ruin/unpowered/ash_walkers) "al" = ( -/obj/structure/stone_tile/surrounding_tile{ +/obj/effect/mapping_helpers/no_lava, +/obj/structure/railing/wooden_fence{ dir = 1 }, -/turf/closed/mineral/volcanic/lava_land_surface, +/turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "aq" = ( /obj/structure/stone_tile/block/cracked{ @@ -76,13 +77,11 @@ /turf/closed/mineral/volcanic/lava_land_surface, /area/lavaland/surface/outdoors) "ar" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 4 +/obj/effect/mapping_helpers/no_lava, +/obj/structure/railing/wooden_fence{ + dir = 9 }, -/turf/closed/mineral/volcanic/lava_land_surface, +/turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "as" = ( /turf/closed/wall/mineral/wood, @@ -155,12 +154,6 @@ /obj/item/flashlight/flare/torch, /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) -"az" = ( -/obj/structure/stone_tile/block{ - dir = 4 - }, -/turf/closed/mineral/volcanic/lava_land_surface, -/area/lavaland/surface/outdoors) "aF" = ( /obj/structure/stone_tile/block{ dir = 8 @@ -213,7 +206,7 @@ dir = 1 }, /obj/structure/stone_tile, -/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck, +/mob/living/basic/mining/gutlunch/milk, /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) "aR" = ( @@ -287,7 +280,7 @@ /obj/structure/stone_tile{ dir = 4 }, -/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen, +/mob/living/basic/mining/gutlunch/warrior, /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) "bd" = ( @@ -331,13 +324,11 @@ /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) "bh" = ( -/obj/structure/stone_tile/block{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 8 +/obj/effect/mapping_helpers/no_lava, +/obj/structure/railing/wooden_fence{ + dir = 5 }, -/turf/closed/mineral/volcanic/lava_land_surface, +/turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "bi" = ( /obj/structure/stone_tile/block/cracked{ @@ -520,15 +511,16 @@ /turf/closed/mineral/volcanic/lava_land_surface, /area/lavaland/surface/outdoors) "bJ" = ( -/obj/structure/stone_tile/surrounding_tile, -/turf/closed/mineral/volcanic/lava_land_surface, +/obj/effect/mapping_helpers/no_lava, +/mob/living/basic/mining/gutlunch/milk, +/turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "cp" = ( -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile/block{ - dir = 1 +/obj/effect/mapping_helpers/no_lava, +/obj/structure/railing/wooden_fence{ + dir = 8 }, -/turf/closed/mineral/volcanic/lava_land_surface, +/turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "cF" = ( /obj/structure/stone_tile/block{ @@ -687,6 +679,12 @@ /obj/item/flashlight/flare/torch, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/ash_walkers) +"fM" = ( +/obj/effect/mapping_helpers/no_lava, +/mob/living/basic/mining/gutlunch/warrior, +/obj/item/flashlight/lantern, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "gi" = ( /obj/structure/table/optable, /obj/structure/stone_tile{ @@ -758,6 +756,10 @@ /obj/effect/decal/cleanable/blood, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/ash_walkers) +"mo" = ( +/obj/structure/stone_tile/block, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "mp" = ( /obj/structure/stone_tile/surrounding/cracked, /turf/open/misc/asteroid/basalt/lava_land_surface, @@ -808,6 +810,16 @@ /obj/effect/mapping_helpers/no_lava, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"qm" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "qn" = ( /obj/item/storage/box/rxglasses, /obj/structure/stone_tile{ @@ -821,6 +833,11 @@ /obj/effect/mapping_helpers/no_lava, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"qH" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/structure/railing/wooden_fence, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "qV" = ( /obj/structure/stone_tile/surrounding_tile{ dir = 8 @@ -882,6 +899,16 @@ /obj/effect/mapping_helpers/no_lava, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"sz" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"ty" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "tY" = ( /obj/structure/stone_tile/block/cracked{ dir = 1 @@ -924,6 +951,13 @@ /obj/item/flashlight/flare/torch, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/ash_walkers) +"vV" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/structure/railing/wooden_fence{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "wB" = ( /obj/structure/stone_tile/block, /obj/structure/stone_tile{ @@ -1047,6 +1081,14 @@ /obj/effect/mapping_helpers/no_lava, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"Dz" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "Ee" = ( /obj/structure/stone_tile/block/cracked, /obj/structure/stone_tile{ @@ -1114,12 +1156,21 @@ /obj/item/seeds/lavaland/porcini, /obj/item/seeds/tower, /obj/item/seeds/tower, +/obj/item/seeds/bamboo, +/obj/item/seeds/bamboo, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/ash_walkers) "GW" = ( -/obj/structure/stone_tile/surrounding_tile{ - dir = 8 +/obj/structure/stone_tile/cracked{ + dir = 4 }, +/obj/structure/closet/crate/internals, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/pickaxe, /obj/effect/mapping_helpers/no_lava, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) @@ -1175,6 +1226,18 @@ /obj/effect/mapping_helpers/no_lava, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"JD" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/structure/ore_container/gutlunch_trough, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"Kg" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/structure/railing/wooden_fence{ + dir = 10 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "Kt" = ( /obj/structure/water_source/puddle{ pixel_x = -3; @@ -1183,6 +1246,12 @@ /obj/effect/mapping_helpers/no_lava, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"KQ" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/structure/table/wood, +/obj/item/reagent_containers/cup/bucket/wooden, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "KR" = ( /obj/structure/stone_tile/block/cracked, /obj/effect/mapping_helpers/no_lava, @@ -1246,9 +1315,10 @@ /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "Oe" = ( -/obj/structure/stone_tile/surrounding_tile/cracked, -/obj/structure/ore_box, /obj/effect/mapping_helpers/no_lava, +/obj/structure/stone_tile{ + dir = 8 + }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "OY" = ( @@ -1256,6 +1326,29 @@ /obj/effect/mapping_helpers/no_lava, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"Pk" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/structure/railing/corner/end/wooden_fence, +/obj/structure/railing/corner/end/flip/wooden_fence, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"PA" = ( +/obj/effect/mapping_helpers/no_lava, +/mob/living/basic/mining/gutlunch/warrior, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"PK" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/structure/stone_tile, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"Rq" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/structure/railing/wooden_fence{ + dir = 6 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "RE" = ( /obj/structure/stone_tile/block/cracked{ dir = 1 @@ -1300,6 +1393,12 @@ /obj/effect/mapping_helpers/no_lava, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"Tl" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/structure/table/wood, +/obj/item/flashlight/lantern, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "Tr" = ( /obj/machinery/hydroponics/soil, /obj/structure/stone_tile/block{ @@ -1308,6 +1407,11 @@ /obj/effect/mapping_helpers/no_lava, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"TC" = ( +/obj/effect/mapping_helpers/no_lava, +/obj/item/flashlight/lantern, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "TO" = ( /obj/structure/stone_tile{ dir = 4 @@ -1335,17 +1439,8 @@ /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "Uh" = ( -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/structure/closet/crate/internals, -/obj/item/pickaxe, -/obj/item/pickaxe, -/obj/item/pickaxe, -/obj/item/pickaxe, -/obj/item/pickaxe, -/obj/item/pickaxe, /obj/effect/mapping_helpers/no_lava, +/obj/structure/stone_tile/block, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "UI" = ( @@ -1382,6 +1477,12 @@ /obj/effect/mapping_helpers/no_lava, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"Zr" = ( +/obj/structure/stone_tile/surrounding_tile/cracked, +/obj/structure/ore_box, +/obj/effect/mapping_helpers/no_lava, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) (1,1,1) = {" aa @@ -1637,8 +1738,8 @@ ak ak ak IS -RH -Aj +Gv +ty Nv Kt du @@ -1768,10 +1869,10 @@ ak ak ak ak -KR -Aj -eu -ah +Zr +Gv +qm +Gv as mm cF @@ -1791,9 +1892,9 @@ ak ak bI Oe -Uh -ah -cp +Gv +qm +Gv as as as @@ -1802,24 +1903,310 @@ ak cQ "} (20,1,1) = {" -aa -al -ar -az -az -az -bh -az +ah +Gv +Gv +Gv +Gv +Gv +Gv +Gv +Gv +Gv +Gv +Dz +qm +Gv +ah +ah bC +ah +ah +cR +"} +(21,1,1) = {" +ah +Gv +ar +cp +cp +cp +cp +cp +Kg +Gv +Gv +Gv +qm +Gv +ah +ah +ah +ah +ah +ah +"} +(22,1,1) = {" +ah +Gv +al +fM +Gv +Gv +TC +Gv +qH +KQ +Gv +Gv +qm +Gv +Gv +ah +ah +ah +ah +ah +"} +(23,1,1) = {" +ah +Gv +al +Gv +Gv +Gv +Gv +PA +qH +KQ +Gv +Gv +qm +Gv +PK +ah +ah +ah +ah +ah +"} +(24,1,1) = {" +ah +Gv +al +Gv +bJ +bJ +Gv +Gv +qH +Tl +Gv +Gv +qm +sz +Gv +ah +ah +ah +ah +ah +"} +(25,1,1) = {" +ah +Gv +al +bJ +Gv +Gv +Gv +Gv +qH +Gv +sz +sz +qm +Gv +Gv +ah +ah +ah +ah +ah +"} +(26,1,1) = {" +ah +Gv +al +Gv +bJ bJ +Gv +Gv +Pk +sz +Gv +Oe +Gv +Gv +Gv ah ah ah +aa +aa +"} +(27,1,1) = {" +ah +Gv al +Gv +Gv +TC +Gv +Gv +qH +Gv +Dz +Oe +Gv +Gv +Gv ah ah -bC ah +aa +aa +"} +(28,1,1) = {" ah -cR +Gv +al +Gv +JD +Gv +Gv +Gv +qH +Gv +Gv +Gv +Gv +Dz +Gv +ah +ah +ah +aa +aa +"} +(29,1,1) = {" +ah +Gv +al +Gv +Gv +Gv +Gv +PA +qH +Gv +Gv +Gv +Gv +Gv +Gv +ah +ah +ah +aa +aa +"} +(30,1,1) = {" +ah +Gv +al +TC +Gv +PA +Gv +TC +qH +Gv +mo +ah +ah +ah +ah +ah +ah +aa +aa +aa +"} +(31,1,1) = {" +ah +Gv +bh +vV +vV +vV +vV +vV +Rq +Uh +ty +ah +ah +ah +ah +ah +ah +aa +aa +aa +"} +(32,1,1) = {" +ah +Gv +Gv +Gv +Gv +Gv +Gv +Gv +Gv +Gv +ty +ah +ah +aa +aa +aa +aa +aa +aa +aa +"} +(33,1,1) = {" +ah +ah +ah +ah +ah +ah +ah +ah +ah +ah +ah +ah +ah +aa +aa +aa +aa +aa +aa +aa "} diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_mookvillage.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_mookvillage.dmm index 9b9157f92faa1..70ebd3ce42860 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_mookvillage.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_mookvillage.dmm @@ -68,7 +68,7 @@ /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "p" = ( -/obj/structure/material_stand, +/obj/structure/ore_container/material_stand, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "q" = ( diff --git a/_maps/RandomRuins/SpaceRuins/allamericandiner.dmm b/_maps/RandomRuins/SpaceRuins/allamericandiner.dmm index 4cdeea3c327b3..3f45ad37837fe 100644 --- a/_maps/RandomRuins/SpaceRuins/allamericandiner.dmm +++ b/_maps/RandomRuins/SpaceRuins/allamericandiner.dmm @@ -331,14 +331,6 @@ /obj/structure/urinal/directional/north, /turf/open/floor/iron/freezer, /area/ruin/space/has_grav/allamericandiner) -"qp" = ( -/obj/machinery/chem_dispenser/drinks{ - dir = 8; - pixel_x = 17; - pixel_y = 0 - }, -/turf/open/floor/iron/kitchen/small, -/area/ruin/space/has_grav/allamericandiner) "qB" = ( /obj/structure/closet/crate/trashcart/filled, /turf/open/misc/asteroid/airless, @@ -471,6 +463,7 @@ /obj/structure/table/reinforced, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, +/obj/item/storage/box/cups, /turf/open/floor/iron/kitchen/small, /area/ruin/space/has_grav/allamericandiner) "wC" = ( @@ -1159,8 +1152,11 @@ /area/ruin/space/has_grav/allamericandiner) "Vq" = ( /obj/structure/table/reinforced, -/obj/item/storage/box/cups, /obj/machinery/light/dim/directional/east, +/obj/machinery/chem_dispenser/drinks/fullupgrade{ + dir = 1 + }, +/obj/structure/window/spawner/directional/south, /turf/open/floor/iron/kitchen/small, /area/ruin/space/has_grav/allamericandiner) "Vy" = ( @@ -1981,9 +1977,9 @@ EK ej jZ LR -qp +jZ Vq -FB +rd rd lI yQ diff --git a/_maps/RandomRuins/SpaceRuins/anomaly_research.dmm b/_maps/RandomRuins/SpaceRuins/anomaly_research.dmm index e3015469bcea4..831e024754193 100644 --- a/_maps/RandomRuins/SpaceRuins/anomaly_research.dmm +++ b/_maps/RandomRuins/SpaceRuins/anomaly_research.dmm @@ -66,7 +66,6 @@ /area/misc/anomaly_research) "dj" = ( /obj/structure/window/spawner/directional/north, -/obj/structure/window/spawner/directional/north, /obj/structure/window/spawner/directional/east, /obj/structure/flora/bush/flowers_br/style_random, /turf/open/floor/grass, @@ -1516,7 +1515,6 @@ /area/misc/anomaly_research) "Ox" = ( /obj/structure/window/spawner/directional/north, -/obj/structure/window/spawner/directional/north, /obj/structure/flora/bush/flowers_br/style_random, /obj/machinery/light/broken/directional/south, /turf/open/floor/grass, diff --git a/_maps/RandomRuins/SpaceRuins/garbagetruck1.dmm b/_maps/RandomRuins/SpaceRuins/garbagetruck1.dmm new file mode 100644 index 0000000000000..e3a80fb657a6c --- /dev/null +++ b/_maps/RandomRuins/SpaceRuins/garbagetruck1.dmm @@ -0,0 +1,1494 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aF" = ( +/obj/item/trash/can/food/envirochow{ + pixel_x = 2 + }, +/obj/item/trash/can/food/envirochow{ + pixel_x = -8; + pixel_y = -6 + }, +/obj/item/trash/can/food/envirochow{ + pixel_y = -12 + }, +/obj/effect/decal/cleanable/insectguts, +/mob/living/basic/cockroach, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"aP" = ( +/obj/item/kitchen/fork{ + pixel_x = -10; + pixel_y = 0 + }, +/obj/effect/decal/cleanable/ants, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"bj" = ( +/obj/structure/closet/crate/trashcart/filled, +/obj/item/food/badrecipe/moldy/bacteria, +/obj/item/food/deadmouse, +/obj/item/sticker/syndicate/larva, +/mob/living/basic/mouse/rat, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"bs" = ( +/obj/structure/kitchenspike_frame, +/obj/item/paper/crumpled, +/obj/item/restraints/handcuffs/cable/zipties/used, +/obj/effect/decal/cleanable/blood/gibs/old, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"bx" = ( +/obj/effect/decal/cleanable/garbage, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"bF" = ( +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"ew" = ( +/obj/item/trash/can/food/peaches/maint, +/obj/item/food/breadslice/moldy/bacteria, +/obj/effect/decal/cleanable/food/egg_smudge, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"fb" = ( +/obj/item/trash/boritos/green, +/obj/effect/decal/cleanable/plastic, +/obj/item/storage/bag/trash, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"fk" = ( +/obj/item/kirbyplants/fern, +/obj/item/food/deadmouse, +/obj/effect/spawner/random/entertainment/money_small, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"fx" = ( +/obj/item/food/badrecipe/moldy/bacteria{ + pixel_y = -10 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"fI" = ( +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"fP" = ( +/obj/item/match, +/obj/item/trash/popcorn, +/obj/item/trash/spacers_sidekick, +/obj/item/food/pizzaslice/moldy/bacteria, +/obj/effect/decal/cleanable/plastic, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"fR" = ( +/obj/effect/spawner/random/structure/crate_empty, +/obj/item/kitchen/spoon/soup_ladle{ + pixel_x = -5; + pixel_y = 7 + }, +/obj/item/food/badrecipe/moldy{ + pixel_x = 3; + pixel_y = 0 + }, +/obj/item/food/badrecipe/moldy{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/food/badrecipe/moldy{ + pixel_y = 3 + }, +/obj/item/food/badrecipe/moldy, +/obj/item/food/grown/mushroom/odious_puffball{ + pixel_y = 3 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"fV" = ( +/obj/item/food/butter{ + pixel_x = 10; + pixel_y = 4 + }, +/obj/item/food/butter{ + pixel_x = 2; + pixel_y = 4 + }, +/obj/structure/closet/crate/freezer, +/obj/item/food/butter{ + pixel_x = -6; + pixel_y = 4 + }, +/obj/item/reagent_containers/condiment/flour{ + pixel_x = -6; + pixel_y = -6 + }, +/obj/item/reagent_containers/condiment/flour{ + pixel_x = 6; + pixel_y = -6 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"gb" = ( +/obj/structure/closet/crate/trashcart, +/obj/item/plate_shard, +/obj/item/popsicle_stick, +/obj/item/popsicle_stick, +/obj/item/food/egg/rotten, +/obj/effect/decal/cleanable/plastic, +/obj/item/storage/bag/tray/cafeteria, +/obj/item/storage/bag/tray/cafeteria, +/obj/item/storage/bag/tray/cafeteria, +/obj/item/knife/butcher{ + desc = "A huge thing used for chopping and chopping up meat. Years of service has scarred its metal and worn groves into the handle, but its blade is well-maintained and sharp."; + name = "antique cleaver" + }, +/mob/living/basic/cockroach, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"gI" = ( +/obj/item/storage/box/mousetraps, +/obj/structure/table/reinforced, +/obj/item/melee/flyswatter, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"hq" = ( +/obj/structure/chair/comfy/shuttle, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"hH" = ( +/obj/item/clothing/mask/surgical, +/obj/effect/spawner/random/trash/botanical_waste, +/obj/structure/closet/crate/trashcart/filled, +/obj/item/seeds/onion/red{ + pixel_x = 6; + pixel_y = 4 + }, +/obj/item/seeds/onion{ + pixel_x = 2; + pixel_y = 2 + }, +/obj/item/food/grown/mushroom/odious_puffball{ + pixel_x = -8; + pixel_y = 2 + }, +/obj/effect/spawner/random/food_or_drink/seed, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"hN" = ( +/obj/item/shard, +/obj/item/food/pizzaslice/moldy/bacteria, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"iu" = ( +/obj/structure/plasticflaps/opaque, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"iH" = ( +/obj/structure/closet/crate/freezer, +/obj/item/food/hard_taco_shell/empty{ + pixel_x = 4; + pixel_y = 4 + }, +/obj/item/food/hard_taco_shell/empty{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/food/hard_taco_shell/empty{ + pixel_x = 2; + pixel_y = 2 + }, +/obj/item/food/hard_taco_shell/empty{ + pixel_x = 1; + pixel_y = 1 + }, +/obj/item/storage/box/donkpockets{ + pixel_x = -5; + pixel_y = -5 + }, +/obj/effect/spawner/random/food_or_drink/donkpockets_single, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"jo" = ( +/obj/item/trash/can, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"js" = ( +/obj/item/food/egg/rotten{ + pixel_x = -6; + pixel_y = -8 + }, +/obj/item/food/egg/rotten{ + pixel_x = -10; + pixel_y = -8 + }, +/obj/item/food/egg/rotten{ + pixel_x = -14; + pixel_y = -8 + }, +/obj/item/food/meat/slab/rawcrab{ + pixel_x = 2; + pixel_y = -8 + }, +/obj/item/food/meat/slab/rawcrab{ + pixel_x = 2; + pixel_y = -8 + }, +/obj/item/food/meat/slab/rawcrab{ + pixel_x = 3; + pixel_y = -6 + }, +/obj/item/food/meat/slab/rawcrab{ + pixel_x = 2; + pixel_y = -2 + }, +/obj/item/food/meat/slab/rawcrab{ + pixel_x = 2 + }, +/obj/item/storage/fancy/pickles_jar{ + pixel_x = -8; + pixel_y = 6 + }, +/obj/structure/closet/secure_closet/freezer/empty, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"ki" = ( +/obj/effect/spawner/random/trash/food_packaging, +/obj/item/shard, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"ku" = ( +/obj/structure/fermenting_barrel, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"kJ" = ( +/obj/structure/table/reinforced, +/obj/item/storage/box/gloves{ + pixel_x = 10; + pixel_y = 8 + }, +/obj/item/storage/box/masks{ + pixel_x = -6; + pixel_y = 8 + }, +/obj/machinery/recharger{ + pixel_y = -10 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"kS" = ( +/obj/machinery/light/warm, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"kV" = ( +/obj/machinery/computer/terminal{ + content = list("Property of Spinward-Upsilon Sanitation Department. Authorised employees only."); + desc = "A garbage truck's dusty old control console."; + name = "dashboard"; + upperinfo = "Controls locked." + }, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"nN" = ( +/obj/item/trash/candy, +/obj/item/reagent_containers/cup/glass/colocup, +/obj/item/reagent_containers/cup/glass/colocup, +/obj/item/reagent_containers/cup/glass/colocup, +/obj/item/reagent_containers/cup/glass/colocup, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"nQ" = ( +/obj/item/trash/shrimp_chips, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"nS" = ( +/obj/effect/spawner/random/structure/crate_empty, +/obj/item/vending_refill/dinnerware, +/obj/item/vending_refill/snack, +/obj/item/circuitboard/machine/coffeemaker, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"og" = ( +/obj/structure/lattice, +/obj/structure/grille, +/obj/effect/spawner/random/entertainment/plushie, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"oq" = ( +/obj/item/food/cheese/wheel, +/obj/item/food/cheese/wheel, +/obj/item/food/cheese/wheel, +/obj/item/food/cheese/wheel, +/obj/item/food/cheese/wheel, +/obj/item/food/cheese/firm_cheese, +/obj/item/food/cheese/firm_cheese, +/obj/item/food/cheese/firm_cheese, +/obj/item/food/cheese/firm_cheese, +/obj/item/food/cheese/firm_cheese, +/obj/item/thermometer, +/obj/structure/closet/secure_closet/freezer/empty, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"oL" = ( +/obj/structure/table/reinforced, +/obj/item/analyzer{ + pixel_y = 6 + }, +/obj/item/geiger_counter{ + pixel_x = -8; + pixel_y = -2 + }, +/obj/item/flashlight{ + pixel_x = 4 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"pp" = ( +/obj/effect/spawner/random/trash/garbage, +/obj/item/broken_bottle, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"ps" = ( +/obj/item/trash/can/food/larvae, +/obj/item/food/bait/worm, +/obj/effect/decal/cleanable/garbage, +/obj/effect/decal/cleanable/ants, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"pF" = ( +/obj/item/food/badrecipe/moldy/bacteria, +/obj/item/food/deadmouse/moldy, +/obj/structure/broken_flooring/pile, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"pP" = ( +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"qd" = ( +/obj/item/food/breadslice/moldy/bacteria{ + pixel_y = -10 + }, +/obj/structure/reagent_dispensers/servingdish{ + anchored = 0 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"qm" = ( +/obj/effect/decal/cleanable/food/egg_smudge, +/obj/item/food/pizzaslice/moldy, +/mob/living/basic/mouse/brown, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"qM" = ( +/turf/open/space/basic, +/area/space) +"re" = ( +/obj/item/trash/shrimp_chips, +/obj/item/trash/sosjerky, +/mob/living/basic/mouse/rat, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"rx" = ( +/obj/item/surprise_egg, +/obj/structure/closet/crate/trashcart, +/obj/item/trash/raisins, +/obj/effect/decal/cleanable/food/egg_smudge, +/obj/item/book/manual/chef_recipes, +/obj/item/trash/semki/healthy, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"rL" = ( +/obj/item/food/badrecipe, +/obj/item/pen/charcoal{ + desc = "It's just a wooden stick with some compressed ash on the end. At least it can write."; + name = "charcoal stick" + }, +/obj/effect/decal/cleanable/oil/streak, +/obj/structure/closet/crate/trashcart, +/obj/item/food/grown/ash_flora/shavings, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"tr" = ( +/obj/structure/broken_flooring/singular, +/obj/effect/spawner/random/trash/food_packaging, +/obj/effect/spawner/random/trash/food_packaging, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"ty" = ( +/obj/item/trash/can/food/peaches, +/obj/item/trash/boritos/red, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"tU" = ( +/obj/machinery/door/poddoor/shutters/preopen, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"uJ" = ( +/obj/item/trash/cnds, +/obj/item/food/breadslice/moldy/bacteria, +/obj/effect/decal/cleanable/wrapping, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"vA" = ( +/obj/machinery/power/terminal, +/obj/structure/tank_dispenser/oxygen, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"vI" = ( +/obj/item/poster/random_contraband, +/obj/item/tank/internals/emergency_oxygen/empty, +/obj/effect/decal/cleanable/garbage{ + pixel_x = -8; + pixel_y = -8 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"wb" = ( +/obj/effect/spawner/random/trash/bacteria, +/obj/item/trash/can, +/obj/item/trash/can{ + pixel_x = 8; + pixel_y = 1 + }, +/obj/item/trash/can{ + pixel_x = 5; + pixel_y = -2 + }, +/obj/item/food/badrecipe/moldy/bacteria{ + pixel_x = 12; + pixel_y = -8 + }, +/obj/effect/decal/cleanable/fuel_pool{ + desc = "A sticky patch of dried cola. It smells very sweet."; + name = "puddle of cola" + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"wv" = ( +/obj/structure/closet/cardboard, +/obj/item/toy/plush/snakeplushie, +/obj/item/clothing/glasses/eyepatch, +/obj/item/clothing/mask/cigarette/cigar/havana, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"wR" = ( +/obj/structure/reagent_dispensers/water_cooler, +/obj/item/food/badrecipe/moldy/bacteria{ + pixel_x = 2; + pixel_y = -8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"xf" = ( +/obj/item/trash/tray, +/obj/item/trash/waffles, +/obj/item/trash/waffles, +/obj/item/trash/waffles, +/obj/item/food/grown/mushroom/plumphelmet, +/obj/structure/closet/crate/trashcart, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"xg" = ( +/obj/structure/closet/crate/cardboard, +/obj/item/knife/kitchen, +/obj/item/storage/box/mousetraps, +/obj/structure/broken_flooring/pile, +/obj/item/food/grown/parsnip, +/obj/item/food/grown/parsnip, +/obj/item/food/cheese/wedge, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"xk" = ( +/obj/structure/table/reinforced, +/obj/item/gps/spaceruin{ + pixel_x = 6; + pixel_y = 2 + }, +/obj/item/storage/backpack/industrial{ + pixel_x = -8; + pixel_y = 4 + }, +/obj/item/clothing/suit/hazardvest{ + pixel_x = -8; + pixel_y = -6 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"xZ" = ( +/obj/item/restraints/handcuffs/cable/zipties/used, +/obj/effect/spawner/random/decoration/flower, +/obj/item/reagent_containers/cup/glass/bottle/wine/unlabeled, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"ye" = ( +/obj/item/trash/semki/healthy, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"yh" = ( +/obj/effect/spawner/random/trash, +/mob/living/basic/mouse, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"yi" = ( +/obj/structure/sign/warning, +/turf/closed/wall/r_wall, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"yv" = ( +/obj/item/trash/can{ + pixel_x = -8; + pixel_y = -2 + }, +/obj/item/trash/can{ + pixel_y = -8 + }, +/obj/effect/decal/cleanable/fuel_pool{ + desc = "A sticky patch of dried cola. It smells very sweet."; + name = "puddle of cola" + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"yC" = ( +/obj/item/trash/popcorn/caramel{ + pixel_y = -6 + }, +/mob/living/basic/cockroach, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"zK" = ( +/obj/item/trash/chips{ + pixel_x = -8 + }, +/obj/item/broken_bottle{ + pixel_x = 8; + pixel_y = 2 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Aj" = ( +/obj/effect/decal/cleanable/ants, +/mob/living/basic/mouse/white, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"An" = ( +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"AM" = ( +/obj/item/trash/can{ + pixel_x = -8; + pixel_y = -2; + pixel_z = 0 + }, +/obj/item/reagent_containers/cup/soda_cans/random{ + pixel_x = -8; + pixel_y = 6 + }, +/obj/structure/closet/crate/cardboard, +/obj/item/vending_refill/cola, +/obj/item/vending_refill/boozeomat, +/obj/item/trash/can{ + pixel_x = 8; + pixel_y = 0 + }, +/obj/item/trash/can{ + pixel_x = 2; + pixel_y = -4 + }, +/obj/item/reagent_containers/cup/soda_cans/random{ + pixel_x = -2; + pixel_y = -2 + }, +/obj/item/reagent_containers/cup/soda_cans/random{ + pixel_x = 8; + pixel_y = -2 + }, +/obj/effect/decal/cleanable/fuel_pool{ + desc = "A sticky patch of dried cola. It smells very sweet."; + name = "puddle of cola" + }, +/obj/effect/spawner/random/food_or_drink/refreshing_beverage, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"AR" = ( +/obj/structure/lattice, +/obj/structure/grille, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"BS" = ( +/obj/item/storage/bag/trash/filled{ + pixel_x = -8 + }, +/obj/effect/decal/cleanable/garbage{ + pixel_x = 2; + pixel_y = 5 + }, +/obj/effect/decal/cleanable/food/egg_smudge{ + pixel_x = -2; + pixel_y = -8 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Cc" = ( +/obj/item/trash/tray, +/obj/item/food/breadslice/moldy/bacteria{ + pixel_x = -8; + pixel_y = -8 + }, +/obj/item/food/tofu/prison{ + pixel_x = -8; + pixel_y = 4 + }, +/obj/item/food/tofu/prison{ + pixel_x = -8; + pixel_y = -2 + }, +/obj/effect/decal/cleanable/ants, +/obj/structure/closet/crate/preopen, +/obj/item/food/meat/slab/human/mutant/zombie{ + pixel_x = 8; + pixel_y = 4 + }, +/obj/item/mail/junkmail, +/obj/item/trash/raisins, +/obj/item/trash/candy{ + pixel_x = 10; + pixel_y = -6 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Ci" = ( +/obj/item/kitchen/fork/plastic{ + pixel_x = -8 + }, +/obj/item/kitchen/spoon/plastic{ + pixel_x = -2; + pixel_y = -2 + }, +/obj/item/paper/crumpled{ + pixel_x = 7; + pixel_y = -4 + }, +/obj/effect/decal/cleanable/glass, +/obj/effect/spawner/random/food_or_drink/condiment, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Ct" = ( +/obj/machinery/door/airlock/shuttle, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"CF" = ( +/obj/machinery/reagentgrinder{ + anchored = 0 + }, +/obj/item/food/badrecipe{ + pixel_x = -4; + pixel_y = -6 + }, +/obj/effect/decal/cleanable/fuel_pool{ + desc = "A sticky patch of dried cola. It smells very sweet."; + name = "puddle of cola" + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Do" = ( +/obj/item/food/badrecipe/moldy/bacteria, +/obj/item/food/bait/worm, +/obj/effect/decal/cleanable/food/tomato_smudge, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Ec" = ( +/obj/effect/spawner/random/trash/bucket, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Fp" = ( +/obj/item/food/badrecipe/moldy/bacteria, +/obj/item/storage/bag/trash/filled, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Fs" = ( +/obj/structure/closet/cardboard, +/obj/item/restraints/handcuffs/cable/zipties/used, +/obj/item/food/cornchips/blue, +/obj/item/food/cornchips/blue, +/obj/item/food/cornchips/green, +/obj/item/food/cornchips/green, +/obj/item/food/cornchips/purple, +/obj/item/food/cornchips/purple, +/obj/item/food/cornchips/red, +/obj/item/food/cornchips/red, +/obj/item/food/cornchips/random, +/obj/item/food/cornchips/random, +/obj/item/food/cornchips/blue{ + desc = "Limited edition flavour. Only for sale within the space commonwealth."; + name = "\improper Space Salt and Vinegar Boritos corn chips"; + tastes = list("salt" = 1, "vinegar" = 3) + }, +/obj/item/food/cornchips/blue{ + desc = "Limited edition flavour. Only for sale within the space commonwealth."; + name = "\improper Space Salt and Vinegar Boritos corn chips"; + tastes = list("salt" = 1, "vinegar" = 3) + }, +/obj/item/food/cornchips/random, +/obj/item/food/cornchips/random, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Fz" = ( +/obj/structure/table/reinforced, +/obj/machinery/cell_charger, +/obj/item/stock_parts/cell/lead, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"FL" = ( +/obj/structure/closet/cardboard, +/obj/item/pen/blue, +/obj/item/ph_paper, +/obj/item/petri_dish, +/obj/item/healthanalyzer/simple/disease, +/obj/item/biopsy_tool, +/obj/effect/spawner/random/medical/surgery_tool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Gh" = ( +/obj/item/trash/semki/healthy, +/mob/living/basic/mouse, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"GB" = ( +/obj/item/trash/can, +/obj/item/storage/bag/trash, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"GP" = ( +/obj/effect/decal/cleanable/garbage, +/obj/item/crowbar/hammer{ + desc = "It's a heavy iron hammer with a plastic grip. A triangle has been chiselled into the handle."; + name = "heirloom hammer" + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"GU" = ( +/obj/item/reagent_containers/cup/glass/waterbottle/empty, +/obj/effect/decal/cleanable/wrapping, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Hh" = ( +/obj/structure/closet/crate/trashcart/filled, +/obj/item/reagent_containers/cup/glass/bottle/juice/orangejuice{ + desc = "Best before '32"; + pixel_x = -6 + }, +/obj/effect/decal/cleanable/insectguts, +/obj/item/food/grown/mushroom/odious_puffball{ + pixel_x = 8; + pixel_y = 4 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Hu" = ( +/obj/effect/spawner/random/structure/crate_empty, +/obj/item/knife/plastic{ + pixel_x = 12 + }, +/obj/item/food/badrecipe/moldy/bacteria{ + pixel_x = -6 + }, +/obj/item/food/meat/slab/pig, +/obj/item/food/deadmouse, +/obj/item/food/salami{ + pixel_x = 1; + pixel_y = 2 + }, +/obj/item/food/salami{ + pixel_x = 1; + pixel_y = 3 + }, +/obj/item/food/salami{ + pixel_x = 1; + pixel_y = 6 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"HC" = ( +/obj/effect/spawner/random/structure/crate_empty, +/obj/item/kitchen/fork/plastic{ + pixel_x = -8 + }, +/obj/item/kitchen/fork/plastic{ + pixel_x = 8; + pixel_y = 0 + }, +/obj/item/kitchen/fork/plastic, +/obj/item/storage/box/papersack/meat, +/obj/effect/spawner/random/food_or_drink/condiment, +/obj/item/popsicle_stick, +/obj/item/popsicle_stick{ + pixel_x = -4; + pixel_y = 1 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Ie" = ( +/obj/machinery/airalarm{ + pixel_y = 25 + }, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"II" = ( +/obj/structure/closet/crate/trashcart/filled, +/obj/item/food/cracker, +/obj/item/food/canned/beans{ + desc = "Probably still good."; + name = "rust-covered tin of beans" + }, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"IR" = ( +/obj/structure/table/reinforced, +/obj/item/gas_filter, +/obj/item/gas_filter, +/obj/item/clothing/mask/gas, +/obj/item/clothing/head/utility/hardhat/orange{ + pixel_y = 8 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"JH" = ( +/obj/item/petri_dish/random, +/obj/item/petri_dish/random, +/obj/item/petri_dish, +/obj/item/petri_dish, +/obj/item/petri_dish, +/obj/item/organ/internal/tongue/rat, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/glass, +/obj/item/organ/internal/stomach/rat, +/obj/item/fish/ratfish, +/obj/structure/closet/crate/freezer, +/obj/effect/spawner/random/medical/surgery_tool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"KD" = ( +/obj/structure/closet/crate/critter, +/obj/item/dog_bone{ + pixel_y = -6 + }, +/mob/living/basic/cockroach, +/mob/living/basic/cockroach, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"KT" = ( +/obj/structure/broken_flooring/singular, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Le" = ( +/obj/effect/spawner/random/trash/bacteria, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Mq" = ( +/obj/structure/closet/crate/cardboard, +/obj/item/stack/tile/bamboo/tatami{ + amount = 40 + }, +/obj/item/stack/sticky_tape{ + pixel_y = -2 + }, +/obj/effect/decal/cleanable/plastic, +/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/glass, +/obj/effect/spawner/random/engineering/material_cheap, +/obj/item/crowbar/hammer{ + desc = "It's a heavy claw hammer. The handle is covered in fangmarks of varying sizes."; + name = "old hammer" + }, +/obj/item/food/deadmouse, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"MA" = ( +/obj/item/food/badrecipe/moldy/bacteria, +/obj/item/food/deadmouse, +/obj/item/grown/bananapeel, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Nm" = ( +/obj/item/trash/energybar, +/obj/item/trash/energybar, +/obj/item/trash/energybar, +/obj/item/trash/energybar, +/obj/item/food/candy/bronx, +/obj/item/food/candy/bronx, +/obj/effect/spawner/random/structure/crate_empty, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Od" = ( +/obj/structure/grille, +/obj/structure/window/reinforced/shuttle, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Oh" = ( +/obj/effect/spawner/random/trash/bacteria, +/mob/living/basic/mouse/brown, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Ok" = ( +/obj/item/plate/large, +/obj/item/plate/large, +/obj/item/storage/box/drinkingglasses{ + pixel_x = 10; + pixel_y = 2 + }, +/obj/structure/closet/crate/preopen, +/obj/item/reagent_containers/cup/glass/coffee_cup{ + pixel_x = 4; + pixel_y = -3 + }, +/mob/living/basic/mouse/brown, +/mob/living/basic/mouse/brown, +/mob/living/basic/mouse/brown, +/mob/living/basic/mouse, +/mob/living/basic/mouse, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Or" = ( +/obj/item/food/sustenance_bar/cheese{ + pixel_x = -6; + pixel_y = -8 + }, +/obj/structure/closet/crate/large, +/obj/item/food/sustenance_bar/cheese{ + pixel_x = -6; + pixel_y = -4 + }, +/obj/item/food/sustenance_bar/neapolitan{ + maptext_x = 0; + maptext_y = 0; + pixel_x = -6 + }, +/obj/item/food/sustenance_bar/neapolitan{ + pixel_x = -6; + pixel_y = 4 + }, +/obj/item/food/sustenance_bar/mint{ + pixel_x = -6; + pixel_y = 8 + }, +/obj/item/food/sustenance_bar/mint{ + pixel_x = -6; + pixel_y = 12 + }, +/obj/item/food/sustenance_bar{ + pixel_x = 6; + pixel_y = -10 + }, +/obj/item/food/sustenance_bar{ + pixel_x = 6; + pixel_y = -6 + }, +/obj/item/food/sustenance_bar{ + pixel_x = 6; + pixel_y = -2 + }, +/obj/item/food/sustenance_bar{ + pixel_x = 6; + pixel_y = 2 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Ox" = ( +/obj/effect/spawner/random/structure/crate_empty, +/obj/item/trash/candy{ + pixel_x = 6; + pixel_y = 6 + }, +/obj/item/trash/can/food/desert_snails{ + pixel_x = -4; + pixel_y = 2 + }, +/obj/item/trash/can/food/envirochow{ + pixel_x = -8; + pixel_y = -2 + }, +/obj/effect/decal/cleanable/food/flour, +/obj/item/thermometer/pen{ + pixel_x = 8 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"OD" = ( +/turf/closed/wall/mineral/titanium, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"OZ" = ( +/obj/effect/spawner/random/structure/crate_empty, +/obj/item/plate/small{ + pixel_x = -6 + }, +/obj/item/food/meat/slab/human/mutant/zombie{ + pixel_x = 4; + pixel_y = 6 + }, +/obj/item/food/meat/slab/human/mutant/zombie{ + pixel_x = 5 + }, +/obj/item/food/meat/slab/human/mutant/zombie{ + pixel_x = 2; + pixel_y = -5 + }, +/obj/item/food/meat/slab/human{ + pixel_x = 1; + pixel_y = 3 + }, +/obj/effect/decal/cleanable/ants, +/obj/effect/decal/cleanable/food/tomato_smudge, +/obj/item/organ/internal/heart/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"PU" = ( +/obj/item/clothing/head/cone{ + pixel_x = 8; + pixel_y = 8 + }, +/obj/machinery/light/warm, +/obj/machinery/power/apc{ + cell_type = /obj/item/stock_parts/cell/lead; + locked = 0; + pixel_y = -25; + start_charge = 0 + }, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Qi" = ( +/obj/item/book/bible, +/obj/structure/closet/crate/cardboard, +/obj/item/mail/junkmail{ + pixel_x = -10; + pixel_y = 2 + }, +/obj/item/mail/junkmail{ + pixel_x = 6; + pixel_y = 1 + }, +/obj/item/mail/junkmail, +/obj/effect/decal/cleanable/insectguts, +/mob/living/basic/mouse/rat, +/mob/living/basic/mouse/rat, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"QH" = ( +/obj/structure/closet/crate/trashcart/filled, +/obj/effect/decal/cleanable/insectguts, +/obj/item/pinata, +/obj/item/food/cornchips/green, +/obj/effect/spawner/random/food_or_drink/condiment, +/mob/living/basic/mouse, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"QL" = ( +/obj/item/broken_bottle, +/obj/item/grown/bananapeel, +/obj/effect/spawner/random/trash/garbage, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Rq" = ( +/obj/machinery/door/airlock/external/glass, +/obj/structure/fans/tiny, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Sa" = ( +/turf/closed/wall/r_wall, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Sb" = ( +/obj/item/food/deadmouse/moldy, +/obj/item/reagent_containers/spray/pestspray{ + pixel_x = 6; + pixel_y = 8 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"TB" = ( +/obj/structure/window/reinforced/shuttle, +/obj/structure/grille, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"TG" = ( +/obj/item/mop, +/obj/item/food/deadmouse/moldy, +/obj/item/pushbroom, +/obj/effect/decal/cleanable/insectguts, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"TX" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"UX" = ( +/obj/structure/lattice/catwalk, +/obj/item/crowbar/large/emergency, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Vb" = ( +/obj/structure/closet/crate/cardboard/mothic, +/obj/item/trash/can/food/pine_nuts, +/obj/item/broken_bottle, +/obj/item/broken_bottle, +/obj/effect/decal/cleanable/wrapping, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"VB" = ( +/obj/machinery/power/smes, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"VL" = ( +/obj/machinery/power/shuttle_engine/propulsion, +/turf/open/space/basic, +/area/space) +"Xi" = ( +/obj/item/food/badrecipe/moldy/bacteria, +/obj/effect/decal/cleanable/food/egg_smudge, +/mob/living/basic/mouse, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"XF" = ( +/obj/item/shard, +/obj/item/trash/boritos, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"XY" = ( +/obj/structure/lattice, +/obj/structure/grille/broken, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Yu" = ( +/obj/structure/table/reinforced, +/obj/item/storage/bag/trash{ + pixel_x = -12; + pixel_y = 0 + }, +/obj/item/storage/bag/trash, +/obj/item/storage/bag/trash{ + pixel_x = -6; + pixel_y = 0 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Yx" = ( +/obj/structure/reagent_dispensers/cooking_oil{ + anchored = 0 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Yz" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"YB" = ( +/obj/item/trash/peanuts{ + pixel_x = -4; + pixel_y = -8 + }, +/obj/structure/closet/crate/freezer, +/obj/item/trash/pistachios{ + pixel_x = 8; + pixel_y = -4 + }, +/obj/item/trash/pistachios, +/obj/item/c_tube, +/obj/item/food/uncooked_rice{ + pixel_y = -4 + }, +/obj/item/trash/peanuts{ + pixel_x = -2; + pixel_y = 6 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) +"Zb" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/grown/bananapeel, +/obj/item/food/deadmouse, +/mob/living/basic/mouse/rat, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/foodwaste) + +(1,1,1) = {" +qM +qM +pP +pP +pP +OD +VL +qM +qM +qM +qM +qM +qM +qM +qM +qM +qM +qM +qM +qM +"} +(2,1,1) = {" +qM +OD +TB +TB +OD +OD +Sa +Sa +Sa +Sa +Sa +Sa +Sa +Sa +Sa +Sa +Sa +Sa +Sa +Sa +"} +(3,1,1) = {" +XY +Od +kJ +Fz +gI +OD +Sa +Hu +rL +HC +YB +iH +wv +KD +wR +nS +fV +Vb +bs +yi +"} +(4,1,1) = {" +og +TB +kV +hq +kS +OD +Sa +xf +ku +OZ +Fp +Ok +MA +aF +vI +xg +ps +ye +GP +Sa +"} +(5,1,1) = {" +AR +TB +xk +IR +bF +OD +Sa +Ci +qm +qd +zK +aP +GU +KT +An +TX +ki +Fp +xZ +Sa +"} +(6,1,1) = {" +XY +TB +Od +OD +Ie +Ct +tU +TX +yh +bx +Yz +Do +Le +fx +wb +gb +hH +QH +bj +Sa +"} +(7,1,1) = {" +XY +Od +Yu +oL +bF +Ct +tU +fb +pF +Gh +hN +QL +TX +Mq +AM +CF +rx +II +Hh +Sa +"} +(8,1,1) = {" +og +Od +fI +fI +bF +OD +Sa +js +BS +Oh +oq +XF +jo +Aj +yv +GB +pp +re +Yx +Sa +"} +(9,1,1) = {" +XY +Od +fI +bF +PU +OD +Sa +Qi +yC +nN +Fs +fk +TG +nQ +ku +ty +ew +tr +Zb +Sa +"} +(10,1,1) = {" +AR +Od +fI +vA +VB +OD +Sa +Cc +Ox +fR +fP +Or +Ec +Sb +Xi +uJ +FL +Nm +JH +yi +"} +(11,1,1) = {" +qM +OD +Rq +Od +OD +OD +Sa +Sa +Sa +Sa +Sa +Sa +Sa +iu +iu +iu +Sa +Sa +Sa +Sa +"} +(12,1,1) = {" +qM +qM +pP +pP +UX +OD +VL +qM +qM +qM +qM +qM +qM +qM +qM +qM +qM +qM +qM +qM +"} diff --git a/_maps/RandomRuins/SpaceRuins/garbagetruck2.dmm b/_maps/RandomRuins/SpaceRuins/garbagetruck2.dmm new file mode 100644 index 0000000000000..a2ed3ff8dbae9 --- /dev/null +++ b/_maps/RandomRuins/SpaceRuins/garbagetruck2.dmm @@ -0,0 +1,955 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"bb" = ( +/obj/item/organ/external/wings/moth, +/obj/structure/closet/crate/trashcart, +/obj/item/bodypart/arm/left/skeleton, +/obj/item/bodypart/arm/right/skeleton, +/obj/item/evidencebag, +/obj/item/organ/internal/heart/cybernetic/tier2, +/obj/structure/broken_flooring/pile, +/obj/item/stack/sheet/animalhide/human/five, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"bv" = ( +/obj/structure/showcase/horrific_experiment, +/obj/effect/decal/cleanable/blood/gibs/old, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"eO" = ( +/obj/effect/spawner/random/contraband/narcotics, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"gh" = ( +/turf/open/space/basic, +/area/space) +"gr" = ( +/obj/machinery/door/poddoor/shutters/preopen, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"gy" = ( +/obj/machinery/door/airlock/external/glass, +/obj/structure/fans/tiny, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"hf" = ( +/obj/item/circuitboard/machine/medical_kiosk, +/obj/structure/frame/machine, +/obj/effect/spawner/random/engineering/tool, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"hp" = ( +/obj/structure/table/reinforced, +/obj/item/gps/spaceruin{ + pixel_x = 6; + pixel_y = 2 + }, +/obj/item/storage/backpack/industrial{ + pixel_x = -8; + pixel_y = 4 + }, +/obj/item/clothing/suit/hazardvest{ + pixel_x = -8; + pixel_y = -6 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"hu" = ( +/obj/structure/filingcabinet/chestdrawer, +/obj/item/stack/spacecash/c20, +/obj/item/pen/fountain, +/obj/structure/broken_flooring/singular, +/obj/item/swab, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"hv" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/reagent_containers/pill/maintenance{ + pixel_x = 3; + pixel_y = 7 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"io" = ( +/obj/structure/closet/body_bag, +/obj/structure/table/optable, +/obj/effect/mob_spawn/corpse/human{ + brute_damage = 35; + mob_type = /mob/living/carbon/human/species/fly; + oxy_damage = 65 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"iw" = ( +/obj/structure/lattice, +/obj/structure/grille, +/obj/effect/spawner/random/entertainment/plushie, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"iU" = ( +/obj/effect/spawner/random/trash/garbage, +/obj/effect/spawner/random/medical/medkit, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"kf" = ( +/obj/machinery/power/smes, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"kl" = ( +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"kp" = ( +/obj/structure/safe, +/obj/item/stamp/syndicate, +/obj/item/traitor_bug, +/obj/item/eyesnatcher, +/obj/item/stack/spacecash/c1000, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"kx" = ( +/obj/structure/lattice, +/obj/structure/grille, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"lT" = ( +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"mB" = ( +/obj/effect/spawner/random/engineering/tank, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"mZ" = ( +/obj/machinery/airalarm{ + pixel_y = 25 + }, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"nW" = ( +/obj/item/storage/box/disks{ + pixel_x = -7; + pixel_y = -3 + }, +/obj/structure/broken_flooring/singular, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"pu" = ( +/obj/structure/plasticflaps/opaque, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"py" = ( +/obj/structure/closet/body_bag, +/obj/structure/table/optable, +/obj/item/surgical_drapes, +/obj/effect/mob_spawn/corpse/human{ + brute_damage = 50; + burn_damage = 50 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"pD" = ( +/obj/machinery/iv_drip/saline, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"pR" = ( +/obj/machinery/iv_drip, +/obj/item/storage/box/syringes{ + pixel_x = 6; + pixel_y = -2 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"qh" = ( +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/rack_parts, +/obj/item/storage/pill_bottle/mannitol, +/obj/item/retractor/advanced, +/obj/effect/decal/cleanable/oil/slippery, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"qC" = ( +/turf/closed/wall/mineral/titanium, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"qX" = ( +/obj/effect/decal/cleanable/plastic, +/obj/structure/broken_flooring/corner, +/obj/item/trash/syndi_cakes, +/obj/item/trash/syndi_cakes, +/obj/item/trash/syndi_cakes, +/obj/item/poster/random_contraband, +/obj/item/organ/internal/tongue/zombie, +/obj/structure/closet/crate/trashcart, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"rB" = ( +/obj/structure/closet/crate/freezer, +/obj/item/stack/medical/bone_gel, +/obj/item/stack/medical/ointment, +/obj/item/thermometer, +/obj/effect/decal/cleanable/blood/splatter, +/obj/item/clothing/suit/apron/surgical, +/obj/item/clothing/neck/stethoscope, +/obj/item/clothing/neck/stethoscope, +/obj/item/biopsy_tool, +/obj/effect/spawner/random/contraband/narcotics, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"sa" = ( +/obj/structure/frame/computer, +/obj/item/circuitboard/computer/operating, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"sU" = ( +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"tI" = ( +/obj/structure/tank_holder/anesthetic, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"uo" = ( +/obj/machinery/computer/terminal{ + content = list("Property of Spinward-Upsilon Sanitation Department. Authorised employees only."); + desc = "A garbage truck's dusty old control console."; + name = "dashboard"; + upperinfo = "Controls locked." + }, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"uG" = ( +/obj/structure/chair/plastic, +/obj/item/reagent_containers/syringe/lethal/choral, +/obj/effect/spawner/random/maintenance, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"uR" = ( +/obj/machinery/iv_drip, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/plastic, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"vf" = ( +/obj/structure/table/reinforced, +/obj/machinery/cell_charger, +/obj/item/stock_parts/cell/lead, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"vM" = ( +/obj/structure/closet/cardboard, +/obj/item/toy/plush/snakeplushie, +/obj/item/bodypart/arm/left/robot/surplus, +/obj/item/clothing/glasses/eyepatch, +/obj/item/toy/nuke, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"wh" = ( +/mob/living/basic/trooper/syndicate/ranged, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"wk" = ( +/obj/structure/frame/computer, +/obj/effect/decal/cleanable/glass, +/obj/effect/decal/cleanable/cobweb, +/obj/item/circuitboard/computer/operating, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"xj" = ( +/obj/structure/window/reinforced/shuttle, +/obj/structure/grille, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"xw" = ( +/obj/item/restraints/handcuffs/cable/zipties/used, +/obj/structure/closet/crate/trashcart/filled, +/obj/item/reagent_containers/condiment/soysauce, +/obj/item/reagent_containers/pill/mannitol, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"xH" = ( +/obj/item/food/badrecipe/moldy, +/obj/item/food/badrecipe/moldy, +/obj/structure/closet/mini_fridge/grimy, +/obj/effect/decal/cleanable/oil, +/obj/item/reagent_containers/cup/bottle/morphine, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"zb" = ( +/obj/item/wheelchair, +/obj/item/cane/white, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"zj" = ( +/obj/structure/table/rolling{ + desc = "An Interdyne Pharmaceutics brand 'Crash Cart Classic' rolling table for surgical tools. It can and will move."; + name = "rolling surgical tray" + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"zn" = ( +/obj/structure/closet/cardboard, +/obj/item/stack/medical/suture, +/obj/item/stack/medical/gauze, +/obj/item/stack/sticky_tape/surgical, +/obj/structure/broken_flooring/corner, +/obj/item/organ/internal/cyberimp/arm/surgery, +/obj/item/organ/internal/cyberimp/eyes/hud/medical, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"zu" = ( +/obj/structure/toilet{ + anchored = 0 + }, +/obj/effect/spawner/random/contraband/permabrig_weapon, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"zZ" = ( +/obj/item/pillow, +/obj/structure/closet/crate/trashcart/laundry, +/obj/item/bodybag, +/obj/item/bodybag, +/obj/item/clothing/under/rank/medical/scrubs/blue, +/obj/item/clothing/under/rank/medical/scrubs/blue, +/obj/item/clothing/under/rank/medical/scrubs/coroner, +/obj/item/clothing/under/rank/medical/scrubs/green, +/obj/item/clothing/under/rank/medical/scrubs/green, +/obj/item/clothing/suit/toggle/labcoat, +/obj/item/clothing/suit/toggle/labcoat, +/obj/item/clothing/suit/toggle/labcoat, +/obj/item/clothing/suit/toggle/labcoat, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Al" = ( +/obj/structure/frame/computer, +/obj/effect/decal/cleanable/glass, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Am" = ( +/obj/structure/mannequin/plastic, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"AB" = ( +/obj/structure/shipping_container/interdyne{ + armor_type = /datum/armor/immune + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"AG" = ( +/obj/structure/chair/comfy/shuttle, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"AU" = ( +/obj/item/paper/crumpled, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/broken_flooring/side, +/obj/item/suppressor, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"BE" = ( +/obj/structure/table/reinforced, +/obj/item/storage/bag/trash{ + pixel_x = -12; + pixel_y = 0 + }, +/obj/item/storage/bag/trash, +/obj/item/storage/bag/trash{ + pixel_x = -6; + pixel_y = 0 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Cv" = ( +/obj/item/storage/box/mousetraps, +/obj/structure/table/reinforced, +/obj/item/melee/flyswatter, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"CJ" = ( +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"CM" = ( +/obj/item/toy/braintoy, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/fuel_pool, +/obj/structure/closet/crate/trashcart, +/obj/item/shard, +/obj/item/stack/cable_coil, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"CU" = ( +/obj/structure/mannequin/skeleton, +/obj/structure/broken_flooring/plating, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Dj" = ( +/obj/item/food/deadmouse/moldy, +/obj/item/statuebust/hippocratic, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Dv" = ( +/obj/item/popsicle_stick{ + pixel_x = -4; + pixel_y = 9 + }, +/obj/item/rack_parts, +/obj/item/shard, +/obj/item/wrench/medical, +/obj/effect/decal/cleanable/plastic, +/obj/effect/spawner/random/contraband/permabrig_gear, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"EJ" = ( +/obj/item/stack/sticky_tape/surgical, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Go" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/pill/cyanide{ + pixel_y = 8 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Gp" = ( +/obj/item/organ/internal/eyes/robotic/basic, +/obj/item/kitchen/spoon, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Hx" = ( +/obj/effect/decal/cleanable/plastic, +/obj/structure/closet/crate/freezer, +/obj/item/skillchip/entrails_reader, +/obj/item/mod/module/health_analyzer, +/obj/item/shovel, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"HE" = ( +/obj/structure/bed/maint, +/obj/structure/bedsheetbin, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"IM" = ( +/obj/effect/decal/cleanable/robot_debris, +/obj/structure/closet/crate/freezer, +/obj/item/organ/internal/liver/roach, +/obj/item/organ/internal/stomach, +/obj/item/organ/internal/tongue/robot, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"IS" = ( +/obj/structure/broken_flooring/singular, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"JW" = ( +/obj/item/plate, +/obj/effect/decal/cleanable/plastic, +/obj/structure/closet/crate/trashcart, +/obj/item/food/deadmouse, +/obj/effect/spawner/random/medical/medkit, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Kk" = ( +/obj/item/wheelchair, +/obj/item/screwdriver, +/obj/effect/spawner/random/maintenance/three, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Ky" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Lh" = ( +/obj/item/food/deadmouse/moldy, +/obj/item/pushbroom, +/obj/item/storage/bag/trash/filled, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Ll" = ( +/obj/item/trash/boritos/red, +/obj/item/storage/box/gloves, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"LA" = ( +/obj/item/mail/junkmail, +/obj/effect/decal/cleanable/plastic, +/obj/item/clothing/mask/surgical, +/obj/item/extinguisher/empty, +/obj/item/sticker/assistant, +/obj/item/reagent_containers/cup/coffeepot, +/obj/item/coffee_cartridge/decaf, +/obj/structure/closet/crate/trashcart, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"LG" = ( +/obj/structure/lattice/catwalk, +/obj/item/crowbar/large/emergency, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"LI" = ( +/obj/structure/table/reinforced, +/obj/item/gas_filter, +/obj/item/gas_filter, +/obj/item/clothing/mask/gas, +/obj/item/clothing/head/utility/hardhat/orange{ + pixel_y = 8 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"LR" = ( +/obj/machinery/power/terminal, +/obj/structure/tank_dispenser/oxygen, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"MC" = ( +/turf/closed/wall/r_wall, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"NJ" = ( +/obj/structure/table/reinforced, +/obj/item/storage/box/gloves{ + pixel_x = 10; + pixel_y = 8 + }, +/obj/item/storage/box/masks{ + pixel_x = -6; + pixel_y = 8 + }, +/obj/machinery/recharger{ + pixel_y = -10 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Od" = ( +/obj/item/clothing/head/cone{ + pixel_x = 8; + pixel_y = 8 + }, +/obj/machinery/light/warm, +/obj/machinery/power/apc{ + cell_type = /obj/item/stock_parts/cell/lead; + locked = 0; + pixel_y = -25; + start_charge = 0 + }, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Ok" = ( +/obj/item/reagent_containers/pill/cyanide, +/obj/effect/spawner/random/medical/minor_healing, +/obj/effect/spawner/random/medical/surgery_tool, +/obj/item/reagent_containers/blood/o_minus, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"OA" = ( +/obj/machinery/door/airlock/shuttle, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Pd" = ( +/obj/structure/lattice, +/obj/structure/grille/broken, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Pe" = ( +/obj/effect/decal/cleanable/robot_debris/up, +/obj/structure/frame/computer, +/obj/item/stack/sheet/glass{ + amount = 2 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"PM" = ( +/obj/structure/closet/mini_fridge/grimy, +/obj/item/storage/organbox, +/obj/effect/decal/cleanable/blood/gibs/old, +/obj/item/storage/pill_bottle/epinephrine, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Qq" = ( +/obj/structure/microscope, +/obj/structure/broken_flooring/singular, +/obj/effect/spawner/random/trash/food_packaging, +/obj/item/instrument/bilehorn, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"QK" = ( +/obj/effect/decal/cleanable/robot_debris/down, +/obj/item/circular_saw, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Rn" = ( +/obj/structure/closet/crate/cardboard, +/obj/item/book/manual/wiki/surgery, +/obj/item/book/manual/wiki/surgery, +/obj/item/book/manual/wiki/medicine{ + name = "Medical Space Compendium, Volume 637" + }, +/obj/item/book/manual/wiki/medicine{ + name = "Medical Space Compendium, Volume 637" + }, +/obj/item/book/manual/wiki/medicine{ + name = "Medical Space Compendium, Volume 637" + }, +/obj/item/book/manual/wiki/medicine{ + name = "Medical Space Compendium, Volume 637" + }, +/obj/item/stamp/denied, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"RT" = ( +/obj/structure/frame/machine, +/obj/item/shard, +/obj/effect/decal/cleanable/glass, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Tp" = ( +/obj/structure/barricade/wooden, +/obj/structure/barricade/wooden/crude, +/obj/structure/curtain/cloth, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"TM" = ( +/obj/structure/closet/body_bag, +/obj/structure/table/optable, +/obj/effect/decal/cleanable/blood/old, +/obj/effect/mob_spawn/corpse/human{ + brute_damage = 200; + mob_type = /mob/living/carbon/human/species/lizard + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Ua" = ( +/obj/structure/table/reinforced, +/obj/item/analyzer{ + pixel_y = 6 + }, +/obj/item/geiger_counter{ + pixel_x = -8; + pixel_y = -2 + }, +/obj/item/flashlight{ + pixel_x = 4 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Um" = ( +/obj/effect/decal/cleanable/garbage, +/obj/item/lipstick, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"UJ" = ( +/obj/item/storage/box/masks, +/obj/item/storage/box/masks, +/obj/item/storage/box/masks, +/obj/item/clothing/mask/surgical, +/obj/item/reagent_containers/spray/cleaner{ + pixel_x = 7; + pixel_y = 5 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"VL" = ( +/obj/machinery/power/shuttle_engine/propulsion, +/turf/open/space/basic, +/area/space) +"WX" = ( +/obj/machinery/light/warm, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"XC" = ( +/obj/structure/sign/warning, +/turf/closed/wall/r_wall, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"XD" = ( +/obj/structure/sinkframe, +/obj/structure/broken_flooring/pile, +/obj/effect/decal/cleanable/blood/gibs/old, +/obj/item/reagent_containers/cup/rag{ + pixel_x = 6; + pixel_y = -3 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"XR" = ( +/obj/structure/broken_flooring/pile, +/obj/effect/spawner/random/trash/garbage, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Yj" = ( +/obj/structure/reflector/single/mapping{ + rotation_angle = 360 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) +"Zi" = ( +/obj/structure/grille, +/obj/structure/window/reinforced/shuttle, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/medicalwaste) + +(1,1,1) = {" +gh +gh +sU +sU +sU +qC +VL +gh +gh +gh +gh +gh +gh +gh +gh +gh +gh +gh +gh +gh +"} +(2,1,1) = {" +gh +qC +xj +xj +qC +qC +MC +MC +MC +MC +MC +MC +MC +MC +MC +MC +MC +MC +MC +MC +"} +(3,1,1) = {" +Pd +Zi +NJ +vf +Cv +qC +MC +wk +nW +sa +HE +PM +zZ +hu +vM +AB +py +io +TM +XC +"} +(4,1,1) = {" +iw +xj +uo +AG +WX +qC +MC +Dj +XR +Al +QK +CJ +Um +zb +tI +CJ +uG +CJ +Ok +MC +"} +(5,1,1) = {" +kx +xj +hp +LI +kl +qC +MC +Pe +CJ +CJ +CJ +eO +CJ +CJ +Kk +CJ +zj +Go +bv +MC +"} +(6,1,1) = {" +Pd +xj +Zi +qC +mZ +OA +gr +CJ +Ky +iU +Rn +CM +qh +CJ +wh +CJ +CJ +Ky +Yj +MC +"} +(7,1,1) = {" +Pd +Zi +BE +Ua +kl +OA +gr +CJ +CJ +mB +Dv +rB +JW +CJ +EJ +AB +xw +CJ +kp +MC +"} +(8,1,1) = {" +iw +Zi +lT +lT +kl +qC +MC +uR +CJ +CJ +hv +CJ +CJ +CJ +Gp +CJ +pD +CJ +IM +MC +"} +(9,1,1) = {" +Pd +Zi +lT +kl +Od +qC +MC +pR +eO +XD +UJ +RT +Lh +CJ +Hx +CJ +zu +IS +bb +MC +"} +(10,1,1) = {" +kx +Zi +lT +LR +kf +qC +MC +CU +Ll +xH +Qq +hf +LA +CJ +Am +Tp +zn +AU +qX +XC +"} +(11,1,1) = {" +gh +qC +gy +Zi +qC +qC +MC +MC +MC +MC +MC +MC +MC +pu +pu +pu +MC +MC +MC +MC +"} +(12,1,1) = {" +gh +gh +sU +sU +LG +qC +VL +gh +gh +gh +gh +gh +gh +gh +gh +gh +gh +gh +gh +gh +"} diff --git a/_maps/RandomRuins/SpaceRuins/garbagetruck3.dmm b/_maps/RandomRuins/SpaceRuins/garbagetruck3.dmm new file mode 100644 index 0000000000000..45947bb411263 --- /dev/null +++ b/_maps/RandomRuins/SpaceRuins/garbagetruck3.dmm @@ -0,0 +1,1185 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"ac" = ( +/obj/item/trash/semki/healthy, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"ap" = ( +/obj/machinery/power/terminal, +/obj/structure/tank_dispenser/oxygen, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/squat) +"aG" = ( +/obj/item/storage/toolbox/electrical{ + pixel_x = 9; + pixel_y = 8 + }, +/obj/item/storage/toolbox/mechanical{ + pixel_x = -9; + pixel_y = 8 + }, +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/storage/toolbox/mechanical{ + pixel_x = -9; + pixel_y = 2 + }, +/obj/item/stack/rods/ten, +/obj/structure/closet/crate/preopen, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"aI" = ( +/obj/structure/bed/maint, +/obj/item/knife/shiv, +/obj/item/storage/backpack/satchel/leather/withwallet, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"bb" = ( +/obj/item/food/badrecipe/moldy, +/obj/item/tank/internals/plasma/empty{ + pixel_x = -10; + pixel_y = 4 + }, +/obj/item/tank/internals/plasma/empty{ + pixel_y = 4 + }, +/obj/item/popsicle_stick, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"bP" = ( +/obj/item/cigbutt/cigarbutt, +/obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/syringe/contraband/krokodil, +/obj/item/screwdriver, +/obj/effect/decal/cleanable/fuel_pool, +/obj/structure/reagent_dispensers/fueltank/large, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"bR" = ( +/obj/item/bedsheet/rainbow, +/obj/item/cigbutt, +/obj/item/clothing/ears/earmuffs, +/obj/structure/bed/maint, +/obj/effect/decal/cleanable/fuel_pool, +/obj/effect/spawner/random/contraband/permabrig_gear, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"dh" = ( +/obj/machinery/light/warm, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/squat) +"do" = ( +/obj/structure/chair/comfy/shuttle, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/squat) +"dC" = ( +/obj/item/storage/box/mousetraps, +/obj/structure/table/reinforced, +/obj/item/melee/flyswatter, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/squat) +"dF" = ( +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/squat) +"dL" = ( +/obj/item/toy/mecha/marauder, +/obj/structure/closet/cardboard, +/obj/item/toy/plush/snakeplushie, +/obj/item/storage/fancy/cigarettes/cigpack_robust, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"fF" = ( +/obj/item/clothing/suit/caution, +/obj/item/trash/syndi_cakes, +/obj/effect/decal/cleanable/plastic, +/obj/item/t_scanner, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"gq" = ( +/obj/structure/grille, +/obj/structure/window/reinforced/shuttle, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/squat) +"gy" = ( +/obj/structure/window/reinforced/shuttle, +/obj/structure/grille, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/squat) +"hk" = ( +/obj/structure/table/reinforced, +/obj/item/storage/bag/trash{ + pixel_x = -12; + pixel_y = 0 + }, +/obj/item/storage/bag/trash, +/obj/item/storage/bag/trash{ + pixel_x = -6; + pixel_y = 0 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/squat) +"hm" = ( +/obj/item/mecha_parts/chassis/ripley, +/obj/item/mecha_parts/part/ripley_right_leg{ + pixel_x = 4; + pixel_y = -8 + }, +/obj/item/mecha_parts/part/ripley_left_leg{ + pixel_x = -4; + pixel_y = -7 + }, +/obj/item/mecha_parts/part/ripley_torso, +/obj/effect/decal/cleanable/fuel_pool, +/obj/structure/closet/crate/large{ + desc = "A hefty wooden crate with the word \"REJECT\" stamped on it. You'll need a crowbar to get it open." + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"ih" = ( +/obj/item/bedsheet/purple, +/obj/item/clothing/mask/cigarette/space_cigarette, +/obj/structure/bed/maint, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/fuel_pool, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"iU" = ( +/obj/structure/chair/stool, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"jl" = ( +/obj/structure/table/reinforced, +/obj/item/gps/spaceruin{ + pixel_x = 6; + pixel_y = 2 + }, +/obj/item/storage/backpack/industrial{ + pixel_x = -8; + pixel_y = 4 + }, +/obj/item/clothing/suit/hazardvest{ + pixel_x = -8; + pixel_y = -6 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/squat) +"jJ" = ( +/obj/effect/spawner/random/trash/cigbutt, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"jN" = ( +/obj/structure/reagent_dispensers/fueltank, +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/stock_parts/scanning_module, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"jZ" = ( +/obj/machinery/door/airlock/external/glass, +/obj/structure/fans/tiny, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/squat) +"kb" = ( +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/stock_parts/cell/crap/empty, +/obj/effect/decal/cleanable/plastic, +/obj/effect/spawner/random/maintenance/two, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"kR" = ( +/obj/item/tank/internals/oxygen/yellow, +/obj/structure/closet/crate/preopen, +/obj/effect/decal/cleanable/shreds, +/obj/effect/spawner/random/maintenance, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"la" = ( +/obj/structure/lattice, +/obj/structure/grille/broken, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/squat) +"le" = ( +/obj/structure/door_assembly/door_assembly_mhatch, +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/shard, +/obj/item/stack/cable_coil/cut, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"lv" = ( +/obj/item/storage/box/zipties{ + pixel_x = -6; + pixel_y = 3 + }, +/obj/item/storage/box/stockparts/basic{ + pixel_x = 8; + pixel_y = -2 + }, +/obj/item/storage/box/disks{ + pixel_x = -8; + pixel_y = -4 + }, +/obj/structure/closet/crate/large, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"lA" = ( +/obj/item/sticker/toolbox, +/obj/structure/closet/crate/cardboard, +/obj/item/book/manual/wiki/engineering_guide, +/obj/item/book/manual/wiki/engineering_construction, +/obj/item/book/manual/ripley_build_and_repair, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"lE" = ( +/obj/machinery/airalarm{ + pixel_y = 25 + }, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/squat) +"lY" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"mV" = ( +/turf/closed/wall/r_wall, +/area/ruin/space/has_grav/garbagetruck/squat) +"nX" = ( +/obj/structure/closet/crate/engineering/electrical, +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/electronics/airlock, +/obj/item/electronics/airlock, +/obj/item/electronics/airlock, +/obj/item/electronics/airlock, +/obj/item/electronics/airlock, +/obj/item/electronics/airlock, +/obj/item/electronics/airlock, +/obj/item/electronics/airlock, +/obj/item/electronics/airlock, +/obj/item/electronics/airlock, +/obj/item/electronics/firelock, +/obj/item/electronics/firelock, +/obj/item/electronics/firelock, +/obj/item/electronics/firelock, +/obj/item/electronics/firelock, +/obj/item/stack/cable_coil, +/obj/item/stack/cable_coil, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"oD" = ( +/obj/effect/spawner/random/trash/cigbutt, +/obj/item/trash/boritos/purple, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"pd" = ( +/obj/item/stack/rods/ten, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"pk" = ( +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/squat) +"pC" = ( +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/storage/bag/construction, +/obj/item/clothing/shoes/winterboots/ice_boots/eva{ + desc = "A heavy pair of boots with grips applied to the bottom to keep the wearer vertical while walking in freezing conditions. It's clearly been well used."; + name = "ice climbing boots" + }, +/obj/structure/closet/crate/engineering/electrical, +/obj/item/stock_parts/capacitor/adv, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"pM" = ( +/obj/item/lead_pipe, +/obj/structure/door_assembly/door_assembly_mhatch, +/obj/effect/decal/cleanable/glass, +/obj/item/restraints/handcuffs/cable/zipties/used, +/obj/item/shard, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"qF" = ( +/obj/structure/closet/cardboard, +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/pushbroom, +/obj/item/restraints/handcuffs/cable/zipties/used, +/obj/item/toy/brokenradio, +/obj/effect/spawner/random/engineering/tool, +/mob/living/basic/cockroach, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"rq" = ( +/obj/effect/decal/cleanable/fuel_pool, +/obj/effect/decal/cleanable/dirt, +/obj/structure/bed/dogbed, +/turf/open/floor/plating/dumpsterair, +/area/space) +"sb" = ( +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/boxcutter, +/obj/item/boxcutter, +/obj/item/folder/yellow, +/obj/item/geiger_counter, +/obj/item/stack/sticky_tape, +/obj/structure/closet/crate/preopen, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"sf" = ( +/obj/item/burner/fuel{ + pixel_x = -5; + pixel_y = -2 + }, +/obj/effect/decal/cleanable/glass, +/obj/effect/decal/cleanable/ash, +/obj/item/reagent_containers/cup/beaker/plastic{ + pixel_x = -5; + pixel_y = 4 + }, +/obj/structure/table, +/obj/item/reagent_containers/dropper{ + pixel_x = 7; + pixel_y = 0 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"sF" = ( +/obj/structure/table/reinforced, +/obj/item/storage/box/gloves{ + pixel_x = 10; + pixel_y = 8 + }, +/obj/item/storage/box/masks{ + pixel_x = -6; + pixel_y = 8 + }, +/obj/machinery/recharger{ + pixel_y = -10 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/squat) +"tu" = ( +/obj/item/clothing/mask/cigarette/robust, +/obj/structure/closet/emcloset, +/obj/item/clothing/suit/utility/fire/heavy, +/obj/item/clothing/head/utility/hardhat/welding/atmos, +/obj/item/survivalcapsule/bathroom, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"tL" = ( +/obj/structure/reagent_dispensers/fueltank/large, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"ui" = ( +/obj/item/rollingpaper, +/obj/item/book/random{ + pixel_x = 7; + pixel_y = 2 + }, +/obj/item/clothing/gloves/fingerless{ + pixel_x = -8; + pixel_y = 4 + }, +/obj/structure/table, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"un" = ( +/obj/item/food/branrequests, +/obj/item/kitchen/spoon/plastic, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"ut" = ( +/obj/item/clothing/suit/apron/overalls{ + pixel_y = -3 + }, +/obj/effect/decal/cleanable/fuel_pool, +/obj/structure/reagent_dispensers/fueltank/large, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"uW" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/fuel_pool, +/obj/structure/bonfire{ + desc = "Begging to be lit." + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"vq" = ( +/obj/item/shard, +/obj/effect/decal/cleanable/fuel_pool, +/obj/structure/closet/crate/trashcart/filled, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"vI" = ( +/obj/item/clothing/head/beanie/red{ + pixel_x = 4; + pixel_y = 4 + }, +/obj/item/clothing/glasses/regular, +/obj/structure/table, +/obj/item/food/grown/kronkus{ + pixel_x = -5; + pixel_y = 8 + }, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"vJ" = ( +/obj/effect/decal/cleanable/fuel_pool, +/obj/effect/decal/cleanable/molten_object/large, +/obj/structure/broken_flooring/pile, +/obj/item/food/deadmouse/moldy, +/obj/item/stock_parts/water_recycler, +/obj/item/stock_parts/cell/lead, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"vW" = ( +/obj/effect/spawner/random/engineering/material_cheap, +/obj/structure/girder/displaced, +/obj/item/stock_parts/scanning_module, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"xg" = ( +/obj/structure/chair/office, +/obj/item/reagent_containers/cup/mortar, +/obj/item/pestle, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"yo" = ( +/obj/item/clothing/head/cone{ + pixel_x = 8; + pixel_y = 8 + }, +/obj/machinery/light/warm, +/obj/machinery/power/apc{ + cell_type = /obj/item/stock_parts/cell/lead; + locked = 0; + pixel_y = -25; + start_charge = 0 + }, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/squat) +"yF" = ( +/obj/item/trash/spacers_sidekick, +/obj/item/trash/flare, +/obj/effect/decal/cleanable/fuel_pool, +/obj/effect/spawner/random/contraband/narcotics, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"za" = ( +/obj/item/cigbutt/cigarbutt{ + desc = "A manky old cigar butt. A little cobweb is on the end."; + pixel_x = -8; + pixel_y = -2 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"zh" = ( +/obj/item/cigbutt, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"zo" = ( +/obj/effect/decal/cleanable/fuel_pool, +/obj/structure/girder/displaced, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"zz" = ( +/obj/item/cigbutt/cigarbutt, +/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/fuel_pool, +/obj/structure/closet/crate/trashcart, +/obj/item/storage/bag/trash, +/obj/item/clothing/shoes/sneakers/black, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"zC" = ( +/obj/structure/lattice, +/obj/structure/grille, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/squat) +"zN" = ( +/obj/structure/table/reinforced, +/obj/item/gas_filter, +/obj/item/gas_filter, +/obj/item/clothing/mask/gas, +/obj/item/clothing/head/utility/hardhat/orange{ + pixel_y = 8 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/squat) +"zY" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/toy/minimeteor, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"BN" = ( +/obj/item/tank/internals/plasma/full, +/obj/effect/decal/cleanable/fuel_pool, +/obj/structure/reagent_dispensers/fueltank/large, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Cm" = ( +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/mod/module/jetpack, +/obj/item/stock_parts/servo, +/obj/item/stock_parts/subspace/filter, +/obj/structure/fluff/oldturret, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Dq" = ( +/obj/item/match, +/obj/effect/decal/cleanable/fuel_pool, +/obj/effect/spawner/random/entertainment/cigarette, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"DR" = ( +/obj/item/shard/plasma{ + pixel_x = -8; + pixel_y = 4 + }, +/obj/item/trash/semki{ + pixel_x = 6; + pixel_y = 6 + }, +/obj/item/food/badrecipe/moldy{ + pixel_x = -6; + pixel_y = -4 + }, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Er" = ( +/obj/item/clothing/suit/space, +/obj/item/clothing/head/helmet/space, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Fe" = ( +/obj/structure/fermenting_barrel, +/obj/item/reagent_containers/cup/bottle/welding_fuel{ + pixel_x = 9; + pixel_y = -6 + }, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"FD" = ( +/obj/structure/table/reinforced, +/obj/item/analyzer{ + pixel_y = 6 + }, +/obj/item/geiger_counter{ + pixel_x = -8; + pixel_y = -2 + }, +/obj/item/flashlight{ + pixel_x = 4 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/squat) +"FN" = ( +/obj/item/storage/fancy/cigarettes/cigpack_robust{ + pixel_x = -9; + pixel_y = 4 + }, +/obj/item/storage/fancy/cigarettes/cigpack_robust{ + pixel_x = 1; + pixel_y = 4 + }, +/obj/structure/closet/crate/cardboard, +/obj/item/storage/fancy/cigarettes/cigpack_syndicate{ + pixel_x = -9 + }, +/obj/item/storage/fancy/cigarettes/cigpack_shadyjims{ + pixel_x = 1 + }, +/obj/item/gas_filter/damaged{ + pixel_x = -5; + pixel_y = -4 + }, +/obj/item/clothing/mask/gas{ + pixel_x = 1; + pixel_y = -3 + }, +/obj/item/clothing/mask/gas{ + desc = "This gas mask feels different. It's not quite like the others."; + pixel_x = -1; + pixel_y = -3 + }, +/obj/item/clothing/mask/gas{ + pixel_x = -4; + pixel_y = -3 + }, +/obj/item/clothing/mask/gas{ + pixel_x = -7; + pixel_y = -3 + }, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Gn" = ( +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/squat) +"Hk" = ( +/obj/item/food/pizzaslice/moldy/bacteria, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Hn" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/fuel_pool, +/obj/effect/decal/cleanable/oil/slippery, +/obj/item/pen, +/obj/item/stock_parts/subspace/analyzer, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Hw" = ( +/obj/effect/decal/cleanable/fuel_pool, +/obj/effect/spawner/random/trash/cigbutt, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"HD" = ( +/obj/structure/mecha_wreckage/ripley, +/obj/effect/decal/cleanable/fuel_pool, +/obj/effect/decal/cleanable/molten_object, +/obj/item/organ/internal/tongue/robot, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"HN" = ( +/obj/structure/table/reinforced, +/obj/machinery/cell_charger, +/obj/item/stock_parts/cell/lead, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/squat) +"HZ" = ( +/turf/closed/wall/mineral/titanium, +/area/ruin/space/has_grav/garbagetruck/squat) +"Jx" = ( +/obj/structure/chem_separator, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"JL" = ( +/obj/machinery/space_heater/improvised_chem_heater, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"JO" = ( +/obj/item/storage/pill_bottle/stimulant{ + pixel_x = 1; + pixel_y = 3 + }, +/obj/item/storage/pill_bottle/maintenance_pill/full{ + pixel_x = -2; + pixel_y = -2 + }, +/obj/structure/closet/crate/preopen, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/reagent_containers/syringe/contraband/methamphetamine{ + pixel_x = -5; + pixel_y = -7 + }, +/obj/item/reagent_containers/syringe/contraband/krokodil{ + pixel_x = -1; + pixel_y = -2 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"JR" = ( +/obj/effect/decal/cleanable/ash, +/obj/effect/decal/cleanable/oil/streak, +/mob/living/basic/trooper/russian, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"JW" = ( +/obj/machinery/door/poddoor/shutters/preopen, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"JX" = ( +/turf/open/space/basic, +/area/space) +"Ko" = ( +/obj/machinery/computer/terminal{ + content = list("Property of Spinward-Upsilon Sanitation Department. Authorised employees only."); + desc = "A garbage truck's dusty old control console."; + name = "dashboard"; + upperinfo = "Controls locked." + }, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/squat) +"Kq" = ( +/obj/structure/closet/crate, +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/airlock_painter, +/obj/item/pen/screwdriver, +/obj/item/rcd_ammo, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"LV" = ( +/obj/machinery/power/smes, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/squat) +"Ml" = ( +/obj/structure/plasticflaps/opaque, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"MJ" = ( +/obj/structure/lattice/catwalk, +/obj/item/crowbar/large/emergency, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/squat) +"MQ" = ( +/obj/item/stock_parts/cell/crap/empty{ + pixel_x = -4; + pixel_y = 10 + }, +/obj/item/clothing/mask/cigarette/space_cigarette{ + pixel_x = -5; + pixel_y = 7 + }, +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/crowbar/hammer{ + desc = "A large claw hammer. It's been heavily used, as evidenced by the dents and scratches covering its head."; + name = "claw hammer" + }, +/obj/item/storage/fancy/cigarettes/cigpack_cannabis{ + pixel_x = 6; + pixel_y = 2 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Nd" = ( +/obj/item/binoculars, +/obj/item/crowbar/large/old, +/obj/item/tank/jetpack/improvised, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Ol" = ( +/obj/item/plate_shard, +/obj/effect/decal/cleanable/fuel_pool, +/obj/effect/decal/cleanable/oil, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Pz" = ( +/obj/structure/sign/warning, +/turf/closed/wall/r_wall, +/area/ruin/space/has_grav/garbagetruck/squat) +"PE" = ( +/obj/machinery/door/airlock/shuttle, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/squat) +"PH" = ( +/obj/item/bikehorn/rubberducky, +/obj/structure/closet/mini_fridge/grimy, +/obj/item/reagent_containers/cup/soda_cans/grey_bull, +/obj/item/reagent_containers/cup/soda_cans/monkey_energy, +/obj/item/reagent_containers/cup/soda_cans/monkey_energy, +/obj/item/reagent_containers/cup/soda_cans/pwr_game, +/obj/item/reagent_containers/cup/blastoff_ampoule, +/obj/structure/table, +/obj/item/food/drug/moon_rock, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Rw" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"RD" = ( +/obj/effect/decal/cleanable/fuel_pool, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"RP" = ( +/obj/structure/table, +/obj/item/food/drug/moon_rock{ + pixel_x = 7; + pixel_y = 4 + }, +/obj/item/lighter/skull{ + light_color = "#F57247"; + pixel_x = 8; + pixel_y = -3 + }, +/obj/item/weldingtool/largetank{ + light_color = "#F57247"; + max_fuel = 50; + pixel_x = -7; + pixel_y = 3 + }, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Ss" = ( +/obj/item/cigbutt/roach, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"To" = ( +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Tv" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/trash/can/food/beans{ + pixel_x = 8; + pixel_y = -4 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"TD" = ( +/obj/item/food/deadmouse, +/obj/item/trash/candy, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Vw" = ( +/obj/item/rollingpaper{ + pixel_x = 8; + pixel_y = -6 + }, +/obj/item/rollingpaper{ + pixel_x = -2; + pixel_y = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/crate/wooden, +/obj/item/clothing/glasses/night{ + pixel_x = -1; + pixel_y = -2 + }, +/obj/item/melee/roastingstick{ + pixel_x = 11 + }, +/obj/item/flamethrower/full/tank{ + pixel_x = -2; + pixel_y = 4 + }, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"VL" = ( +/obj/machinery/power/shuttle_engine/propulsion, +/turf/open/space/basic, +/area/space) +"WK" = ( +/obj/effect/decal/cleanable/fuel_pool, +/obj/item/clothing/shoes/workboots{ + pixel_x = 7; + pixel_y = 5 + }, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"WV" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Xt" = ( +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Xv" = ( +/obj/item/food/deadmouse, +/obj/item/clothing/shoes/sneakers/red, +/obj/item/clothing/mask/cigarette/carp, +/obj/item/extinguisher/mini, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"XS" = ( +/obj/effect/decal/cleanable/fuel_pool, +/obj/structure/firelock_frame, +/obj/structure/broken_flooring/pile, +/obj/item/reagent_containers/syringe/contraband/methamphetamine, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) +"Ye" = ( +/obj/structure/lattice, +/obj/structure/grille, +/obj/effect/spawner/random/entertainment/plushie, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/squat) +"Zu" = ( +/obj/item/food/candy, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/closet/crate/trashcart, +/obj/item/storage/bag/trash/filled, +/obj/item/trash/champagne_cork, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating/dumpsterair, +/area/ruin/space/has_grav/garbagetruck/squat) + +(1,1,1) = {" +JX +JX +pk +pk +pk +HZ +VL +JX +JX +JX +JX +JX +JX +JX +JX +JX +JX +JX +JX +JX +"} +(2,1,1) = {" +JX +HZ +gy +gy +HZ +HZ +mV +mV +mV +mV +mV +mV +mV +mV +mV +mV +mV +mV +mV +mV +"} +(3,1,1) = {" +la +gq +sF +HN +dC +HZ +mV +bR +ih +un +aI +rq +Fe +lv +pM +tu +hm +pC +fF +Pz +"} +(4,1,1) = {" +Ye +gy +Ko +do +dh +HZ +mV +ut +WK +zh +WV +Tv +za +aG +zo +HD +MQ +qF +Cm +mV +"} +(5,1,1) = {" +zC +gy +jl +zN +dF +HZ +mV +zz +Xt +jJ +Xt +Xt +DR +uW +XS +nX +BN +vJ +vW +mV +"} +(6,1,1) = {" +la +gy +gq +HZ +lE +PE +JW +WV +WV +WV +Xt +To +Hw +Hk +vq +zY +Hn +kb +le +mV +"} +(7,1,1) = {" +la +gq +hk +FD +dF +PE +JW +oD +Xt +JO +RD +To +Xt +TD +pd +JR +Kq +sb +dL +mV +"} +(8,1,1) = {" +Ye +gq +Gn +Gn +dF +HZ +mV +vI +Ss +sf +iU +Xt +Xt +ac +Xt +bb +jN +lA +kR +mV +"} +(9,1,1) = {" +la +gq +Gn +dF +yo +HZ +mV +ui +xg +RP +Jx +lY +JL +tL +Xt +Rw +To +Ol +To +mV +"} +(10,1,1) = {" +zC +gq +Gn +ap +LV +HZ +mV +PH +Xt +FN +Vw +bP +Zu +To +Dq +yF +Nd +Er +Xv +Pz +"} +(11,1,1) = {" +JX +HZ +jZ +gq +HZ +HZ +mV +mV +mV +mV +mV +mV +mV +Ml +Ml +Ml +mV +mV +mV +mV +"} +(12,1,1) = {" +JX +JX +pk +pk +MJ +HZ +VL +JX +JX +JX +JX +JX +JX +JX +JX +JX +JX +JX +JX +JX +"} diff --git a/_maps/RandomRuins/SpaceRuins/garbagetruck4.dmm b/_maps/RandomRuins/SpaceRuins/garbagetruck4.dmm new file mode 100644 index 0000000000000..761990a97d597 --- /dev/null +++ b/_maps/RandomRuins/SpaceRuins/garbagetruck4.dmm @@ -0,0 +1,1147 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aj" = ( +/obj/machinery/power/smes, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/toystore) +"bL" = ( +/obj/structure/table/reinforced, +/obj/item/storage/bag/trash{ + pixel_x = -12; + pixel_y = 0 + }, +/obj/item/storage/bag/trash, +/obj/item/storage/bag/trash{ + pixel_x = -6; + pixel_y = 0 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/toystore) +"bU" = ( +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/toystore) +"cf" = ( +/obj/item/paint_palette, +/obj/item/storage/crayons, +/obj/structure/spider/stickyweb, +/obj/structure/table_frame/wood, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"cg" = ( +/obj/structure/spider/stickyweb, +/obj/item/clothing/under/costume/mummy, +/obj/item/clothing/mask/mummy, +/obj/effect/decal/cleanable/glass, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"cq" = ( +/obj/machinery/light/warm, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/toystore) +"cT" = ( +/obj/item/c_tube, +/obj/effect/spawner/random/trash/garbage, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"dn" = ( +/obj/structure/window/reinforced/shuttle, +/obj/structure/grille, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"dq" = ( +/obj/effect/spawner/random/structure/crate_empty, +/obj/item/trash/candy{ + pixel_x = 7 + }, +/obj/item/lead_pipe{ + pixel_x = -2; + pixel_y = -4 + }, +/obj/item/plate_shard{ + pixel_x = 6; + pixel_y = 0 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"eL" = ( +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/toystore) +"hD" = ( +/obj/structure/mannequin/wood{ + desc = "Oh, so this is a dress-up game now. It makes eye contact." + }, +/obj/item/clothing/shoes/kindle_kicks{ + pixel_y = -10 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"hH" = ( +/obj/structure/spider/solid, +/obj/item/book/manual/wiki/cytology, +/obj/effect/decal/cleanable/plastic, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"hS" = ( +/obj/structure/closet/crate/trashcart/filled, +/obj/item/toy/xmas_cracker, +/obj/item/toy/xmas_cracker, +/obj/item/toy/toy_xeno, +/obj/item/clothing/head/costume/party/festive, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"it" = ( +/obj/item/trash/candle, +/obj/item/food/canned/pine_nuts, +/obj/item/kitchen/fork, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"jD" = ( +/obj/structure/grille, +/obj/structure/window/reinforced/shuttle, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"kj" = ( +/obj/structure/mannequin/plastic, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"kz" = ( +/obj/item/storage/wallet/random, +/obj/item/coin/plastic, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"ld" = ( +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"lg" = ( +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/toystore) +"lm" = ( +/obj/structure/spider/stickyweb, +/obj/structure/spider/sticky, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"mf" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/structure/tank_holder, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"mM" = ( +/obj/structure/spider/stickyweb, +/obj/item/food/badrecipe/moldy, +/obj/item/storage/box/pdas, +/obj/effect/spawner/random/entertainment/money_small, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"ng" = ( +/obj/item/vending_refill/snack, +/obj/item/food/candy, +/obj/structure/broken_flooring/side, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"nM" = ( +/turf/closed/wall/mineral/titanium, +/area/ruin/space/has_grav/garbagetruck/toystore) +"nP" = ( +/obj/structure/bed/maint, +/obj/item/pen/survival, +/obj/item/bedsheet/grey, +/obj/effect/decal/cleanable/shreds, +/obj/effect/spawner/random/bureaucracy/pen, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"pi" = ( +/obj/item/chair/wood, +/obj/item/c_tube, +/obj/effect/decal/cleanable/generic, +/obj/structure/broken_flooring/corner, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"ps" = ( +/obj/effect/spawner/random/trash, +/obj/effect/spawner/random/bureaucracy/paper, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"pA" = ( +/obj/structure/spider/effigy, +/obj/structure/spider/stickyweb, +/obj/item/coin/silver, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"pN" = ( +/obj/structure/closet/crate/cardboard/mothic, +/obj/item/clothing/head/mothcap, +/obj/item/clothing/mask/gas/explorer, +/obj/item/clothing/under/misc/overalls, +/obj/item/clothing/shoes/magboots, +/obj/item/clothing/glasses/meson, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"qX" = ( +/obj/structure/spider/sticky, +/obj/item/food/badrecipe/moldy, +/obj/structure/spider/stickyweb, +/obj/item/food/spidereggs{ + pixel_x = 4; + pixel_y = 6 + }, +/obj/structure/closet/crate/trashcart, +/obj/item/food/spidereggs{ + pixel_x = -4; + pixel_y = 6 + }, +/obj/effect/spawner/random/trash/food_packaging, +/obj/item/food/spidereggs, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"rb" = ( +/obj/structure/sign/warning, +/turf/closed/wall/r_wall, +/area/ruin/space/has_grav/garbagetruck/toystore) +"rc" = ( +/obj/effect/decal/cleanable/oil, +/obj/item/flashlight/flare/torch, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"ri" = ( +/obj/structure/lattice/catwalk, +/obj/item/crowbar/large/emergency, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/toystore) +"rr" = ( +/obj/structure/floodlight_frame, +/obj/effect/spawner/random/decoration/glowstick, +/obj/effect/spawner/random/decoration/glowstick, +/obj/effect/spawner/random/decoration/glowstick, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"rI" = ( +/obj/structure/lattice, +/obj/structure/grille, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/toystore) +"sh" = ( +/obj/item/food/badrecipe/moldy/bacteria, +/obj/effect/decal/cleanable/ants, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"sw" = ( +/obj/effect/decal/cleanable/glass/plastitanium/screws, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/cardboard_cutout, +/obj/item/clothing/neck/tie/horrible, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"sA" = ( +/obj/item/clothing/head/costume/rabbitears, +/obj/item/grown/bananapeel, +/obj/effect/decal/cleanable/garbage, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"sO" = ( +/obj/item/clothing/suit/syndicatefake, +/obj/item/weldingtool/largetank{ + pixel_x = -4; + pixel_y = 2 + }, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"ts" = ( +/obj/structure/spider/solid, +/obj/structure/spider/stickyweb, +/obj/structure/closet/crate/trashcart/filled, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"tQ" = ( +/obj/item/rack_parts, +/obj/structure/spider/stickyweb, +/obj/item/folder/blue{ + pixel_x = -3; + pixel_y = -2 + }, +/obj/item/folder/blue, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"ub" = ( +/obj/structure/filingcabinet, +/obj/structure/spider/stickyweb, +/obj/item/storage/wallet/random, +/obj/item/pen/blue, +/obj/item/paper/fluff/junkmail_redpill, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"uT" = ( +/obj/structure/table/reinforced, +/obj/item/gas_filter, +/obj/item/gas_filter, +/obj/item/clothing/mask/gas, +/obj/item/clothing/head/utility/hardhat/orange{ + pixel_y = 8 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/toystore) +"uX" = ( +/obj/structure/table/reinforced, +/obj/item/gps/spaceruin{ + pixel_x = 6; + pixel_y = 2 + }, +/obj/item/storage/backpack/industrial{ + pixel_x = -8; + pixel_y = 4 + }, +/obj/item/clothing/suit/hazardvest{ + pixel_x = -8; + pixel_y = -6 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/toystore) +"vz" = ( +/obj/structure/frame/computer, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"wo" = ( +/obj/machinery/door/airlock/shuttle, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"wu" = ( +/obj/machinery/airalarm{ + pixel_y = 25 + }, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/toystore) +"ww" = ( +/obj/machinery/door/airlock/external/glass, +/obj/structure/fans/tiny, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"wy" = ( +/obj/item/barcodescanner, +/obj/effect/decal/cleanable/dirt, +/obj/item/cardpack/series_one{ + pixel_x = 2; + pixel_y = 1 + }, +/obj/item/cardpack/series_one{ + pixel_y = 4 + }, +/obj/item/cardpack/series_one{ + pixel_x = -3; + pixel_y = 2 + }, +/obj/item/cardpack/series_one, +/obj/structure/closet/crate/cardboard, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"wE" = ( +/obj/structure/closet/crate/wooden, +/obj/item/toy/figure/wizard{ + pixel_x = 8; + pixel_y = 6 + }, +/obj/item/toy/figure/clown{ + pixel_x = -2; + pixel_y = 6 + }, +/obj/item/toy/figure/secofficer{ + pixel_x = 2; + pixel_y = 2 + }, +/obj/item/toy/figure/secofficer{ + pixel_x = 8; + pixel_y = 2 + }, +/obj/item/toy/figure/secofficer{ + pixel_x = -4; + pixel_y = 2 + }, +/obj/item/toy/figure/dsquad{ + pixel_x = 4; + pixel_y = -1 + }, +/obj/item/toy/figure/dsquad{ + pixel_y = -1 + }, +/obj/item/toy/figure/dsquad{ + pixel_x = -4; + pixel_y = -1 + }, +/obj/item/toy/figure/dsquad{ + pixel_x = -8; + pixel_y = -1 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"wK" = ( +/obj/effect/decal/cleanable/robot_debris/down, +/obj/item/clothing/under/costume/skeleton, +/obj/item/clothing/mask/gas/prop, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"wW" = ( +/obj/structure/spider/stickyweb, +/obj/item/food/badrecipe/moldy, +/obj/item/grown/bananapeel, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"xd" = ( +/obj/effect/decal/cleanable/robot_debris/up, +/obj/effect/decal/cleanable/oil, +/obj/item/melee/skateboard, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"xf" = ( +/obj/structure/door_assembly/door_assembly_wood, +/obj/effect/decal/cleanable/plastic, +/obj/effect/decal/cleanable/oil/slippery, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"xC" = ( +/obj/item/stack/sheet/plastic/five, +/obj/item/stack/sheet/plastic/five, +/obj/structure/mannequin/plastic, +/obj/item/clothing/neck/tie/black, +/obj/effect/decal/cleanable/glass, +/obj/effect/decal/cleanable/plastic, +/obj/item/spear, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"xI" = ( +/obj/structure/reagent_dispensers/watertank, +/obj/effect/decal/cleanable/plastic, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"xQ" = ( +/obj/item/storage/box/mousetraps, +/obj/structure/table/reinforced, +/obj/item/melee/flyswatter, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/toystore) +"xW" = ( +/obj/structure/broken_flooring/pile, +/obj/effect/spawner/random/maintenance, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"yb" = ( +/obj/item/food/canned/tomatoes{ + pixel_x = 3; + pixel_y = 6 + }, +/obj/item/food/canned/tomatoes{ + pixel_x = 5; + pixel_y = 7 + }, +/obj/structure/closet/crate/cardboard/mothic, +/obj/item/food/uncooked_rice{ + pixel_x = 0; + pixel_y = -6 + }, +/obj/item/food/uncooked_rice{ + pixel_x = 2; + pixel_y = -6 + }, +/obj/item/food/uncooked_rice{ + pixel_x = 4; + pixel_y = -6 + }, +/obj/item/food/uncooked_rice{ + pixel_x = 6; + pixel_y = -6 + }, +/obj/item/food/uncooked_rice{ + pixel_x = 8; + pixel_y = -6 + }, +/obj/item/food/cracker, +/obj/item/food/cracker, +/obj/item/food/cracker, +/obj/item/food/cracker, +/obj/item/food/cracker, +/obj/item/food/cracker{ + pixel_x = -2; + pixel_y = -4 + }, +/obj/item/food/cracker{ + pixel_x = -7; + pixel_y = -2 + }, +/obj/item/food/cracker{ + pixel_y = 1 + }, +/obj/item/food/cracker{ + pixel_x = 2; + pixel_y = 1 + }, +/obj/item/food/cracker{ + pixel_y = -2 + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"yP" = ( +/obj/structure/lattice, +/obj/structure/grille, +/obj/effect/spawner/random/entertainment/plushie, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/toystore) +"yS" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"zs" = ( +/obj/machinery/computer/terminal{ + content = list("Property of Spinward-Upsilon Sanitation Department. Authorised employees only."); + desc = "A garbage truck's dusty old control console."; + name = "dashboard"; + upperinfo = "Controls locked." + }, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/toystore) +"AG" = ( +/obj/item/clothing/glasses/blindfold, +/obj/effect/decal/cleanable/plastic, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"AQ" = ( +/obj/item/food/spidereggs, +/obj/effect/mob_spawn/corpse/human{ + brute_damage = 200; + mob_type = /mob/living/carbon/human/species/moth; + outfit = /datum/outfit/abductorcorpse; + oxy_damage = 200 + }, +/obj/structure/spider/cocoon{ + pixel_x = -2; + pixel_y = 4 + }, +/obj/item/mod/control/pre_equipped/standard{ + pixel_x = -6; + pixel_y = 4 + }, +/mob/living/basic/spider/giant/viper, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"BK" = ( +/obj/structure/closet/mini_fridge, +/obj/item/storage/cans/sixsoda, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"BO" = ( +/obj/structure/spider/stickyweb, +/obj/item/stock_parts/water_recycler, +/obj/effect/decal/cleanable/insectguts, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Dm" = ( +/obj/item/trash/cheesie, +/obj/item/shovel, +/obj/item/seeds/nettle, +/obj/item/popsicle_stick, +/obj/item/hatchet/wooden, +/obj/item/cigbutt, +/obj/item/secateurs, +/obj/item/pickaxe/rusted, +/obj/item/boxcutter, +/obj/structure/closet/crate/preopen, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Dv" = ( +/obj/machinery/door/poddoor/shutters/preopen, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"ER" = ( +/obj/structure/chair/comfy/shuttle, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/toystore) +"FM" = ( +/obj/structure/closet/crate/trashcart, +/obj/item/clothing/mask/surgical, +/obj/item/clothing/suit/costume/whitedress, +/obj/structure/broken_flooring/singular, +/obj/item/clothing/head/costume/nursehat, +/obj/item/clothing/neck/stethoscope, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Gt" = ( +/obj/structure/sign/flag/mothic, +/turf/closed/wall/r_wall, +/area/ruin/space/has_grav/garbagetruck/toystore) +"He" = ( +/obj/structure/spider/passage, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Hj" = ( +/obj/structure/lattice, +/obj/structure/grille/broken, +/turf/open/space/basic, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Hv" = ( +/obj/effect/decal/cleanable/glass/plastitanium/screws, +/obj/effect/spawner/random/bureaucracy/paper, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Hy" = ( +/obj/item/toy/xmas_cracker, +/obj/item/kirbyplants/synthetic/plant26, +/obj/item/storage/pill_bottle/probital, +/obj/item/clothing/head/costume/festive, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"HK" = ( +/obj/structure/closet/crate/large, +/obj/item/rwd/loaded, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Ix" = ( +/obj/structure/closet/cardboard, +/obj/item/bodypart/chest/robot, +/obj/item/toy/katana, +/obj/item/toy/plush/snakeplushie, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"IQ" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/broken_flooring/pile, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"IS" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Ja" = ( +/obj/structure/closet/crate/trashcart/filled, +/obj/effect/decal/cleanable/plastic, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/card/cardboard, +/obj/item/broken_bottle, +/obj/item/cardpack/resin, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"JB" = ( +/obj/structure/spider/stickyweb, +/obj/structure/closet/crate/cardboard, +/obj/item/bikehorn/rubberducky, +/obj/item/clothing/glasses/monocle, +/obj/item/clothing/head/hats/tophat{ + desc = "It's a fancy looking hat. Inside is a label with a triangle drawn on it." + }, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"JI" = ( +/obj/item/dice/d10, +/obj/structure/filingcabinet/chestdrawer, +/obj/item/computer_disk/maintenance/modsuit_control, +/obj/item/computer_disk/maintenance/modsuit_control, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"KR" = ( +/obj/item/clothing/head/cone{ + pixel_x = 8; + pixel_y = 8 + }, +/obj/machinery/light/warm, +/obj/machinery/power/apc{ + cell_type = /obj/item/stock_parts/cell/lead; + locked = 0; + pixel_y = -25; + start_charge = 0 + }, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Lm" = ( +/obj/effect/decal/cleanable/garbage, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Lu" = ( +/obj/item/kirbyplants/synthetic/plant27, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Mp" = ( +/obj/structure/table/reinforced, +/obj/machinery/cell_charger, +/obj/item/stock_parts/cell/lead, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/toystore) +"MK" = ( +/obj/structure/filingcabinet/chestdrawer, +/obj/item/mail/junkmail, +/obj/item/healthanalyzer/simple/disease, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"OZ" = ( +/obj/item/trash/candy, +/obj/structure/broken_flooring/pile, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Pn" = ( +/obj/structure/closet/crate/mail, +/obj/item/trash/can, +/obj/item/mail/junkmail, +/obj/item/mail/junkmail, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Pv" = ( +/obj/structure/spider/stickyweb, +/obj/item/kirbyplants/synthetic/plant29, +/obj/item/crowbar/hammer, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"PJ" = ( +/obj/structure/spider/passage, +/obj/effect/spawner/random/mod/maint, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"PU" = ( +/obj/structure/table/reinforced, +/obj/item/storage/box/gloves{ + pixel_x = 10; + pixel_y = 8 + }, +/obj/item/storage/box/masks{ + pixel_x = -6; + pixel_y = 8 + }, +/obj/machinery/recharger{ + pixel_y = -10 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Qe" = ( +/obj/item/hand_labeler, +/obj/item/hand_labeler_refill, +/obj/structure/spider/stickyweb, +/mob/living/basic/spider/giant/hunter/scrawny, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"QD" = ( +/obj/effect/spawner/random/structure/crate_empty, +/obj/effect/spawner/random/entertainment/plushie_delux, +/obj/effect/spawner/random/entertainment/toy, +/obj/item/c_tube{ + pixel_y = -6 + }, +/obj/structure/spider/stickyweb, +/obj/item/toy/sword{ + pixel_y = 4 + }, +/obj/item/toy/sword{ + pixel_y = 8 + }, +/obj/item/kitchen/spoon/plastic, +/obj/effect/spawner/random/entertainment/toy, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Rb" = ( +/obj/item/stack/spacecash/c500, +/obj/item/coin/plastic, +/obj/structure/safe, +/obj/structure/spider/stickyweb, +/obj/item/tank/jetpack/oxygen, +/obj/item/switchblade, +/obj/item/survivalcapsule/bathroom, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Rl" = ( +/obj/item/paper/crumpled, +/obj/item/stock_parts/cell/hyper, +/obj/item/hand_labeler, +/obj/item/hand_labeler_refill, +/obj/item/hand_labeler_refill, +/obj/item/hand_labeler_refill, +/obj/item/hand_labeler_refill, +/obj/item/barcodescanner, +/obj/item/pen, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Sb" = ( +/obj/structure/reagent_dispensers/beerkeg, +/obj/structure/spider/stickyweb, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Sj" = ( +/obj/item/trash/pistachios, +/obj/structure/closet/crate/cardboard/mothic, +/obj/item/storage/fancy/pickles_jar, +/obj/item/food/spaghetti/raw, +/obj/item/food/spaghetti/raw, +/obj/item/food/sustenance_bar/wonka, +/obj/item/food/fueljacks_lunch, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Sk" = ( +/obj/effect/spawner/random/decoration/paint, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"ST" = ( +/obj/machinery/power/terminal, +/obj/structure/tank_dispenser/oxygen, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/toystore) +"TO" = ( +/obj/item/mop, +/obj/item/multitool{ + pixel_x = 8; + pixel_y = -6 + }, +/obj/structure/mop_bucket, +/obj/item/broken_bottle, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"UD" = ( +/obj/structure/closet/preopen, +/obj/item/stack/spacecash/c200, +/obj/item/storage/backpack/satchel, +/obj/item/toy/plush/shark, +/obj/item/instrument/banjo, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"VL" = ( +/obj/machinery/power/shuttle_engine/propulsion, +/turf/open/space/basic, +/area/space) +"Wl" = ( +/obj/structure/plasticflaps/opaque, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"WZ" = ( +/obj/item/paper/fluff/junkmail_generic, +/obj/item/pen/red, +/obj/structure/table_frame/wood, +/obj/item/mod/paint, +/obj/effect/spawner/random/decoration/paint, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Xg" = ( +/obj/structure/spider/stickyweb, +/obj/item/clothing/ears/earmuffs, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Xs" = ( +/obj/structure/spider/passage, +/mob/living/basic/spider/giant/hunter/scrawny, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"XI" = ( +/obj/structure/spider/solid, +/obj/item/food/badrecipe/moldy/bacteria, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"XL" = ( +/obj/item/scooter_frame, +/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/garbage, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Ym" = ( +/obj/structure/table/reinforced, +/obj/item/analyzer{ + pixel_y = 6 + }, +/obj/item/geiger_counter{ + pixel_x = -8; + pixel_y = -2 + }, +/obj/item/flashlight{ + pixel_x = 4 + }, +/turf/open/floor/iron/smooth, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Yr" = ( +/turf/closed/wall/r_wall, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Yz" = ( +/obj/structure/spider/stickyweb, +/obj/structure/tank_holder/extinguisher, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"YR" = ( +/obj/item/food/badrecipe/moldy/bacteria, +/obj/effect/spawner/random/bureaucracy/paper, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) +"Zi" = ( +/turf/open/space/basic, +/area/space) +"ZM" = ( +/obj/item/papercutter, +/obj/item/paper_bin, +/obj/structure/spider/stickyweb, +/obj/structure/spider/spikes, +/obj/structure/table_frame/wood, +/obj/effect/spawner/random/bureaucracy/paper, +/turf/open/floor/plating, +/area/ruin/space/has_grav/garbagetruck/toystore) + +(1,1,1) = {" +Zi +Zi +lg +lg +lg +nM +VL +Zi +Zi +Zi +Zi +Zi +Zi +Zi +Zi +Zi +Zi +Zi +Zi +Zi +"} +(2,1,1) = {" +Zi +nM +dn +dn +nM +nM +Yr +Yr +Yr +Yr +Yr +Yr +Yr +Yr +Yr +Yr +Yr +Yr +Yr +Yr +"} +(3,1,1) = {" +Hj +jD +PU +Mp +xQ +nM +Yr +sw +wy +FM +YR +Qe +cf +ZM +WZ +xC +Ix +dq +TO +rb +"} +(4,1,1) = {" +yP +dn +zs +ER +cq +nM +Yr +ng +pi +OZ +xI +IS +xf +ub +AG +lm +cg +sO +Dm +Yr +"} +(5,1,1) = {" +rI +dn +uX +uT +bU +nM +Yr +mf +xW +rc +Hv +ps +HK +ts +Pv +cT +xd +wK +QD +Yr +"} +(6,1,1) = {" +Hj +dn +jD +nM +wu +wo +Dv +IS +ld +ld +ld +Lu +XL +He +Xs +wW +JB +sA +wE +Yr +"} +(7,1,1) = {" +Hj +jD +bL +Ym +bU +wo +Dv +ld +ld +ld +IS +ld +Sb +Rb +IQ +Yz +PJ +pA +mM +Yr +"} +(8,1,1) = {" +yP +jD +eL +eL +bU +nM +Yr +rr +ld +Sk +ld +ld +Ja +hS +Lm +BO +XI +hH +qX +Yr +"} +(9,1,1) = {" +Hj +jD +eL +bU +KR +nM +Gt +UD +nP +pN +Pn +ld +kj +JI +sh +ld +Xg +AQ +tQ +Yr +"} +(10,1,1) = {" +rI +jD +eL +ST +aj +nM +Yr +BK +it +Sj +yb +yS +vz +MK +kz +ld +Hy +Rl +hD +rb +"} +(11,1,1) = {" +Zi +nM +ww +jD +nM +nM +Yr +Yr +Yr +Yr +Yr +Yr +Yr +Wl +Wl +Wl +Yr +Yr +Yr +Yr +"} +(12,1,1) = {" +Zi +Zi +lg +lg +ri +nM +VL +Zi +Zi +Zi +Zi +Zi +Zi +Zi +Zi +Zi +Zi +Zi +Zi +Zi +"} diff --git a/_maps/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/RandomRuins/SpaceRuins/oldstation.dmm index b872b6bc02d86..b9e918588d596 100644 --- a/_maps/RandomRuins/SpaceRuins/oldstation.dmm +++ b/_maps/RandomRuins/SpaceRuins/oldstation.dmm @@ -2842,9 +2842,7 @@ /area/ruin/space/ancientstation/charlie/hall) "mm" = ( /obj/machinery/power/supermatter_crystal/shard, -/obj/structure/closet/crate/engineering{ - name = "supermatter shard crate" - }, +/obj/structure/closet/crate/radiation, /turf/open/floor/iron/white/textured, /area/ruin/space/ancientstation/delta/proto) "mo" = ( diff --git a/_maps/RandomRuins/SpaceRuins/russian_derelict.dmm b/_maps/RandomRuins/SpaceRuins/russian_derelict.dmm index 65c1413bec84b..e1671448e3486 100644 --- a/_maps/RandomRuins/SpaceRuins/russian_derelict.dmm +++ b/_maps/RandomRuins/SpaceRuins/russian_derelict.dmm @@ -519,6 +519,10 @@ "fU" = ( /turf/open/floor/iron, /area/ruin/space/ks13/ai/corridor) +"gd" = ( +/obj/machinery/portable_atmospherics/canister/plasma, +/turf/open/floor/iron/airless, +/area/ruin/space/ks13/engineering/singulo) "ge" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -741,11 +745,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating/airless, /area/ruin/space/ks13/engineering/singulo) -"jD" = ( -/obj/machinery/light/small/directional/east, -/obj/structure/closet/emcloset, -/turf/open/floor/iron/airless, -/area/ruin/space/ks13/dorms) "jV" = ( /obj/effect/spawner/structure/window/hollow/reinforced/middle, /turf/open/floor/plating/airless, @@ -3625,15 +3624,6 @@ /obj/structure/cable, /turf/open/floor/plating/airless, /area/ruin/space/ks13/security/cell) -"Cd" = ( -/obj/machinery/light/small/directional/west, -/obj/structure/table_frame, -/obj/item/wallframe/apc{ - pixel_x = -5; - pixel_y = 9 - }, -/turf/open/floor/iron/airless, -/area/ruin/space/ks13/engineering/tech_storage) "Ce" = ( /obj/effect/mapping_helpers/burnt_floor, /obj/machinery/airalarm/directional/north, @@ -4075,10 +4065,6 @@ }, /turf/open/floor/plating/airless, /area/ruin/space/ks13/science/rnd) -"EC" = ( -/obj/machinery/portable_atmospherics/canister/plasma, -/turf/open/floor/iron/airless, -/area/ruin/space/ks13/engineering/singulo) "ED" = ( /obj/machinery/door/airlock/maintenance{ name = "Atmospherics Access" @@ -4248,11 +4234,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/airless, /area/ruin/space/ks13/hallway/aft) -"Fy" = ( -/obj/machinery/light/small/directional/west, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/iron/airless, -/area/ruin/space/ks13/engineering/singulo) "FB" = ( /obj/machinery/light/small/directional/west, /obj/structure/closet, @@ -4549,6 +4530,13 @@ }, /turf/open/floor/plating/airless, /area/ruin/space/ks13/command/bridge) +"GW" = ( +/obj/item/circuitboard/machine/smes, +/obj/structure/table, +/obj/effect/spawner/random/maintenance, +/obj/effect/mapping_helpers/burnt_floor, +/turf/open/floor/iron/airless, +/area/ruin/space/ks13/engineering/secure_storage) "GY" = ( /obj/structure/cable, /turf/open/floor/iron/chapel{ @@ -4888,6 +4876,10 @@ /obj/structure/cable, /turf/open/floor/plating/airless, /area/ruin/space/ks13/engineering/singulo) +"IZ" = ( +/obj/effect/mapping_helpers/burnt_floor, +/turf/open/floor/iron/airless, +/area/ruin/space/ks13/engineering/singulo) "Jc" = ( /obj/effect/mapping_helpers/broken_floor, /obj/effect/mapping_helpers/broken_floor, @@ -4930,11 +4922,6 @@ /obj/item/wallframe/firealarm, /turf/open/floor/iron/airless, /area/ruin/space/ks13/engineering/atmos) -"Jm" = ( -/obj/machinery/light/small/directional/east, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/plating/airless, -/area/ruin/space/ks13/engineering/singulo) "Jp" = ( /obj/effect/spawner/structure/window/hollow/reinforced/middle{ dir = 4 @@ -6061,14 +6048,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/ruin/space/ks13/security/court) -"Ps" = ( -/obj/machinery/light/small/directional/east, -/obj/item/circuitboard/machine/smes, -/obj/structure/table, -/obj/effect/spawner/random/maintenance, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/iron/airless, -/area/ruin/space/ks13/engineering/secure_storage) "Pt" = ( /obj/structure/cable, /obj/effect/mapping_helpers/broken_floor, @@ -6731,6 +6710,10 @@ /obj/structure/chair, /turf/open/floor/iron/airless, /area/ruin/space/ks13/security/court_hall) +"SI" = ( +/obj/structure/closet/emcloset, +/turf/open/floor/iron/airless, +/area/ruin/space/ks13/dorms) "SJ" = ( /obj/structure/frame/computer{ anchored = 1; @@ -7596,6 +7579,15 @@ "Xa" = ( /turf/open/floor/plating/airless, /area/ruin/space/ks13/ai/corridor) +"Xb" = ( +/obj/machinery/light/small/directional/west, +/obj/structure/table_frame, +/obj/item/wallframe/apc{ + pixel_x = -5; + pixel_y = 9 + }, +/turf/open/floor/iron/airless, +/area/ruin/space/ks13/engineering/tech_storage) "Xd" = ( /obj/structure/closet/crate/bin, /obj/effect/decal/cleanable/dirt, @@ -9601,7 +9593,7 @@ Fq yq rm uf -jD +SI oU sm wc @@ -10939,7 +10931,7 @@ rk QG QG Xt -Cd +Xb DT QG QG @@ -11381,7 +11373,7 @@ rk rk sU sU -EC +gd CX PI PI @@ -11726,7 +11718,7 @@ PI Ex pi FI -Fy +IZ FI FI zv @@ -12856,7 +12848,7 @@ fg Jc gB PI -Jm +zv zv zv HX @@ -13651,7 +13643,7 @@ rk rr rr ab -Ps +GW DL rr rr diff --git a/_maps/map_files/Basketball/ash_gladiators.dmm b/_maps/map_files/Basketball/ash_gladiators.dmm index 3a8c74b42013e..75315e028a83c 100644 --- a/_maps/map_files/Basketball/ash_gladiators.dmm +++ b/_maps/map_files/Basketball/ash_gladiators.dmm @@ -132,7 +132,7 @@ /turf/open/floor/fakebasalt, /area/centcom/basketball) "ie" = ( -/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen, +/mob/living/basic/mining/gutlunch/warrior, /turf/open/floor/fakebasalt, /area/centcom/basketball) "ix" = ( @@ -609,7 +609,7 @@ /turf/open/lava/smooth/basketball, /area/centcom/basketball) "Fy" = ( -/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck, +/mob/living/basic/mining/gutlunch/milk, /turf/open/floor/fakebasalt, /area/centcom/basketball) "FS" = ( diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 5ed67062985d7..7e9264079620e 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -487,6 +487,9 @@ }, /obj/effect/turf_decal/trimline/yellow/line, /obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold/cyan/visible{ + dir = 1 + }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "ajG" = ( @@ -2017,7 +2020,7 @@ /area/station/science/ordnance/bomb) "aPG" = ( /obj/effect/spawner/structure/window/reinforced/plasma, -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ +/obj/machinery/atmospherics/pipe/smart/simple/pink/visible{ dir = 5 }, /turf/open/floor/plating, @@ -2058,7 +2061,7 @@ /turf/open/floor/iron/dark/small, /area/station/security/checkpoint/customs) "aQn" = ( -/obj/machinery/atmospherics/pipe/smart/manifold/cyan/visible, +/obj/machinery/atmospherics/pipe/smart/manifold/pink/visible, /turf/closed/wall/mineral/titanium/nodiagonal, /area/station/engineering/supermatter) "aQr" = ( @@ -2077,7 +2080,7 @@ /area/station/engineering/engine_smes) "aQB" = ( /obj/machinery/meter, -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ +/obj/machinery/atmospherics/pipe/smart/simple/pink/visible{ dir = 9 }, /turf/closed/wall/mineral/titanium/nodiagonal, @@ -2305,6 +2308,9 @@ dir = 1 }, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold/cyan/visible{ + dir = 1 + }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "aTG" = ( @@ -2323,10 +2329,16 @@ /obj/effect/turf_decal/stripes/line{ dir = 5 }, +/obj/machinery/atmospherics/pipe/smart/manifold/cyan/visible{ + dir = 1 + }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "aTW" = ( /obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ + dir = 9 + }, /turf/open/floor/iron/dark, /area/station/engineering/supermatter/room) "aUA" = ( @@ -2341,6 +2353,9 @@ }, /obj/effect/turf_decal/trimline/yellow/arrow_cw, /obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ + dir = 4 + }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "aVj" = ( @@ -2349,9 +2364,11 @@ }, /obj/effect/turf_decal/trimline/yellow/corner, /obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible, /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/engineering/tracking_beacon, +/obj/machinery/atmospherics/pipe/smart/manifold/cyan/visible{ + dir = 4 + }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "aVq" = ( @@ -2668,9 +2685,6 @@ dir = 4 }, /obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ - dir = 8 - }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "bcv" = ( @@ -2682,10 +2696,10 @@ /area/station/medical/medbay/lobby) "bcK" = ( /obj/effect/turf_decal/stripes/corner, -/obj/machinery/atmospherics/pipe/smart/manifold/cyan/visible{ +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ dir = 1 }, -/obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "bcR" = ( @@ -3275,8 +3289,8 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/machinery/atmospherics/components/trinary/filter/critical{ - dir = 4 +/obj/machinery/atmospherics/components/trinary/filter/flipped/critical{ + dir = 8 }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) @@ -4473,8 +4487,10 @@ dir = 4 }, /obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold/cyan/visible, /obj/machinery/meter, +/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ + dir = 5 + }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "bJZ" = ( @@ -5905,8 +5921,12 @@ /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "engine" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/iron/smooth, -/area/station/engineering/supermatter) +/area/station/engineering/supermatter/room) "coJ" = ( /obj/structure/chair/stool/directional/east, /obj/effect/decal/cleanable/dirt, @@ -7850,8 +7870,8 @@ /obj/structure/sink/kitchen/directional/east, /obj/machinery/airalarm/directional/south, /obj/machinery/button/door/directional/west{ - pixel_y = 8; - id = "custodialshutters" + id = "custodialshutters"; + pixel_y = 8 }, /turf/open/floor/iron/white/small, /area/station/service/janitor) @@ -8475,7 +8495,7 @@ dir = 6 }, /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ - dir = 9 + dir = 4 }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) @@ -9165,10 +9185,11 @@ /turf/open/floor/iron/smooth, /area/station/maintenance/disposal/incinerator) "dyH" = ( -/obj/machinery/atmospherics/components/trinary/filter/critical{ - dir = 4 - }, /obj/effect/landmark/start/station_engineer, +/obj/machinery/atmospherics/components/trinary/filter/flipped/critical{ + dir = 8; + filter_type = list(/datum/gas/nitrogen) + }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "dyO" = ( @@ -9863,6 +9884,13 @@ /obj/item/clothing/glasses/meson, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) +"dLE" = ( +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ + dir = 10 + }, +/turf/open/floor/iron/dark, +/area/station/engineering/supermatter/room) "dLQ" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -10724,8 +10752,8 @@ /area/station/security/prison/shower) "dZT" = ( /obj/machinery/button/transport/tram/directional/south{ - specific_transport_id = "bird_2"; - id = 2 + id = 2; + specific_transport_id = "bird_2" }, /turf/open/floor/iron, /area/station/maintenance/department/medical/central) @@ -16771,8 +16799,12 @@ /obj/machinery/atmospherics/pipe/smart/simple/purple/visible, /obj/machinery/airalarm/directional/east, /obj/effect/mapping_helpers/airalarm/mixingchamber_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "ordnancefreezer" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/iron/dark, -/area/station/science/ordnance/freezerchamber) +/area/station/science/ordnance) "gfE" = ( /obj/effect/turf_decal/siding/red{ dir = 8 @@ -18758,6 +18790,9 @@ }, /obj/effect/turf_decal/trimline/yellow/corner, /obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ + dir = 8 + }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "gPN" = ( @@ -20010,8 +20045,8 @@ pixel_y = 11 }, /obj/item/mod/module/signlang_radio{ - pixel_y = 2; - pixel_x = -2 + pixel_x = -2; + pixel_y = 2 }, /turf/open/floor/iron/small, /area/station/security/office) @@ -29105,7 +29140,9 @@ /area/station/maintenance/hallway/abandoned_recreation) "kvh" = ( /obj/effect/turf_decal/stripes/line, -/obj/machinery/atmospherics/pipe/smart/manifold/scrubbers/visible, +/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ + dir = 4 + }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "kvl" = ( @@ -30572,6 +30609,9 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ + dir = 6 + }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "kYQ" = ( @@ -33135,9 +33175,6 @@ /area/station/maintenance/hallway/abandoned_command) "lOh" = ( /obj/effect/turf_decal/stripes/line, -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ - dir = 8 - }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "lOi" = ( @@ -36000,8 +36037,8 @@ "mNG" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/button/transport/tram/directional/south{ - specific_transport_id = "bird_2"; - id = 1 + id = 1; + specific_transport_id = "bird_2" }, /turf/open/floor/iron, /area/station/maintenance/port/aft) @@ -40927,6 +40964,7 @@ /obj/effect/turf_decal/stripes/white/line{ dir = 4 }, +/obj/machinery/air_sensor/engine_chamber, /turf/open/floor/engine, /area/station/engineering/supermatter) "oFf" = ( @@ -42867,10 +42905,10 @@ /turf/open/floor/iron/textured_large, /area/station/security/checkpoint/escape) "poI" = ( -/obj/machinery/atmospherics/components/trinary/filter/critical{ - dir = 4 - }, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/trinary/filter/flipped/critical{ + dir = 8 + }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "poM" = ( @@ -43855,10 +43893,12 @@ /area/station/medical/paramedic) "pEu" = ( /obj/effect/turf_decal/stripes/line, -/obj/machinery/atmospherics/pipe/smart/manifold/scrubbers/visible, /obj/effect/decal/cleanable/dirt, /obj/machinery/meter, /obj/machinery/light/directional/south, +/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ + dir = 4 + }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "pEy" = ( @@ -46372,7 +46412,7 @@ /turf/open/floor/iron/grimy, /area/station/service/theater) "qrP" = ( -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ +/obj/machinery/atmospherics/pipe/smart/simple/pink/visible{ dir = 6 }, /turf/closed/wall/mineral/titanium/nodiagonal, @@ -46813,8 +46853,8 @@ "qzp" = ( /obj/structure/window/reinforced/spawner/directional/west, /obj/machinery/button/transport/tram/directional/north{ - specific_transport_id = "bird_1"; - id = 1 + id = 1; + specific_transport_id = "bird_1" }, /obj/machinery/transport/destination_sign/indicator/directional/north, /turf/open/floor/noslip, @@ -49876,8 +49916,8 @@ /obj/structure/table, /obj/machinery/airalarm/directional/south, /obj/item/storage/box/bandages{ - pixel_y = 6; - pixel_x = -6 + pixel_x = -6; + pixel_y = 6 }, /obj/item/clipboard{ pixel_x = 4; @@ -56708,8 +56748,8 @@ "tGv" = ( /obj/structure/window/reinforced/spawner/directional/west, /obj/machinery/button/transport/tram/directional/north{ - specific_transport_id = "bird_1"; - id = 2 + id = 2; + specific_transport_id = "bird_1" }, /obj/machinery/transport/destination_sign/indicator/directional/north, /turf/open/floor/noslip, @@ -59927,11 +59967,6 @@ }, /turf/open/floor/iron/showroomfloor, /area/station/commons/toilet/auxiliary) -"uJZ" = ( -/obj/structure/window/reinforced/shuttle, -/obj/structure/window/reinforced/shuttle, -/turf/open/floor/plating, -/area/station/commons/fitness/recreation/entertainment) "uKl" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -61666,6 +61701,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/machinery/camera/autoname/directional/north, /obj/machinery/light/small/directional/north, +/obj/vehicle/sealed/mecha/ripley/paddy/preset, /turf/open/floor/iron, /area/station/security/tram) "vmX" = ( @@ -63659,6 +63695,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold/purple/visible{ dir = 4 }, +/obj/machinery/air_sensor/ordnance_freezer_chamber, /turf/open/floor/engine/vacuum, /area/station/science/ordnance/freezerchamber) "vTm" = ( @@ -66714,18 +66751,9 @@ /turf/open/floor/iron/dark, /area/station/security/interrogation) "wPf" = ( -/obj/structure/cable, -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/door/poddoor/preopen{ - id = "hop"; - name = "Privacy Shutters" - }, -/obj/machinery/door/poddoor/preopen{ - id = "hop"; - name = "Privacy Shutters" - }, -/turf/open/floor/plating, -/area/station/command/heads_quarters/hop) +/obj/item/clothing/glasses/blindfold, +/turf/open/space/basic, +/area/space) "wPh" = ( /obj/structure/disposalpipe/trunk{ dir = 8 @@ -66929,8 +66957,8 @@ /obj/item/radio/intercom/directional/south, /obj/structure/extinguisher_cabinet/directional/west, /obj/item/storage/box/bandages{ - pixel_y = 6; - pixel_x = 4 + pixel_x = 4; + pixel_y = 6 }, /obj/item/stack/medical/gauze{ pixel_x = -2; @@ -68543,8 +68571,12 @@ /obj/effect/decal/cleanable/dirt, /obj/machinery/airalarm/directional/east, /obj/effect/mapping_helpers/airalarm/mixingchamber_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "ordnanceburn" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/iron/dark, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "xoa" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -82396,8 +82428,8 @@ geQ aRR pbt aPG -aTW bAq +dLE aTW bhc bng @@ -95296,7 +95328,7 @@ njA lqt cpT xQv -wPf +xQw mvT vrn ncL @@ -109933,7 +109965,7 @@ tIE aJN aJN aJN -uJZ +aJN aJN doX doX @@ -132052,7 +132084,7 @@ dDB dDB dDB dDB -dDB +wPf dDB dDB dDB diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index b02a5e7d770e8..bb4f8c4c16b49 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -1290,6 +1290,14 @@ }, /turf/open/floor/iron, /area/station/maintenance/port/aft) +"apf" = ( +/obj/machinery/mech_bay_recharge_port{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "apu" = ( /obj/machinery/holopad, /obj/effect/turf_decal/bot, @@ -4073,6 +4081,21 @@ /obj/effect/spawner/structure/window/reinforced/plasma, /turf/open/floor/plating, /area/station/engineering/main) +"aZj" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/obj/structure/table/reinforced, +/obj/item/clothing/glasses/welding, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/item/weldingtool/empty{ + pixel_y = 8; + pixel_x = 9 + }, +/obj/machinery/power/apc/auto_name/directional/south, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "aZo" = ( /obj/structure/table/reinforced, /obj/item/electronics/airalarm, @@ -7404,12 +7427,6 @@ /obj/effect/turf_decal/trimline/purple/filled/warning, /turf/open/floor/iron/white, /area/station/science/lab) -"bMw" = ( -/obj/structure/window/reinforced/spawner/directional/north, -/obj/structure/window/reinforced/spawner/directional/west, -/obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, -/area/space/nearstation) "bMB" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -22117,6 +22134,13 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron, /area/station/cargo/miningoffice) +"fvD" = ( +/obj/effect/turf_decal/trimline/dark_red/filled/line{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "fvE" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/engine, @@ -25042,6 +25066,11 @@ /obj/effect/turf_decal/siding/white, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) +"ggW" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable, +/turf/open/floor/plating, +/area/station/security/lockers) "gho" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -25287,6 +25316,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/grimy, /area/station/tcommsat/computer) +"gkt" = ( +/obj/effect/turf_decal/caution/stand_clear, +/obj/effect/turf_decal/box, +/obj/machinery/door/poddoor/shutters{ + dir = 8; + id = "secmechbay"; + name = "Security Mech Bay Shutters" + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "gku" = ( /obj/machinery/meter, /obj/machinery/door/window/right/directional/west, @@ -26822,6 +26861,19 @@ /obj/effect/turf_decal/tile/neutral/half/contrasted, /turf/open/floor/iron, /area/station/commons/dorms) +"gCa" = ( +/obj/effect/turf_decal/caution/stand_clear, +/obj/effect/turf_decal/box, +/obj/machinery/door/poddoor/shutters{ + dir = 8; + id = "secmechbay"; + name = "Security Mech Bay Shutters" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "gCn" = ( /obj/structure/sign/warning/electric_shock/directional/east, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -30408,6 +30460,20 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/entry) +"hyR" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 5 + }, +/obj/machinery/vending/wardrobe/sec_wardrobe, +/obj/machinery/button/door/directional/east{ + name = "Security Mech Garage Door Controls"; + id = "secmechbay"; + req_access = list("security") + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/security/lockers) "hza" = ( /obj/effect/turf_decal/tile/yellow{ dir = 8 @@ -31427,6 +31493,11 @@ }, /turf/open/floor/iron, /area/station/engineering/main) +"hOk" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/security/lockers) "hOw" = ( /obj/structure/chair/office{ dir = 4 @@ -34916,6 +34987,12 @@ /obj/machinery/light/floor, /turf/open/floor/iron/dark, /area/station/command/bridge) +"iGF" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/visible/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/green/visible/layer4, +/obj/machinery/air_sensor/engine_chamber, +/turf/open/floor/engine, +/area/station/engineering/supermatter) "iGI" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/maintenance_hatch{ @@ -34967,6 +35044,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/security/holding_cell) +"iHn" = ( +/obj/machinery/computer/mech_bay_power_console{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "iHq" = ( /obj/effect/turf_decal/trimline/neutral/warning{ dir = 10 @@ -36150,14 +36235,6 @@ /obj/effect/mapping_helpers/airlock/access/all/security/general, /turf/open/floor/iron, /area/station/security/checkpoint/escape) -"iXE" = ( -/obj/structure/window/reinforced/spawner/directional/east, -/obj/structure/window/reinforced/spawner/directional/east, -/obj/structure/window/reinforced/spawner/directional/west, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/station/ai_monitored/aisat/exterior) "iXM" = ( /obj/structure/cable, /obj/item/kirbyplants/random, @@ -37079,6 +37156,7 @@ /obj/effect/turf_decal/trimline/red/filled/warning{ dir = 1 }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/lockers) "jhs" = ( @@ -40136,8 +40214,8 @@ /obj/machinery/newscaster/directional/north, /obj/effect/turf_decal/siding/dark_red, /obj/item/storage/box/bandages{ - pixel_y = 6; - pixel_x = -6 + pixel_x = -6; + pixel_y = 6 }, /obj/item/reagent_containers/cup/bottle/morphine, /obj/item/reagent_containers/syringe, @@ -41701,6 +41779,17 @@ /obj/effect/turf_decal/tile/blue/opposingcorners, /turf/open/floor/iron/white, /area/station/medical/storage) +"knp" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/table/reinforced, +/obj/item/cigbutt/cigarbutt, +/obj/item/stack/cable_coil{ + pixel_x = -10; + pixel_y = 7 + }, +/obj/machinery/airalarm/directional/south, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "knu" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/green{ @@ -46329,6 +46418,7 @@ dir = 1 }, /obj/machinery/light/directional/north, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/lockers) "lyx" = ( @@ -47833,6 +47923,8 @@ /obj/effect/turf_decal/trimline/red/filled/line{ dir = 4 }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/security/lockers) "lPM" = ( @@ -48608,11 +48700,6 @@ dir = 4 }, /area/station/hallway/secondary/entry) -"mcF" = ( -/obj/structure/window/reinforced/spawner/directional/west, -/obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, -/area/space/nearstation) "mcG" = ( /obj/machinery/button/door/directional/east{ id = "Dorm6"; @@ -48692,6 +48779,8 @@ /obj/effect/turf_decal/trimline/red/filled/warning{ dir = 1 }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/security/lockers) "mdB" = ( @@ -51892,11 +51981,6 @@ "mTA" = ( /turf/closed/wall/r_wall, /area/station/security/holding_cell) -"mTB" = ( -/obj/structure/window/reinforced/spawner/directional/north, -/obj/structure/window/reinforced/spawner/directional/north, -/turf/open/space, -/area/space/nearstation) "mTT" = ( /obj/machinery/holopad, /obj/structure/cable, @@ -53568,7 +53652,12 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/green/visible, /obj/machinery/atmospherics/pipe/smart/manifold4w/green/visible/layer4, -/obj/structure/sign/warning/secure_area/directional/west, +/obj/machinery/airalarm/directional/west, +/obj/effect/mapping_helpers/airalarm/engine_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "engine" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/iron, /area/station/engineering/supermatter/room) "nsd" = ( @@ -54534,6 +54623,9 @@ /obj/structure/sign/warning/electric_shock/directional/east, /turf/open/space/basic, /area/space) +"nEZ" = ( +/turf/closed/wall/r_wall, +/area/station/security/mechbay) "nFb" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/landmark/generic_maintenance_landmark, @@ -57753,8 +57845,12 @@ }, /obj/machinery/airalarm/directional/west, /obj/effect/mapping_helpers/airalarm/mixingchamber_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "ordnanceburn" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/iron/dark, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "owY" = ( /obj/structure/table/reinforced, /obj/item/stack/sheet/iron{ @@ -60366,6 +60462,23 @@ /obj/machinery/newscaster/directional/south, /turf/open/floor/iron, /area/station/engineering/supermatter/room) +"pgZ" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/button/door/directional/north{ + id = "secmechbay"; + name = "Security Mech Garage Door Controls"; + req_access = list("security") + }, +/obj/effect/turf_decal/trimline/dark_red/filled/line{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "phn" = ( /obj/structure/cable, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ @@ -60459,6 +60572,7 @@ /obj/effect/turf_decal/trimline/red/filled/line{ dir = 1 }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/lockers) "phX" = ( @@ -70897,8 +71011,8 @@ dir = 1 }, /obj/item/storage/box/bandages{ - pixel_y = 6; - pixel_x = 4 + pixel_x = 4; + pixel_y = 6 }, /obj/item/storage/toolbox/mechanical, /obj/item/storage/belt/utility, @@ -71224,6 +71338,14 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/science/research) +"rPb" = ( +/obj/machinery/light/directional/north, +/obj/effect/turf_decal/trimline/dark_red/filled/line{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "rPc" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -71858,8 +71980,6 @@ /turf/open/floor/iron/white, /area/station/science/research) "rVM" = ( -/obj/machinery/airalarm/directional/north, -/obj/effect/mapping_helpers/airalarm/engine_access, /turf/open/floor/engine, /area/station/engineering/supermatter) "rVX" = ( @@ -76336,6 +76456,7 @@ /obj/effect/turf_decal/trimline/red/filled/line{ dir = 1 }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/lockers) "tch" = ( @@ -76612,12 +76733,6 @@ /obj/effect/turf_decal/tile/blue, /turf/open/floor/iron/white, /area/station/medical/paramedic) -"tfO" = ( -/obj/structure/window/reinforced/spawner/directional/north, -/obj/structure/window/reinforced/spawner/directional/north, -/obj/structure/window/reinforced/spawner/directional/east, -/turf/open/space, -/area/space/nearstation) "tgl" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -80447,9 +80562,11 @@ }, /area/station/service/chapel) "udb" = ( -/obj/effect/spawner/structure/window/reinforced, +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 6 + }, /obj/structure/cable, -/turf/open/floor/plating, +/turf/open/floor/iron, /area/station/security/lockers) "udd" = ( /obj/structure/cable, @@ -82853,6 +82970,17 @@ /obj/structure/cable, /turf/open/floor/circuit/telecomms/mainframe, /area/station/tcommsat/server) +"uHu" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/dark_red/filled/line, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "uHE" = ( /obj/structure/table/wood/poker, /obj/effect/decal/cleanable/dirt, @@ -84127,8 +84255,12 @@ }, /obj/machinery/airalarm/directional/east, /obj/effect/mapping_helpers/airalarm/mixingchamber_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "ordnancefreezer" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/iron/dark, -/area/station/science/ordnance/freezerchamber) +/area/station/science/ordnance) "uXU" = ( /obj/structure/disposaloutlet{ dir = 8 @@ -85401,6 +85533,13 @@ }, /turf/open/floor/iron, /area/station/command/heads_quarters/cmo) +"vpI" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 8 + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "vpJ" = ( /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -86532,10 +86671,7 @@ /area/station/construction/mining/aux_base) "vCQ" = ( /obj/machinery/newscaster/directional/south, -/obj/machinery/vending/wardrobe/sec_wardrobe, -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 6 - }, +/obj/effect/turf_decal/trimline/red/filled/line, /turf/open/floor/iron, /area/station/security/lockers) "vCU" = ( @@ -87731,9 +87867,9 @@ dir = 4 }, /obj/machinery/door/window/left/directional/west{ + dir = 4; name = "Pharmacy Desk"; - req_access = list("pharmacy"); - dir = 4 + req_access = list("pharmacy") }, /turf/open/floor/iron/dark, /area/station/medical/pharmacy) @@ -88060,8 +88196,10 @@ /area/station/solars/port/fore) "vYw" = ( /obj/effect/turf_decal/trimline/red/filled/line{ - dir = 5 + dir = 1 }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/security/lockers) "vYG" = ( @@ -93396,6 +93534,10 @@ /obj/machinery/duct, /turf/open/floor/iron/white, /area/station/medical/virology) +"xqp" = ( +/obj/vehicle/sealed/mecha/ripley/paddy/preset, +/turf/open/floor/iron/recharge_floor, +/area/station/security/mechbay) "xqM" = ( /obj/effect/turf_decal/stripes/line{ dir = 10 @@ -96111,6 +96253,12 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/command/heads_quarters/qm) +"xZP" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/reagent_dispensers/fueltank, +/obj/machinery/camera/directional/south, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "yah" = ( /obj/machinery/computer/bank_machine, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -103262,7 +103410,7 @@ nOy smV smV nOy -mcF +smV aaa bPC bRz @@ -103273,7 +103421,7 @@ caa bPC pYJ ePZ -tfO +nCB cVr bAU cVr @@ -107385,7 +107533,7 @@ pGJ bPC pYJ ePZ -bMw +qpQ smV aOl smV @@ -107628,7 +107776,7 @@ pSa chU chU chU -iXE +chU chU chU iIm @@ -108413,7 +108561,7 @@ chU chU chU aaQ -mTB +pzp qYo qYo qYo @@ -118444,7 +118592,7 @@ aVW lbl sHT msB -kXR +iGF owf fUY jjw @@ -151074,7 +151222,7 @@ dwU wtB qBw vYw -lPH +hOk vCQ hEF hEF @@ -151330,10 +151478,10 @@ teo pKD pbN bLs -hEF -udb +hyR +lPH udb -hEF +ggW aad aad efQ @@ -151587,11 +151735,11 @@ lIy uro bLs bLs -aaa -aad -aaa -aKU -aaa +nEZ +gCa +gkt +nEZ +nEZ aad aaa aaa @@ -151844,11 +151992,11 @@ bLs bLs bLs ptN -efQ -qYo -efQ -efQ -qYo +nEZ +pgZ +uHu +aZj +nEZ qYo efQ qYo @@ -152101,11 +152249,11 @@ mfO aaa aaa aaa -aaa -qYo -aaa -aaa -aaa +nEZ +rPb +fvD +knp +nEZ qYo aaa aaa @@ -152358,12 +152506,12 @@ efQ efQ efQ efQ +nEZ +xqp +vpI +xZP +nEZ qYo -efQ -efQ -efQ -qYo -efQ lvw qYo efQ @@ -152615,14 +152763,14 @@ qYo aaa aaa qYo +nEZ +apf +iHn +nEZ +nEZ qYo aaa aaa -aaa -aaa -aaa -aaa -aaa efQ aaa uKw @@ -152872,12 +153020,12 @@ efQ efQ efQ qYo +nEZ +nEZ +nEZ +nEZ aaa -aaa -aaa -aaa -aaa -aaa +qYo aaa aaa efQ @@ -153128,15 +153276,15 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +qYo +qYo +lvw +qYo +qYo +uHd +qYo +uHd +qYo aad dTS uKw @@ -153386,13 +153534,13 @@ aaa aaa aaa aaa +lvw aaa +uHd aaa +lvw aaa -aaa -aaa -aaa -aaa +uHd aaa efQ aad @@ -153643,13 +153791,13 @@ aaa aaa aaa aaa +uHd aaa +lvw aaa +uHd aaa -aaa -aaa -aaa -aaa +lvw aaa efQ aaa diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 63b4e5ee9455e..2b92201ed4a93 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -1392,8 +1392,8 @@ /area/station/security/courtroom) "awR" = ( /obj/machinery/conveyor{ - id = "garbage"; - dir = 1 + dir = 1; + id = "garbage" }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ @@ -1677,6 +1677,12 @@ }, /turf/open/floor/circuit/red, /area/station/ai_monitored/turret_protected/ai_upload) +"aAl" = ( +/obj/machinery/computer/mech_bay_power_console{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/security/mechbay) "aAv" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -2815,8 +2821,8 @@ "aUi" = ( /obj/structure/table, /obj/item/storage/briefcase{ - pixel_y = 3; - pixel_x = 2 + pixel_x = 2; + pixel_y = 3 }, /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/item/storage/wallet, @@ -3181,8 +3187,8 @@ pixel_x = 7 }, /obj/item/reagent_containers/cup/soda_cans/sol_dry{ - pixel_y = 4; - pixel_x = -7 + pixel_x = -7; + pixel_y = 4 }, /turf/open/floor/iron/white/corner, /area/station/hallway/secondary/entry) @@ -3533,7 +3539,6 @@ /turf/open/floor/plating, /area/mine/eva/lower) "bfB" = ( -/obj/item/kirbyplants/random, /obj/machinery/firealarm/directional/east, /turf/open/floor/iron/dark/textured, /area/station/security/office) @@ -5312,8 +5317,8 @@ dir = 8; id = "garbage"; name = "disposal conveyor"; - pixel_y = 5; - pixel_x = -5 + pixel_x = -5; + pixel_y = 5 }, /obj/structure/railing/corner, /obj/effect/turf_decal/box/corners{ @@ -7149,8 +7154,8 @@ name = "Disposal Exit Vent" }, /obj/machinery/conveyor{ - id = "garbage"; - dir = 1 + dir = 1; + id = "garbage" }, /obj/effect/turf_decal/stripes/red/box, /turf/open/floor/plating, @@ -7832,8 +7837,8 @@ /obj/structure/table, /obj/item/storage/wallet, /obj/item/storage/wallet{ - pixel_y = 3; - pixel_x = 4 + pixel_x = 4; + pixel_y = 3 }, /turf/open/floor/plastic, /area/station/commons/dorms/laundry) @@ -16889,8 +16894,8 @@ /area/icemoon/underground/explored) "fdX" = ( /obj/item/toy/cards/deck{ - pixel_y = 13; - pixel_x = -9 + pixel_x = -9; + pixel_y = 13 }, /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/generic, @@ -18188,6 +18193,13 @@ /obj/item/reagent_containers/cup/glass/waterbottle, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"fAH" = ( +/obj/effect/turf_decal/tile/red/anticorner/contrasted, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "fAV" = ( /obj/item/kirbyplants/random, /turf/open/floor/iron, @@ -19479,9 +19491,9 @@ }, /obj/effect/turf_decal/tile/yellow/fourcorners, /obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; id = "pharmacy_shutters2"; - name = "Pharmacy Shutters"; - dir = 4 + name = "Pharmacy Shutters" }, /turf/open/floor/iron, /area/station/medical/pharmacy) @@ -21081,8 +21093,8 @@ /area/station/security/prison/workout) "gvp" = ( /obj/item/chair/stool{ - pixel_y = -3; - pixel_x = -1 + pixel_x = -1; + pixel_y = -3 }, /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/dim/directional/west, @@ -22474,6 +22486,7 @@ }, /obj/item/geiger_counter, /obj/item/clothing/glasses/meson, +/obj/machinery/firealarm/directional/north, /turf/open/floor/engine, /area/station/engineering/supermatter/room) "gSy" = ( @@ -22643,13 +22656,13 @@ /area/station/science/breakroom) "gVm" = ( /obj/item/coin/silver{ - pixel_y = -3; - pixel_x = -5 + pixel_x = -5; + pixel_y = -3 }, /obj/item/toy/plush/moth{ - pixel_y = 5; + name = "Marcellus"; pixel_x = 5; - name = "Marcellus" + pixel_y = 5 }, /turf/open/floor/plating, /area/station/commons/dorms/laundry) @@ -24722,17 +24735,17 @@ "hCY" = ( /obj/structure/table/wood, /obj/item/folder/yellow{ - pixel_y = 8; - pixel_x = 3 + pixel_x = 3; + pixel_y = 8 }, /obj/item/folder/white{ - pixel_y = 12; - pixel_x = -3 + pixel_x = -3; + pixel_y = 12 }, /obj/structure/sign/poster/contraband/random/directional/south, /obj/item/folder/blue{ - pixel_y = 3; - pixel_x = -3 + pixel_x = -3; + pixel_y = 3 }, /obj/item/folder/red{ pixel_x = 5; @@ -27515,8 +27528,8 @@ "ixb" = ( /obj/machinery/button/door/directional/south{ id = "vacantofficemaintshutter"; - pixel_x = 4; name = "Privacy Shutters"; + pixel_x = 4; pixel_y = -28 }, /turf/open/floor/iron/grimy, @@ -30640,6 +30653,12 @@ /obj/machinery/atmospherics/components/binary/pump{ dir = 8 }, +/obj/machinery/airalarm/directional/south, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "ordnancefreezer" + }, +/obj/effect/mapping_helpers/airalarm/mixingchamber_access, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/iron/dark, /area/station/science/ordnance) "jwl" = ( @@ -31282,8 +31301,8 @@ /area/station/engineering/atmos) "jHV" = ( /obj/machinery/mineral/stacking_machine{ - stack_amt = 10; - output_dir = 2 + output_dir = 2; + stack_amt = 10 }, /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -32546,6 +32565,12 @@ /obj/item/clothing/shoes/workboots, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"kbm" = ( +/obj/machinery/mech_bay_recharge_port{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/security/mechbay) "kbn" = ( /obj/effect/decal/cleanable/food/pie_smudge, /turf/open/floor/iron, @@ -32557,8 +32582,8 @@ /area/icemoon/surface/outdoors/nospawn) "kbq" = ( /obj/machinery/conveyor{ - id = "garbage"; - dir = 1 + dir = 1; + id = "garbage" }, /obj/effect/turf_decal/stripes/line{ dir = 5 @@ -32701,6 +32726,16 @@ /obj/structure/sign/warning/test_chamber/directional/south, /turf/open/floor/iron, /area/station/science/ordnance/testlab) +"kdy" = ( +/obj/machinery/door/poddoor/shutters{ + id = "secmechbay"; + name = "Security Mech Bay Shutters" + }, +/obj/structure/cable, +/obj/effect/turf_decal/caution/stand_clear, +/obj/effect/turf_decal/box, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "kdD" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -33699,6 +33734,16 @@ /obj/machinery/power/apc/auto_name/directional/east, /turf/open/floor/iron/kitchen/diagonal, /area/station/service/kitchen) +"kqG" = ( +/obj/structure/table/reinforced, +/obj/machinery/light/small/directional/east, +/obj/effect/spawner/random/engineering/tool{ + pixel_x = 1; + pixel_y = 3 + }, +/obj/machinery/airalarm/directional/east, +/turf/open/floor/iron, +/area/station/security/mechbay) "kqK" = ( /obj/effect/spawner/random/trash/mess, /obj/effect/decal/cleanable/dirt, @@ -33857,7 +33902,7 @@ /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/underground/explored) "ksu" = ( -/mob/living/simple_animal/hostile/asteroid/gutlunch, +/mob/living/basic/mining/gutlunch/warrior, /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/underground/explored) "ksC" = ( @@ -33934,13 +33979,18 @@ /area/station/security/prison/work) "ktw" = ( /obj/effect/turf_decal/stripes/line, -/obj/machinery/firealarm/directional/south, /obj/machinery/camera/directional/south{ c_tag = "Engineering Supermatter Fore"; network = list("ss13","engine"); pixel_x = 23 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/green/visible, +/obj/machinery/airalarm/directional/south, +/obj/effect/mapping_helpers/airalarm/engine_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "engine" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/engine, /area/station/engineering/supermatter/room) "ktx" = ( @@ -34091,6 +34141,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 }, +/obj/item/kirbyplants/random, /turf/open/floor/iron/dark/textured, /area/station/security/office) "kvR" = ( @@ -34578,8 +34629,8 @@ pixel_y = 2 }, /obj/item/clothing/suit/hooded/wintercoat/eva{ - pixel_y = 5; - pixel_x = 1 + pixel_x = 1; + pixel_y = 5 }, /obj/machinery/light/small/directional/east, /obj/machinery/mining_weather_monitor/directional/north, @@ -36450,6 +36501,10 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/underground/explored) +"lgg" = ( +/obj/machinery/air_sensor/engine_chamber, +/turf/open/floor/engine, +/area/station/engineering/supermatter) "lgk" = ( /obj/effect/turf_decal/trimline/blue/filled/corner{ dir = 4 @@ -36890,6 +36945,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/mine/laborcamp) +"lmM" = ( +/obj/structure/cable, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "lmY" = ( /obj/machinery/newscaster/directional/west, /obj/machinery/camera{ @@ -37023,8 +37087,14 @@ /turf/open/floor/iron, /area/station/construction) "loy" = ( -/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/red/anticorner/contrasted, +/obj/machinery/button/door/directional/east{ + id = "secmechbay"; + name = "Security Mech Garage Door Controls"; + req_access = list("security") + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/brig/upper) "loG" = ( @@ -38247,6 +38317,19 @@ }, /turf/open/floor/iron/dark/corner, /area/station/engineering/atmos/storage/gas) +"lHL" = ( +/obj/structure/cable, +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/obj/machinery/button/door/directional/north{ + id = "secmechbay"; + name = "Security Mech Garage Door Controls"; + req_access = list("security") + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "lIk" = ( /obj/effect/spawner/structure/window, /turf/open/floor/plating, @@ -38440,8 +38523,8 @@ /obj/structure/table, /obj/effect/turf_decal/tile/brown/half/contrasted, /obj/item/storage/box/bandages{ - pixel_y = 6; - pixel_x = -6 + pixel_x = -6; + pixel_y = 6 }, /obj/item/food/cheesiehonkers, /turf/open/floor/iron, @@ -38796,6 +38879,11 @@ /obj/machinery/light/small/directional/east, /turf/open/floor/iron, /area/station/commons/fitness) +"lRc" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable, +/turf/open/floor/plating, +/area/station/security/mechbay) "lRd" = ( /obj/structure/chair, /obj/effect/turf_decal/stripes/line{ @@ -40601,9 +40689,9 @@ "mwF" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; id = "pharmacy_shutters"; - name = "Pharmacy Shutters"; - dir = 4 + name = "Pharmacy Shutters" }, /turf/open/floor/plating, /area/station/medical/pharmacy) @@ -43161,6 +43249,19 @@ }, /turf/open/floor/iron, /area/station/commons/dorms) +"nmq" = ( +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/cable, +/obj/structure/table/reinforced, +/obj/effect/spawner/random/engineering/tool{ + pixel_x = -11 + }, +/obj/effect/spawner/random/engineering/tool{ + pixel_x = 5; + pixel_y = 8 + }, +/turf/open/floor/iron, +/area/station/security/mechbay) "nmr" = ( /obj/machinery/hydroponics/soil, /obj/item/cultivator, @@ -43824,8 +43925,8 @@ dir = 4 }, /obj/machinery/door/airlock/multi_tile/public/glass{ - name = "Arrivals Dock"; - dir = 4 + dir = 4; + name = "Arrivals Dock" }, /turf/open/floor/iron/dark/textured, /area/station/hallway/secondary/entry) @@ -46002,8 +46103,12 @@ /obj/effect/turf_decal/box/red, /obj/machinery/airalarm/directional/east, /obj/effect/mapping_helpers/airalarm/mixingchamber_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "ordnanceburn" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/iron/dark, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "odi" = ( /obj/item/toy/snowball{ pixel_x = 5; @@ -46719,8 +46824,8 @@ dir = 4 }, /obj/machinery/door/airlock/multi_tile/public/glass{ - name = "Arrivals Dock"; - dir = 4 + dir = 4; + name = "Arrivals Dock" }, /turf/open/floor/iron/dark/textured, /area/station/hallway/secondary/entry) @@ -47123,8 +47228,8 @@ /obj/structure/rack, /obj/machinery/light/cold/directional/north, /obj/item/storage/box/bandages{ - pixel_y = 6; - pixel_x = -6 + pixel_x = -6; + pixel_y = 6 }, /obj/item/healthanalyzer, /turf/open/floor/iron/white/textured, @@ -47426,6 +47531,13 @@ /obj/structure/sign/poster/contraband/random/directional/north, /turf/open/floor/plating, /area/station/security/prison/safe) +"oyL" = ( +/obj/effect/turf_decal/tile/red/half/contrasted, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "oyV" = ( /obj/effect/turf_decal/tile/neutral/diagonal_edge, /obj/structure/cable, @@ -49329,12 +49441,12 @@ /area/station/medical/medbay/central) "pcc" = ( /obj/item/stack/spacecash/c10{ - pixel_y = 4; - pixel_x = 4 + pixel_x = 4; + pixel_y = 4 }, /obj/item/toy/plush/beeplushie{ - pixel_y = -6; - name = "Coolidge" + name = "Coolidge"; + pixel_y = -6 }, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, @@ -50394,6 +50506,17 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/cargo/office) +"psY" = ( +/obj/machinery/door/poddoor/shutters{ + id = "secmechbay"; + name = "Security Mech Bay Shutters" + }, +/obj/effect/turf_decal/caution/stand_clear, +/obj/effect/turf_decal/box, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "ptd" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -52274,6 +52397,9 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/engineering/main) +"pVL" = ( +/turf/closed/wall/r_wall, +/area/station/security/mechbay) "pVN" = ( /obj/structure/cable, /turf/open/floor/plating, @@ -54279,8 +54405,6 @@ dir = 1; name = "Gas to Filter" }, -/obj/effect/mapping_helpers/airalarm/engine_access, -/obj/machinery/airalarm/directional/west, /turf/open/floor/engine, /area/station/engineering/supermatter) "qDD" = ( @@ -55794,9 +55918,9 @@ /obj/machinery/smartfridge/chemistry/preloaded, /obj/machinery/door/firedoor, /obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; id = "pharmacy_shutters"; - name = "Pharmacy Shutters"; - dir = 4 + name = "Pharmacy Shutters" }, /turf/open/floor/iron/white, /area/station/medical/pharmacy) @@ -56882,8 +57006,8 @@ pixel_y = 3 }, /obj/item/assembly/flash/handheld{ - pixel_y = 3; - pixel_x = -19 + pixel_x = -19; + pixel_y = 3 }, /obj/structure/table, /obj/effect/turf_decal/tile/red/anticorner/contrasted, @@ -57918,9 +58042,9 @@ /obj/machinery/smartfridge/chemistry/preloaded, /obj/machinery/door/firedoor, /obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; id = "pharmacy_shutters2"; - name = "Pharmacy Shutters"; - dir = 4 + name = "Pharmacy Shutters" }, /turf/open/floor/iron/white, /area/station/medical/pharmacy) @@ -59099,9 +59223,9 @@ }, /obj/effect/turf_decal/tile/yellow/fourcorners, /obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; id = "pharmacy_shutters"; - name = "Pharmacy Shutters"; - dir = 4 + name = "Pharmacy Shutters" }, /turf/open/floor/iron, /area/station/medical/pharmacy) @@ -60076,13 +60200,13 @@ pixel_y = -5 }, /obj/item/coin/plasma{ - pixel_y = -2; - pixel_x = 3 + pixel_x = 3; + pixel_y = -2 }, /obj/item/toy/plush/lizard_plushie{ + name = "Cassius"; pixel_x = 11; - pixel_y = -4; - name = "Cassius" + pixel_y = -4 }, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, @@ -61627,8 +61751,8 @@ /area/station/medical/chemistry) "sLR" = ( /obj/machinery/conveyor{ - id = "garbage"; - dir = 1 + dir = 1; + id = "garbage" }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ @@ -62412,6 +62536,14 @@ /obj/effect/mapping_helpers/airlock/access/all/medical/chemistry, /turf/open/floor/plating, /area/station/maintenance/department/medical/morgue) +"taj" = ( +/obj/structure/cable, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/light/small/directional/west, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "tak" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -62598,9 +62730,9 @@ "teE" = ( /obj/effect/spawner/structure/window, /obj/machinery/door/poddoor/shutters{ + dir = 8; id = "vacantofficemaintshutter"; - name = "Privacy Shutters"; - dir = 8 + name = "Privacy Shutters" }, /turf/open/floor/plating, /area/station/commons/vacant_room/office) @@ -62922,8 +63054,8 @@ dir = 4 }, /obj/machinery/door/airlock/multi_tile/public/glass{ - name = "Auxiliary Dock"; - dir = 4 + dir = 4; + name = "Auxiliary Dock" }, /turf/open/floor/iron/dark/textured, /area/station/hallway/secondary/entry) @@ -68037,10 +68169,8 @@ dir = 4 }, /obj/machinery/meter, -/obj/machinery/airalarm/directional/east, -/obj/effect/mapping_helpers/airalarm/mixingchamber_access, /turf/open/floor/iron/dark, -/area/station/science/ordnance/freezerchamber) +/area/station/science/ordnance) "uSS" = ( /obj/machinery/recharge_station, /obj/effect/turf_decal/stripes/box, @@ -69391,6 +69521,11 @@ /obj/structure/sign/warning/gas_mask/directional/west, /turf/open/floor/iron, /area/station/cargo/drone_bay) +"vpn" = ( +/obj/vehicle/sealed/mecha/ripley/paddy/preset, +/obj/structure/cable, +/turf/open/floor/iron/recharge_floor, +/area/station/security/mechbay) "vpR" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, @@ -69544,6 +69679,16 @@ /obj/structure/marker_beacon/burgundy, /turf/open/floor/plating/snowed/icemoon, /area/icemoon/surface/outdoors/nospawn) +"vsL" = ( +/obj/structure/cable, +/obj/effect/turf_decal/tile/red/anticorner/contrasted{ + dir = 8 + }, +/obj/machinery/camera/directional/west{ + c_tag = "Security - Office - Port" + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "vsM" = ( /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/west, @@ -73344,6 +73489,8 @@ "wAT" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/red/half/contrasted, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/brig/upper) "wAW" = ( @@ -75553,8 +75700,8 @@ "xgX" = ( /obj/structure/table/wood, /obj/effect/spawner/random/entertainment/deck{ - pixel_y = 15; - pixel_x = -2 + pixel_x = -2; + pixel_y = 15 }, /obj/effect/spawner/random/food_or_drink/snack{ pixel_x = 5; @@ -239026,7 +239173,7 @@ tfR iNa tLW seR -esE +lgg uey esE uLe @@ -240726,7 +240873,7 @@ jNp jNp jNp jNp -sDl +pVL sDl sDl sDl @@ -240979,11 +241126,11 @@ law eqI ewM wAT -lbk -bln -bln -bln -sDl +kdy +taj +vsL +vpn +lRc sDl sDl sDl @@ -241236,11 +241383,11 @@ eyb hAQ ksC loy -lbk -bln -bln -bln -sDl +psY +lmM +oyL +kbm +lRc sDl sDl sDl @@ -241494,10 +241641,10 @@ mfH cIY mfH mfH -ntK -bln -sDl -sDl +lHL +fAH +aAl +lRc sDl sDl sDl @@ -241750,11 +241897,11 @@ ykw tSi kfc dcX -lbk -bln -bln -sDl -sDl +mfH +nmq +kqG +pVL +pVL sDl sDl sDl @@ -242008,9 +242155,9 @@ nOQ cqx sQB mfH -bln -sDl -sDl +pVL +pVL +pVL sDl sDl tOq diff --git a/_maps/map_files/Mafia/mafia_lavaland.dmm b/_maps/map_files/Mafia/mafia_lavaland.dmm index c6189750b0aab..d086ab3f5318a 100644 --- a/_maps/map_files/Mafia/mafia_lavaland.dmm +++ b/_maps/map_files/Mafia/mafia_lavaland.dmm @@ -52,7 +52,7 @@ "al" = ( /obj/item/shovel, /obj/item/pickaxe, -/obj/structure/closet/secure_closet/miner/unlocked, +/obj/structure/closet/crate/miningcar, /turf/open/floor/fakebasalt, /area/centcom/mafia) "am" = ( @@ -72,7 +72,7 @@ }, /obj/item/shovel, /obj/item/pickaxe, -/obj/structure/closet/secure_closet/miner/unlocked, +/obj/structure/closet/crate/miningcar, /turf/open/floor/iron, /area/centcom/mafia) "ap" = ( @@ -94,7 +94,7 @@ }, /obj/item/shovel, /obj/item/pickaxe, -/obj/structure/closet/secure_closet/miner/unlocked, +/obj/structure/closet/crate/miningcar, /turf/open/floor/iron, /area/centcom/mafia) "as" = ( @@ -135,7 +135,7 @@ }, /obj/item/shovel, /obj/item/pickaxe, -/obj/structure/closet/secure_closet/miner/unlocked, +/obj/structure/closet/crate/miningcar, /turf/open/floor/iron, /area/centcom/mafia) "aB" = ( @@ -184,7 +184,7 @@ }, /obj/item/shovel, /obj/item/pickaxe, -/obj/structure/closet/secure_closet/miner/unlocked, +/obj/structure/closet/crate/miningcar, /turf/open/floor/iron, /area/centcom/mafia) "aI" = ( @@ -193,7 +193,7 @@ }, /obj/item/shovel, /obj/item/pickaxe, -/obj/structure/closet/secure_closet/miner/unlocked, +/obj/structure/closet/crate/miningcar, /turf/open/floor/iron, /area/centcom/mafia) "aJ" = ( @@ -211,7 +211,7 @@ }, /obj/item/shovel, /obj/item/pickaxe, -/obj/structure/closet/secure_closet/miner/unlocked, +/obj/structure/closet/crate/miningcar, /turf/open/floor/iron, /area/centcom/mafia) "aM" = ( diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 059775f4d94aa..234b5fd4ab63b 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -589,6 +589,12 @@ "alE" = ( /turf/open/floor/iron, /area/station/security/courtroom) +"alF" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "alI" = ( /obj/machinery/door/window/left/directional/west{ dir = 4; @@ -7668,6 +7674,13 @@ /obj/effect/mapping_helpers/airlock/access/any/supply/maintenance, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"cQn" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "cQx" = ( /obj/machinery/computer/atmos_control/nitrous_tank{ dir = 1 @@ -9896,8 +9909,12 @@ }, /obj/effect/mapping_helpers/airalarm/mixingchamber_access, /obj/machinery/airalarm/directional/west, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "ordnancefreezer" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/iron/dark, -/area/station/science/ordnance/freezerchamber) +/area/station/science/ordnance) "dJk" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -10511,6 +10528,10 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/commons/locker) +"dTN" = ( +/obj/machinery/atmospherics/pipe/smart/simple/dark/visible, +/turf/closed/wall/r_wall, +/area/station/science/ordnance) "dTQ" = ( /obj/effect/turf_decal/trimline/green/filled/corner{ dir = 4 @@ -13160,6 +13181,13 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai_upload) +"eQr" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/light_switch/directional/south, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "eQs" = ( /obj/machinery/air_sensor/air_tank, /turf/open/floor/engine/air, @@ -13701,6 +13729,16 @@ /obj/item/food/pizzaslice/moldy/bacteria, /turf/open/floor/iron/white, /area/station/medical/abandoned) +"faW" = ( +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/table, +/obj/structure/cable, +/obj/item/poster/random_official, +/obj/item/poster/random_official{ + pixel_y = 10 + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "fbf" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable, @@ -16223,6 +16261,10 @@ /obj/structure/table, /obj/structure/cable, /obj/effect/turf_decal/tile/red/half/contrasted, +/obj/machinery/fax{ + fax_name = "Security Office"; + name = "Security Office Fax Machine" + }, /turf/open/floor/iron/dark, /area/station/security/office) "fYq" = ( @@ -16404,6 +16446,18 @@ /obj/effect/turf_decal/tile/neutral/half/contrasted, /turf/open/floor/iron, /area/station/hallway/primary/port) +"gcL" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/stripes/corner, +/obj/structure/cable, +/obj/machinery/button/door/directional/east{ + name = "Security Mech Garage Door Controls"; + id = "secmechbay"; + req_access = list("security") + }, +/turf/open/floor/iron, +/area/station/security/office) "gcU" = ( /obj/structure/disposalpipe/segment, /obj/effect/mapping_helpers/airlock/access/all/science/robotics, @@ -18212,6 +18266,15 @@ /obj/machinery/firealarm/directional/west, /turf/open/floor/iron/white, /area/station/science/xenobiology) +"gKH" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 1 + }, +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/security/office) "gKK" = ( /obj/effect/turf_decal/stripes/white/line{ dir = 1 @@ -18469,6 +18532,11 @@ }, /turf/open/floor/iron/white, /area/station/medical/virology) +"gOT" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable, +/turf/open/floor/plating, +/area/station/security/mechbay) "gOY" = ( /obj/structure/chair{ dir = 8 @@ -20332,6 +20400,10 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai) +"hza" = ( +/obj/vehicle/sealed/mecha/ripley/paddy/preset, +/turf/open/floor/iron/recharge_floor, +/area/station/security/mechbay) "hzt" = ( /obj/structure/transit_tube/curved/flipped, /obj/effect/turf_decal/tile/blue{ @@ -24611,6 +24683,13 @@ }, /turf/open/floor/iron, /area/station/command/gateway) +"iVJ" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "iVN" = ( /obj/effect/spawner/structure/window/reinforced/tinted, /turf/open/floor/plating, @@ -24794,8 +24873,12 @@ }, /obj/machinery/airalarm/directional/east, /obj/effect/mapping_helpers/airalarm/mixingchamber_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "ordnanceburn" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/iron/dark, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "iYG" = ( /obj/effect/landmark/event_spawn, /obj/effect/turf_decal/tile/neutral{ @@ -26612,8 +26695,8 @@ dir = 8 }, /obj/item/storage/box/bandages{ - pixel_y = 6; - pixel_x = -6 + pixel_x = -6; + pixel_y = 6 }, /obj/item/storage/medkit/regular, /obj/item/reagent_containers/cup/bottle/multiver, @@ -28167,6 +28250,12 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/hallway/primary/central) +"kdy" = ( +/obj/structure/frame/computer{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/security/mechbay) "kdA" = ( /obj/machinery/door/airlock/mining{ name = "Warehouse" @@ -28815,6 +28904,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) +"kqM" = ( +/obj/effect/turf_decal/stripes/corner, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "kqZ" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -29743,8 +29839,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/green/visible, /obj/machinery/airalarm/directional/east, /obj/effect/mapping_helpers/airalarm/engine_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "engine" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/engine, -/area/station/engineering/supermatter) +/area/station/engineering/supermatter/room) "kKp" = ( /obj/structure/rack, /obj/item/gun/energy/laser/carbine/practice{ @@ -31229,6 +31329,12 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/glass/reinforced, /area/station/science/research) +"llU" = ( +/obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "lma" = ( /obj/structure/chair/stool/directional/north, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -33332,6 +33438,21 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/engineering/atmos) +"mcu" = ( +/obj/machinery/door/poddoor/shutters{ + dir = 8; + id = "secmechbay"; + name = "Security Mech Bay Shutters" + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/caution/stand_clear{ + dir = 4 + }, +/obj/effect/turf_decal/box, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "mcF" = ( /obj/structure/table, /obj/machinery/button/door{ @@ -35034,8 +35155,8 @@ dir = 1 }, /obj/item/storage/box/bandages{ - pixel_y = 6; - pixel_x = 4 + pixel_x = 4; + pixel_y = 6 }, /turf/open/floor/iron, /area/station/cargo/miningoffice) @@ -36925,7 +37046,6 @@ /turf/open/floor/iron, /area/station/commons/vacant_room/commissary) "nnt" = ( -/obj/vehicle/ridden/secway, /obj/effect/turf_decal/bot, /obj/structure/cable, /turf/open/floor/iron/dark, @@ -38214,7 +38334,7 @@ }, /obj/effect/mapping_helpers/airlock/access/all/science/ordnance, /turf/open/floor/engine, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "nJG" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -39665,6 +39785,12 @@ /obj/machinery/duct, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"omA" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "omF" = ( /obj/machinery/teleport/station, /obj/machinery/status_display/evac/directional/north, @@ -39783,6 +39909,9 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) +"ope" = ( +/turf/closed/wall, +/area/station/security/mechbay) "oph" = ( /obj/structure/chair/wood/wings{ dir = 8 @@ -40305,6 +40434,10 @@ /obj/item/storage/photo_album/chapel, /turf/open/floor/iron/grimy, /area/station/service/chapel/office) +"oxV" = ( +/obj/machinery/air_sensor/engine_chamber, +/turf/open/floor/engine, +/area/station/engineering/supermatter) "oxW" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/stripes/line{ @@ -43014,9 +43147,6 @@ /turf/open/floor/iron, /area/station/security/courtroom) "pyh" = ( -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 1 - }, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -43210,14 +43340,9 @@ /turf/open/floor/iron, /area/station/security/checkpoint/customs) "pBL" = ( -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 9 - }, /obj/machinery/newscaster/directional/west, -/obj/structure/table, -/obj/machinery/fax{ - fax_name = "Security Office"; - name = "Security Office Fax Machine" +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 8 }, /turf/open/floor/iron, /area/station/security/office) @@ -50299,6 +50424,26 @@ /obj/effect/turf_decal/tile/blue/fourcorners, /turf/open/floor/iron/white, /area/station/medical/storage) +"saa" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/obj/structure/cable, +/obj/structure/table, +/obj/machinery/camera/directional/west{ + c_tag = "Security - Office - Port" + }, +/obj/machinery/button/door/directional/west{ + id = "secmechbay"; + name = "Security Mech Garage Door Controls"; + req_access = list("security") + }, +/obj/item/circuitboard/computer/mech_bay_power_console, +/obj/item/stack/sheet/glass{ + pixel_y = 14 + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "sab" = ( /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plating, @@ -52552,6 +52697,18 @@ /obj/structure/window/reinforced/spawner/directional/east, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"sQz" = ( +/obj/machinery/door/poddoor/shutters{ + dir = 8; + id = "secmechbay"; + name = "Security Mech Bay Shutters" + }, +/obj/effect/turf_decal/caution/stand_clear{ + dir = 4 + }, +/obj/effect/turf_decal/box, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "sQB" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -57166,6 +57323,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"uuO" = ( +/obj/machinery/mech_bay_recharge_port{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/security/mechbay) "uvw" = ( /obj/machinery/status_display/supply{ pixel_y = 32 @@ -57682,6 +57845,15 @@ /obj/structure/extinguisher_cabinet/directional/north, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"uEW" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "uFf" = ( /obj/machinery/holopad, /obj/effect/spawner/random/engineering/tracking_beacon, @@ -58732,6 +58904,12 @@ /obj/effect/turf_decal/trimline/red/filled/corner, /turf/open/floor/iron, /area/station/security/brig) +"uWs" = ( +/obj/machinery/computer/mech_bay_power_console{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/security/mechbay) "uWt" = ( /obj/structure/rack, /obj/item/stack/medical/mesh, @@ -61677,6 +61855,16 @@ "vTX" = ( /turf/open/floor/iron/dark, /area/station/engineering/atmospherics_engine) +"vUa" = ( +/obj/structure/table, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/airalarm/directional/north, +/obj/item/stack/rods/two, +/obj/item/stack/cable_coil/five, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "vUx" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, @@ -61872,6 +62060,13 @@ }, /turf/open/floor/circuit/green/off, /area/station/science/research) +"vXj" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 9 + }, +/obj/machinery/light/small/directional/west, +/turf/open/floor/iron, +/area/station/security/office) "vXt" = ( /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ dir = 9 @@ -62670,6 +62865,9 @@ dir = 1 }, /area/station/engineering/storage_shared) +"wlz" = ( +/turf/closed/wall/r_wall, +/area/station/security/mechbay) "wlL" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 4 @@ -62697,6 +62895,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/science/robotics/lab) +"wmr" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 8 + }, +/obj/vehicle/ridden/secway, +/turf/open/floor/iron, +/area/station/security/office) "wmz" = ( /obj/machinery/atmospherics/pipe/smart/simple/dark/visible, /turf/open/floor/iron, @@ -63389,6 +63594,15 @@ /obj/item/flashlight/lamp, /turf/open/floor/iron/dark, /area/station/security/execution/education) +"wzq" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/security/office) "wzy" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -64569,9 +64783,9 @@ /turf/open/floor/iron, /area/station/hallway/primary/aft) "wVt" = ( -/obj/item/storage/box/deputy, /obj/structure/table, /obj/item/radio/intercom/directional/west, +/obj/item/storage/box/deputy, /turf/open/floor/iron/dark, /area/station/security/office) "wVy" = ( @@ -64911,6 +65125,13 @@ /obj/structure/cable, /turf/open/floor/iron/white/smooth_large, /area/station/command/heads_quarters/cmo) +"xcv" = ( +/obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "xcz" = ( /obj/effect/turf_decal/stripes/corner, /obj/structure/reagent_dispensers/watertank, @@ -65345,6 +65566,15 @@ }, /turf/open/floor/iron, /area/station/commons/storage/tools) +"xkq" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/security/office) "xkr" = ( /obj/effect/turf_decal/plaque{ icon_state = "L13" @@ -66762,6 +66992,10 @@ }, /turf/open/floor/iron/dark, /area/station/command/bridge) +"xJv" = ( +/obj/machinery/light/directional/north, +/turf/open/floor/iron/recharge_floor, +/area/station/security/mechbay) "xJA" = ( /obj/structure/sign/warning/docking, /turf/closed/wall, @@ -67569,6 +67803,10 @@ }, /turf/open/floor/plating, /area/station/maintenance/fore/lesser) +"xYZ" = ( +/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, +/turf/closed/wall/r_wall, +/area/station/science/ordnance) "xZb" = ( /obj/effect/spawner/random/structure/grille, /turf/open/floor/plating, @@ -97159,11 +97397,11 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa +gdb +gdb +gdb +gdb +gdb iTZ ahj ahj @@ -97414,11 +97652,6 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa rrt lMJ gdb @@ -97426,12 +97659,17 @@ rDE fOw nQC ikZ +vXj +iGj +iGj +iGj +iGj pBL iGj iGj iGj vdi -iGj +wmr ljf kYg nnt @@ -97671,11 +97909,6 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa rrt aaa vaB @@ -97683,6 +97916,11 @@ kKp iDq mPT fCn +gKH +gcL +wzq +wzq +xkq pyh aja lyF @@ -97928,11 +98166,6 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa rrt lMJ gdb @@ -97940,6 +98173,11 @@ hhl fOf eZI dgD +ope +ope +mcu +sQz +ope kYg vGt fYb @@ -98187,16 +98425,16 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa gdb nMV luV rqs dgD +faW +saa +uEW +eQr +ope jGl kxA wxj @@ -98444,16 +98682,16 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa gdb ksg aGM rpz dgD +vUa +cQn +kqM +omA +ope jGl kxA xXh @@ -98699,11 +98937,6 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa rrt lMJ gdb @@ -98711,6 +98944,11 @@ ksg aGM rpz dgD +xJv +alF +xcv +hza +ope rtI kxA kAT @@ -98956,11 +99194,6 @@ aaa aav aaa aaa -aaa -aaa -aaa -aaa -aaa rrt aaa ikZ @@ -98968,6 +99201,11 @@ ksg vuP rpz dgD +uuO +alF +xcv +uuO +ope jGl kxA qmu @@ -99213,11 +99451,6 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa rrt lMJ gdb @@ -99225,6 +99458,11 @@ dhN nuI qJa dgD +kdy +iVJ +llU +uWs +ope kYg jAN wxj @@ -99471,17 +99709,17 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa -aaa tLb gdb ikZ gdb ikZ gdb +wlz +gOT +gOT +wlz +wlz hYd olD mLx @@ -99585,7 +99823,7 @@ fhi fhi uEo fiS -hqj +gyQ eRn hqj hqj @@ -99842,7 +100080,7 @@ huj fhi xEU iqx -deY +xYZ gil deY oet @@ -100356,7 +100594,7 @@ ujk jvo aHH iYE -pCa +dTN dEF pCa cOT @@ -111327,7 +111565,7 @@ wBE oNs eyD qZB -oNs +oxV hRl jWE auc diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index 04f346498521f..81811c222b6ab 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -1600,9 +1600,9 @@ dir = 8 }, /obj/machinery/atmospherics/components/unary/outlet_injector/on{ - volume_rate = 200; dir = 8; - initialize_directions = 8 + initialize_directions = 8; + volume_rate = 200 }, /turf/open/floor/engine, /area/station/science/cytology) @@ -3259,6 +3259,9 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/exit) +"aRU" = ( +/turf/closed/wall, +/area/station/security/mechbay) "aRX" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -13011,15 +13014,9 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/railing{ - dir = 8 - }, -/obj/machinery/door/firedoor/border_only{ - dir = 8 - }, /obj/machinery/duct, /turf/open/floor/catwalk_floor, -/area/station/maintenance/floor4/port) +/area/station/security/mechbay) "dqB" = ( /obj/item/clothing/mask/breath{ pixel_x = -4 @@ -18416,13 +18413,8 @@ /turf/open/floor/pod/light, /area/station/maintenance/floor3/starboard/aft) "eNj" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/closet/emcloset/anchored, -/obj/machinery/door/firedoor/border_only{ - dir = 1 - }, -/turf/open/floor/pod/light, -/area/station/maintenance/floor4/port) +/turf/closed/wall/r_wall, +/area/station/security/mechbay) "eNk" = ( /obj/machinery/door/firedoor/heavy, /obj/effect/turf_decal/stripes/line{ @@ -20470,6 +20462,21 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/service/hydroponics) +"ftt" = ( +/obj/structure/table, +/obj/structure/cable, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/item/radio/intercom/directional/west, +/obj/effect/spawner/random/engineering/tool{ + pixel_x = 1; + pixel_y = 3 + }, +/obj/effect/spawner/random/engineering/tool{ + pixel_x = 1; + pixel_y = 3 + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "ftu" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -26036,8 +26043,6 @@ /area/station/medical/treatment_center) "gSd" = ( /obj/effect/baseturf_helper/reinforced_plating/ceiling, -/obj/machinery/airalarm/directional/south, -/obj/effect/mapping_helpers/airalarm/engine_access, /turf/open/floor/engine, /area/station/engineering/supermatter) "gSj" = ( @@ -28165,6 +28170,14 @@ }, /turf/open/floor/pod/light, /area/station/maintenance/floor3/starboard/fore) +"hvb" = ( +/obj/machinery/mech_bay_recharge_port{ + dir = 2 + }, +/obj/effect/turf_decal/tile/red/anticorner, +/obj/machinery/light/directional/east, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "hvc" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -28188,7 +28201,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/any/science/robotics, /obj/machinery/door/firedoor, /obj/effect/mapping_helpers/airlock/access/any/command/minisat, /obj/effect/mapping_helpers/airlock/access/any/command/general, @@ -29729,10 +29741,11 @@ /obj/machinery/door/airlock/hatch{ name = "MiniSat Access" }, -/obj/effect/mapping_helpers/airlock/access/any/science/robotics, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/any/command/minisat, +/obj/effect/mapping_helpers/airlock/access/any/command/general, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/hallway) "hQl" = ( @@ -34766,8 +34779,8 @@ /obj/structure/table/glass, /obj/item/radio/intercom/directional/south, /obj/item/storage/box/bandages{ - pixel_y = 6; - pixel_x = -6 + pixel_x = -6; + pixel_y = 6 }, /obj/item/storage/medkit/regular, /turf/open/floor/iron/white, @@ -35048,6 +35061,17 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/pod/light, /area/station/maintenance/floor2/starboard) +"jlK" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/orange/visible, +/obj/structure/cable, +/obj/machinery/airalarm/directional/east, +/obj/effect/mapping_helpers/airalarm/engine_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "engine" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, +/turf/open/floor/engine, +/area/station/engineering/supermatter/room) "jlS" = ( /obj/structure/table/wood, /obj/item/flashlight/lamp/green, @@ -35539,6 +35563,10 @@ dir = 1 }, /area/station/security/brig) +"jsL" = ( +/obj/effect/turf_decal/tile/red/opposingcorners, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "jsP" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 4 @@ -35638,6 +35666,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/orange/visible, /turf/open/floor/plating, /area/station/engineering/supermatter) +"jun" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/duct, +/obj/machinery/airalarm/directional/west, +/turf/open/floor/catwalk_floor, +/area/station/security/mechbay) "juq" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -38218,6 +38254,19 @@ /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/floor/iron/dark, /area/station/security/evidence) +"kcw" = ( +/obj/machinery/computer/mech_bay_power_console{ + dir = 8 + }, +/obj/machinery/button/door/directional/north{ + id = "secmechbay"; + name = "Security Mech Garage Door Controls"; + req_access = list("security") + }, +/obj/effect/turf_decal/tile/red/opposingcorners, +/obj/machinery/light_switch/directional/east, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "kcy" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -42961,7 +43010,12 @@ /obj/machinery/computer/department_orders/security{ dir = 8 }, -/obj/item/radio/intercom/directional/south, +/obj/item/radio/intercom/directional/east, +/obj/machinery/button/door/directional/south{ + id = "secmechbay"; + name = "Security Mech Garage Door Controls"; + req_access = list("security") + }, /turf/open/floor/iron, /area/station/security/office) "lkB" = ( @@ -43415,8 +43469,8 @@ "lqD" = ( /obj/structure/table, /obj/item/storage/box/bandages{ - pixel_y = 6; - pixel_x = -6 + pixel_x = -6; + pixel_y = 6 }, /obj/item/storage/box/donkpockets{ pixel_x = 6 @@ -44376,6 +44430,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/machinery/air_sensor/engine_chamber, /turf/open/floor/engine, /area/station/engineering/supermatter) "lFa" = ( @@ -44999,8 +45054,12 @@ }, /obj/machinery/airalarm/directional/north, /obj/effect/mapping_helpers/airalarm/mixingchamber_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "ordnancefreezer" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/iron/dark, -/area/station/science/ordnance/freezerchamber) +/area/station/science/ordnance/testlab) "lNA" = ( /obj/effect/turf_decal/trimline/green/warning{ dir = 8 @@ -47940,6 +47999,13 @@ dir = 4 }, /area/station/hallway/secondary/exit/departure_lounge) +"myp" = ( +/obj/effect/turf_decal/tile/red/anticorner, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 8 + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "myr" = ( /turf/open/floor/iron/textured_large, /area/station/hallway/secondary/entry) @@ -54080,7 +54146,6 @@ "oad" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/portable_atmospherics/pump, -/obj/machinery/portable_atmospherics/pump, /turf/open/floor/pod/light, /area/station/maintenance/floor4/port/fore) "oar" = ( @@ -54300,6 +54365,13 @@ }, /turf/open/floor/iron/white, /area/station/command/heads_quarters/rd) +"odH" = ( +/obj/effect/turf_decal/tile/red/opposingcorners, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "odJ" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 6 @@ -57063,6 +57135,15 @@ dir = 8 }, /area/station/security/brig) +"oQu" = ( +/obj/effect/turf_decal/caution/stand_clear, +/obj/effect/turf_decal/box, +/obj/machinery/door/poddoor/shutters{ + id = "secmechbay"; + name = "Security Mech Bay Shutters" + }, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "oQv" = ( /obj/structure/flora/bush/sparsegrass/style_random, /obj/machinery/light/directional/west, @@ -59233,7 +59314,6 @@ /turf/open/floor/iron/dark/corner, /area/station/commons/storage/primary) "pvO" = ( -/obj/item/kirbyplants/organic/plant10, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/floor/iron/dark, @@ -60146,8 +60226,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/duct, +/obj/machinery/door/airlock/hatch{ + name = "Maintenance Bulkhead" + }, +/obj/effect/mapping_helpers/airlock/access/all/security/general, /turf/open/floor/catwalk_floor, -/area/station/maintenance/floor4/port) +/area/station/security/mechbay) "pIS" = ( /obj/machinery/requests_console/directional/east{ department = "Captain's Desk"; @@ -60892,8 +60976,12 @@ /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, /obj/machinery/airalarm/directional/west, /obj/effect/mapping_helpers/airalarm/mixingchamber_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "ordnanceburn" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/iron/dark, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance/testlab) "pSV" = ( /obj/machinery/griddle, /turf/open/floor/iron/kitchen, @@ -64891,7 +64979,8 @@ /obj/machinery/door/airlock/hatch{ name = "MiniSat Access" }, -/obj/effect/mapping_helpers/airlock/access/any/science/robotics, +/obj/effect/mapping_helpers/airlock/access/any/command/minisat, +/obj/effect/mapping_helpers/airlock/access/any/command/general, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/hallway) "qVv" = ( @@ -69024,9 +69113,6 @@ "scn" = ( /obj/machinery/netpod, /obj/machinery/airalarm/directional/east, -/obj/machinery/airalarm/directional/east, -/obj/machinery/airalarm/directional/east, -/obj/machinery/airalarm/directional/east, /turf/open/floor/catwalk_floor/iron_dark, /area/station/bitrunning/den) "sct" = ( @@ -73478,16 +73564,18 @@ /turf/open/floor/catwalk_floor, /area/station/maintenance/floor2/port/fore) "tlx" = ( -/obj/effect/mapping_helpers/airlock/access/any/security/brig, /obj/structure/cable, -/obj/machinery/door/airlock/hatch{ - name = "Maintenance Access" - }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/duct, -/turf/open/floor/plating, -/area/station/maintenance/floor4/port) +/obj/machinery/door/poddoor/shutters{ + id = "secmechbay"; + name = "Security Mech Bay Shutters" + }, +/obj/effect/turf_decal/caution/stand_clear, +/obj/effect/turf_decal/box, +/turf/open/floor/iron/dark, +/area/station/security/mechbay) "tlJ" = ( /obj/machinery/camera/autoname/directional/east, /turf/open/space/openspace, @@ -76777,6 +76865,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, /obj/effect/turf_decal/tile/red/fourcorners, +/obj/item/kirbyplants/organic/plant10, /turf/open/floor/iron/dark, /area/station/security/office) "ufL" = ( @@ -79141,9 +79230,9 @@ /area/station/maintenance/floor2/port/aft) "uLB" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/on{ - volume_rate = 200; dir = 8; - initialize_directions = 8 + initialize_directions = 8; + volume_rate = 200 }, /obj/machinery/atmospherics/pipe/heat_exchanging/manifold/layer2{ dir = 8 @@ -83530,6 +83619,10 @@ /obj/structure/disposalpipe/trunk/multiz, /turf/open/floor/plating, /area/station/maintenance/floor3/port/fore) +"vRF" = ( +/obj/vehicle/sealed/mecha/ripley/paddy/preset, +/turf/open/floor/iron/recharge_floor, +/area/station/security/mechbay) "vRO" = ( /turf/open/openspace, /area/station/hallway/floor4/aft) @@ -138330,7 +138423,7 @@ oqA wlP klY klY -klY +jlK nHv cAf klY @@ -313072,7 +313165,7 @@ mSG mSG doC mSG -mSG +sJm sJm sJm nPE @@ -315122,7 +315215,7 @@ ucA ucA ucA ucA -lYx +sJm lNx koC oOA @@ -317740,10 +317833,10 @@ lnl uYM eOy cgv -vEa -jbV -jbV -jbV +eNj +ftt +eNj +eNj eNj fPD jbV @@ -317999,7 +318092,7 @@ mbx rVS tlx dqs -dqs +jun dqs pIP hOs @@ -318254,11 +318347,11 @@ mBg dPf rDw pse -vEa -fXs -fXs -fXs -fXs +oQu +odH +jsL +myp +eNj jjh fXs fXs @@ -318511,11 +318604,11 @@ fNA ebz vuQ lku -vEa -owb -owb -owb -fXs +eNj +kcw +hvb +vRF +eNj mgx kHx fXs @@ -318768,11 +318861,11 @@ fNA ufI dnU dnU -fXs -vEa -vEa -owb -fXs +aRU +eNj +eNj +eNj +eNj xGh vPu fXs diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm index 6f9a351910ed8..1519368c79ecc 100644 --- a/_maps/map_files/debug/runtimestation.dmm +++ b/_maps/map_files/debug/runtimestation.dmm @@ -2431,6 +2431,7 @@ "SN" = ( /obj/structure/table/reinforced, /obj/machinery/light/directional/south, +/obj/item/bitrunning_debug, /turf/open/floor/iron, /area/station/bitrunning/den) "Td" = ( @@ -3108,12 +3109,12 @@ aa aa aa aa -uI -uI -uI -uI -uI -uI +aa +aa +aa +aa +aa +aa aa aa aa @@ -3201,10 +3202,10 @@ aa aa aa uI -hU -hU -jR -Oq +uI +uI +uI +uI uI aa aa diff --git a/_maps/map_files/tramstation/maintenance_modules/arrivalsecupper_1.dmm b/_maps/map_files/tramstation/maintenance_modules/arrivalsecupper_1.dmm index 658ed7e840d0f..67bdf4f43e910 100644 --- a/_maps/map_files/tramstation/maintenance_modules/arrivalsecupper_1.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/arrivalsecupper_1.dmm @@ -277,7 +277,7 @@ M M "} (11,1,1) = {" -w +a w w s @@ -292,7 +292,7 @@ a a "} (12,1,1) = {" -w +a w w s @@ -307,7 +307,7 @@ a a "} (13,1,1) = {" -w +a w w s @@ -322,7 +322,7 @@ a a "} (14,1,1) = {" -w +a w w s @@ -337,7 +337,7 @@ a a "} (15,1,1) = {" -w +a w w s diff --git a/_maps/map_files/tramstation/maintenance_modules/arrivalsecupper_2.dmm b/_maps/map_files/tramstation/maintenance_modules/arrivalsecupper_2.dmm index ee5e2a4a69440..ed00e590e9d2e 100644 --- a/_maps/map_files/tramstation/maintenance_modules/arrivalsecupper_2.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/arrivalsecupper_2.dmm @@ -256,7 +256,7 @@ R R "} (11,1,1) = {" -T +a T t j @@ -271,7 +271,7 @@ a a "} (12,1,1) = {" -T +a T t d @@ -286,7 +286,7 @@ a a "} (13,1,1) = {" -T +a T t s @@ -301,7 +301,7 @@ a a "} (14,1,1) = {" -T +a T t N @@ -316,7 +316,7 @@ a a "} (15,1,1) = {" -T +a T t I diff --git a/_maps/map_files/tramstation/maintenance_modules/arrivalsecupper_3.dmm b/_maps/map_files/tramstation/maintenance_modules/arrivalsecupper_3.dmm index 21be0b689bd7c..085542568ac84 100644 --- a/_maps/map_files/tramstation/maintenance_modules/arrivalsecupper_3.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/arrivalsecupper_3.dmm @@ -32,6 +32,9 @@ /obj/effect/spawner/random/engineering/atmospherics_portable, /turf/open/floor/iron/smooth, /area/station/maintenance/department/eva) +"h" = ( +/turf/closed/wall/r_wall, +/area/station/maintenance/department/eva) "k" = ( /obj/effect/turf_decal/sand, /obj/structure/closet, @@ -108,6 +111,13 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/catwalk_floor, /area/station/maintenance/department/eva) +"X" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Security Maintenance Hatch" + }, +/obj/effect/mapping_helpers/airlock/access/any/security/maintenance, +/turf/open/floor/plating, +/area/station/maintenance/department/eva) "Y" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/table, @@ -276,7 +286,7 @@ N N "} (11,1,1) = {" -t +h t L t @@ -291,7 +301,7 @@ a a "} (12,1,1) = {" -t +h r k t @@ -306,7 +316,7 @@ a a "} (13,1,1) = {" -t +h d d t @@ -321,7 +331,7 @@ a a "} (14,1,1) = {" -t +X e e K @@ -336,7 +346,7 @@ a a "} (15,1,1) = {" -t +h Y e t diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 8ffdf89bfbaef..09f7fb52e4cda 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -3302,6 +3302,10 @@ /obj/structure/sign/warning/no_smoking, /turf/closed/wall, /area/station/engineering/atmos) +"asT" = ( +/obj/machinery/air_sensor/engine_chamber, +/turf/open/floor/engine, +/area/station/engineering/supermatter) "asY" = ( /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 4 @@ -4064,6 +4068,8 @@ /area/station/commons/vacant_room) "aBK" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, /turf/open/floor/iron, /area/station/security/brig) "aBL" = ( @@ -4226,14 +4232,14 @@ /turf/open/floor/iron, /area/station/hallway/secondary/exit) "aCM" = ( -/obj/effect/turf_decal/siding/thinplating/dark{ - dir = 5 - }, /obj/machinery/disposal/bin, /obj/structure/disposalpipe/trunk{ dir = 4 }, /obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 1 + }, /turf/open/floor/iron/dark, /area/station/hallway/secondary/exit) "aCR" = ( @@ -5658,6 +5664,10 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/atmos) +"aOW" = ( +/obj/machinery/light/directional/west, +/turf/open/floor/catwalk_floor, +/area/station/security/mechbay) "aPe" = ( /obj/machinery/door/airlock/maintenance_hatch{ name = "Library Maintenance Hatch" @@ -6468,7 +6478,7 @@ /obj/machinery/power/apc/auto_name/directional/north, /obj/structure/cable, /obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, +/turf/open/floor/catwalk_floor, /area/station/medical/virology) "bfa" = ( /obj/effect/turf_decal/trimline/red/filled/line, @@ -6632,6 +6642,11 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/security/interrogation) +"biB" = ( +/obj/effect/decal/cleanable/dirt, +/obj/vehicle/sealed/mecha/ripley/paddy/preset, +/turf/open/floor/iron/recharge_floor, +/area/station/security/mechbay) "biS" = ( /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 6 @@ -7256,6 +7271,13 @@ /obj/structure/cable, /turf/open/space/basic, /area/station/solars/starboard/fore) +"bwu" = ( +/obj/machinery/computer/mech_bay_power_console{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/smooth, +/area/station/security/mechbay) "bwz" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/trimline/neutral/filled/corner{ @@ -7896,6 +7918,14 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/exit) +"bIz" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/machinery/airalarm/directional/north, +/turf/open/floor/iron/smooth, +/area/station/security/mechbay) "bIC" = ( /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 6 @@ -9214,7 +9244,7 @@ /obj/effect/mapping_helpers/airlock/access/all/medical/virology, /obj/structure/cable, /obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, +/turf/open/floor/catwalk_floor, /area/station/medical/virology) "cdr" = ( /obj/effect/turf_decal/trimline/red/filled/line{ @@ -10263,6 +10293,14 @@ }, /turf/open/floor/iron, /area/station/cargo/storage) +"cyb" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/machinery/light/directional/south, +/turf/open/floor/iron/smooth, +/area/station/security/mechbay) "cye" = ( /obj/structure/chair/stool/bar/directional/west, /obj/effect/turf_decal/siding/thinplating/dark{ @@ -13037,7 +13075,12 @@ /obj/structure/disposalpipe/junction/flip{ dir = 1 }, -/turf/closed/wall, +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 5 + }, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/closet/firecloset, +/turf/open/floor/iron/dark, /area/station/hallway/secondary/exit) "dvc" = ( /obj/effect/decal/cleanable/dirt, @@ -13588,6 +13631,18 @@ /obj/machinery/firealarm/directional/east, /turf/open/floor/iron, /area/station/hallway/secondary/command) +"dFN" = ( +/obj/machinery/door/poddoor/shutters{ + id = "secmechbay"; + name = "Security Mech Bay Shutters" + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/plating, +/area/station/security/mechbay) "dFP" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -14621,6 +14676,10 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/service/hydroponics) +"dXH" = ( +/obj/structure/disposalpipe/segment, +/turf/closed/wall, +/area/station/cargo/sorting) "dXM" = ( /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 5 @@ -19159,6 +19218,15 @@ /obj/machinery/atmospherics/pipe/smart/simple/dark/visible, /turf/open/floor/engine/vacuum, /area/station/maintenance/disposal/incinerator) +"fLY" = ( +/obj/machinery/door/poddoor/shutters{ + id = "secmechbay"; + name = "Security Mech Bay Shutters" + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plating, +/area/station/security/mechbay) "fMm" = ( /obj/machinery/atmospherics/pipe/smart/manifold/scrubbers/visible{ dir = 8 @@ -20623,7 +20691,6 @@ /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 1 }, -/obj/machinery/firealarm/directional/north, /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/hallway/secondary/exit) @@ -23906,6 +23973,13 @@ /obj/machinery/light/floor, /turf/open/floor/engine/n2o, /area/station/engineering/atmos) +"hCO" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/station/security/mechbay) "hDj" = ( /obj/machinery/door/airlock/atmos/glass{ name = "Atmospherics Testing Room" @@ -24712,6 +24786,7 @@ /obj/machinery/firealarm/directional/south, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, /turf/open/floor/iron, /area/station/security/brig) "hRK" = ( @@ -25426,6 +25501,13 @@ /obj/effect/turf_decal/stripes/corner, /turf/open/floor/iron/dark, /area/station/service/chapel/monastery) +"ifI" = ( +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 1 + }, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit) "ifN" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -26088,6 +26170,12 @@ }, /turf/open/misc/asteroid, /area/station/asteroid) +"itH" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/oil/slippery, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/smooth, +/area/station/security/mechbay) "itN" = ( /obj/effect/turf_decal/stripes/white/corner{ dir = 1 @@ -29176,6 +29264,13 @@ }, /turf/open/floor/plating, /area/station/medical/storage) +"jwV" = ( +/obj/effect/turf_decal/trimline/red/filled/corner, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/security/brig) "jwX" = ( /obj/structure/railing{ dir = 1 @@ -29937,6 +30032,10 @@ id = "cargoupperbelt" }, /obj/structure/plasticflaps, +/obj/structure/disposaloutlet{ + dir = 1 + }, +/obj/structure/disposalpipe/trunk, /turf/open/floor/plating, /area/station/cargo/sorting) "jKg" = ( @@ -30480,6 +30579,17 @@ "jWs" = ( /turf/closed/wall/r_wall, /area/station/security/execution/transfer) +"jWy" = ( +/obj/machinery/button/door/directional/east{ + name = "Security Mech Garage Door Controls"; + id = "secmechbay"; + req_access = list("security") + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/catwalk_floor, +/area/station/security/mechbay) "jXc" = ( /obj/effect/turf_decal/trimline/yellow/filled/corner{ dir = 8 @@ -31018,6 +31128,17 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/engineering/atmos) +"kcV" = ( +/obj/structure/table, +/obj/effect/decal/cleanable/dirt, +/obj/item/stack/cable_coil{ + amount = 15; + pixel_x = 6; + pixel_y = 6 + }, +/obj/item/stack/cable_coil/cut, +/turf/open/floor/iron/smooth, +/area/station/security/mechbay) "kcZ" = ( /obj/item/kirbyplants/random, /turf/open/floor/carpet, @@ -31153,6 +31274,13 @@ /obj/machinery/light/dim/directional/west, /turf/open/floor/iron, /area/station/science/lower) +"kft" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 1 + }, +/obj/machinery/light/directional/north, +/turf/open/floor/iron, +/area/station/security/brig) "kfD" = ( /obj/effect/turf_decal/sand, /obj/machinery/door/airlock/external{ @@ -31934,8 +32062,8 @@ dir = 6 }, /obj/item/storage/box/donkpockets/donkpocketberry{ - pixel_y = 10; - pixel_x = -6 + pixel_x = -6; + pixel_y = 10 }, /turf/open/floor/iron, /area/station/engineering/break_room) @@ -32761,6 +32889,15 @@ /obj/machinery/airalarm/directional/north, /turf/open/floor/iron/showroomfloor, /area/station/security/lockers) +"kIA" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/obj/item/stack/rods/two, +/obj/machinery/light_switch/directional/west, +/turf/open/floor/iron/smooth, +/area/station/security/mechbay) "kIE" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/white/line{ @@ -33250,6 +33387,7 @@ /obj/effect/landmark/event_spawn, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, /turf/open/floor/iron, /area/station/security/brig) "kRL" = ( @@ -34683,9 +34821,9 @@ "lqu" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; id = "pharmacy_shutters_2"; - name = "Pharmacy Shutters"; - dir = 4 + name = "Pharmacy Shutters" }, /turf/open/floor/plating, /area/station/medical/pharmacy) @@ -35331,8 +35469,12 @@ }, /obj/machinery/airalarm/directional/west, /obj/effect/mapping_helpers/airalarm/mixingchamber_access, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "ordnancefreezer" + }, /turf/open/floor/iron/white, -/area/station/science/ordnance/freezerchamber) +/area/station/science/ordnance) "lBP" = ( /obj/machinery/holopad, /obj/effect/turf_decal/bot, @@ -36369,7 +36511,8 @@ /obj/structure/disposalpipe/sorting/wrap/flip{ dir = 1 }, -/turf/closed/wall, +/obj/structure/falsewall, +/turf/open/floor/plating, /area/station/cargo/sorting) "lTc" = ( /obj/effect/turf_decal/stripes/line, @@ -37105,6 +37248,12 @@ }, /turf/open/floor/iron/white, /area/station/science/lobby) +"mez" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/oil/slippery, +/obj/structure/reagent_dispensers/fueltank, +/turf/open/floor/iron/smooth, +/area/station/security/mechbay) "meA" = ( /obj/machinery/disposal/bin, /obj/effect/turf_decal/trimline/green/filled/line{ @@ -38699,10 +38848,12 @@ /turf/open/floor/iron/checker, /area/station/commons/lounge) "mJQ" = ( -/obj/structure/closet/secure_closet/brig, /obj/effect/turf_decal/trimline/red/filled/line{ dir = 8 }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, /turf/open/floor/iron, /area/station/security/brig) "mKe" = ( @@ -45441,9 +45592,9 @@ "pob" = ( /obj/machinery/smartfridge/chemistry/preloaded, /obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; id = "pharmacy_shutters_2"; - name = "Pharmacy Shutters"; - dir = 4 + name = "Pharmacy Shutters" }, /obj/machinery/door/firedoor, /turf/open/floor/plating, @@ -47436,6 +47587,12 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/command/bridge) +"pWO" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/security/brig) "pWP" = ( /obj/structure/railing{ dir = 8 @@ -48058,8 +48215,8 @@ /obj/machinery/power/apc/auto_name/directional/west, /obj/structure/cable, /obj/item/storage/box/bandages{ - pixel_y = 6; - pixel_x = -6 + pixel_x = -6; + pixel_y = 6 }, /obj/item/storage/box/bodybags{ pixel_x = 3; @@ -49185,12 +49342,17 @@ "qCG" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/atmospherics/pipe/smart/manifold4w/green/visible, -/obj/machinery/firealarm/directional/south, /obj/effect/turf_decal/trimline/yellow/arrow_ccw, /obj/effect/turf_decal/trimline/yellow/arrow_cw{ dir = 1 }, /obj/structure/cable/layer1, +/obj/machinery/airalarm/directional/south, +/obj/effect/mapping_helpers/airalarm/engine_access, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "engine" + }, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, /turf/open/floor/engine, /area/station/engineering/supermatter/room) "qCJ" = ( @@ -50333,6 +50495,27 @@ /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible, /turf/open/floor/iron, /area/station/engineering/atmos) +"qXK" = ( +/obj/structure/table, +/obj/effect/decal/cleanable/dirt, +/obj/item/stock_parts/cell/crap/empty{ + pixel_y = 10; + pixel_x = 6 + }, +/obj/item/stock_parts/cell/crap/empty{ + pixel_y = 2; + pixel_x = 6 + }, +/obj/item/stock_parts/cell/crap/empty{ + pixel_y = 7; + pixel_x = -7 + }, +/obj/item/stock_parts/cell/crap/empty{ + pixel_y = -2; + pixel_x = -2 + }, +/turf/open/floor/iron/smooth, +/area/station/security/mechbay) "qXS" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -50736,6 +50919,13 @@ /obj/machinery/light/directional/east, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"rdN" = ( +/obj/machinery/mech_bay_recharge_port{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/smooth, +/area/station/security/mechbay) "rdO" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, /turf/closed/wall/r_wall, @@ -52250,10 +52440,9 @@ }, /obj/effect/turf_decal/trimline/yellow/arrow_cw, /obj/structure/cable/layer1, -/obj/machinery/airalarm/directional/south, -/obj/effect/mapping_helpers/airalarm/engine_access, +/obj/machinery/firealarm/directional/south, /turf/open/floor/engine, -/area/station/engineering/supermatter) +/area/station/engineering/supermatter/room) "rJE" = ( /obj/machinery/door/airlock/medical/glass{ name = "Medical Freezer" @@ -54418,6 +54607,17 @@ /obj/machinery/light/directional/south, /turf/open/floor/iron, /area/station/science/ordnance/testlab) +"sub" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 10 + }, +/obj/machinery/button/door/directional/south{ + name = "Security Mech Garage Door Controls"; + id = "secmechbay"; + req_access = list("security") + }, +/turf/open/floor/iron, +/area/station/security/brig) "sud" = ( /obj/structure/table, /obj/item/food/cakeslice/birthday, @@ -57875,13 +58075,8 @@ /turf/open/floor/iron/dark, /area/station/service/chapel) "tFk" = ( -/obj/structure/closet/secure_closet/brig, -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 9 - }, -/obj/machinery/light/directional/west, -/turf/open/floor/iron, -/area/station/security/brig) +/turf/closed/wall/r_wall, +/area/station/security/mechbay) "tFB" = ( /obj/structure/cable, /turf/open/floor/iron/white, @@ -61059,6 +61254,13 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/entry) +"uGn" = ( +/obj/effect/turf_decal/trimline/red/filled/line, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/security/brig) "uGo" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/trimline/purple/filled/line{ @@ -61577,6 +61779,13 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) +"uNJ" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/catwalk_floor, +/area/station/security/mechbay) "uNK" = ( /obj/effect/turf_decal/trimline/red/filled/line{ dir = 1 @@ -62044,8 +62253,12 @@ /obj/machinery/airalarm/directional/south, /obj/effect/mapping_helpers/airalarm/mixingchamber_access, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airalarm/tlv_no_checks, +/obj/effect/mapping_helpers/airalarm/link{ + chamber_id = "ordnanceburn" + }, /turf/open/floor/iron/white, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "uXv" = ( /obj/effect/turf_decal/stripes/corner{ dir = 4 @@ -62067,6 +62280,12 @@ }, /turf/open/space/openspace, /area/station/solars/port) +"uXN" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/disposalpipe/segment, +/obj/effect/spawner/random/maintenance/three, +/turf/open/floor/plating, +/area/station/cargo/sorting) "uYa" = ( /obj/machinery/skill_station, /turf/open/floor/iron/grimy, @@ -63612,6 +63831,10 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/hallway/primary/tram/right) +"vyO" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/catwalk_floor, +/area/station/security/mechbay) "vyR" = ( /obj/effect/spawner/random/structure/closet_private, /turf/open/floor/carpet, @@ -65922,8 +66145,8 @@ /area/station/hallway/secondary/service) "wrJ" = ( /obj/structure/railing{ - layer = 3.1; - dir = 4 + dir = 4; + layer = 3.1 }, /obj/machinery/netpod, /turf/open/floor/catwalk_floor/iron_dark, @@ -67650,9 +67873,9 @@ pixel_x = -7 }, /obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; id = "pharmacy_shutters_2"; - name = "Pharmacy Shutters"; - dir = 4 + name = "Pharmacy Shutters" }, /obj/machinery/door/firedoor, /obj/machinery/door/window/left/directional/south{ @@ -68421,6 +68644,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/medical/virology) +"xsg" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/smooth, +/area/station/security/mechbay) "xsh" = ( /obj/machinery/door/airlock/medical{ name = "Surgery" @@ -69520,6 +69747,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/security/checkpoint/science) +"xNL" = ( +/obj/structure/table, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, +/obj/machinery/power/apc/auto_name/directional/east, +/obj/item/crowbar, +/turf/open/floor/iron/smooth, +/area/station/security/mechbay) "xNP" = ( /obj/structure/chair/stool/bar/directional/south, /turf/open/floor/eighties, @@ -101345,7 +101580,7 @@ svA jBn bKt gqf -bKt +asT dQn bKt frN @@ -149067,11 +149302,11 @@ aac aaa aaa aaa -aaa -aaa -aaa -aaa -aaa +tFk +tFk +tFk +tFk +tFk aaa aaa abM @@ -149321,14 +149556,14 @@ aac aac aac aac -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +tFk +tFk +tFk +tFk +biB +rdN +bwu +tFk aaa aaa abM @@ -149578,14 +149813,14 @@ aac aac aac aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +tFk +mez +kIA +aOW +xsg +vyO +cyb +tFk aaa aaa abM @@ -149835,14 +150070,14 @@ aac aac aaa aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +tFk +bIz +hCO +jWy +hCO +uNJ +itH +tFk aaa aaa abM @@ -150092,14 +150327,14 @@ aaa aaa aaa yji -yji -yji -yji -yji -aaa -aaa -aaa -aaa +tFk +dFN +fLY +tFk +kcV +xNL +qXK +tFk aaa aaa abM @@ -150349,9 +150584,9 @@ aaa aaa aaa yji -tFk +wOb mJQ -dTL +sub yji run run @@ -150606,8 +150841,8 @@ aaa aaa aaa yji -nDj -dkO +kft +aBK rGN dTL mjM @@ -151378,7 +151613,7 @@ qhI kDS mOZ wvG -gvQ +pWO kEc ntp mjM @@ -151892,7 +152127,7 @@ avA xSX xDQ iko -gvQ +pWO iGJ gki nca @@ -152149,7 +152384,7 @@ avB jPx xDQ rOh -iBO +jwV pNI gki nca @@ -152663,7 +152898,7 @@ avD hYT xSX rOh -rco +uGn awp hWL vgl @@ -185071,8 +185306,8 @@ skX fpU fpU jKb -fpU -eos +dXH +uXN lSQ duO goC @@ -185332,7 +185567,7 @@ uno uno uno lCy -vPB +ifI uCO aDK bMb diff --git a/_maps/modular_generic/beach_l_ribs.dmm b/_maps/modular_generic/beach_l_ribs.dmm new file mode 100644 index 0000000000000..ea0a2a9abd09c --- /dev/null +++ b/_maps/modular_generic/beach_l_ribs.dmm @@ -0,0 +1,828 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"av" = ( +/obj/effect/turf_decal/weather/sand, +/obj/effect/turf_decal/weather/sand{ + dir = 8 + }, +/obj/structure/flora/ash/leaf_shroom{ + icon_state = "s_mushroom4" + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 10 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"aJ" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"bT" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/obj/structure/flora/rock/pile/style_3, +/turf/open/misc/beach/sand, +/area/template_noop) +"bV" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/vehicle/ridden/atv{ + dir = 4 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"fi" = ( +/obj/structure/reagent_dispensers/fueltank, +/obj/effect/decal/cleanable/fuel_pool, +/obj/effect/decal/cleanable/oil, +/turf/open/misc/beach/sand, +/area/template_noop) +"fw" = ( +/obj/effect/turf_decal/trimline/dark/corner{ + dir = 8 + }, +/mob/living/basic/mining/goldgrub/baby, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"gP" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"gR" = ( +/obj/item/fuel_pellet{ + pixel_x = 10; + pixel_y = 8 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"ic" = ( +/obj/structure/flora/rock/pile/style_random, +/obj/effect/turf_decal/weather/sand{ + dir = 6 + }, +/obj/item/stack/sheet/mineral/sandbags, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 6 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid10" + }, +/area/template_noop) +"iD" = ( +/obj/structure/flora/rock/pile/style_3, +/turf/open/misc/beach/sand, +/area/template_noop) +"jT" = ( +/obj/item/fish/boned, +/turf/open/misc/asteroid{ + icon_state = "asteroid_dug" + }, +/area/template_noop) +"ky" = ( +/obj/structure/flora/ash/cacti{ + icon_state = "cactus_fruit"; + pixel_x = -12 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 10 + }, +/obj/item/flashlight/lantern{ + icon_state = "floodlight" + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid11" + }, +/area/template_noop) +"ml" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 6 + }, +/obj/structure/frame/machine/secured, +/obj/item/stack/cable_coil/cut, +/turf/open/misc/beach/sand, +/area/template_noop) +"mP" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"oX" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/engineering/toolbox{ + pixel_x = 5; + pixel_y = -14 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"ph" = ( +/obj/item/knife/combat/bone, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 8 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid_dug" + }, +/area/template_noop) +"pk" = ( +/obj/structure/flora/rock/pile/style_3, +/obj/effect/turf_decal/weather/sand, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"pr" = ( +/obj/effect/turf_decal/trimline/dark/corner{ + dir = 4 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"pZ" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 8 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"qD" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 9 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"tr" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/structure/flora/ash/cap_shroom{ + icon_state = "l_mushroom2p" + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 5 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"tA" = ( +/obj/effect/turf_decal/weather/sand, +/obj/effect/turf_decal/trimline/dark/warning, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"uf" = ( +/obj/structure/flora/rock/pile/style_2, +/obj/effect/turf_decal/weather/sand{ + dir = 9 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 6 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"uy" = ( +/obj/item/stack/sheet/bone, +/mob/living/basic/mining/goldgrub/baby, +/turf/open/misc/asteroid{ + icon_state = "asteroid_dug" + }, +/area/template_noop) +"uS" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 6 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/structure/flora/rock/pile/style_random, +/turf/open/misc/beach/sand, +/area/template_noop) +"wf" = ( +/obj/structure/flora/ash/cacti{ + icon_state = "cactus3p" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/asteroid{ + icon_state = "asteroid7" + }, +/area/template_noop) +"wy" = ( +/obj/item/chair/wood, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid6" + }, +/area/template_noop) +"wI" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 9 + }, +/obj/structure/holosign/barrier/engineering, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"xA" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 1 + }, +/obj/item/modular_computer/laptop{ + icon_state = "laptop"; + pixel_y = 16; + pixel_x = 4 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"xG" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 9 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/structure/holosign/barrier/engineering, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"xS" = ( +/obj/effect/turf_decal/trimline/dark/corner{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"xU" = ( +/obj/structure/chair/wood{ + dir = 8 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"zh" = ( +/obj/structure/flora/ash/cacti{ + icon_state = "cactus2" + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid7" + }, +/area/template_noop) +"zH" = ( +/turf/open/misc/asteroid{ + icon_state = "asteroid2" + }, +/area/template_noop) +"Cv" = ( +/obj/structure/flora/ash/cacti{ + icon_state = "cactus_fruit"; + pixel_y = 24 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 9 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/machinery/exoscanner, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"Ds" = ( +/obj/structure/flora/ash/cacti, +/obj/effect/turf_decal/trimline/dark/corner{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"DX" = ( +/obj/structure/flora/rock/pile/style_2, +/turf/open/misc/beach/sand, +/area/template_noop) +"Eo" = ( +/obj/structure/flora/ash/cacti{ + icon_state = "cactus_fruit"; + pixel_y = 24 + }, +/obj/structure/water_source/puddle, +/obj/structure/flora/bush/reed/style_random{ + pixel_y = 6 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"ED" = ( +/obj/structure/flora/rock/pile/style_random, +/obj/effect/turf_decal/weather/sand{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 8 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"Ff" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 9 + }, +/obj/structure/holosign/barrier/engineering, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"Fi" = ( +/obj/structure/statue/bone/rib{ + dir = 1 + }, +/obj/effect/decal/cleanable/xenoblood{ + icon_state = "xfloor4" + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid3" + }, +/area/template_noop) +"Ft" = ( +/obj/structure/rack, +/obj/item/shovel, +/obj/item/shovel{ + pixel_y = 3 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"FD" = ( +/obj/effect/turf_decal/weather/sand, +/turf/open/misc/beach/sand, +/area/template_noop) +"Gh" = ( +/obj/structure/flora/ash/cacti{ + icon_state = "cactus_fruit"; + pixel_x = -12 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 5 + }, +/obj/item/flashlight/lantern{ + icon_state = "floodlight" + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid11" + }, +/area/template_noop) +"Go" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/obj/vehicle/ridden/atv{ + dir = 4 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"Iw" = ( +/obj/item/fishing_hook/bone, +/turf/open/misc/asteroid{ + icon_state = "asteroid_dug" + }, +/area/template_noop) +"Jy" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"JM" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 9 + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 9 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid_dug" + }, +/area/template_noop) +"La" = ( +/obj/structure/flora/ash/cacti{ + icon_state = "cactus_fruit"; + pixel_y = 24 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/asteroid{ + icon_state = "asteroid10" + }, +/area/template_noop) +"LD" = ( +/obj/effect/turf_decal/trimline/dark/corner, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"LK" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 6 + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 6 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"Mg" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"NO" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 9 + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 9 + }, +/obj/effect/decal/cleanable/dirt, +/obj/item/flashlight/lantern{ + icon_state = "floodlight" + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid9" + }, +/area/template_noop) +"Oi" = ( +/obj/structure/table_frame, +/obj/effect/decal/cleanable/glass, +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 5 + }, +/obj/item/binoculars, +/turf/open/misc/asteroid{ + icon_state = "asteroid5" + }, +/area/template_noop) +"OJ" = ( +/obj/structure/statue/bone/rib, +/obj/effect/decal/cleanable/xenoblood{ + icon_state = "xfloor5" + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"OM" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"OW" = ( +/obj/effect/turf_decal/weather/sand, +/obj/vehicle/ridden/atv, +/turf/open/misc/beach/sand, +/area/template_noop) +"PS" = ( +/obj/structure/statue/bone/rib, +/obj/effect/decal/cleanable/xenoblood{ + icon_state = "xfloor7" + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 1 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid8" + }, +/area/template_noop) +"Rs" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 1 + }, +/obj/structure/flora/rock/pile/style_3, +/turf/open/misc/beach/sand, +/area/template_noop) +"RG" = ( +/obj/structure/firepit{ + icon_state = "firepit" + }, +/obj/item/reagent_containers/cup/glass/waterbottle/empty{ + pixel_y = 11; + pixel_x = 11 + }, +/obj/item/reagent_containers/cup/glass/waterbottle/empty{ + pixel_y = 16 + }, +/obj/effect/decal/cleanable/ash{ + pixel_x = -9 + }, +/obj/effect/decal/cleanable/ash, +/obj/effect/decal/cleanable/ash{ + pixel_x = 7 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/asteroid{ + icon_state = "asteroid7" + }, +/area/template_noop) +"SE" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 6 + }, +/obj/item/key/atv{ + pixel_y = 4 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"Tt" = ( +/obj/structure/flora/ash/cacti{ + icon_state = "cactus_fruit"; + pixel_x = -12 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 6 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/structure/holosign/barrier/engineering, +/turf/open/misc/asteroid{ + icon_state = "asteroid9" + }, +/area/template_noop) +"TL" = ( +/obj/structure/flora/rock/pile/style_random, +/turf/open/misc/beach/sand, +/area/template_noop) +"Ua" = ( +/turf/open/misc/beach/sand, +/area/template_noop) +"UJ" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 6 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/mob/living/basic/mining/goldgrub, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"Vw" = ( +/obj/structure/flora/ash/cacti{ + icon_state = "cactus4" + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"Wd" = ( +/obj/effect/turf_decal/weather/sand, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"WA" = ( +/obj/effect/turf_decal/trimline/dark/corner, +/turf/open/misc/asteroid{ + icon_state = "asteroid8" + }, +/area/template_noop) +"YD" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 1 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"YK" = ( +/obj/item/chair/wood{ + dir = 4 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 1 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid10" + }, +/area/template_noop) +"YQ" = ( +/obj/structure/statue/bone/rib{ + dir = 1 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/obj/effect/decal/cleanable/xenoblood{ + icon_state = "xfloor5" + }, +/obj/effect/turf_decal/trimline/dark/warning{ + dir = 6 + }, +/turf/open/misc/asteroid{ + icon_state = "asteroid0" + }, +/area/template_noop) +"ZO" = ( +/turf/template_noop, +/area/template_noop) + +(1,1,1) = {" +ZO +ZO +ZO +ZO +ZO +ZO +ZO +ZO +ZO +ZO +aJ +"} +(2,1,1) = {" +ZO +Ua +gR +bT +Go +Jy +oX +mP +Ua +Ua +ZO +"} +(3,1,1) = {" +ZO +fi +SE +NO +ED +av +ml +xG +bV +TL +ZO +"} +(4,1,1) = {" +ZO +Wd +wI +PS +jT +fw +La +ph +ky +gP +ZO +"} +(5,1,1) = {" +ZO +DX +UJ +YK +zh +zH +OJ +Vw +pk +YD +ZO +"} +(6,1,1) = {" +ZO +OW +JM +xS +Eo +RG +uy +WA +LK +xA +ZO +"} +(7,1,1) = {" +ZO +Wd +tr +pr +Fi +xU +wf +tA +Cv +Ua +ZO +"} +(8,1,1) = {" +ZO +OM +uS +Gh +Ds +Iw +LD +YQ +wy +Rs +ZO +"} +(9,1,1) = {" +ZO +FD +uf +Ff +Oi +Ft +ic +qD +Tt +YD +ZO +"} +(10,1,1) = {" +ZO +Ua +pZ +iD +Mg +pZ +Mg +Ua +pZ +Ua +ZO +"} +(11,1,1) = {" +ZO +ZO +ZO +ZO +ZO +ZO +ZO +ZO +ZO +ZO +ZO +"} diff --git a/_maps/modular_generic/beach_m_oasis.dmm b/_maps/modular_generic/beach_m_oasis.dmm new file mode 100644 index 0000000000000..80d9b7dae578f --- /dev/null +++ b/_maps/modular_generic/beach_m_oasis.dmm @@ -0,0 +1,341 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/structure/flora/bush/sparsegrass{ + pixel_y = 9; + pixel_x = -3 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"b" = ( +/turf/open/misc/beach/coast/corner{ + dir = 1 + }, +/area/template_noop) +"c" = ( +/obj/structure/flora/tree/palm, +/obj/structure/flora/bush/fullgrass/style_3, +/turf/open/misc/beach/sand, +/area/template_noop) +"d" = ( +/turf/template_noop, +/area/template_noop) +"e" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/rock, +/turf/open/misc/beach/sand, +/area/template_noop) +"f" = ( +/obj/structure/flora/bush/sparsegrass/style_2{ + pixel_x = 6; + pixel_y = -14 + }, +/turf/open/misc/beach/coast/corner{ + dir = 4 + }, +/area/template_noop) +"g" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"h" = ( +/obj/structure/flora/tree/palm, +/obj/structure/flora/coconuts, +/turf/open/misc/beach/sand, +/area/template_noop) +"j" = ( +/obj/structure/flora/rock/pile, +/turf/open/misc/beach/sand, +/area/template_noop) +"k" = ( +/obj/structure/flora/rock/style_2, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"l" = ( +/obj/structure/flora/bush/grassy, +/turf/open/misc/beach/coast/corner{ + dir = 8 + }, +/area/template_noop) +"m" = ( +/obj/structure/flora/bush/sparsegrass/style_3{ + pixel_y = -6; + pixel_x = -6 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"n" = ( +/turf/open/misc/beach/coast/corner, +/area/template_noop) +"p" = ( +/turf/open/misc/beach/coast{ + dir = 5 + }, +/area/template_noop) +"q" = ( +/obj/structure/flora/bush/stalky/style_random{ + pixel_x = -7 + }, +/turf/open/misc/beach/coast{ + dir = 8 + }, +/area/template_noop) +"s" = ( +/obj/structure/flora/bush/grassy/style_4{ + pixel_y = 11; + pixel_x = 5 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"t" = ( +/turf/open/misc/beach/coast/corner{ + dir = 4 + }, +/area/template_noop) +"u" = ( +/obj/structure/flora/bush/sparsegrass/style_2{ + pixel_y = 3; + pixel_x = 4 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"w" = ( +/turf/open/water/beach, +/area/template_noop) +"y" = ( +/turf/open/misc/beach/coast{ + dir = 1 + }, +/area/template_noop) +"z" = ( +/obj/structure/flora/bush/reed/style_random{ + pixel_x = -2; + pixel_y = 6 + }, +/turf/open/misc/beach/coast{ + dir = 10 + }, +/area/template_noop) +"C" = ( +/obj/item/toy/beach_ball, +/turf/open/water/beach, +/area/template_noop) +"D" = ( +/obj/structure/flora/coconuts, +/turf/open/misc/beach/coast/corner{ + dir = 8 + }, +/area/template_noop) +"E" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"F" = ( +/turf/open/misc/beach/sand, +/area/template_noop) +"G" = ( +/obj/structure/flora/bush/stalky/style_random{ + pixel_y = 6 + }, +/turf/open/misc/beach/coast, +/area/template_noop) +"H" = ( +/obj/structure/flora/bush/sparsegrass{ + pixel_x = 12; + pixel_y = -4 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"I" = ( +/obj/structure/fluff/beach_umbrella, +/turf/open/misc/beach/sand, +/area/template_noop) +"J" = ( +/turf/open/misc/beach/coast{ + dir = 6 + }, +/area/template_noop) +"K" = ( +/obj/structure/flora/rock/pile/style_2, +/turf/open/misc/beach/sand, +/area/template_noop) +"M" = ( +/obj/structure/flora/bush/sparsegrass/style_3{ + pixel_y = 1; + pixel_x = 1 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"N" = ( +/obj/item/pillow{ + pixel_y = 7; + pixel_x = -2 + }, +/obj/item/binoculars{ + pixel_x = -6; + pixel_y = -12 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 8 + }, +/turf/open/floor/carpet/cyan, +/area/template_noop) +"O" = ( +/obj/structure/flora/bush/sparsegrass/style_2{ + pixel_y = 9; + pixel_x = -4 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"P" = ( +/obj/structure/flora/tree/palm/style_2, +/turf/open/misc/beach/sand, +/area/template_noop) +"Q" = ( +/obj/structure/flora/bush/fullgrass/style_2, +/turf/open/misc/beach/sand, +/area/template_noop) +"R" = ( +/obj/item/reagent_containers/cup/glass/bottle/beer/almost_empty{ + pixel_y = 2; + pixel_x = 16 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 6 + }, +/turf/open/floor/carpet/cyan, +/area/template_noop) +"T" = ( +/obj/structure/flora/bush/reed/style_random{ + pixel_y = 8 + }, +/turf/open/misc/beach/coast{ + dir = 9 + }, +/area/template_noop) +"U" = ( +/obj/structure/flora/bush/sparsegrass/style_2, +/turf/open/misc/beach/sand, +/area/template_noop) +"W" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/rock/pile, +/turf/open/misc/beach/sand, +/area/template_noop) +"X" = ( +/obj/structure/flora/tree/palm/style_2{ + pixel_x = -5 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"Y" = ( +/turf/open/misc/beach/coast{ + dir = 4 + }, +/area/template_noop) +"Z" = ( +/obj/structure/flora/bush/sparsegrass/style_2{ + pixel_y = 2 + }, +/turf/open/misc/beach/sand, +/area/template_noop) + +(1,1,1) = {" +d +d +d +d +d +d +d +d +g +"} +(2,1,1) = {" +d +k +F +E +K +F +U +u +d +"} +(3,1,1) = {" +d +F +P +n +l +s +X +a +d +"} +(4,1,1) = {" +d +N +R +G +p +Y +D +E +d +"} +(5,1,1) = {" +d +I +n +J +w +T +f +j +d +"} +(6,1,1) = {" +d +E +b +z +C +y +c +Q +d +"} +(7,1,1) = {" +d +H +K +b +q +t +m +M +d +"} +(8,1,1) = {" +d +F +Z +O +h +e +W +F +d +"} +(9,1,1) = {" +d +d +d +d +d +d +d +d +d +"} diff --git a/_maps/modular_generic/beach_m_shipping.dmm b/_maps/modular_generic/beach_m_shipping.dmm new file mode 100644 index 0000000000000..a05aa53fec7cb --- /dev/null +++ b/_maps/modular_generic/beach_m_shipping.dmm @@ -0,0 +1,440 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/spawner/random/structure/shipping_container, +/obj/effect/turf_decal/weather/sand{ + dir = 8 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"b" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/weather/sand, +/obj/effect/spawner/random/trash/box, +/turf/open/misc/beach/sand, +/area/template_noop) +"c" = ( +/obj/effect/spawner/random/trash/botanical_waste, +/obj/effect/turf_decal/weather/sand{ + dir = 1 + }, +/obj/effect/decal/cleanable/generic, +/turf/open/misc/beach/sand, +/area/template_noop) +"d" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/confetti, +/obj/item/reagent_containers/spray/chemsprayer/party, +/turf/open/misc/beach/sand, +/area/template_noop) +"e" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 1 + }, +/turf/open/misc/beach/coast, +/area/template_noop) +"f" = ( +/turf/open/misc/beach/coast, +/area/template_noop) +"g" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/effect/decal/cleanable/confetti, +/turf/open/misc/sandy_dirt, +/area/template_noop) +"h" = ( +/obj/effect/spawner/random/structure/crate, +/obj/effect/turf_decal/weather/sand{ + dir = 8 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/obj/effect/decal/cleanable/confetti, +/obj/item/reagent_containers/cup/glass/bottle/beer{ + pixel_y = 6; + pixel_x = 18 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"i" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/effect/spawner/random/trash/hobo_squat, +/obj/item/reagent_containers/cup/glass/bottle/beer{ + pixel_y = 11; + pixel_x = 18 + }, +/turf/open/misc/sandy_dirt, +/area/template_noop) +"j" = ( +/obj/structure/fluff/beach_umbrella/engine, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/weather/sand{ + dir = 8 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"k" = ( +/obj/effect/spawner/random/trash, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/weather/sand, +/obj/effect/decal/cleanable/generic, +/turf/open/misc/beach/sand, +/area/template_noop) +"l" = ( +/obj/effect/spawner/random/structure/crate, +/obj/effect/turf_decal/weather/sand, +/turf/open/misc/beach/sand, +/area/template_noop) +"m" = ( +/turf/open/misc/beach/coast{ + dir = 6 + }, +/area/template_noop) +"n" = ( +/turf/open/misc/beach/coast/corner, +/area/template_noop) +"p" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"q" = ( +/turf/open/misc/beach/coast{ + dir = 1 + }, +/area/template_noop) +"s" = ( +/obj/structure/flora/ash/cacti{ + icon_state = "cactus3p" + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"t" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"u" = ( +/obj/structure/flora/bush/stalky/style_random, +/turf/open/water/beach, +/area/template_noop) +"v" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 1 + }, +/obj/structure/flora/ash/cacti{ + icon_state = "cactus2" + }, +/turf/open/misc/beach/sand, +/area/template_noop) +"w" = ( +/obj/item/toy/beach_ball, +/turf/open/water/beach, +/area/template_noop) +"x" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 8 + }, +/obj/item/chair/stool/bar, +/obj/effect/decal/cleanable/generic, +/turf/open/misc/beach/sand, +/area/template_noop) +"z" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"A" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/weather/sand, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = 9; + pixel_y = 21 + }, +/obj/item/clothing/head/costume/party/festive, +/turf/open/misc/beach/sand, +/area/template_noop) +"B" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/turf/open/misc/beach/coast{ + dir = 8 + }, +/area/template_noop) +"C" = ( +/turf/open/misc/beach/coast/corner{ + dir = 4 + }, +/area/template_noop) +"D" = ( +/turf/open/misc/beach/coast{ + dir = 9 + }, +/area/template_noop) +"E" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 8 + }, +/turf/open/misc/beach/coast{ + dir = 4 + }, +/area/template_noop) +"F" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/effect/spawner/random/trash/mess, +/turf/open/misc/sandy_dirt, +/area/template_noop) +"G" = ( +/obj/structure/flora/rock/pile/style_random, +/turf/open/water/beach, +/area/template_noop) +"H" = ( +/turf/open/misc/beach/coast{ + dir = 8 + }, +/area/template_noop) +"I" = ( +/obj/structure/fluff/beach_umbrella/cap, +/turf/open/misc/beach/coast/corner{ + dir = 8 + }, +/area/template_noop) +"J" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/confetti, +/obj/item/clothing/mask/party_horn, +/turf/open/misc/beach/sand, +/area/template_noop) +"K" = ( +/turf/open/misc/beach/coast/corner{ + dir = 1 + }, +/area/template_noop) +"L" = ( +/obj/effect/spawner/random/trash, +/obj/effect/turf_decal/weather/sand{ + dir = 1 + }, +/obj/effect/decal/cleanable/generic, +/turf/open/misc/beach/sand, +/area/template_noop) +"M" = ( +/turf/template_noop, +/area/template_noop) +"N" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/effect/spawner/random/structure/chair_flipped, +/turf/open/misc/sandy_dirt, +/area/template_noop) +"O" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/structure/rack, +/obj/item/circuitboard/machine/sleeper/party, +/turf/open/misc/sandy_dirt, +/area/template_noop) +"P" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/entertainment/arcade{ + dir = 4; + pixel_x = -3; + pixel_y = 7 + }, +/turf/open/misc/sandy_dirt, +/area/template_noop) +"Q" = ( +/obj/effect/spawner/random/trash, +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/obj/effect/decal/cleanable/generic, +/turf/open/misc/beach/sand, +/area/template_noop) +"R" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 1 + }, +/turf/open/misc/beach/coast/corner, +/area/template_noop) +"S" = ( +/obj/effect/spawner/random/structure/crate, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = 9; + pixel_y = 21 + }, +/turf/open/misc/sandy_dirt, +/area/template_noop) +"T" = ( +/turf/open/misc/beach/coast{ + dir = 4 + }, +/area/template_noop) +"U" = ( +/obj/structure/flora/rock/pile/style_2, +/turf/open/water/beach, +/area/template_noop) +"V" = ( +/turf/open/misc/beach/sand, +/area/template_noop) +"W" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/spawner/random/trash/mess, +/turf/open/misc/sandy_dirt, +/area/template_noop) +"X" = ( +/obj/effect/turf_decal/weather/sand, +/turf/open/misc/beach/coast{ + dir = 1 + }, +/area/template_noop) +"Y" = ( +/obj/effect/turf_decal/weather/sand, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/beach/sand, +/area/template_noop) +"Z" = ( +/obj/effect/spawner/random/structure/shipping_container, +/turf/open/misc/beach/sand, +/area/template_noop) + +(1,1,1) = {" +M +M +M +M +M +M +M +M +z +"} +(2,1,1) = {" +M +k +W +c +b +i +v +d +M +"} +(3,1,1) = {" +M +Z +h +n +T +E +I +Q +M +"} +(4,1,1) = {" +M +Y +N +e +w +G +X +S +M +"} +(5,1,1) = {" +M +p +j +f +u +D +C +a +M +"} +(6,1,1) = {" +M +P +R +m +U +q +t +V +M +"} +(7,1,1) = {" +M +x +K +H +B +C +g +p +M +"} +(8,1,1) = {" +M +J +s +A +F +L +l +O +M +"} +(9,1,1) = {" +M +M +M +M +M +M +M +M +M +"} diff --git a/_maps/modular_generic/ice_l_storage.dmm b/_maps/modular_generic/ice_l_storage.dmm new file mode 100644 index 0000000000000..321e50266429d --- /dev/null +++ b/_maps/modular_generic/ice_l_storage.dmm @@ -0,0 +1,458 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"b" = ( +/obj/structure/railing/corner, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plastic, +/area/template_noop) +"d" = ( +/obj/effect/turf_decal/bot/right, +/obj/effect/spawner/random/structure/crate_abandoned, +/turf/open/floor/plating, +/area/template_noop) +"f" = ( +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/template_noop) +"g" = ( +/obj/structure/broken_flooring/singular/directional/east, +/turf/open/floor/plating, +/area/template_noop) +"h" = ( +/obj/item/key/atv{ + pixel_x = -8; + pixel_y = -5 + }, +/obj/item/key/atv{ + pixel_y = -9 + }, +/obj/item/key/atv{ + pixel_y = -4; + pixel_x = 8 + }, +/turf/closed/wall/ice, +/area/template_noop) +"i" = ( +/obj/structure/railing{ + layer = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/space_heater, +/turf/open/floor/plastic, +/area/template_noop) +"j" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"k" = ( +/turf/open/floor/plating, +/area/template_noop) +"l" = ( +/obj/structure/reagent_dispensers/fueltank/large, +/obj/effect/turf_decal/box, +/turf/open/floor/plating, +/area/template_noop) +"m" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/template_noop) +"n" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/crate_loot, +/turf/open/floor/plating, +/area/template_noop) +"p" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/crate_abandoned, +/turf/open/floor/plating, +/area/template_noop) +"q" = ( +/obj/machinery/door/poddoor/shutters{ + id = "modular_room_1"; + name = "Garage Door" + }, +/turf/open/floor/plating, +/area/template_noop) +"r" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/template_noop) +"s" = ( +/obj/structure/table, +/obj/item/storage/fancy/donut_box, +/obj/machinery/button/door/directional/north{ + id = "modular_room_1" + }, +/turf/open/floor/plastic, +/area/template_noop) +"t" = ( +/obj/structure/table, +/obj/item/pizzabox/meat{ + pixel_x = -3; + pixel_y = 8 + }, +/obj/machinery/computer/security/telescreen/entertainment/directional/north, +/turf/open/floor/plastic, +/area/template_noop) +"u" = ( +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/structure/crate_loot, +/turf/open/floor/plating, +/area/template_noop) +"v" = ( +/turf/closed/wall, +/area/template_noop) +"w" = ( +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/template_noop) +"x" = ( +/obj/item/trash/boritos/red{ + pixel_y = 9; + pixel_x = -17 + }, +/obj/item/trash/can, +/obj/effect/decal/cleanable/dirt, +/obj/structure/railing{ + layer = 4 + }, +/turf/open/floor/plastic, +/area/template_noop) +"y" = ( +/obj/structure/closet/crate/bin, +/obj/effect/decal/cleanable/dirt, +/obj/structure/railing{ + layer = 4 + }, +/turf/open/floor/plastic, +/area/template_noop) +"z" = ( +/obj/structure/stairs{ + dir = 1 + }, +/obj/structure/railing{ + dir = 4 + }, +/turf/open/floor/plating, +/area/template_noop) +"A" = ( +/obj/structure/rack, +/obj/item/weldingtool/hugetank, +/turf/open/floor/plating, +/area/template_noop) +"B" = ( +/obj/effect/turf_decal/box, +/obj/vehicle/ridden/atv{ + dir = 8 + }, +/obj/machinery/light/dim/directional/east, +/turf/open/floor/plating, +/area/template_noop) +"C" = ( +/obj/machinery/door/airlock/mining{ + name = "Warehouse" + }, +/turf/open/floor/plating, +/area/template_noop) +"D" = ( +/obj/structure/railing{ + layer = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plastic, +/area/template_noop) +"F" = ( +/obj/effect/turf_decal/box, +/obj/vehicle/ridden/atv{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/template_noop) +"G" = ( +/turf/closed/wall/ice, +/area/template_noop) +"H" = ( +/obj/structure/closet{ + name = "Fuel Tank Closet" + }, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/shoes/winterboots{ + pixel_y = -10 + }, +/obj/item/clothing/shoes/winterboots{ + pixel_y = -10 + }, +/obj/item/clothing/shoes/winterboots{ + pixel_y = -10 + }, +/turf/open/floor/plastic, +/area/template_noop) +"J" = ( +/obj/structure/chair/plastic{ + dir = 1 + }, +/obj/structure/railing{ + layer = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plastic, +/area/template_noop) +"K" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/crate_loot, +/obj/machinery/light/dim/directional/west, +/turf/open/floor/plating, +/area/template_noop) +"L" = ( +/obj/effect/spawner/random/trash/mess, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plastic, +/area/template_noop) +"M" = ( +/obj/effect/turf_decal/bot/right, +/obj/structure/closet/crate/large, +/obj/item/crowbar/large/heavy, +/turf/open/floor/plating, +/area/template_noop) +"N" = ( +/obj/structure/rack, +/obj/item/fuel_pellet, +/obj/item/fuel_pellet{ + pixel_y = -7; + pixel_x = 7 + }, +/obj/item/fuel_pellet{ + pixel_x = -5; + pixel_y = -4 + }, +/turf/open/floor/plating, +/area/template_noop) +"O" = ( +/obj/structure/sign/warning/directional/north, +/turf/template_noop, +/area/template_noop) +"P" = ( +/obj/effect/turf_decal/bot/left, +/obj/structure/closet/crate/large, +/obj/machinery/portable_atmospherics/canister/air, +/turf/open/floor/plating, +/area/template_noop) +"Q" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/caution/stand_clear{ + dir = 1 + }, +/turf/open/floor/plating, +/area/template_noop) +"R" = ( +/obj/effect/turf_decal/bot/left, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/structure/crate_empty, +/turf/open/floor/plating, +/area/template_noop) +"T" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/stairs{ + dir = 1 + }, +/obj/structure/railing{ + dir = 8 + }, +/turf/open/floor/plating, +/area/template_noop) +"U" = ( +/obj/structure/railing/corner{ + dir = 8 + }, +/turf/open/floor/plastic, +/area/template_noop) +"V" = ( +/obj/structure/noticeboard/directional/north, +/obj/structure/broken_flooring/singular/directional/west, +/turf/open/floor/plating, +/area/template_noop) +"W" = ( +/obj/effect/spawner/random/trash/mess, +/turf/open/floor/plating, +/area/template_noop) +"X" = ( +/obj/structure/table, +/obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/cup/glass/bottle/beer/almost_empty{ + pixel_x = 11; + pixel_y = 4 + }, +/obj/item/flashlight/lamp, +/turf/open/floor/plastic, +/area/template_noop) +"Y" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/box, +/obj/vehicle/ridden/atv{ + dir = 8 + }, +/obj/machinery/light/dim/directional/east, +/turf/open/floor/plating, +/area/template_noop) +"Z" = ( +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/turf/open/floor/plating, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +j +"} +(2,1,1) = {" +a +G +v +v +G +G +v +v +G +G +a +"} +(3,1,1) = {" +a +G +X +i +M +n +K +p +d +G +a +"} +(4,1,1) = {" +a +v +t +J +P +n +n +u +R +G +O +"} +(5,1,1) = {" +a +v +s +x +Z +w +w +f +Z +q +a +"} +(6,1,1) = {" +a +C +L +U +T +k +r +r +Q +q +a +"} +(7,1,1) = {" +a +h +V +b +z +k +r +W +m +q +a +"} +(8,1,1) = {" +a +G +g +D +l +k +k +k +k +v +O +"} +(9,1,1) = {" +a +v +H +y +A +N +Y +B +F +G +a +"} +(10,1,1) = {" +a +v +G +G +G +v +v +v +G +G +a +"} +(11,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/modular_generic/ice_l_trophyroom.dmm b/_maps/modular_generic/ice_l_trophyroom.dmm new file mode 100644 index 0000000000000..39aed5bddfe9f --- /dev/null +++ b/_maps/modular_generic/ice_l_trophyroom.dmm @@ -0,0 +1,602 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"ah" = ( +/obj/structure/flora/grass/brown/style_random, +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/structure/railing{ + dir = 1 + }, +/obj/structure/flora/bush/snow/style_random, +/turf/open/misc/snow, +/area/template_noop) +"fI" = ( +/obj/effect/spawner/random/structure/crate, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"gr" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 9 + }, +/obj/structure/chair/office/light, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"gS" = ( +/obj/structure/rack, +/obj/effect/spawner/random/engineering/toolbox, +/turf/open/misc/snow, +/area/template_noop) +"hA" = ( +/turf/closed/wall, +/area/template_noop) +"jO" = ( +/turf/template_noop, +/area/template_noop) +"jV" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 6 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 1 + }, +/obj/structure/hedge, +/turf/open/misc/snow, +/area/template_noop) +"kM" = ( +/obj/structure/flora/grass/brown/style_random, +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/structure/railing{ + dir = 1 + }, +/obj/effect/spawner/random/decoration/flower, +/turf/open/misc/snow, +/area/template_noop) +"ng" = ( +/obj/structure/flora/rock/pile/icy/style_3, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/structure/railing, +/obj/structure/flora/tree/dead/style_random{ + pixel_y = 12 + }, +/turf/open/misc/snow, +/area/template_noop) +"pV" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/effect/decal/cleanable/blood/drip{ + icon_state = "drip2" + }, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"qH" = ( +/obj/effect/spawner/random/trash/bin, +/turf/open/misc/snow, +/area/template_noop) +"rS" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 6 + }, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/effect/decal/cleanable/blood/drip{ + icon_state = "drip1" + }, +/obj/effect/decal/cleanable/blood/drip{ + icon_state = "drip4" + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"tl" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/structure/railing{ + dir = 1 + }, +/obj/structure/flora/tree/dead/style_random, +/turf/open/misc/snow, +/area/template_noop) +"tN" = ( +/obj/structure/flora/grass/brown/style_random, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/structure/flora/bush/flowers_pp, +/obj/item/hatchet/wooden, +/obj/machinery/light/cold/dim/directional/north, +/turf/open/misc/snow, +/area/template_noop) +"ul" = ( +/turf/open/floor/holofloor/stairs/medium{ + dir = 8 + }, +/area/template_noop) +"vs" = ( +/obj/structure/flora/grass/brown/style_random, +/obj/effect/turf_decal/siding/thinplating_new/dark/end, +/obj/structure/railing{ + dir = 6 + }, +/obj/effect/spawner/random/decoration/flower, +/turf/open/misc/snow, +/area/template_noop) +"vv" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/end{ + dir = 1 + }, +/obj/structure/railing{ + dir = 9 + }, +/obj/structure/flora/bush/flowers_pp, +/obj/structure/flora/bush/snow/style_random, +/turf/open/misc/snow, +/area/template_noop) +"wW" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/end{ + dir = 1 + }, +/obj/structure/railing{ + dir = 5 + }, +/obj/structure/hedge, +/turf/open/misc/snow, +/area/template_noop) +"yc" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"yg" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/structure/railing, +/obj/structure/hedge, +/obj/structure/sign/poster/random/directional/north, +/turf/open/misc/snow, +/area/template_noop) +"yk" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/effect/decal/cleanable/plastic, +/turf/open/misc/snow, +/area/template_noop) +"yK" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/end, +/obj/structure/railing{ + dir = 10 + }, +/obj/structure/hedge, +/obj/structure/sign/poster/random/directional/east, +/turf/open/misc/snow, +/area/template_noop) +"yS" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 9 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark/corner, +/obj/structure/hedge, +/turf/open/misc/snow, +/area/template_noop) +"zJ" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 9 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/spawner/random/structure/crate, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"Bo" = ( +/obj/effect/decal/cleanable/blood/drip{ + icon_state = "floor7" + }, +/turf/open/misc/snow, +/area/template_noop) +"Bp" = ( +/obj/structure/flora/rock/icy/style_2, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 8 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/obj/structure/railing{ + dir = 4 + }, +/obj/structure/flora/bush/snow/style_random, +/obj/structure/sign/poster/random/directional/west, +/turf/open/misc/snow, +/area/template_noop) +"BX" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/carpet/blue, +/area/template_noop) +"Eb" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 8 + }, +/obj/structure/filingcabinet, +/turf/open/misc/snow, +/area/template_noop) +"FS" = ( +/obj/effect/turf_decal/weather/snow/corner, +/turf/open/floor/carpet/blue, +/area/template_noop) +"HL" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 10 + }, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"IF" = ( +/obj/structure/flora/grass/brown/style_random, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 8 + }, +/obj/structure/railing{ + dir = 8 + }, +/obj/structure/flora/tree/dead/style_random, +/turf/open/misc/snow, +/area/template_noop) +"JF" = ( +/obj/structure/flora/grass/green/style_random, +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/structure/railing{ + dir = 1 + }, +/obj/structure/flora/bush/flowers_pp, +/obj/structure/flora/bush/snow/style_random, +/obj/structure/sign/clock/directional/south, +/obj/machinery/light/cold/dim/directional/south, +/turf/open/misc/snow, +/area/template_noop) +"Kb" = ( +/obj/effect/decal/cleanable/blood/drip{ + icon_state = "floor4" + }, +/turf/open/misc/snow, +/area/template_noop) +"Lj" = ( +/obj/structure/flora/grass/green/style_random, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/structure/railing, +/obj/structure/flora/bush/snow/style_random, +/obj/structure/sign/poster/random/directional/north, +/turf/open/misc/snow, +/area/template_noop) +"Lo" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 8 + }, +/obj/structure/chair/office/light{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"Ml" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 8 + }, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"Mr" = ( +/obj/structure/flora/grass/green/style_random, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/structure/railing, +/obj/structure/flora/bush/snow/style_random, +/turf/open/misc/snow, +/area/template_noop) +"MO" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 1 + }, +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/effect/spawner/random/bureaucracy/folder, +/obj/effect/spawner/random/bureaucracy/pen, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"Nf" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 9 + }, +/obj/effect/spawner/random/bureaucracy/folder, +/obj/effect/spawner/random/bureaucracy/pen, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"Nk" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/structure/hedge, +/turf/open/misc/snow, +/area/template_noop) +"NJ" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 6 + }, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"Pk" = ( +/obj/structure/flora/grass/green/style_random, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 8 + }, +/obj/structure/railing{ + dir = 8 + }, +/obj/structure/flora/bush/snow/style_random, +/obj/structure/sign/poster/random/directional/east, +/turf/open/misc/snow, +/area/template_noop) +"RA" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner, +/obj/structure/chair/office/light{ + dir = 1 + }, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"Tq" = ( +/obj/effect/turf_decal/weather/snow/corner, +/obj/structure/displaycase/trophy, +/turf/open/floor/carpet/blue, +/area/template_noop) +"Uo" = ( +/obj/effect/decal/cleanable/plastic, +/turf/open/misc/snow, +/area/template_noop) +"UO" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 10 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 4 + }, +/obj/structure/flora/bush/flowers_pp, +/obj/structure/flora/rock/pile/icy/style_2, +/turf/open/misc/snow, +/area/template_noop) +"VA" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"VD" = ( +/obj/structure/table/reinforced, +/obj/effect/spawner/random/decoration/ornament, +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"Xc" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 5 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 8 + }, +/obj/structure/flora/bush/flowers_pp, +/obj/structure/flora/rock/icy/style_3, +/turf/open/misc/snow, +/area/template_noop) +"XH" = ( +/obj/structure/flora/grass/green/style_random, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 8 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/obj/structure/railing{ + dir = 4 + }, +/obj/structure/flora/tree/dead/style_random, +/obj/structure/sign/poster/random/directional/west, +/turf/open/misc/snow, +/area/template_noop) +"XX" = ( +/turf/open/floor/holofloor/stairs/medium{ + dir = 4 + }, +/area/template_noop) +"Yn" = ( +/obj/structure/barricade/wooden/crude/snow, +/obj/machinery/door/airlock/wood, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"ZR" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/template_noop) + +(1,1,1) = {" +jO +jO +jO +jO +jO +jO +jO +jO +jO +jO +yc +"} +(2,1,1) = {" +jO +hA +hA +hA +hA +Yn +hA +hA +hA +hA +jO +"} +(3,1,1) = {" +jO +hA +yS +Bp +vs +XX +wW +XH +UO +hA +jO +"} +(4,1,1) = {" +jO +hA +Lj +VD +RA +pV +NJ +qH +ah +ZR +jO +"} +(5,1,1) = {" +jO +hA +ng +gS +rS +FS +Kb +Uo +Nk +ZR +jO +"} +(6,1,1) = {" +jO +hA +tN +yk +BX +Tq +Bo +zJ +JF +hA +jO +"} +(7,1,1) = {" +jO +hA +yg +Eb +HL +BX +gr +MO +tl +ZR +jO +"} +(8,1,1) = {" +jO +hA +Mr +Nf +Lo +Ml +VA +fI +kM +ZR +jO +"} +(9,1,1) = {" +jO +hA +Xc +IF +yK +ul +vv +Pk +jV +hA +jO +"} +(10,1,1) = {" +jO +hA +hA +hA +hA +Yn +hA +hA +hA +hA +jO +"} +(11,1,1) = {" +jO +jO +jO +jO +jO +jO +jO +jO +jO +jO +jO +"} diff --git a/_maps/modular_generic/ice_m_comms.dmm b/_maps/modular_generic/ice_m_comms.dmm new file mode 100644 index 0000000000000..34c4ed8864fbb --- /dev/null +++ b/_maps/modular_generic/ice_m_comms.dmm @@ -0,0 +1,330 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/wall, +/area/template_noop) +"b" = ( +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/spawner/random/structure/tank_holder, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"c" = ( +/obj/effect/spawner/structure/window, +/obj/machinery/door/poddoor/shutters{ + dir = 4; + id = "vdomsnow" + }, +/turf/open/floor/plating, +/area/template_noop) +"e" = ( +/obj/structure/railing{ + dir = 8 + }, +/obj/effect/spawner/random/structure/crate, +/obj/effect/turf_decal/bot_white{ + color = "#52B4E9" + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"f" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"i" = ( +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/effect/spawner/random/trash/bin, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"j" = ( +/obj/structure/barricade/wooden/crude/snow, +/obj/machinery/door/airlock/wood, +/turf/open/floor/iron/dark, +/area/template_noop) +"l" = ( +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/structure/hedge, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"n" = ( +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/chair/stool/directional/east{ + pixel_x = -6 + }, +/obj/machinery/light_switch/directional/west, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"o" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 8 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 5 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 1 + }, +/turf/open/floor/carpet/blue, +/area/template_noop) +"p" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner, +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 8 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/turf/open/floor/carpet/blue, +/area/template_noop) +"r" = ( +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/machinery/exoscanner, +/obj/effect/turf_decal/weather/snow/corner, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"t" = ( +/obj/structure/chair/office/light{ + dir = 4 + }, +/turf/open/misc/snow, +/area/template_noop) +"u" = ( +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/structure/hedge, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"v" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 9 + }, +/obj/structure/flora/grass/green/style_random, +/obj/structure/flora/bush/snow/style_random, +/turf/open/misc/snow, +/area/template_noop) +"w" = ( +/obj/machinery/computer/terminal/derelict{ + dir = 8 + }, +/obj/machinery/light/cold/dim/directional/east, +/turf/open/misc/snow, +/area/template_noop) +"y" = ( +/obj/structure/table/reinforced, +/obj/structure/sign/poster/random/directional/east, +/obj/machinery/recharger, +/turf/open/misc/snow, +/area/template_noop) +"A" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 6 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/turf/open/floor/carpet/blue, +/area/template_noop) +"D" = ( +/turf/template_noop, +/area/template_noop) +"F" = ( +/obj/effect/spawner/random/structure/crate, +/obj/effect/turf_decal/bot_white{ + color = "#52B4E9" + }, +/obj/structure/noticeboard/directional/north, +/obj/machinery/light/cold/dim/directional/north, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"K" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/effect/spawner/random/structure/crate, +/obj/effect/turf_decal/bot_white{ + color = "#52B4E9" + }, +/obj/structure/sign/poster/random/directional/north, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"L" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 10 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 5 + }, +/turf/open/floor/carpet/blue, +/area/template_noop) +"M" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/end, +/turf/open/floor/carpet/blue, +/area/template_noop) +"N" = ( +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/structure/filingcabinet, +/obj/effect/decal/cleanable/cobweb, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"O" = ( +/obj/effect/spawner/structure/window, +/obj/machinery/door/poddoor/shutters{ + dir = 1; + id = "vdomsnow" + }, +/turf/open/floor/plating, +/area/template_noop) +"P" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/end{ + dir = 8 + }, +/turf/open/floor/carpet/blue, +/area/template_noop) +"R" = ( +/obj/structure/flora/grass/brown, +/obj/structure/flora/bush/snow/style_2, +/turf/open/misc/snow, +/area/template_noop) +"S" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/decal/cleanable/blood/drip, +/obj/effect/decal/cleanable/blood/drip{ + icon_state = "bloodyhands_left" + }, +/obj/effect/decal/cleanable/blood/drip{ + icon_state = "drip1" + }, +/turf/open/misc/snow, +/area/template_noop) +"T" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 10 + }, +/obj/structure/chair/office/light, +/turf/open/floor/carpet/blue, +/area/template_noop) +"V" = ( +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/structure/table/reinforced, +/obj/structure/sign/poster/random/directional/west, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/spawner/random/bureaucracy/stamp, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"Z" = ( +/obj/effect/turf_decal/tile/dark_blue/diagonal_centre, +/obj/structure/table/reinforced, +/obj/effect/spawner/random/bureaucracy/folder, +/obj/effect/spawner/random/bureaucracy/crayon, +/obj/machinery/button/door/directional/south{ + id = "vdomsnow" + }, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) + +(1,1,1) = {" +D +D +D +D +D +D +D +D +f +"} +(2,1,1) = {" +D +a +a +a +j +c +a +a +D +"} +(3,1,1) = {" +D +a +N +n +P +i +V +a +D +"} +(4,1,1) = {" +D +a +e +v +o +T +Z +a +D +"} +(5,1,1) = {" +D +a +F +S +R +p +M +j +D +"} +(6,1,1) = {" +D +a +K +L +t +A +b +O +D +"} +(7,1,1) = {" +D +a +u +r +w +y +l +a +D +"} +(8,1,1) = {" +D +a +a +a +a +a +a +a +D +"} +(9,1,1) = {" +D +D +D +D +D +D +D +D +D +"} diff --git a/_maps/modular_generic/ice_s_freezer.dmm b/_maps/modular_generic/ice_s_freezer.dmm new file mode 100644 index 0000000000000..b150be62220dc --- /dev/null +++ b/_maps/modular_generic/ice_s_freezer.dmm @@ -0,0 +1,190 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/weather/snow/corner, +/obj/structure/rack, +/obj/item/food/meat/slab/monkey, +/turf/open/floor/plating/snowed, +/area/template_noop) +"c" = ( +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/obj/machinery/light/cold/directional/west, +/obj/item/food/meat/slab/xeno{ + pixel_x = -4; + pixel_y = 3 + }, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating/snowed, +/area/template_noop) +"d" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/snowed, +/area/template_noop) +"e" = ( +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 4 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating/snowed, +/area/template_noop) +"h" = ( +/obj/effect/turf_decal/weather/snow/corner, +/turf/template_noop, +/area/template_noop) +"j" = ( +/obj/machinery/door/airlock/freezer, +/turf/open/floor/plating/snowed, +/area/template_noop) +"o" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 4 + }, +/obj/effect/decal/cleanable/blood/gibs/old, +/obj/item/food/meat/slab/bear{ + pixel_x = -7; + pixel_y = -3 + }, +/turf/open/floor/plating/snowed, +/area/template_noop) +"q" = ( +/obj/structure/table, +/obj/item/food/meat/slab/goliath, +/obj/item/food/meat/slab/pig{ + pixel_y = 4 + }, +/turf/open/floor/fake_snow, +/area/template_noop) +"t" = ( +/obj/machinery/door/airlock/maintenance/external, +/obj/structure/barricade/wooden/crude/snow, +/turf/open/floor/plating/snowed, +/area/template_noop) +"w" = ( +/obj/structure/closet/secure_closet/freezer/empty/open, +/obj/item/food/meat/slab/spider, +/obj/item/food/meat/slab/chicken, +/obj/item/food/meat/slab/rawcrab, +/turf/open/floor/fake_snow, +/area/template_noop) +"G" = ( +/turf/template_noop, +/area/template_noop) +"L" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"M" = ( +/obj/effect/decal/cleanable/xenoblood, +/obj/item/food/meat/slab/meatproduct{ + pixel_y = 6; + pixel_x = 6 + }, +/obj/item/food/meat/slab/meatwheat{ + pixel_x = -9; + pixel_y = -8 + }, +/turf/open/floor/fake_snow, +/area/template_noop) +"N" = ( +/turf/closed/wall/ice, +/area/template_noop) +"O" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/turf/template_noop, +/area/template_noop) +"R" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 4 + }, +/turf/open/floor/plating/snowed, +/area/template_noop) +"W" = ( +/turf/closed/wall, +/area/template_noop) + +(1,1,1) = {" +G +G +G +G +G +G +L +"} +(2,1,1) = {" +G +N +N +W +W +W +G +"} +(3,1,1) = {" +G +W +w +c +d +t +O +"} +(4,1,1) = {" +h +j +e +R +o +W +G +"} +(5,1,1) = {" +G +W +a +M +q +N +G +"} +(6,1,1) = {" +G +W +W +W +N +N +G +"} +(7,1,1) = {" +G +G +G +G +G +G +G +"} diff --git a/_maps/modular_generic/jungle_l_dock.dmm b/_maps/modular_generic/jungle_l_dock.dmm new file mode 100644 index 0000000000000..e29f1fbec2877 --- /dev/null +++ b/_maps/modular_generic/jungle_l_dock.dmm @@ -0,0 +1,707 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aC" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/tree/jungle/small/style_random, +/turf/open/misc/grass/jungle, +/area/template_noop) +"bz" = ( +/obj/structure/flora/bush/ferny/style_random, +/obj/structure/flora/bush/large/style_random{ + pixel_y = -3 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"cg" = ( +/obj/structure/flora/rock/style_3, +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/obj/item/flashlight/lantern{ + icon_state = "lantern-on"; + pixel_y = 15; + pixel_x = -2 + }, +/turf/open/water/jungle, +/area/template_noop) +"cF" = ( +/obj/structure/flora/bush/ferny/style_random, +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/rock/pile/jungle/large/style_random{ + pixel_x = 0; + pixel_y = 0 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"de" = ( +/obj/effect/turf_decal/siding/wood/end{ + dir = 8 + }, +/obj/structure/chair/plastic{ + dir = 8 + }, +/obj/item/reagent_containers/cup/bucket/wooden{ + pixel_x = 16; + pixel_y = 11 + }, +/obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/cup/glass/bottle/beer{ + pixel_x = -4; + pixel_y = 16 + }, +/obj/structure/railing, +/turf/open/floor/wood/large, +/area/template_noop) +"ez" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/turf_decal/weather/dirt{ + dir = 4 + }, +/obj/structure/railing{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/gun/syringe/blowgun, +/turf/open/floor/wood/large, +/area/template_noop) +"eI" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/crate/grave/filled, +/obj/effect/spawner/random/exotic/syndie, +/obj/effect/spawner/random/exotic/antag_gear, +/turf/open/misc/dirt/jungle/dark, +/area/template_noop) +"fE" = ( +/obj/structure/flora/bush/ferny/style_random, +/obj/effect/turf_decal/weather/dirt, +/turf/open/misc/grass/jungle, +/area/template_noop) +"ge" = ( +/obj/structure/flora/bush/fullgrass/style_random, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/grass/jungle, +/area/template_noop) +"gj" = ( +/obj/structure/flora/bush/reed/style_random, +/turf/open/water/jungle, +/area/template_noop) +"gq" = ( +/obj/structure/flora/bush/grassy/style_random, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/grass/jungle, +/area/template_noop) +"gI" = ( +/obj/structure/flora/bush/fullgrass/style_random, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/vomit/old/black_bile, +/obj/structure/flora/rock/pile/style_random, +/turf/open/misc/grass/jungle, +/area/template_noop) +"gL" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/grass/jungle, +/area/template_noop) +"is" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/effect/turf_decal/weather/dirt{ + dir = 4 + }, +/turf/open/water/jungle, +/area/template_noop) +"iL" = ( +/obj/structure/flora/bush/grassy/style_random, +/obj/structure/closet/crate/grave/filled, +/obj/effect/spawner/random/contraband/armory, +/obj/effect/spawner/random/exotic/antag_gear, +/turf/open/misc/dirt/jungle/dark, +/area/template_noop) +"iW" = ( +/obj/structure/flora/rock, +/obj/effect/turf_decal/weather/dirt{ + dir = 9 + }, +/turf/open/water/jungle, +/area/template_noop) +"ja" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 10 + }, +/turf/open/water/jungle, +/area/template_noop) +"jk" = ( +/obj/structure/flora/bush/ferny/style_random, +/turf/open/misc/grass/jungle, +/area/template_noop) +"kb" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/structure/flora/rock/pile/style_2, +/turf/open/misc/grass/jungle, +/area/template_noop) +"ll" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = -6; + pixel_y = 5 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"mF" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/effect/turf_decal/weather/dirt{ + dir = 6 + }, +/turf/open/water/jungle, +/area/template_noop) +"mV" = ( +/obj/structure/flora/rock/style_2, +/obj/effect/turf_decal/weather/dirt, +/turf/open/water/jungle, +/area/template_noop) +"nl" = ( +/obj/effect/turf_decal/weather/dirt, +/obj/structure/flora/bush/large/style_random{ + pixel_y = -3 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"nF" = ( +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 1 + }, +/obj/item/fishing_line/reinforced{ + pixel_y = 9 + }, +/obj/item/fishing_hook{ + pixel_x = 11 + }, +/obj/effect/turf_decal/weather/dirt, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/wood/large, +/area/template_noop) +"nY" = ( +/obj/effect/turf_decal/weather/dirt, +/turf/open/misc/grass/jungle, +/area/template_noop) +"pE" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 5 + }, +/obj/structure/railing{ + dir = 5 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/vomit/old/black_bile, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = 8; + pixel_y = 13 + }, +/turf/open/floor/wood/large, +/area/template_noop) +"qx" = ( +/obj/effect/decal/cleanable/vomit/old/black_bile, +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/structure/punji_sticks/spikes{ + icon_state = "punji" + }, +/obj/effect/decal/cleanable/blood/old{ + icon_state = "floor7-old" + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"qS" = ( +/obj/structure/flora/bush/fullgrass/style_random, +/obj/structure/flora/rock/pile/jungle/large/style_random{ + pixel_x = 0; + pixel_y = 0 + }, +/obj/item/poster/random_contraband, +/obj/effect/spawner/random/clothing/pirate_or_bandana, +/turf/open/misc/dirt/jungle/dark, +/area/template_noop) +"qT" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/grass/jungle, +/area/template_noop) +"rJ" = ( +/turf/template_noop, +/area/template_noop) +"sE" = ( +/obj/structure/flora/bush/grassy/style_random, +/obj/structure/punji_sticks/spikes{ + icon_state = "punji" + }, +/obj/effect/decal/cleanable/blood/old, +/turf/open/misc/grass/jungle, +/area/template_noop) +"tD" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 6 + }, +/obj/structure/railing{ + dir = 6 + }, +/obj/structure/closet/crate/wooden, +/obj/item/shovel, +/obj/effect/spawner/random/engineering/flashlight, +/obj/effect/spawner/random/maintenance/two, +/turf/open/floor/wood/large, +/area/template_noop) +"ul" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/effect/decal/cleanable/vomit/old/black_bile, +/obj/structure/flora/rock/pile/style_3, +/turf/open/misc/grass/jungle, +/area/template_noop) +"vl" = ( +/obj/structure/flora/bush/reed/style_random, +/obj/effect/turf_decal/weather/dirt{ + dir = 8 + }, +/turf/open/water/jungle, +/area/template_noop) +"vG" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"vY" = ( +/obj/structure/flora/rock/pile/jungle/style_random, +/turf/open/water/jungle, +/area/template_noop) +"xR" = ( +/obj/structure/flora/bush/grassy/style_random, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = 8; + pixel_y = 13 + }, +/obj/structure/punji_sticks/spikes{ + icon_state = "punji" + }, +/obj/effect/decal/cleanable/blood/old{ + icon_state = "floor6-old" + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"yN" = ( +/obj/structure/flora/bush/large/style_random{ + pixel_y = -3 + }, +/obj/effect/turf_decal/weather/dirt{ + dir = 9 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"yO" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/rock/pile/jungle/style_random, +/turf/open/misc/grass/jungle, +/area/template_noop) +"zP" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/turf/open/misc/grass/jungle, +/area/template_noop) +"AG" = ( +/obj/structure/flora/bush/fullgrass/style_random, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/dirt/jungle/dark, +/area/template_noop) +"AK" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/effect/turf_decal/weather/dirt{ + dir = 10 + }, +/turf/open/water/jungle, +/area/template_noop) +"Er" = ( +/turf/open/misc/dirt/jungle/dark, +/area/template_noop) +"EQ" = ( +/obj/structure/flora/rock/pile/jungle/style_random, +/turf/open/misc/grass/jungle, +/area/template_noop) +"GK" = ( +/obj/structure/flora/rock/pile/jungle/style_random, +/obj/effect/turf_decal/weather/dirt{ + dir = 9 + }, +/turf/open/water/jungle, +/area/template_noop) +"Hd" = ( +/obj/structure/flora/bush/fullgrass/style_random, +/obj/structure/flora/bush/large/style_random{ + pixel_y = -3 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"HW" = ( +/obj/structure/flora/bush/large/style_random{ + pixel_y = -3 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"Ij" = ( +/obj/structure/flora/bush/grassy/style_random, +/obj/effect/turf_decal/weather/dirt{ + dir = 4 + }, +/obj/structure/flora/rock/pile/jungle/large/style_random{ + pixel_x = 0; + pixel_y = 0 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"Jf" = ( +/obj/structure/flora/rock/style_3, +/obj/item/flashlight/lantern{ + icon_state = "lantern-on"; + pixel_y = 15; + pixel_x = -2 + }, +/turf/open/water/jungle, +/area/template_noop) +"JB" = ( +/obj/effect/mob_spawn/corpse/human/pirate, +/turf/open/water/jungle, +/area/template_noop) +"JC" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/rock/pile/jungle/large/style_random{ + pixel_x = 0; + pixel_y = 0 + }, +/obj/structure/closet/crate/grave/filled, +/obj/effect/spawner/random/engineering/material_rare, +/obj/effect/spawner/random/exotic/antag_gear, +/turf/open/misc/dirt/jungle/dark, +/area/template_noop) +"JF" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/structure/flora/rock/pile/style_2, +/obj/structure/punji_sticks/spikes{ + icon_state = "punji" + }, +/obj/effect/decal/cleanable/blood/old{ + icon_state = "floor5-old" + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"Kz" = ( +/obj/structure/flora/bush/grassy/style_random, +/turf/open/misc/dirt/jungle/dark, +/area/template_noop) +"KW" = ( +/turf/open/water/jungle, +/area/template_noop) +"LL" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = 9; + pixel_y = 21 + }, +/obj/effect/decal/cleanable/vomit/old/black_bile, +/obj/effect/spawner/random/entertainment/money_small, +/turf/open/misc/grass/jungle, +/area/template_noop) +"LW" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/mob/living/basic/frog, +/obj/effect/spawner/random/trash/mess, +/obj/effect/decal/cleanable/blood/tracks{ + dir = 9 + }, +/turf/open/floor/wood/large, +/area/template_noop) +"Mv" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/tree/jungle/small/style_random, +/turf/open/misc/grass/jungle, +/area/template_noop) +"NG" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/crate/grave/filled, +/obj/effect/spawner/random/food_or_drink/booze, +/obj/effect/spawner/random/exotic/antag_gear, +/turf/open/misc/dirt/jungle/dark, +/area/template_noop) +"Pb" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/bush/large/style_random{ + pixel_y = -3 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"Qk" = ( +/obj/item/fishing_rod, +/obj/structure/flora/bush/stalky/style_random, +/turf/open/water/jungle, +/area/template_noop) +"Rn" = ( +/obj/structure/flora/rock/style_4, +/turf/open/water/jungle, +/area/template_noop) +"RX" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/turf/open/water/jungle, +/area/template_noop) +"Sb" = ( +/obj/structure/flora/bush/grassy/style_random, +/obj/effect/decal/cleanable/dirt, +/obj/structure/punji_sticks/spikes{ + icon_state = "punji" + }, +/obj/effect/decal/cleanable/blood/old{ + icon_state = "floor4-old" + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"TU" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = -6; + pixel_y = 5 + }, +/obj/effect/decal/cleanable/blood/tracks{ + dir = 6 + }, +/obj/structure/railing{ + dir = 8 + }, +/turf/open/floor/wood/large, +/area/template_noop) +"Uw" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 5 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/tree/jungle/small/style_random, +/turf/open/misc/grass/jungle, +/area/template_noop) +"UE" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 5 + }, +/obj/effect/turf_decal/siding/wood, +/obj/structure/railing, +/obj/item/chair/plastic{ + pixel_y = 6 + }, +/obj/item/reagent_containers/cup/glass/bottle/beer{ + pixel_x = 5; + pixel_y = 15 + }, +/obj/effect/decal/cleanable/blood/tracks{ + dir = 8 + }, +/obj/item/bait_can{ + pixel_y = 16; + pixel_x = -8 + }, +/turf/open/floor/wood/large, +/area/template_noop) +"VC" = ( +/obj/structure/flora/bush/fullgrass/style_random, +/obj/structure/flora/tree/jungle/small/style_random, +/turf/open/misc/grass/jungle, +/area/template_noop) +"WZ" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/dirt/jungle/dark, +/area/template_noop) +"Xn" = ( +/obj/effect/turf_decal/weather/dirt, +/turf/open/water/jungle, +/area/template_noop) +"Yf" = ( +/obj/structure/flora/bush/fullgrass/style_random, +/turf/open/water/jungle, +/area/template_noop) +"Yt" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/grass/jungle, +/area/template_noop) +"Zl" = ( +/obj/structure/flora/bush/stalky/style_random, +/turf/open/water/jungle, +/area/template_noop) + +(1,1,1) = {" +rJ +rJ +rJ +rJ +rJ +rJ +rJ +rJ +rJ +rJ +vG +"} +(2,1,1) = {" +rJ +zP +xR +gI +jk +Pb +gL +Ij +JF +jk +rJ +"} +(3,1,1) = {" +rJ +qT +Mv +iL +iW +AK +WZ +AG +Uw +EQ +rJ +"} +(4,1,1) = {" +rJ +nY +qS +GK +KW +JB +vl +ja +NG +ll +rJ +"} +(5,1,1) = {" +rJ +nl +Er +cg +Zl +KW +de +KW +yN +Sb +rJ +"} +(6,1,1) = {" +rJ +fE +pE +ez +LW +TU +nF +Jf +vY +ul +rJ +"} +(7,1,1) = {" +rJ +Hd +Rn +gj +UE +Qk +tD +Yf +mF +aC +rJ +"} +(8,1,1) = {" +rJ +qx +gq +is +JB +KW +KW +Xn +Kz +cF +rJ +"} +(9,1,1) = {" +rJ +EQ +HW +JC +RX +vY +bz +mV +eI +ge +rJ +"} +(10,1,1) = {" +rJ +kb +zP +Yt +VC +sE +LL +yO +Pb +zP +rJ +"} +(11,1,1) = {" +rJ +rJ +rJ +rJ +rJ +rJ +rJ +rJ +rJ +rJ +rJ +"} diff --git a/_maps/modular_generic/jungle_m_armory.dmm b/_maps/modular_generic/jungle_m_armory.dmm new file mode 100644 index 0000000000000..a99a173cc8a1c --- /dev/null +++ b/_maps/modular_generic/jungle_m_armory.dmm @@ -0,0 +1,445 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"d" = ( +/obj/effect/turf_decal/siding/wood, +/obj/effect/turf_decal/weather/dirt{ + dir = 10 + }, +/obj/structure/flora/rock/pile/jungle/style_random, +/obj/structure/sign/poster/contraband/calada_jelly/directional/south, +/turf/open/floor/wood, +/area/template_noop) +"e" = ( +/obj/structure/flora/rock/pile/jungle/style_random, +/obj/effect/turf_decal/weather/dirt{ + dir = 5 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/structure/railing{ + dir = 8 + }, +/turf/open/floor/wood, +/area/template_noop) +"g" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/structure/flora/bush/reed/style_random, +/turf/open/water/jungle, +/area/template_noop) +"h" = ( +/obj/structure/closet/crate/wooden, +/obj/item/gun/ballistic/rifle/boltaction, +/turf/open/water/jungle, +/area/template_noop) +"i" = ( +/obj/item/stack/sheet/mineral/wood{ + pixel_x = -8 + }, +/obj/effect/turf_decal/weather/dirt{ + dir = 9 + }, +/obj/effect/turf_decal/weather/dirt{ + dir = 10 + }, +/obj/structure/flora/bush/large/style_random{ + pixel_y = -3 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"j" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/effect/turf_decal/weather/dirt, +/obj/item/hatchet/wooden, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/wood, +/area/template_noop) +"k" = ( +/obj/effect/turf_decal/siding/wood, +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/item/stack/sheet/mineral/wood{ + pixel_x = 7 + }, +/turf/open/floor/wood, +/area/template_noop) +"m" = ( +/obj/effect/turf_decal/weather/dirt, +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/mess, +/obj/effect/spawner/random/trash/hobo_squat, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/obj/effect/mob_spawn/corpse/human/pirate, +/turf/open/floor/wood, +/area/template_noop) +"n" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"p" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 5 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/firepit, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = -11 + }, +/obj/structure/railing{ + dir = 5 + }, +/turf/open/misc/dirt, +/area/template_noop) +"q" = ( +/obj/item/stack/sheet/mineral/wood, +/obj/effect/turf_decal/weather/dirt{ + dir = 4 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/railing/corner/end{ + dir = 4 + }, +/obj/item/reagent_containers/cup/glass/bottle/beer{ + pixel_x = -8; + pixel_y = 9 + }, +/turf/open/floor/wood, +/area/template_noop) +"r" = ( +/obj/structure/flora/rock/style_random, +/turf/open/water/jungle, +/area/template_noop) +"s" = ( +/obj/effect/spawner/random/trash/botanical_waste, +/obj/effect/decal/cleanable/dirt, +/turf/open/misc/dirt, +/area/template_noop) +"u" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 10 + }, +/obj/effect/turf_decal/weather/dirt{ + dir = 6 + }, +/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/remains/xeno, +/obj/structure/flora/bush/large/style_random{ + pixel_y = -3 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"v" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wood/corner, +/obj/effect/turf_decal/weather/dirt, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = 9; + pixel_y = 21 + }, +/turf/open/floor/wood, +/area/template_noop) +"x" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/structure/flora/rock/pile/jungle/large/style_random{ + pixel_x = 0; + pixel_y = 0 + }, +/obj/effect/turf_decal/weather/dirt{ + dir = 4 + }, +/obj/effect/turf_decal/siding/wood/corner, +/turf/open/floor/wood, +/area/template_noop) +"y" = ( +/turf/closed/wall/mineral/wood, +/area/template_noop) +"z" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 6 + }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/engineering/flashlight, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = 9 + }, +/turf/open/floor/wood, +/area/template_noop) +"A" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 9 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/crate/wooden, +/obj/effect/decal/cleanable/cobweb, +/obj/structure/sign/poster/contraband/free_tonto/directional/west, +/obj/effect/spawner/random/medical/medkit_rare, +/obj/effect/spawner/random/exotic/antag_gear, +/turf/open/floor/wood, +/area/template_noop) +"B" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/barricade/wooden, +/turf/open/misc/dirt, +/area/template_noop) +"C" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/bush/jungle/c/style_random, +/obj/effect/turf_decal/weather/dirt{ + dir = 9 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"D" = ( +/obj/effect/spawner/random/structure/crate, +/turf/open/misc/dirt, +/area/template_noop) +"G" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash, +/turf/open/misc/dirt, +/area/template_noop) +"J" = ( +/obj/effect/turf_decal/siding/wood, +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/obj/structure/flora/rock/style_2, +/obj/structure/railing, +/turf/open/floor/wood, +/area/template_noop) +"K" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/turf/open/water/jungle, +/area/template_noop) +"L" = ( +/obj/effect/turf_decal/siding/wood/corner{ + dir = 8 + }, +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/item/ammo_box/strilka310, +/obj/effect/decal/cleanable/dirt, +/obj/structure/railing/corner/end/flip{ + dir = 8 + }, +/obj/item/reagent_containers/cup/glass/bottle/beer{ + pixel_x = 6; + pixel_y = -3 + }, +/turf/open/floor/wood, +/area/template_noop) +"M" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 5 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/bush/large/style_random{ + pixel_y = -3 + }, +/turf/open/misc/grass/jungle, +/area/template_noop) +"O" = ( +/obj/structure/barricade/wooden, +/turf/open/misc/dirt, +/area/template_noop) +"P" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/structure/flora/bush/style_random, +/turf/open/water/jungle, +/area/template_noop) +"Q" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/railing{ + dir = 8 + }, +/obj/effect/spawner/random/clothing/backpack, +/turf/open/misc/dirt, +/area/template_noop) +"R" = ( +/obj/effect/turf_decal/weather/dirt, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/structure/flora/rock/style_3, +/turf/open/floor/wood, +/area/template_noop) +"T" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 6 + }, +/obj/structure/railing{ + dir = 6 + }, +/turf/open/misc/dirt, +/area/template_noop) +"U" = ( +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/weather/dirt{ + dir = 10 + }, +/obj/structure/flora/grass/jungle/a/style_random, +/turf/open/floor/wood, +/area/template_noop) +"W" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/bush/jungle, +/obj/effect/turf_decal/weather/dirt{ + dir = 6 + }, +/obj/effect/spawner/random/structure/crate, +/turf/open/misc/grass/jungle, +/area/template_noop) +"X" = ( +/obj/effect/spawner/random/decoration/glowstick, +/turf/open/water/jungle, +/area/template_noop) +"Y" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/effect/turf_decal/weather/dirt{ + dir = 8 + }, +/obj/item/stack/sheet/mineral/wood{ + pixel_x = 7 + }, +/obj/effect/decal/cleanable/blood/old{ + icon_state = "floor5-old" + }, +/turf/open/floor/wood, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +n +"} +(2,1,1) = {" +a +y +y +y +W +s +y +y +a +"} +(3,1,1) = {" +a +y +A +x +Y +U +M +y +a +"} +(4,1,1) = {" +a +y +v +T +P +q +d +y +a +"} +(5,1,1) = {" +a +G +k +g +r +p +m +O +a +"} +(6,1,1) = {" +a +u +J +h +K +X +j +C +a +"} +(7,1,1) = {" +a +B +L +R +Q +e +z +y +a +"} +(8,1,1) = {" +a +y +y +y +i +D +y +y +a +"} +(9,1,1) = {" +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/modular_generic/station_l_bathroom.dmm b/_maps/modular_generic/station_l_bathroom.dmm new file mode 100644 index 0000000000000..19d54e2a849b9 --- /dev/null +++ b/_maps/modular_generic/station_l_bathroom.dmm @@ -0,0 +1,617 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"b" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = 8; + pixel_y = 13 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 8 + }, +/obj/structure/broken_flooring/pile/directional/east, +/obj/structure/sign/poster/random/directional/east, +/obj/structure/fluff/paper{ + dir = 4 + }, +/turf/open/floor/iron/small, +/area/template_noop) +"c" = ( +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"d" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/structure/mop_bucket, +/obj/item/mop, +/turf/open/floor/plating, +/area/template_noop) +"e" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 8 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 4 + }, +/obj/effect/spawner/random/trash/garbage, +/obj/structure/fluff/paper/corner{ + dir = 8 + }, +/turf/open/floor/iron/small, +/area/template_noop) +"f" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 8 + }, +/obj/structure/fluff/paper/corner, +/obj/effect/spawner/random/trash/caution_sign, +/turf/open/floor/iron/small, +/area/template_noop) +"g" = ( +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 8 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 4 + }, +/obj/effect/spawner/random/trash, +/turf/open/floor/iron/small, +/area/template_noop) +"h" = ( +/obj/structure/chair/stool/directional/east{ + pixel_x = -6 + }, +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"i" = ( +/obj/structure/rack, +/obj/effect/decal/cleanable/cobweb, +/obj/structure/sign/poster/random/directional/west, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 9 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner, +/obj/effect/spawner/random/engineering/toolbox, +/obj/structure/extinguisher_cabinet/directional/north, +/turf/open/floor/iron/small, +/area/template_noop) +"j" = ( +/obj/effect/spawner/random/clothing/costume, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 6 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 1 + }, +/obj/structure/fluff/paper{ + dir = 6; + plane = -9 + }, +/obj/structure/table, +/turf/open/floor/iron/small, +/area/template_noop) +"l" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = 9; + pixel_y = 13 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new, +/obj/effect/decal/cleanable/vomit, +/obj/machinery/light/small/dim/directional/north, +/obj/item/trash/semki/healthy, +/turf/open/floor/iron/small, +/area/template_noop) +"m" = ( +/obj/structure/sign/poster/random/directional/north, +/obj/effect/spawner/random/trash/graffiti, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new, +/turf/open/floor/iron/small, +/area/template_noop) +"o" = ( +/obj/item/kirbyplants/random, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 10 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 4 + }, +/obj/structure/fluff/paper{ + dir = 10 + }, +/turf/open/floor/iron/small, +/area/template_noop) +"p" = ( +/obj/structure/toilet{ + dir = 1 + }, +/obj/structure/closet/crate/trashcart, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/armory/shotgun, +/obj/effect/spawner/random/bureaucracy/folder, +/obj/effect/spawner/random/bureaucracy, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/small/dim/directional/west, +/turf/open/floor/iron/freezer, +/area/template_noop) +"q" = ( +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/obj/machinery/light/small/dim/directional/east, +/obj/item/cigbutt, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"r" = ( +/obj/item/chair/stool{ + pixel_x = -3; + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/plating, +/area/template_noop) +"s" = ( +/obj/machinery/door/airlock, +/turf/open/floor/iron/freezer, +/area/template_noop) +"t" = ( +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"u" = ( +/obj/structure/toilet{ + pixel_y = 8 + }, +/mob/living/basic/blankbody, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/cobweb, +/obj/effect/spawner/random/trash/soap, +/obj/effect/decal/remains/human, +/obj/effect/decal/cleanable/blood/old{ + icon_state = "floor5-old" + }, +/obj/effect/decal/cleanable/blood/gibs/up, +/obj/machinery/light/small/red/dim/directional/west, +/turf/open/floor/iron/freezer, +/area/template_noop) +"v" = ( +/obj/effect/turf_decal/siding/thinplating_new, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 1 + }, +/obj/machinery/light_switch/directional/south, +/obj/structure/broken_flooring/pile/directional/west, +/turf/open/floor/iron/small, +/area/template_noop) +"w" = ( +/obj/structure/sink/directional/west, +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/obj/effect/decal/cleanable/glass, +/obj/item/shard, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"x" = ( +/obj/item/kirbyplants/random, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 5 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 8 + }, +/obj/structure/fluff/paper/corner, +/turf/open/floor/iron/small, +/area/template_noop) +"y" = ( +/obj/structure/sign/poster/random/directional/east, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/cigbutt{ + pixel_y = 7 + }, +/obj/structure/fluff/paper{ + dir = 4 + }, +/obj/effect/decal/cleanable/ash, +/turf/open/floor/iron/small, +/area/template_noop) +"z" = ( +/obj/effect/spawner/random/clothing/wardrobe_closet_colored, +/obj/effect/turf_decal/siding/thinplating_new, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 1 + }, +/obj/machinery/light/small/dim/directional/south, +/obj/structure/sign/poster/random/directional/south, +/obj/structure/fluff/paper/corner, +/turf/open/floor/iron/small, +/area/template_noop) +"A" = ( +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"C" = ( +/obj/machinery/door/airlock, +/turf/open/floor/plating, +/area/template_noop) +"E" = ( +/obj/effect/turf_decal/siding/thinplating_new, +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/small, +/area/template_noop) +"F" = ( +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 6 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 1 + }, +/obj/item/trash/boritos/purple{ + pixel_x = -11; + pixel_y = 6 + }, +/turf/open/floor/iron/small, +/area/template_noop) +"G" = ( +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"H" = ( +/turf/closed/wall, +/area/template_noop) +"I" = ( +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/obj/structure/sign/clock/directional/west, +/obj/machinery/light/warm/dim/directional/west, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/structure/fluff/paper{ + dir = 8 + }, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"J" = ( +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/obj/effect/decal/cleanable/dirt, +/obj/item/cigbutt{ + pixel_y = 7 + }, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"K" = ( +/obj/structure/sign/poster/random/directional/west, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner, +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/trash/boritos{ + pixel_x = -6; + pixel_y = -8 + }, +/obj/structure/fluff/paper/corner{ + dir = 4 + }, +/turf/open/floor/iron/small, +/area/template_noop) +"L" = ( +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/obj/effect/spawner/random/trash/graffiti, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"N" = ( +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/obj/effect/decal/cleanable/ants, +/obj/machinery/light/small/dim/directional/west, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"O" = ( +/obj/effect/spawner/random/structure/closet_maintenance, +/obj/effect/turf_decal/siding/thinplating_new, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/small, +/area/template_noop) +"P" = ( +/obj/structure/sink/directional/west, +/obj/structure/mirror/broken/directional/east, +/obj/effect/decal/cleanable/blood/old{ + icon_state = "floor3-old" + }, +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"Q" = ( +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new, +/obj/structure/chair/stool/directional/south{ + pixel_y = 16 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/small, +/area/template_noop) +"R" = ( +/obj/structure/hedge, +/obj/structure/window/reinforced/tinted/spawner/directional/south, +/obj/structure/window/reinforced/tinted/spawner/directional/north, +/obj/structure/window/reinforced/tinted/spawner/directional/west, +/obj/structure/window/reinforced/tinted/spawner/directional/east, +/turf/open/floor/iron/small, +/area/template_noop) +"S" = ( +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 8 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/small, +/area/template_noop) +"T" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"U" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/fluff/paper/corner{ + dir = 1 + }, +/turf/open/floor/plating, +/area/template_noop) +"V" = ( +/obj/effect/turf_decal/tile/dark/diagonal_centre, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/diagonal, +/area/template_noop) +"W" = ( +/obj/machinery/door/airlock, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/freezer, +/area/template_noop) +"X" = ( +/obj/effect/turf_decal/siding/thinplating_new, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 1 + }, +/obj/effect/decal/cleanable/blood/old{ + icon_state = "tracks" + }, +/obj/structure/fluff/paper/corner{ + dir = 8 + }, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = -6 + }, +/turf/open/floor/iron/small, +/area/template_noop) +"Y" = ( +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 5 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/cigbutt, +/obj/item/cigbutt{ + pixel_x = -8; + pixel_y = 6 + }, +/obj/effect/decal/cleanable/ash, +/turf/open/floor/iron/small, +/area/template_noop) +"Z" = ( +/obj/effect/spawner/random/structure/closet_maintenance, +/obj/effect/decal/cleanable/dirt, +/obj/structure/sign/poster/random/directional/south, +/obj/effect/turf_decal/siding/thinplating_new, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 1 + }, +/obj/structure/fluff/paper/corner{ + dir = 8 + }, +/turf/open/floor/iron/small, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +T +"} +(2,1,1) = {" +a +H +H +H +H +H +H +H +H +H +a +"} +(3,1,1) = {" +a +H +u +W +X +I +K +s +p +H +a +"} +(4,1,1) = {" +a +H +H +H +Q +d +v +H +H +H +a +"} +(5,1,1) = {" +a +H +i +g +F +t +Y +e +o +H +a +"} +(6,1,1) = {" +a +H +l +c +P +q +w +G +Z +H +a +"} +(7,1,1) = {" +a +C +E +J +H +R +H +L +O +H +a +"} +(8,1,1) = {" +a +H +m +V +r +N +h +A +z +H +a +"} +(9,1,1) = {" +a +H +x +b +U +S +f +y +j +H +a +"} +(10,1,1) = {" +a +H +H +H +H +C +H +H +H +H +a +"} +(11,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/modular_generic/station_l_crates.dmm b/_maps/modular_generic/station_l_crates.dmm new file mode 100644 index 0000000000000..cc81a16ae12ac --- /dev/null +++ b/_maps/modular_generic/station_l_crates.dmm @@ -0,0 +1,552 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/food_packaging, +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/obj/effect/turf_decal/siding/wideplating_new/dark, +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 + }, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 4 + }, +/area/template_noop) +"c" = ( +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/structure/crate, +/turf/open/floor/plating/rust, +/area/template_noop) +"d" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/engineering/canister, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/template_noop) +"e" = ( +/turf/template_noop, +/area/template_noop) +"g" = ( +/obj/effect/spawner/random/structure/table_or_rack, +/obj/effect/spawner/random/entertainment/toy, +/obj/effect/spawner/random/entertainment/toy, +/obj/effect/spawner/random/entertainment/toy, +/obj/item/poster/random_contraband, +/obj/effect/turf_decal/bot_red, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"h" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Warehouse Maintenance" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/template_noop) +"i" = ( +/obj/effect/spawner/random/maintenance/two, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 + }, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 4 + }, +/area/template_noop) +"j" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"k" = ( +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/obj/structure/sign/poster/random/directional/west, +/obj/effect/spawner/random/trash/moisture_trap, +/turf/open/floor/plating/rust, +/area/template_noop) +"l" = ( +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/obj/structure/reagent_dispensers/fueltank, +/turf/open/floor/plating, +/area/template_noop) +"m" = ( +/obj/effect/spawner/random/trash/botanical_waste, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 8 + }, +/area/template_noop) +"n" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/crate_empty, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/engineering/flashlight, +/obj/effect/spawner/random/engineering/flashlight, +/obj/effect/spawner/random/engineering/tool, +/turf/open/floor/plating, +/area/template_noop) +"o" = ( +/obj/effect/spawner/random/trash/graffiti, +/turf/closed/wall, +/area/template_noop) +"p" = ( +/obj/effect/spawner/random/trash/cigbutt, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 8 + }, +/area/template_noop) +"q" = ( +/obj/effect/turf_decal/bot, +/obj/structure/reagent_dispensers/watertank, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/template_noop) +"r" = ( +/obj/effect/turf_decal/bot, +/obj/structure/reagent_dispensers/fueltank, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating/rust, +/area/template_noop) +"s" = ( +/turf/closed/wall/rust, +/area/template_noop) +"t" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/structure/crate_empty, +/obj/effect/spawner/random/contraband/permabrig_weapon, +/obj/effect/turf_decal/stripes/corner, +/obj/effect/turf_decal/siding/wideplating_new/dark{ + dir = 1 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 + }, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 4 + }, +/area/template_noop) +"u" = ( +/obj/machinery/door/airlock/mining{ + name = "Warehouse" + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/loading_area{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"v" = ( +/obj/effect/spawner/random/trash/graffiti, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 4 + }, +/area/template_noop) +"w" = ( +/obj/effect/spawner/random/structure/table_or_rack, +/obj/item/stack/sheet/iron/five, +/obj/item/stack/rods/ten, +/obj/effect/turf_decal/bot_red, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"y" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/box, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 8 + }, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 8 + }, +/area/template_noop) +"z" = ( +/obj/effect/spawner/random/structure/table_or_rack, +/obj/effect/spawner/random/engineering/flashlight, +/obj/effect/spawner/random/engineering/material_rare, +/obj/effect/turf_decal/bot_red, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"B" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/cigbutt, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 + }, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 4 + }, +/area/template_noop) +"D" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/grime, +/obj/item/poster/random_contraband, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 8 + }, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 8 + }, +/area/template_noop) +"E" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/closet_maintenance, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/engineering/material_rare, +/turf/open/floor/plating, +/area/template_noop) +"F" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/crate_empty, +/obj/effect/spawner/random/maintenance/two, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/engineering/tool, +/turf/open/floor/plating, +/area/template_noop) +"G" = ( +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/box, +/turf/open/floor/plating, +/area/template_noop) +"H" = ( +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/structure/crate, +/turf/open/floor/plating, +/area/template_noop) +"I" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/structure/tank_holder, +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wideplating_new/dark{ + dir = 1 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 8 + }, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 8 + }, +/area/template_noop) +"J" = ( +/obj/effect/spawner/random/trash/mess, +/obj/effect/spawner/random/contraband/permabrig_weapon, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 4 + }, +/area/template_noop) +"K" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/closet_maintenance, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/engineering/material_cheap, +/turf/open/floor/plating, +/area/template_noop) +"L" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/crate_empty, +/obj/effect/spawner/random/maintenance/two, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small/directional/south, +/obj/structure/sign/poster/random/directional/south, +/turf/open/floor/plating, +/area/template_noop) +"M" = ( +/obj/effect/spawner/random/trash/mess, +/obj/effect/spawner/random/trash/cigbutt, +/turf/open/floor/iron/dark, +/area/template_noop) +"N" = ( +/obj/effect/spawner/random/maintenance, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 8 + }, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 8 + }, +/area/template_noop) +"O" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 + }, +/obj/effect/spawner/random/structure/girder, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 4 + }, +/area/template_noop) +"P" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/crate_empty, +/obj/effect/spawner/random/maintenance/four, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/engineering/vending_restock, +/obj/structure/sign/poster/random/directional/east, +/turf/open/floor/plating, +/area/template_noop) +"Q" = ( +/obj/effect/spawner/random/trash/botanical_waste, +/obj/effect/spawner/random/trash/food_packaging, +/obj/effect/spawner/random/structure/steam_vent, +/turf/open/floor/iron/dark, +/area/template_noop) +"R" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/mess, +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wideplating_new/dark, +/obj/effect/turf_decal/tile/brown/half{ + dir = 8 + }, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 8 + }, +/area/template_noop) +"S" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/crate_empty, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/engineering/flashlight, +/turf/open/floor/plating, +/area/template_noop) +"T" = ( +/turf/closed/wall, +/area/template_noop) +"U" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/bin, +/obj/effect/turf_decal/siding/wideplating_new/dark, +/turf/open/floor/iron/dark, +/area/template_noop) +"V" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/engineering/canister, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small/directional/north, +/turf/open/floor/plating/rust, +/area/template_noop) +"W" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/crate_empty, +/obj/effect/spawner/random/maintenance/three, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating/rust, +/area/template_noop) +"X" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/crate_empty, +/obj/effect/spawner/random/maintenance/four, +/obj/effect/decal/cleanable/dirt, +/obj/structure/sign/poster/random/directional/west, +/turf/open/floor/plating, +/area/template_noop) +"Y" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/crate_abandoned, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/template_noop) +"Z" = ( +/obj/effect/spawner/random/maintenance, +/obj/effect/decal/cleanable/dirt, +/obj/structure/sign/poster/random/directional/north, +/obj/effect/turf_decal/siding/wideplating_new/dark{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/template_noop) + +(1,1,1) = {" +e +e +e +e +e +e +e +e +e +e +j +"} +(2,1,1) = {" +e +e +T +T +T +s +s +s +T +e +e +"} +(3,1,1) = {" +e +e +T +l +X +H +W +k +T +e +e +"} +(4,1,1) = {" +e +T +s +V +H +n +q +E +o +T +e +"} +(5,1,1) = {" +e +o +I +m +N +p +D +y +R +u +e +"} +(6,1,1) = {" +e +T +Z +g +M +w +Q +z +U +s +e +"} +(7,1,1) = {" +e +h +t +B +v +O +J +i +a +u +e +"} +(8,1,1) = {" +e +T +T +K +d +G +Y +L +T +T +e +"} +(9,1,1) = {" +e +e +T +c +F +P +S +r +T +e +e +"} +(10,1,1) = {" +e +e +T +s +o +T +s +s +T +e +e +"} +(11,1,1) = {" +e +e +e +e +e +e +e +e +e +e +e +"} diff --git a/_maps/modular_generic/station_l_kilojan.dmm b/_maps/modular_generic/station_l_kilojan.dmm new file mode 100644 index 0000000000000..9183b617f54e6 --- /dev/null +++ b/_maps/modular_generic/station_l_kilojan.dmm @@ -0,0 +1,644 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"b" = ( +/obj/machinery/conveyor{ + dir = 4; + id = "garbage"; + name = "trash belt" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"c" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/iron, +/area/template_noop) +"d" = ( +/turf/open/floor/plating, +/area/template_noop) +"e" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/template_noop) +"f" = ( +/obj/structure/closet/l3closet/janitor, +/obj/structure/window/reinforced/spawner/directional/south, +/obj/effect/turf_decal/bot, +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/tile/neutral/half/contrasted{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"g" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/purple/half/contrasted{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"h" = ( +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/tile/purple/half/contrasted, +/obj/effect/turf_decal/tile/blue, +/obj/structure/closet/crate/trashcart/filled, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"i" = ( +/obj/machinery/door/airlock/grunge{ + name = "Custodial Closet" + }, +/turf/open/floor/iron, +/area/template_noop) +"j" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/template_noop) +"k" = ( +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/iron, +/area/template_noop) +"l" = ( +/obj/machinery/conveyor{ + dir = 4; + id = "garbage"; + name = "trash belt" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/machinery/light/small/directional/south, +/turf/open/floor/iron/dark, +/area/template_noop) +"m" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral/half/contrasted, +/obj/effect/turf_decal/delivery, +/obj/structure/mop_bucket/janitorialcart{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"n" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/purple/half/contrasted, +/obj/effect/turf_decal/tile/blue, +/obj/structure/closet/crate/trashcart/filled, +/obj/effect/turf_decal/tile/blue, +/obj/structure/disposalpipe/segment, +/obj/machinery/mineral/stacking_unit_console{ + pixel_x = 64 + }, +/turf/open/floor/iron, +/area/template_noop) +"o" = ( +/obj/machinery/door/airlock/grunge{ + name = "Custodial Closet" + }, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/turf/open/floor/iron, +/area/template_noop) +"p" = ( +/obj/structure/window/reinforced/spawner/directional/south, +/obj/effect/turf_decal/delivery, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 1 + }, +/obj/structure/extinguisher_cabinet/directional/west, +/obj/effect/turf_decal/tile/neutral/half/contrasted{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark, +/area/template_noop) +"r" = ( +/obj/structure/sink/directional/west, +/obj/effect/turf_decal/stripes/corner, +/obj/effect/turf_decal/loading_area, +/obj/machinery/door/window/right/directional/south{ + name = "Trash Chute"; + req_access = list("janitor") + }, +/obj/item/reagent_containers/cup/bucket, +/obj/item/mop, +/obj/effect/turf_decal/tile/purple/half/contrasted{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"s" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/obj/machinery/door/window/left/directional/south{ + name = "Trash Chute"; + req_access = list("janitor") + }, +/obj/machinery/conveyor_switch/oneway{ + dir = 4; + id = "garbage"; + name = "trash chute" + }, +/obj/effect/turf_decal/loading_area, +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/tile/purple/half/contrasted{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/spawner/random/trash/mess, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/template_noop) +"t" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/structure/broken_flooring/side/directional/south, +/turf/open/floor/plating, +/area/template_noop) +"u" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"v" = ( +/turf/closed/wall/r_wall, +/area/template_noop) +"w" = ( +/obj/structure/broken_flooring/pile/directional/west, +/turf/open/floor/plating, +/area/template_noop) +"x" = ( +/turf/closed/wall, +/area/template_noop) +"y" = ( +/obj/structure/disposalpipe/segment{ + dir = 1 + }, +/obj/structure/broken_flooring/side/directional/south, +/obj/structure/closet/crate/trashcart/filled, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/template_noop) +"z" = ( +/obj/machinery/conveyor{ + dir = 4; + id = "garbage"; + name = "trash belt" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/recycler{ + dir = 8 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"A" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"B" = ( +/obj/effect/turf_decal/delivery, +/obj/machinery/disposal/delivery_chute{ + dir = 8 + }, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/light/small/directional/east, +/obj/structure/sign/warning/deathsposal/directional/east, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"C" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/tile/purple/half/contrasted{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/iron, +/area/template_noop) +"D" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"E" = ( +/obj/machinery/conveyor{ + dir = 4; + id = "garbage"; + name = "trash belt" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"F" = ( +/obj/structure/disposalpipe/segment{ + dir = 1 + }, +/turf/open/floor/plating, +/area/template_noop) +"G" = ( +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/blue, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/template_noop) +"H" = ( +/obj/machinery/mineral/stacking_machine{ + input_dir = 2 + }, +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"I" = ( +/turf/closed/wall/rust, +/area/template_noop) +"J" = ( +/obj/machinery/light/directional/south, +/obj/effect/turf_decal/stripes/corner, +/obj/effect/turf_decal/tile/purple/half/contrasted, +/obj/effect/turf_decal/tile/blue, +/obj/structure/sign/poster/random/directional/south, +/obj/structure/closet/crate/trashcart/filled, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"K" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/broken_flooring/singular, +/obj/structure/closet/crate/trashcart/filled, +/turf/open/floor/plating, +/area/template_noop) +"L" = ( +/obj/structure/disposaloutlet{ + dir = 4 + }, +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/light/small/directional/west, +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"M" = ( +/obj/machinery/conveyor{ + dir = 4; + id = "garbage"; + name = "trash belt" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"N" = ( +/obj/machinery/vending/wardrobe/jani_wardrobe, +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/tile/neutral/half/contrasted{ + dir = 4 + }, +/obj/structure/sign/poster/random/directional/west, +/turf/open/floor/iron/dark, +/area/template_noop) +"O" = ( +/obj/structure/reagent_dispensers/watertank, +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/stripes/corner, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/item/reagent_containers/cup/bucket, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral/half/contrasted, +/obj/structure/sign/poster/random/directional/north, +/turf/open/floor/iron/dark, +/area/template_noop) +"Q" = ( +/obj/structure/table, +/obj/item/reagent_containers/spray/cleaner{ + pixel_x = -4; + pixel_y = 4 + }, +/obj/item/flashlight{ + pixel_y = 4 + }, +/obj/item/flashlight{ + pixel_y = 4 + }, +/obj/machinery/light/directional/north, +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/obj/machinery/button/door/directional/north{ + id = "custodialwagon"; + name = "Custodial Bay Toggle"; + pixel_x = 8; + req_access = list("janitor") + }, +/obj/effect/turf_decal/tile/neutral/anticorner/contrasted{ + dir = 8 + }, +/obj/effect/spawner/random/clothing/gloves, +/turf/open/floor/iron/dark, +/area/template_noop) +"R" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"S" = ( +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral/half/contrasted, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark, +/area/template_noop) +"T" = ( +/obj/vehicle/ridden/janicart{ + dir = 4 + }, +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral/half/contrasted, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark, +/area/template_noop) +"U" = ( +/obj/effect/spawner/random/trash/mess, +/turf/open/floor/plating, +/area/template_noop) +"V" = ( +/obj/effect/turf_decal/tile/purple/half/contrasted, +/obj/effect/turf_decal/tile/blue, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"W" = ( +/obj/structure/table, +/obj/item/storage/box/lights/mixed{ + pixel_x = -4; + pixel_y = 4 + }, +/obj/item/storage/box/lights/mixed{ + pixel_x = -4; + pixel_y = 4 + }, +/obj/item/grenade/chem_grenade/cleaner{ + pixel_x = 10; + pixel_y = 6 + }, +/obj/item/grenade/chem_grenade/cleaner{ + pixel_x = 10; + pixel_y = 6 + }, +/obj/item/grenade/chem_grenade/cleaner{ + pixel_x = 10; + pixel_y = 6 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/neutral/anticorner/contrasted{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"X" = ( +/obj/machinery/door/poddoor/shutters/preopen{ + id = "custodialwagon" + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"Y" = ( +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/template_noop) +"Z" = ( +/obj/structure/table, +/obj/item/toy/figure/janitor{ + pixel_x = -8; + pixel_y = 6 + }, +/obj/item/storage/box/mousetraps{ + pixel_x = 4; + pixel_y = 4 + }, +/obj/item/storage/box/mousetraps{ + pixel_x = 4; + pixel_y = 4 + }, +/obj/item/restraints/legcuffs/beartrap{ + pixel_y = 8 + }, +/obj/effect/decal/cleanable/cobweb, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +D +"} +(2,1,1) = {" +a +v +v +v +v +v +v +v +v +v +a +"} +(3,1,1) = {" +a +v +Z +u +W +N +f +p +L +v +a +"} +(4,1,1) = {" +a +i +u +A +g +F +C +s +E +v +a +"} +(5,1,1) = {" +a +v +Q +c +e +Y +G +r +b +v +a +"} +(6,1,1) = {" +a +X +T +w +k +j +J +x +z +v +a +"} +(7,1,1) = {" +a +X +S +U +U +K +h +x +l +v +a +"} +(8,1,1) = {" +a +X +m +d +t +y +n +H +M +v +a +"} +(9,1,1) = {" +a +v +O +e +R +u +V +I +B +v +a +"} +(10,1,1) = {" +a +v +v +o +o +v +v +v +v +v +a +"} +(11,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/modular_generic/station_l_kitchen.dmm b/_maps/modular_generic/station_l_kitchen.dmm new file mode 100644 index 0000000000000..68b5bb3699858 --- /dev/null +++ b/_maps/modular_generic/station_l_kitchen.dmm @@ -0,0 +1,908 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"b" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/light/cold/no_nightlight/directional/west, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Kitchen Shutters"; + dir = 1 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"c" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/grill, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"d" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Kitchen Shutters"; + dir = 1 + }, +/obj/effect/spawner/random/entertainment/musical_instrument, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"e" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 5 + }, +/obj/machinery/griddle, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"f" = ( +/turf/open/floor/iron/kitchen, +/area/template_noop) +"g" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Kitchen Shutters" + }, +/obj/effect/spawner/random/food_or_drink/donkpockets, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"h" = ( +/obj/machinery/smartfridge/food, +/turf/open/floor/iron/dark/textured_half{ + dir = 1 + }, +/area/template_noop) +"i" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Kitchen Shutters"; + dir = 1 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"k" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 4 + }, +/obj/machinery/grill, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"l" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral/half{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral/half{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 8 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 8; + id = "kitchen"; + name = "Kitchen Shutters" + }, +/turf/open/floor/iron/dark/textured_half{ + dir = 1 + }, +/area/template_noop) +"n" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/white{ + dir = 10 + }, +/obj/structure/closet/secure_closet/freezer/fridge{ + locked = 0 + }, +/obj/item/storage/box/ingredients/wildcard, +/obj/item/storage/box/ingredients/wildcard, +/obj/item/storage/box/ingredients/wildcard, +/obj/item/storage/box/ingredients/wildcard, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"o" = ( +/obj/machinery/door/airlock/public/glass{ + name = "Kitchen" + }, +/turf/open/floor/iron/kitchen, +/area/template_noop) +"p" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/griddle, +/obj/item/food/raw_patty{ + pixel_y = 4 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"q" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/light/cold/no_nightlight/directional/east, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Kitchen Shutters" + }, +/obj/effect/spawner/random/food_or_drink/donuts{ + pixel_x = -6 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"r" = ( +/obj/machinery/deepfryer, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/siding/white, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"s" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/siding/white{ + dir = 10 + }, +/obj/item/reagent_containers/condiment/enzyme{ + pixel_x = -2; + pixel_y = 6 + }, +/obj/item/reagent_containers/cup/beaker/large{ + pixel_x = 5 + }, +/obj/item/kitchen/rollingpin, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"t" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral/half{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral/half{ + dir = 4 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 8; + id = "kitchen"; + name = "Kitchen Shutters" + }, +/obj/effect/turf_decal/siding/white{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 8 + }, +/obj/effect/spawner/random/entertainment/deck, +/obj/effect/spawner/random/entertainment/gambling, +/turf/open/floor/iron/dark/textured_half{ + dir = 1 + }, +/area/template_noop) +"u" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/template_noop) +"v" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Kitchen Shutters" + }, +/obj/effect/spawner/random/food_or_drink/donuts{ + pixel_x = 11 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"w" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral/half{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral/half{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 8 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 8; + id = "kitchen"; + name = "Kitchen Shutters" + }, +/obj/item/radio{ + desc = "An old handheld radio. Tuned to the outpost's hit radio station."; + frequency = 1475; + icon_state = "radio"; + name = "old radio" + }, +/turf/open/floor/iron/dark/textured_half{ + dir = 1 + }, +/area/template_noop) +"x" = ( +/turf/closed/wall, +/area/template_noop) +"y" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/siding/white, +/obj/structure/table/reinforced, +/obj/machinery/microwave{ + pixel_y = 5 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"z" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/white{ + dir = 8 + }, +/obj/structure/closet/secure_closet/freezer/fridge{ + locked = 0 + }, +/obj/item/storage/box/ingredients/wildcard, +/obj/item/storage/box/ingredients/wildcard, +/obj/item/storage/box/ingredients/wildcard, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"A" = ( +/obj/machinery/chem_dispenser/drinks/fullupgrade{ + dir = 8; + pixel_x = 16 + }, +/turf/open/floor/iron/kitchen, +/area/template_noop) +"B" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/siding/white{ + dir = 8 + }, +/obj/machinery/vending/wardrobe/chef_wardrobe, +/obj/machinery/light/cold/no_nightlight/directional/east, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"C" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/siding/white{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"D" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"E" = ( +/obj/machinery/deepfryer, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/siding/white{ + dir = 6 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"F" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 8 + }, +/obj/item/clothing/suit/apron/chef, +/obj/item/clothing/head/utility/chefhat, +/obj/item/clothing/mask/fakemoustache/italian, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"G" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"I" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 9 + }, +/obj/machinery/vending/dinnerware, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"J" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/siding/white{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"K" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/light/cold/no_nightlight/directional/west, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Kitchen Shutters" + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"L" = ( +/obj/machinery/button/door/directional/west{ + id = "kitchen"; + name = "Counter Shutters Control" + }, +/obj/structure/sink/kitchen/directional/east{ + pixel_y = 3 + }, +/turf/open/floor/iron/kitchen, +/area/template_noop) +"M" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral/half{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral/half{ + dir = 4 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 8; + id = "kitchen"; + name = "Kitchen Shutters" + }, +/obj/effect/turf_decal/siding/white{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 8 + }, +/obj/effect/spawner/random/entertainment/dice, +/obj/effect/spawner/random/entertainment/coin, +/turf/open/floor/iron/dark/textured_half{ + dir = 1 + }, +/area/template_noop) +"N" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/structure/table/reinforced, +/obj/machinery/processor{ + pixel_y = 7 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"O" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Kitchen Shutters" + }, +/obj/item/storage/bag/tray{ + pixel_y = 6 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"P" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 9 + }, +/obj/structure/table/reinforced, +/obj/machinery/reagentgrinder{ + pixel_x = -10; + pixel_y = 4 + }, +/obj/item/book/manual/chef_recipes{ + pixel_x = 5 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"Q" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Kitchen Shutters"; + dir = 1 + }, +/obj/effect/spawner/random/entertainment/plushie, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"S" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/light/cold/no_nightlight/directional/east, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Kitchen Shutters"; + dir = 1 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"T" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Kitchen Shutters"; + dir = 1 + }, +/obj/effect/spawner/random/entertainment/lighter, +/obj/effect/spawner/random/entertainment/cigarette_pack, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"W" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen"; + name = "Kitchen Shutters" + }, +/obj/effect/spawner/random/food_or_drink/refreshing_beverage{ + pixel_x = -7; + pixel_y = 4 + }, +/obj/effect/spawner/random/food_or_drink/salad{ + pixel_x = 7 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"Y" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/structure/table/reinforced, +/obj/item/storage/box/ingredients/wildcard{ + pixel_y = 5 + }, +/obj/item/stack/sheet/mineral/coal/ten, +/turf/open/floor/iron/dark/textured, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +D +"} +(2,1,1) = {" +a +x +o +h +t +M +w +l +x +x +a +"} +(3,1,1) = {" +a +b +f +f +f +f +f +f +L +K +a +"} +(4,1,1) = {" +a +T +f +P +C +F +C +s +f +O +a +"} +(5,1,1) = {" +a +d +f +N +G +Y +G +y +f +g +a +"} +(6,1,1) = {" +a +i +f +p +G +c +G +r +f +W +a +"} +(7,1,1) = {" +a +Q +f +e +J +k +J +E +f +v +a +"} +(8,1,1) = {" +a +S +f +f +f +f +f +f +f +q +a +"} +(9,1,1) = {" +a +x +z +n +A +f +f +I +B +x +a +"} +(10,1,1) = {" +a +x +x +x +x +u +o +u +x +x +a +"} +(11,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/modular_generic/station_l_morgue.dmm b/_maps/modular_generic/station_l_morgue.dmm new file mode 100644 index 0000000000000..4b4eb63458d1b --- /dev/null +++ b/_maps/modular_generic/station_l_morgue.dmm @@ -0,0 +1,540 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/neutral/filled/corner{ + dir = 4 + }, +/obj/effect/spawner/random/trash/bacteria, +/obj/effect/decal/cleanable/blood/tracks, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark, +/area/template_noop) +"b" = ( +/obj/structure/table/optable, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mob_spawn/corpse/human/damaged, +/obj/machinery/light/small/directional/north, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"c" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark/textured_half, +/area/template_noop) +"d" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Morgue Maintenance" + }, +/obj/effect/spawner/random/structure/barricade, +/turf/open/floor/plating, +/area/template_noop) +"e" = ( +/turf/closed/wall, +/area/template_noop) +"f" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_half, +/area/template_noop) +"g" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 1 + }, +/obj/effect/spawner/random/trash/mess, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark, +/area/template_noop) +"h" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 8 + }, +/obj/machinery/door/airlock/grunge{ + name = "Morgue" + }, +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 4 + }, +/obj/effect/decal/cleanable/blood/tracks, +/turf/open/floor/iron/dark, +/area/template_noop) +"i" = ( +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/plating, +/area/template_noop) +"j" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 8 + }, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted, +/obj/structure/railing{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured_edge{ + dir = 1 + }, +/area/template_noop) +"k" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 4 + }, +/obj/effect/decal/cleanable/blood/tracks, +/turf/open/floor/iron/dark, +/area/template_noop) +"l" = ( +/obj/structure/bodycontainer/morgue, +/turf/open/floor/iron/dark/textured_half, +/area/template_noop) +"m" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating/dark/corner, +/obj/effect/turf_decal/trimline/neutral/filled/corner{ + dir = 8 + }, +/obj/effect/spawner/random/medical/surgery_tool, +/turf/open/floor/iron/dark, +/area/template_noop) +"n" = ( +/obj/structure/rack, +/obj/item/storage/box/bodybags{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/storage/box/bodybags, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/medical/memeorgans{ + spawn_loot_count = 1 + }, +/turf/open/floor/iron/dark/smooth_large, +/area/template_noop) +"o" = ( +/obj/structure/bodycontainer/morgue{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_half, +/area/template_noop) +"p" = ( +/obj/structure/bodycontainer/morgue{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured_half, +/area/template_noop) +"q" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/medical/patient_stretcher, +/obj/machinery/iv_drip, +/obj/machinery/light/small/blacklight/directional/east, +/turf/open/floor/iron/dark/smooth_large, +/area/template_noop) +"r" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 4 + }, +/obj/structure/table/reinforced/plastitaniumglass, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted, +/obj/effect/spawner/random/medical/memeorgans, +/obj/structure/railing{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_edge{ + dir = 1 + }, +/area/template_noop) +"s" = ( +/obj/structure/bodycontainer/morgue, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark/textured_half, +/area/template_noop) +"t" = ( +/obj/effect/turf_decal/siding/thinplating/dark, +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 1 + }, +/obj/effect/mapping_helpers/broken_floor, +/obj/structure/railing, +/turf/open/floor/iron/dark, +/area/template_noop) +"u" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/mess, +/obj/structure/sign/poster/official/random/directional/west, +/turf/open/floor/iron/dark/textured_half, +/area/template_noop) +"v" = ( +/obj/item/stack/tile/iron/dark{ + pixel_x = 12; + pixel_y = -3 + }, +/turf/open/floor/plating, +/area/template_noop) +"w" = ( +/obj/structure/bodycontainer/morgue{ + dir = 2 + }, +/turf/open/floor/iron/dark/textured_half{ + dir = 1 + }, +/area/template_noop) +"x" = ( +/obj/effect/decal/cleanable/blood, +/turf/open/floor/iron/dark/textured_half, +/area/template_noop) +"y" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small/blacklight/directional/west, +/turf/open/floor/iron/dark/textured_half, +/area/template_noop) +"z" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 8 + }, +/obj/machinery/computer/operating, +/obj/effect/decal/cleanable/dirt, +/obj/structure/railing{ + dir = 8 + }, +/obj/structure/sign/poster/official/random/directional/north, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"A" = ( +/obj/machinery/door/airlock/grunge{ + name = "Morgue" + }, +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 8 + }, +/obj/effect/spawner/random/structure/barricade, +/obj/effect/mapping_helpers/airlock/locked, +/turf/open/floor/iron/dark, +/area/template_noop) +"B" = ( +/obj/item/stack/tile/iron/dark/textured_half{ + pixel_x = -7; + pixel_y = -9 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/template_noop) +"C" = ( +/obj/item/stack/tile/iron/dark{ + pixel_x = -11; + pixel_y = 8 + }, +/obj/effect/spawner/random/trash/grime, +/obj/structure/railing/corner/end/flip{ + dir = 1 + }, +/turf/open/floor/plating, +/area/template_noop) +"D" = ( +/obj/effect/turf_decal/siding/thinplating/dark/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/neutral/filled/corner{ + dir = 1 + }, +/obj/item/stack/rods{ + pixel_x = -8; + pixel_y = 3 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"E" = ( +/obj/structure/sign/poster/official/random/directional/east, +/turf/open/floor/iron/dark/smooth_large, +/area/template_noop) +"F" = ( +/obj/structure/bodycontainer/morgue{ + dir = 2 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_half{ + dir = 1 + }, +/area/template_noop) +"G" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 8 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"H" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 1 + }, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/turf_decal/siding/thinplating/dark, +/obj/effect/mob_spawn/corpse/human/assistant, +/obj/effect/decal/cleanable/blood, +/turf/open/floor/iron/dark, +/area/template_noop) +"I" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/structure/railing/corner/end{ + dir = 1 + }, +/turf/open/floor/plating, +/area/template_noop) +"J" = ( +/obj/effect/turf_decal/siding/thinplating/dark, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/spawner/random/trash/mess, +/turf/open/floor/iron/dark, +/area/template_noop) +"K" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"L" = ( +/obj/structure/chair/office/tactical{ + dir = 1 + }, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted, +/turf/open/floor/iron/dark/textured_edge{ + dir = 1 + }, +/area/template_noop) +"M" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/item/stack/rods{ + pixel_x = 5; + pixel_y = 10 + }, +/obj/effect/mapping_helpers/dead_body_placer{ + bodycount = 9 + }, +/turf/open/floor/plating, +/area/template_noop) +"N" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Morgue Maintenance" + }, +/obj/effect/mapping_helpers/airlock/welded, +/turf/open/floor/plating, +/area/template_noop) +"O" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/blood/tracks, +/turf/open/floor/plating, +/area/template_noop) +"P" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/gibspawner/human/bodypartless, +/turf/open/floor/plating, +/area/template_noop) +"Q" = ( +/obj/effect/spawner/random/trash/mess, +/obj/machinery/light/small/blacklight/directional/west, +/turf/open/floor/iron/dark/textured_half{ + dir = 1 + }, +/area/template_noop) +"R" = ( +/obj/effect/turf_decal/siding/thinplating/dark, +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 1 + }, +/obj/effect/spawner/random/medical/surgery_tool_advanced, +/obj/structure/railing/corner/end/flip{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"S" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small/blacklight/directional/east, +/turf/open/floor/iron/dark/textured_half{ + dir = 1 + }, +/area/template_noop) +"T" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 4 + }, +/obj/structure/table/reinforced/plastitaniumglass, +/obj/item/surgery_tray/full/morgue, +/obj/structure/railing{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"U" = ( +/turf/template_noop, +/area/template_noop) +"V" = ( +/obj/item/stack/sheet/iron/ten{ + pixel_x = -5 + }, +/turf/open/floor/iron/dark/textured_half, +/area/template_noop) +"W" = ( +/turf/open/floor/iron/dark/textured_half{ + dir = 1 + }, +/area/template_noop) +"X" = ( +/obj/effect/decal/cleanable/blood, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark/textured_half, +/area/template_noop) +"Z" = ( +/obj/effect/spawner/structure/window/reinforced/tinted, +/obj/effect/mapping_helpers/damaged_window{ + integrity_damage_min = 0.6; + integrity_damage_max = 0.9 + }, +/turf/open/floor/plating, +/area/template_noop) + +(1,1,1) = {" +U +U +U +U +U +U +U +U +U +U +K +"} +(2,1,1) = {" +U +e +e +e +d +e +e +e +e +e +U +"} +(3,1,1) = {" +U +e +w +Q +R +x +u +y +f +e +U +"} +(4,1,1) = {" +U +e +w +W +t +p +p +p +o +e +U +"} +(5,1,1) = {" +U +e +z +j +C +V +s +s +l +e +U +"} +(6,1,1) = {" +U +e +b +L +J +M +B +c +X +e +U +"} +(7,1,1) = {" +U +e +T +r +I +P +O +k +a +h +U +"} +(8,1,1) = {" +U +e +F +W +m +v +G +i +D +Z +U +"} +(9,1,1) = {" +U +e +F +S +H +E +n +q +g +A +U +"} +(10,1,1) = {" +U +e +e +e +N +e +e +e +e +e +U +"} +(11,1,1) = {" +U +U +U +U +U +U +U +U +U +U +U +"} diff --git a/_maps/modular_generic/station_l_security.dmm b/_maps/modular_generic/station_l_security.dmm new file mode 100644 index 0000000000000..0b629f3f388b2 --- /dev/null +++ b/_maps/modular_generic/station_l_security.dmm @@ -0,0 +1,543 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aJ" = ( +/obj/structure/table/reinforced, +/obj/machinery/door/window/brigdoor/left/directional/north{ + name = "Security Desk"; + dir = 4 + }, +/obj/item/flashlight/lamp{ + pixel_x = -5; + pixel_y = 7 + }, +/obj/item/reagent_containers/cup/glass/mug/nanotrasen, +/turf/open/floor/plating, +/area/template_noop) +"aP" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 9 + }, +/turf/closed/wall/r_wall, +/area/template_noop) +"aU" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/template_noop) +"aY" = ( +/obj/structure/closet/secure_closet/brig{ + name = "Prisoner Locker" + }, +/obj/effect/spawner/random/contraband, +/obj/effect/spawner/random/contraband, +/obj/machinery/light/dim/directional/west, +/obj/effect/turf_decal/bot_red, +/obj/effect/turf_decal/siding/dark_red{ + dir = 6 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"bf" = ( +/turf/template_noop, +/area/template_noop) +"bh" = ( +/obj/structure/guncase/shotgun, +/obj/effect/turf_decal/bot_red, +/obj/effect/turf_decal/siding/dark_red{ + dir = 8 + }, +/obj/item/gun/ballistic/shotgun/riot, +/obj/item/gun/ballistic/shotgun/riot, +/turf/open/floor/iron/dark, +/area/template_noop) +"bO" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"ds" = ( +/obj/structure/closet/secure_closet/contraband/armory, +/obj/effect/turf_decal/bot_red, +/obj/effect/turf_decal/siding/dark_red{ + dir = 10 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"es" = ( +/obj/effect/spawner/random/trash/food_packaging{ + pixel_x = 8 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"fA" = ( +/turf/closed/wall/r_wall, +/area/template_noop) +"fC" = ( +/obj/structure/window/reinforced/spawner/directional/south, +/obj/structure/chair/sofa/bench/right{ + dir = 4 + }, +/obj/effect/turf_decal/box/corners, +/obj/effect/turf_decal/box/corners{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"gy" = ( +/obj/effect/turf_decal/trimline/red/filled/line, +/obj/structure/chair/sofa/right/maroon{ + dir = 1 + }, +/obj/machinery/computer/security/telescreen/entertainment/directional/south, +/turf/open/floor/iron/dark, +/area/template_noop) +"hj" = ( +/obj/structure/closet/secure_closet/brig{ + name = "Prisoner Locker" + }, +/obj/effect/spawner/random/contraband, +/obj/effect/spawner/random/contraband, +/obj/effect/spawner/random/contraband, +/obj/effect/turf_decal/bot_red, +/obj/effect/turf_decal/siding/dark_red{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"iP" = ( +/obj/effect/turf_decal/trimline/red/filled/line, +/obj/structure/sign/warning/yes_smoking/circle/directional/south, +/obj/effect/spawner/random/vending/snackvend, +/turf/open/floor/iron/dark, +/area/template_noop) +"lG" = ( +/obj/structure/chair/stool/directional/west, +/turf/open/floor/iron/dark, +/area/template_noop) +"lW" = ( +/obj/structure/table/reinforced, +/obj/machinery/door/window/brigdoor/right/directional/north{ + name = "Security Desk"; + dir = 4 + }, +/obj/item/paper_bin{ + pixel_y = 3 + }, +/obj/effect/spawner/random/bureaucracy/pen, +/obj/effect/spawner/random/bureaucracy/pen{ + pixel_x = 2 + }, +/turf/open/floor/plating, +/area/template_noop) +"ma" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 8 + }, +/obj/structure/filingcabinet, +/turf/open/floor/iron/dark, +/area/template_noop) +"mI" = ( +/obj/structure/closet/secure_closet/brig{ + name = "Prisoner Locker" + }, +/obj/effect/spawner/random/contraband, +/obj/effect/turf_decal/bot_red, +/obj/effect/turf_decal/siding/dark_red{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"mQ" = ( +/obj/structure/table/reinforced, +/obj/machinery/recharger, +/obj/effect/spawner/random/bureaucracy/briefcase{ + pixel_y = 10; + pixel_x = -2 + }, +/obj/item/radio{ + desc = "An old handheld radio. Tuned to the outpost's hit radio station."; + frequency = 1475; + icon_state = "radio"; + name = "old radio" + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"nh" = ( +/obj/structure/chair/sofa/bench/right{ + dir = 8 + }, +/obj/effect/turf_decal/box/corners{ + dir = 1 + }, +/obj/effect/turf_decal/box/corners{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"nu" = ( +/obj/structure/window/reinforced/spawner/directional/south, +/obj/structure/chair/sofa/bench/left{ + dir = 8 + }, +/obj/effect/turf_decal/box/corners{ + dir = 8 + }, +/obj/effect/turf_decal/box/corners, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"nB" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 1 + }, +/obj/structure/chair/stool/bar/directional/east, +/turf/open/floor/iron/dark, +/area/template_noop) +"nR" = ( +/obj/effect/spawner/random/trash/mess, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"oJ" = ( +/obj/effect/turf_decal/trimline/red/filled/line, +/obj/effect/spawner/random/trash/bin, +/turf/open/floor/iron/dark, +/area/template_noop) +"pz" = ( +/obj/effect/turf_decal/trimline/red/filled/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/red/filled/corner{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"sV" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 8 + }, +/obj/machinery/modular_computer/preset/cargochat/security{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"vv" = ( +/obj/effect/turf_decal/trimline/red/filled/line, +/obj/structure/table/reinforced, +/obj/structure/sign/poster/contraband/donut_corp/directional/south, +/obj/item/storage/fancy/donut_box, +/turf/open/floor/iron/dark, +/area/template_noop) +"vJ" = ( +/obj/machinery/door/airlock/security/glass{ + name = "Security Outpost" + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"ys" = ( +/obj/structure/sign/departments/security/directional/east, +/turf/template_noop, +/area/template_noop) +"zf" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"zy" = ( +/obj/structure/chair/sofa/bench/left{ + dir = 4 + }, +/obj/effect/turf_decal/box/corners{ + dir = 4 + }, +/obj/effect/turf_decal/box/corners{ + dir = 1 + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"Bn" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 8 + }, +/turf/closed/wall/r_wall, +/area/template_noop) +"BA" = ( +/obj/structure/sign/departments/security/directional/south, +/turf/template_noop, +/area/template_noop) +"Dj" = ( +/obj/effect/spawner/random/trash/crushed_can{ + pixel_y = 4; + pixel_x = -11 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"DJ" = ( +/obj/machinery/door/window/brigdoor/security/cell/left/directional/south{ + id = "cell-2"; + name = "Holding Cell" + }, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"Ee" = ( +/turf/open/floor/iron/dark, +/area/template_noop) +"FR" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"GC" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 5 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"Hl" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 4 + }, +/obj/structure/chair/stool/directional/east, +/turf/open/floor/iron/dark, +/area/template_noop) +"IF" = ( +/obj/effect/turf_decal/trimline/red/filled/end{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"LN" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"MP" = ( +/obj/structure/chair/stool/bar/directional/east{ + dir = 8 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"NS" = ( +/obj/effect/turf_decal/trimline/red/filled/line, +/obj/structure/chair/sofa/left/maroon{ + dir = 1 + }, +/obj/machinery/light/dim/directional/south, +/turf/open/floor/iron/dark, +/area/template_noop) +"QW" = ( +/obj/structure/guncase/wt550, +/obj/effect/turf_decal/bot_red, +/obj/effect/turf_decal/siding/dark_red{ + dir = 8 + }, +/obj/item/gun/ballistic/automatic/wt550, +/turf/open/floor/iron/dark, +/area/template_noop) +"TA" = ( +/obj/effect/spawner/random/trash/graffiti, +/obj/machinery/light/dim/directional/north, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"TI" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 9 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"TT" = ( +/obj/structure/chair/stool/bar/directional/east{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"Uc" = ( +/obj/structure/table, +/obj/item/paper_bin{ + pixel_y = 3 + }, +/obj/effect/spawner/random/bureaucracy/pen, +/turf/open/floor/iron/dark/textured, +/area/template_noop) +"Vo" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 1 + }, +/obj/structure/table/reinforced, +/obj/item/modular_computer/laptop/preset/civilian, +/obj/machinery/coffeemaker, +/obj/structure/sign/poster/contraband/fun_police/directional/north, +/turf/open/floor/iron/dark, +/area/template_noop) +"Wn" = ( +/obj/effect/mapping_helpers/airlock/access/any/security/brig, +/turf/open/floor/iron/dark, +/area/template_noop) +"WI" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 6 + }, +/obj/structure/table/reinforced, +/obj/machinery/coffeemaker, +/turf/open/floor/iron/dark, +/area/template_noop) +"XZ" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 10 + }, +/obj/structure/filingcabinet, +/turf/open/floor/iron/dark, +/area/template_noop) +"ZU" = ( +/obj/structure/table, +/obj/item/flashlight/lamp, +/turf/open/floor/iron/dark/textured, +/area/template_noop) + +(1,1,1) = {" +bf +bf +bf +bf +ys +bf +ys +bf +bf +bf +bO +"} +(2,1,1) = {" +bf +fA +fA +fA +fA +vJ +fA +fA +fA +fA +bf +"} +(3,1,1) = {" +bf +fA +ZU +zy +fC +TI +ma +sV +XZ +fA +bf +"} +(4,1,1) = {" +bf +fA +TA +nR +DJ +LN +Ee +lG +oJ +fA +bf +"} +(5,1,1) = {" +bf +fA +Uc +nh +nu +nB +Ee +Ee +NS +fA +bf +"} +(6,1,1) = {" +bf +fA +fA +aP +Bn +Vo +mQ +Ee +gy +fA +bf +"} +(7,1,1) = {" +BA +fA +mI +hj +aY +TT +MP +es +iP +fA +bf +"} +(8,1,1) = {" +bf +Wn +IF +FR +FR +pz +Ee +Dj +vv +fA +bf +"} +(9,1,1) = {" +BA +fA +QW +bh +ds +GC +zf +Hl +WI +fA +bf +"} +(10,1,1) = {" +bf +fA +fA +aU +aU +fA +aJ +lW +fA +fA +bf +"} +(11,1,1) = {" +bf +bf +bf +bf +bf +bf +bf +bf +bf +bf +bf +"} diff --git a/_maps/modular_generic/station_l_webs.dmm b/_maps/modular_generic/station_l_webs.dmm new file mode 100644 index 0000000000000..4f2470d71b5b1 --- /dev/null +++ b/_maps/modular_generic/station_l_webs.dmm @@ -0,0 +1,583 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"bq" = ( +/obj/structure/railing{ + dir = 8 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 8 + }, +/obj/effect/turf_decal/bot, +/obj/structure/closet/crate, +/obj/effect/spawner/random/bureaucracy, +/obj/effect/spawner/random/medical/supplies, +/obj/structure/spider/stickyweb{ + plane = -7 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"cP" = ( +/obj/structure/railing{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/machinery/disposal/bin, +/turf/open/floor/iron/dark/side, +/area/template_noop) +"dy" = ( +/obj/structure/railing{ + dir = 10 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 10 + }, +/obj/effect/turf_decal/bot, +/obj/structure/closet/crate, +/obj/effect/spawner/random/bureaucracy, +/obj/structure/spider/stickyweb{ + plane = -7 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"es" = ( +/obj/structure/railing, +/obj/effect/turf_decal/siding/thinplating_new, +/obj/structure/chair/sofa/bench{ + dir = 1; + pixel_y = 8 + }, +/turf/open/floor/plating, +/area/template_noop) +"fN" = ( +/obj/effect/turf_decal/tile/neutral/diagonal_edge, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"fS" = ( +/obj/effect/turf_decal/delivery, +/obj/effect/spawner/random/structure/crate, +/turf/open/floor/iron/dark, +/area/template_noop) +"gu" = ( +/obj/effect/decal/cleanable/cobweb, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/structure/closet_maintenance, +/turf/open/floor/plating, +/area/template_noop) +"gW" = ( +/turf/closed/wall, +/area/template_noop) +"hL" = ( +/obj/structure/broken_flooring/singular/directional/north, +/obj/structure/sign/poster/contraband/random/directional/north, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = -6; + pixel_y = 13 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/template_noop) +"ik" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 1 + }, +/obj/structure/flora/bush/jungle/b/style_random, +/obj/effect/spawner/random/trash/bin, +/obj/item/fireaxe, +/turf/open/floor/iron/dark/corner{ + dir = 1 + }, +/area/template_noop) +"iB" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/stack/tile/iron/dark, +/turf/open/floor/iron/dark, +/area/template_noop) +"jd" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/sign/poster/contraband/random/directional/west, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark, +/area/template_noop) +"kF" = ( +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/effect/decal/cleanable/glass, +/turf/open/floor/iron/dark, +/area/template_noop) +"mK" = ( +/turf/template_noop, +/area/template_noop) +"qH" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"qU" = ( +/obj/structure/barricade/wooden/crude, +/obj/machinery/door/airlock/maintenance_hatch, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/plating, +/area/template_noop) +"rS" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/structure/broken_flooring/side/directional/west, +/obj/structure/barricade/sandbags{ + color = "#737373" + }, +/turf/open/floor/plating, +/area/template_noop) +"sc" = ( +/obj/effect/turf_decal/tile/neutral/diagonal_edge, +/obj/structure/flora/bush/jungle/c/style_random, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"uC" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/effect/decal/cleanable/dirt, +/obj/structure/filingcabinet, +/turf/open/floor/iron/dark/side, +/area/template_noop) +"vI" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 6 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 1 + }, +/obj/structure/railing/corner/end{ + dir = 8 + }, +/obj/structure/barricade/sandbags{ + color = "#737373" + }, +/turf/open/floor/iron/dark/side{ + dir = 6 + }, +/area/template_noop) +"vX" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/structure/broken_flooring/side/directional/north, +/obj/structure/sign/poster/contraband/random/directional/south, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = 9; + pixel_y = 13 + }, +/turf/open/floor/plating, +/area/template_noop) +"wA" = ( +/turf/open/floor/iron/stairs/medium{ + dir = 8 + }, +/area/template_noop) +"xD" = ( +/obj/effect/turf_decal/tile/neutral/diagonal_edge, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"xF" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/obj/structure/sign/poster/contraband/random/directional/west, +/obj/machinery/light/warm/dim/directional/west, +/obj/structure/chair/stool/directional/east, +/turf/open/floor/iron/dark/side{ + dir = 4 + }, +/area/template_noop) +"xW" = ( +/obj/effect/spawner/random/trash/mess, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/machinery/light/warm/dim/directional/north, +/obj/machinery/light_switch/directional/north, +/turf/open/floor/iron/dark, +/area/template_noop) +"yf" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/bot, +/obj/structure/closet/crate, +/obj/structure/spider/stickyweb{ + plane = -7 + }, +/obj/item/multitool, +/turf/open/floor/iron/dark, +/area/template_noop) +"zM" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/item/stack/tile/iron/dark, +/turf/open/floor/plating, +/area/template_noop) +"Bi" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 8 + }, +/obj/structure/chair/office/light{ + dir = 1 + }, +/obj/machinery/light/warm/dim/directional/east, +/turf/open/floor/iron/dark/side{ + dir = 8 + }, +/area/template_noop) +"BB" = ( +/obj/structure/railing{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark/corner, +/obj/structure/rack, +/obj/effect/spawner/random/engineering/toolbox, +/turf/open/floor/iron/dark/corner, +/area/template_noop) +"Cd" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner, +/obj/structure/barricade/sandbags{ + color = "#737373" + }, +/turf/open/floor/iron/dark/corner, +/area/template_noop) +"Dp" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 8 + }, +/obj/structure/barricade/sandbags{ + color = "#737373" + }, +/turf/open/floor/iron/dark/corner{ + dir = 8 + }, +/area/template_noop) +"Ec" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/structure/table, +/obj/effect/spawner/random/contraband/armory, +/turf/open/floor/iron/dark/side{ + dir = 1 + }, +/area/template_noop) +"Gf" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/structure/extinguisher_cabinet/directional/south, +/obj/structure/broken_flooring/side/directional/north, +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/bush/jungle/b/style_2, +/turf/open/floor/plating, +/area/template_noop) +"Gy" = ( +/obj/effect/turf_decal/tile/neutral/diagonal_edge, +/obj/effect/spawner/random/trash/mess, +/turf/open/floor/iron/dark/diagonal, +/area/template_noop) +"GW" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 10 + }, +/obj/structure/broken_flooring/singular, +/turf/open/floor/plating, +/area/template_noop) +"If" = ( +/obj/structure/flora/bush/jungle/b/style_2, +/obj/structure/barricade/sandbags{ + color = "#737373" + }, +/turf/open/floor/iron, +/area/template_noop) +"KL" = ( +/obj/structure/barricade/wooden/crude, +/obj/machinery/door/airlock/maintenance_hatch, +/turf/open/floor/plating, +/area/template_noop) +"Lp" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/template_noop) +"Mi" = ( +/obj/structure/railing{ + dir = 8 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 8 + }, +/obj/effect/turf_decal/delivery, +/obj/effect/spawner/random/structure/crate, +/turf/open/floor/iron/dark, +/area/template_noop) +"Nr" = ( +/obj/effect/decal/cleanable/glass, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/plating, +/area/template_noop) +"NW" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/flora/bush/jungle/c/style_2, +/obj/effect/spawner/random/engineering/tank, +/turf/open/floor/iron/dark/corner{ + dir = 4 + }, +/area/template_noop) +"PB" = ( +/obj/structure/flora/bush/jungle/b/style_2, +/obj/effect/spawner/random/structure/closet_maintenance, +/turf/open/floor/iron/dark, +/area/template_noop) +"Ql" = ( +/obj/structure/broken_flooring/pile/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/plating, +/area/template_noop) +"RW" = ( +/turf/open/floor/iron/stairs/medium{ + dir = 1 + }, +/area/template_noop) +"RY" = ( +/obj/structure/railing, +/obj/effect/turf_decal/siding/thinplating_new, +/obj/structure/chair/sofa/bench/left{ + dir = 1; + pixel_y = 8 + }, +/turf/open/floor/plating, +/area/template_noop) +"Te" = ( +/obj/structure/railing{ + dir = 6 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 6 + }, +/obj/structure/chair/sofa/bench/right{ + dir = 1; + pixel_y = 8 + }, +/turf/open/floor/plating, +/area/template_noop) +"Tf" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/decal/cleanable/glass, +/obj/structure/guncase/wt550, +/obj/structure/fireaxecabinet/empty/directional/south, +/obj/item/gun/ballistic/automatic/wt550, +/turf/open/floor/iron/dark/side{ + dir = 1 + }, +/area/template_noop) +"Uf" = ( +/obj/structure/railing, +/obj/effect/turf_decal/siding/thinplating_new, +/obj/structure/flora/bush/jungle/c/style_2, +/obj/effect/spawner/random/structure/crate, +/obj/effect/turf_decal/delivery, +/turf/open/floor/iron/dark, +/area/template_noop) +"UW" = ( +/obj/structure/table, +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 8 + }, +/obj/structure/sign/clock/directional/east, +/obj/effect/spawner/random/bureaucracy/folder, +/obj/effect/spawner/random/bureaucracy/pen, +/turf/open/floor/iron/dark/corner{ + dir = 8 + }, +/area/template_noop) +"Vf" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/item/stack/tile/iron/dark, +/turf/open/floor/plating, +/area/template_noop) +"VU" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark, +/area/template_noop) +"ZE" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/table, +/obj/item/emptysandbag, +/turf/open/floor/iron/dark/side{ + dir = 1 + }, +/area/template_noop) + +(1,1,1) = {" +mK +mK +mK +mK +mK +mK +mK +mK +mK +mK +qH +"} +(2,1,1) = {" +mK +gW +gW +gW +gW +qU +gW +gW +gW +gW +mK +"} +(3,1,1) = {" +mK +gW +gu +jd +Ql +Vf +BB +xF +NW +gW +mK +"} +(4,1,1) = {" +mK +gW +PB +Vf +RY +wA +cP +xD +Gf +gW +mK +"} +(5,1,1) = {" +mK +gW +hL +Nr +es +Cd +vI +fN +Ec +gW +mK +"} +(6,1,1) = {" +mK +gW +xW +zM +Te +rS +xD +sc +Tf +gW +mK +"} +(7,1,1) = {" +mK +KL +VU +RW +If +Dp +GW +Gy +ZE +gW +mK +"} +(8,1,1) = {" +mK +gW +iB +bq +Mi +dy +uC +fN +vX +gW +mK +"} +(9,1,1) = {" +mK +gW +kF +fS +yf +Uf +UW +Bi +ik +gW +mK +"} +(10,1,1) = {" +mK +gW +gW +Lp +Lp +Lp +gW +gW +gW +gW +mK +"} +(11,1,1) = {" +mK +mK +mK +mK +mK +mK +mK +mK +mK +mK +mK +"} diff --git a/_maps/modular_generic/station_m_arcade.dmm b/_maps/modular_generic/station_m_arcade.dmm new file mode 100644 index 0000000000000..2891605f7806a --- /dev/null +++ b/_maps/modular_generic/station_m_arcade.dmm @@ -0,0 +1,297 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/wall, +/area/template_noop) +"b" = ( +/obj/structure/chair/stool/bar/directional/north{ + pixel_y = 6 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark/corner, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark, +/area/template_noop) +"d" = ( +/obj/structure/railing{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/spawner/random/structure/crate, +/turf/open/floor/iron/dark, +/area/template_noop) +"e" = ( +/obj/machinery/light/small/directional/west, +/turf/template_noop, +/area/template_noop) +"g" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/melee/baseball_bat/ablative{ + pixel_y = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"l" = ( +/obj/machinery/door/airlock, +/turf/open/floor/iron/dark, +/area/template_noop) +"m" = ( +/obj/effect/decal/cleanable/wrapping/pinata, +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"n" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"o" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark, +/area/template_noop) +"q" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/rack, +/obj/item/melee/baseball_bat{ + pixel_x = 4 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"r" = ( +/obj/effect/spawner/random/structure/table_fancy, +/obj/effect/spawner/random/food_or_drink/dinner{ + pixel_y = 5 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"v" = ( +/obj/structure/window/spawner/directional/east, +/obj/item/kirbyplants/random, +/obj/effect/decal/cleanable/dirt, +/obj/structure/sign/poster/random/directional/north, +/turf/open/floor/iron/dark, +/area/template_noop) +"y" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/template_noop) +"A" = ( +/obj/effect/spawner/random/structure/crate, +/obj/structure/sign/poster/random/directional/south, +/turf/open/floor/iron/dark, +/area/template_noop) +"B" = ( +/obj/effect/spawner/random/food_or_drink, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark, +/area/template_noop) +"C" = ( +/obj/machinery/light/small/directional/east, +/turf/template_noop, +/area/template_noop) +"D" = ( +/obj/structure/chair/stool/bar/directional/north{ + pixel_y = 6 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark, +/area/template_noop) +"F" = ( +/obj/effect/spawner/random/food_or_drink, +/obj/effect/decal/cleanable/wrapping/pinata, +/obj/effect/decal/cleanable/dirt, +/obj/structure/sign/poster/random/directional/west, +/turf/open/floor/iron/dark, +/area/template_noop) +"J" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/structure/railing, +/turf/open/floor/iron/dark, +/area/template_noop) +"K" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/structure/railing, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/melee/baseball_bat/homerun, +/turf/open/floor/iron/dark, +/area/template_noop) +"L" = ( +/turf/open/floor/iron/dark/herringbone, +/area/template_noop) +"M" = ( +/obj/effect/spawner/random/entertainment/arcade, +/obj/structure/sign/poster/random/directional/north, +/turf/open/floor/iron/dark, +/area/template_noop) +"N" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 1 + }, +/obj/effect/spawner/random/food_or_drink, +/turf/open/floor/iron/dark, +/area/template_noop) +"O" = ( +/obj/structure/railing{ + dir = 1 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/structure/rack, +/obj/item/pinata{ + pixel_y = 4 + }, +/obj/item/pinata/syndie, +/turf/open/floor/iron/dark, +/area/template_noop) +"S" = ( +/obj/effect/spawner/random/entertainment/arcade, +/turf/open/floor/iron/dark, +/area/template_noop) +"T" = ( +/turf/template_noop, +/area/template_noop) +"U" = ( +/obj/structure/pinata, +/obj/effect/turf_decal/box/white, +/turf/open/floor/iron/dark, +/area/template_noop) +"V" = ( +/obj/effect/decal/cleanable/wrapping/pinata, +/obj/structure/extinguisher_cabinet/directional/south, +/obj/machinery/light/directional/south, +/turf/open/floor/iron/dark, +/area/template_noop) +"W" = ( +/obj/structure/window/spawner/directional/west, +/obj/effect/spawner/random/structure/closet_maintenance, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark, +/area/template_noop) +"X" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/plating, +/area/template_noop) +"Y" = ( +/obj/structure/hedge, +/obj/machinery/digital_clock/directional/north, +/obj/machinery/light/directional/north, +/turf/open/floor/iron/dark, +/area/template_noop) + +(1,1,1) = {" +T +T +C +T +T +T +T +T +n +"} +(2,1,1) = {" +T +a +a +y +l +y +a +a +T +"} +(3,1,1) = {" +T +a +v +K +L +d +F +a +T +"} +(4,1,1) = {" +T +a +S +D +o +N +q +y +T +"} +(5,1,1) = {" +T +a +Y +X +r +U +V +a +T +"} +(6,1,1) = {" +T +a +M +b +g +m +B +y +T +"} +(7,1,1) = {" +T +a +W +J +L +O +A +a +T +"} +(8,1,1) = {" +T +a +a +y +l +y +a +a +T +"} +(9,1,1) = {" +T +T +T +T +T +T +e +T +T +"} diff --git a/_maps/modular_generic/station_m_breakroom.dmm b/_maps/modular_generic/station_m_breakroom.dmm new file mode 100644 index 0000000000000..15580aaa6fd9c --- /dev/null +++ b/_maps/modular_generic/station_m_breakroom.dmm @@ -0,0 +1,220 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"b" = ( +/obj/machinery/light/small/blacklight/directional/west, +/turf/open/floor/iron, +/area/template_noop) +"c" = ( +/obj/structure/table, +/obj/effect/spawner/random/engineering/toolbox, +/turf/open/floor/iron, +/area/template_noop) +"i" = ( +/obj/effect/spawner/random/vending/colavend, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"j" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"o" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"r" = ( +/turf/closed/wall, +/area/template_noop) +"w" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"z" = ( +/obj/effect/spawner/random/trash/graffiti, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"A" = ( +/obj/effect/spawner/random/vending/snackvend, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"B" = ( +/obj/machinery/light/small/blacklight/directional/north, +/turf/template_noop, +/area/template_noop) +"C" = ( +/obj/effect/spawner/random/trash/bin, +/obj/machinery/light/small/blacklight/directional/north, +/turf/open/floor/iron, +/area/template_noop) +"G" = ( +/obj/structure/sign/poster/random/directional/north, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"I" = ( +/obj/structure/table, +/turf/open/floor/iron, +/area/template_noop) +"M" = ( +/obj/machinery/light/small/blacklight/directional/south, +/turf/template_noop, +/area/template_noop) +"N" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/template_noop) +"O" = ( +/obj/effect/spawner/random/trash/mess, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"P" = ( +/obj/effect/spawner/random/structure/chair_maintenance{ + dir = 1 + }, +/turf/open/floor/iron, +/area/template_noop) +"Q" = ( +/obj/effect/spawner/random/structure/crate, +/obj/machinery/light/small/blacklight/directional/north, +/turf/open/floor/iron, +/area/template_noop) +"R" = ( +/turf/open/floor/iron, +/area/template_noop) +"S" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"T" = ( +/obj/structure/sign/poster/random/directional/east, +/obj/machinery/light/small/blacklight/directional/east, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"U" = ( +/obj/effect/spawner/random/trash/caution_sign, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"V" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/turf/open/floor/iron, +/area/template_noop) +"W" = ( +/obj/effect/spawner/random/structure/crate, +/turf/open/floor/iron, +/area/template_noop) +"Y" = ( +/obj/machinery/door/airlock, +/turf/open/floor/plating, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +w +"} +(2,1,1) = {" +a +r +r +r +N +r +r +r +a +"} +(3,1,1) = {" +a +r +C +I +c +b +P +r +a +"} +(4,1,1) = {" +M +r +G +R +S +S +P +r +a +"} +(5,1,1) = {" +a +Y +j +V +S +S +S +Y +a +"} +(6,1,1) = {" +a +r +W +o +A +i +O +r +B +"} +(7,1,1) = {" +a +r +Q +o +z +T +U +r +a +"} +(8,1,1) = {" +a +r +r +r +N +r +r +r +a +"} +(9,1,1) = {" +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/modular_generic/station_m_evidence.dmm b/_maps/modular_generic/station_m_evidence.dmm new file mode 100644 index 0000000000000..d8b587a3713ef --- /dev/null +++ b/_maps/modular_generic/station_m_evidence.dmm @@ -0,0 +1,281 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"d" = ( +/obj/effect/turf_decal/tile/dark_red/opposingcorners, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/cobweb, +/obj/item/storage/secure/safe/directional/north{ + name = "evidence safe" + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"h" = ( +/obj/effect/turf_decal/tile/dark/opposingcorners, +/obj/effect/turf_decal/siding/red{ + dir = 1 + }, +/obj/structure/noticeboard/directional/west, +/turf/open/floor/iron/dark, +/area/template_noop) +"j" = ( +/obj/structure/closet{ + name = "evidence closet" + }, +/obj/effect/spawner/random/engineering/tool_advanced, +/obj/effect/spawner/random/engineering/material_cheap, +/obj/effect/spawner/random/mod/maint, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"m" = ( +/turf/closed/wall, +/area/template_noop) +"n" = ( +/obj/effect/turf_decal/tile/dark/opposingcorners, +/turf/open/floor/iron/dark, +/area/template_noop) +"q" = ( +/obj/structure/closet/secure_closet/evidence, +/obj/effect/spawner/random/sakhno/ammo, +/obj/effect/spawner/random/medical/injector, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/window/reinforced/tinted/spawner/directional/east, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"r" = ( +/obj/structure/closet{ + name = "evidence closet" + }, +/obj/effect/turf_decal/siding/red{ + dir = 8 + }, +/obj/effect/spawner/random/maintenance/four, +/obj/effect/spawner/random/contraband/cannabis, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"s" = ( +/obj/effect/turf_decal/tile/dark_red/opposingcorners, +/obj/machinery/light/small/red/directional/west, +/turf/open/floor/iron/dark, +/area/template_noop) +"v" = ( +/obj/effect/spawner/random/structure/crate_abandoned{ + spawn_loot_chance = 50 + }, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"x" = ( +/obj/effect/turf_decal/siding/red{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/decoration/statue{ + spawn_loot_chance = 35 + }, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"z" = ( +/obj/machinery/door/window/brigdoor{ + name = "Secure Evidence Lockup"; + req_one_access = list("armory","detective") + }, +/obj/effect/turf_decal/tile/dark_red/opposingcorners, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark, +/area/template_noop) +"A" = ( +/obj/machinery/door/airlock/security{ + name = "Evidence Lockup" + }, +/obj/effect/turf_decal/tile/dark/opposingcorners, +/turf/open/floor/iron/dark, +/area/template_noop) +"C" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/template_noop) +"D" = ( +/obj/effect/turf_decal/tile/dark/opposingcorners, +/obj/effect/turf_decal/siding/red{ + dir = 8 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"F" = ( +/obj/structure/closet/secure_closet/evidence, +/obj/effect/spawner/random/contraband/narcotics, +/obj/effect/spawner/random/contraband/permabrig_weapon, +/obj/effect/spawner/random/contraband/permabrig_weapon, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/spawner/random/entertainment/money_large, +/obj/structure/window/reinforced/tinted/spawner/directional/east, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"G" = ( +/turf/closed/wall/r_wall, +/area/template_noop) +"J" = ( +/obj/structure/window/reinforced/tinted/spawner/directional/east, +/obj/structure/window/reinforced/tinted/spawner/directional/south, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"K" = ( +/obj/effect/spawner/random/structure/crate{ + spawn_loot_chance = 80 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"L" = ( +/obj/effect/turf_decal/tile/dark/opposingcorners, +/obj/machinery/light/directional/east, +/obj/structure/table, +/obj/item/stack/package_wrap, +/obj/item/hand_labeler, +/turf/open/floor/iron/dark, +/area/template_noop) +"R" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"T" = ( +/obj/effect/turf_decal/tile/dark/opposingcorners, +/obj/effect/turf_decal/siding/red/corner{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"U" = ( +/obj/structure/closet{ + name = "evidence closet" + }, +/obj/effect/spawner/random/maintenance/three, +/obj/effect/spawner/random/engineering/tool, +/obj/effect/spawner/random/medical/surgery_tool, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"V" = ( +/obj/effect/spawner/random/entertainment/arcade{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) +"X" = ( +/obj/effect/turf_decal/tile/dark/opposingcorners, +/obj/effect/turf_decal/siding/red{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/template_noop) +"Z" = ( +/obj/structure/closet{ + name = "evidence closet" + }, +/obj/effect/spawner/random/engineering/tool, +/obj/effect/spawner/random/engineering/toolbox, +/obj/effect/decal/cleanable/dirt, +/obj/item/poster/random_contraband, +/turf/open/floor/iron/dark/textured_large, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +R +"} +(2,1,1) = {" +a +G +G +G +G +m +m +m +a +"} +(3,1,1) = {" +a +G +d +s +z +h +K +m +a +"} +(4,1,1) = {" +a +G +F +q +J +X +j +m +a +"} +(5,1,1) = {" +a +m +x +r +D +T +n +m +a +"} +(6,1,1) = {" +a +A +n +n +n +n +n +A +a +"} +(7,1,1) = {" +a +m +U +v +L +V +Z +m +a +"} +(8,1,1) = {" +a +m +C +C +m +C +C +m +a +"} +(9,1,1) = {" +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/modular_generic/station_m_kitchen.dmm b/_maps/modular_generic/station_m_kitchen.dmm new file mode 100644 index 0000000000000..4f29d4193ddbd --- /dev/null +++ b/_maps/modular_generic/station_m_kitchen.dmm @@ -0,0 +1,289 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/template_noop) +"b" = ( +/obj/effect/decal/remains/human, +/obj/item/clothing/head/utility/chefhat{ + pixel_y = 6; + pixel_x = 1 + }, +/obj/item/clothing/suit/apron/chef{ + pixel_y = -15; + pixel_x = -6 + }, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"d" = ( +/obj/structure/table/reinforced, +/obj/effect/spawner/random/food_or_drink/salad, +/obj/effect/spawner/random/trash/bacteria, +/obj/effect/turf_decal/siding/wood, +/turf/open/floor/iron/white/side{ + dir = 1 + }, +/area/template_noop) +"e" = ( +/obj/machinery/door/airlock/public/glass{ + name = "Kitchen" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"f" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"g" = ( +/obj/structure/table/reinforced, +/obj/effect/spawner/random/food_or_drink/pizzaparty, +/obj/effect/turf_decal/siding/wood, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/directional/east, +/turf/open/floor/iron/white/side{ + dir = 1 + }, +/area/template_noop) +"k" = ( +/turf/closed/wall, +/area/template_noop) +"l" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/table, +/obj/effect/spawner/random/food_or_drink/three_course_meal, +/obj/item/knife/kitchen, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"m" = ( +/obj/machinery/computer/arcade/amputation, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/wood/large, +/area/template_noop) +"n" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/wood/large, +/area/template_noop) +"o" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/turf/open/floor/iron, +/area/template_noop) +"p" = ( +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"q" = ( +/obj/structure/table/reinforced, +/obj/effect/spawner/random/food_or_drink/donuts, +/obj/effect/turf_decal/siding/wood, +/obj/effect/spawner/random/trash/bacteria, +/obj/machinery/light/directional/west, +/turf/open/floor/iron/white/side{ + dir = 1 + }, +/area/template_noop) +"s" = ( +/obj/machinery/door/airlock/multi_tile/public/glass{ + name = "Cafeteria" + }, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/turf/open/floor/iron, +/area/template_noop) +"v" = ( +/obj/item/chair/stool/bar, +/obj/effect/spawner/random/trash/bacteria, +/turf/open/floor/wood/large, +/area/template_noop) +"w" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"y" = ( +/obj/machinery/door/airlock/multi_tile/public/glass{ + name = "Cafeteria" + }, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/template_noop) +"z" = ( +/turf/open/floor/wood/large, +/area/template_noop) +"A" = ( +/obj/effect/spawner/random/trash/mess, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"B" = ( +/obj/item/food/deadmouse/moldy, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"D" = ( +/obj/machinery/light/small/directional/north, +/turf/template_noop, +/area/template_noop) +"I" = ( +/obj/structure/closet/secure_closet/freezer/kitchen/all_access, +/obj/effect/spawner/random/food_or_drink/booze, +/obj/effect/spawner/random/food_or_drink/booze, +/obj/effect/spawner/random/food_or_drink/booze, +/obj/effect/spawner/random/food_or_drink/booze, +/obj/item/food/fishmeat/carp, +/obj/item/food/meat/slab/gorilla, +/obj/item/food/grown/tomato, +/obj/item/food/grown/corn, +/obj/effect/spawner/random/trash/bacteria, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"K" = ( +/obj/effect/spawner/random/trash/mess, +/turf/open/floor/wood/large, +/area/template_noop) +"L" = ( +/obj/structure/chair/stool/bar/directional/north, +/obj/effect/spawner/random/trash/mess, +/turf/open/floor/wood/large, +/area/template_noop) +"M" = ( +/obj/structure/chair/stool/bar/directional/north, +/turf/open/floor/wood/large, +/area/template_noop) +"R" = ( +/obj/structure/table/reinforced, +/obj/effect/spawner/random/food_or_drink/dinner, +/obj/effect/spawner/random/food_or_drink/booze, +/obj/effect/turf_decal/siding/wood, +/turf/open/floor/iron/white/side{ + dir = 1 + }, +/area/template_noop) +"S" = ( +/obj/machinery/griddle, +/obj/item/food/meat/steak/chicken{ + pixel_y = 6; + pixel_x = -6 + }, +/obj/item/food/meat/steak/plain{ + pixel_x = 3 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"U" = ( +/turf/template_noop, +/area/template_noop) +"X" = ( +/obj/machinery/oven/range, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/cafeteria, +/area/template_noop) +"Y" = ( +/obj/structure/chair/stool/bar/directional/north, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/wood/large, +/area/template_noop) + +(1,1,1) = {" +U +U +U +U +U +U +U +U +f +"} +(2,1,1) = {" +U +k +a +a +k +a +a +k +D +"} +(3,1,1) = {" +U +k +l +I +q +Y +n +y +U +"} +(4,1,1) = {" +U +k +w +p +R +L +z +o +U +"} +(5,1,1) = {" +U +e +b +A +d +M +K +a +U +"} +(6,1,1) = {" +U +k +B +w +g +v +n +s +U +"} +(7,1,1) = {" +U +k +X +S +k +m +n +o +U +"} +(8,1,1) = {" +U +k +k +k +k +a +a +k +D +"} +(9,1,1) = {" +U +U +U +U +U +U +U +U +U +"} diff --git a/_maps/modular_generic/station_m_shipping.dmm b/_maps/modular_generic/station_m_shipping.dmm new file mode 100644 index 0000000000000..0fbfc3f7ddd1d --- /dev/null +++ b/_maps/modular_generic/station_m_shipping.dmm @@ -0,0 +1,309 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/machinery/door/airlock/multi_tile{ + dir = 8; + name = "Cargo Hold" + }, +/obj/effect/decal/cleanable/oil/streak, +/turf/open/floor/iron/smooth, +/area/template_noop) +"b" = ( +/obj/effect/turf_decal/bot, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/plating, +/area/template_noop) +"c" = ( +/obj/effect/turf_decal/stripes{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/smooth, +/area/template_noop) +"d" = ( +/obj/machinery/light/small/directional/north, +/turf/template_noop, +/area/template_noop) +"e" = ( +/obj/machinery/light/broken/directional/north, +/obj/effect/turf_decal/bot, +/turf/open/floor/plating, +/area/template_noop) +"f" = ( +/obj/effect/turf_decal/stripes{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/microwave{ + pixel_y = 6 + }, +/obj/structure/table, +/obj/item/food/ready_donk/donkhiladas{ + pixel_y = 19 + }, +/turf/open/floor/iron/smooth, +/area/template_noop) +"g" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"h" = ( +/turf/template_noop, +/area/template_noop) +"j" = ( +/obj/structure/rack, +/obj/item/paper_bin/carbon, +/obj/item/stamp/denied{ + pixel_y = 7; + pixel_x = 9 + }, +/obj/item/stamp/granted{ + pixel_y = 2; + pixel_x = -9 + }, +/obj/item/folder/yellow{ + name = "Order Collection" + }, +/obj/item/pen, +/turf/open/floor/iron, +/area/template_noop) +"l" = ( +/obj/effect/turf_decal/stripes{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/smooth, +/area/template_noop) +"o" = ( +/obj/effect/turf_decal/bot, +/obj/effect/spawner/random/structure/shipping_container, +/turf/open/floor/plating, +/area/template_noop) +"p" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/smooth, +/area/template_noop) +"q" = ( +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/iron/smooth, +/area/template_noop) +"r" = ( +/obj/effect/turf_decal/bot, +/turf/open/floor/plating, +/area/template_noop) +"s" = ( +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/loading_area{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/sign/poster/official/here_for_your_safety/directional/north, +/turf/open/floor/plating, +/area/template_noop) +"t" = ( +/turf/closed/wall, +/area/template_noop) +"u" = ( +/obj/effect/turf_decal/stripes{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/smooth, +/area/template_noop) +"w" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/smooth, +/area/template_noop) +"x" = ( +/obj/structure/window/fulltile, +/turf/open/floor/plating, +/area/template_noop) +"z" = ( +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/loading_area{ + dir = 8 + }, +/turf/open/floor/plating, +/area/template_noop) +"B" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/obj/effect/decal/cleanable/oil/streak{ + pixel_x = 1 + }, +/turf/open/floor/iron/smooth, +/area/template_noop) +"H" = ( +/obj/structure/closet{ + name = "Equipment Locker" + }, +/obj/item/clothing/suit/hazardvest, +/obj/item/clothing/head/utility/hardhat{ + pixel_y = 11; + pixel_x = 1 + }, +/obj/item/clothing/gloves/cargo_gauntlet, +/obj/structure/railing{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"J" = ( +/obj/machinery/door/airlock/mining/glass{ + name = "Cargo Hold" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/smooth, +/area/template_noop) +"K" = ( +/obj/effect/turf_decal/stripes{ + dir = 8 + }, +/obj/effect/decal/cleanable/oil/streak, +/turf/open/floor/iron/smooth, +/area/template_noop) +"L" = ( +/obj/effect/turf_decal/stripes{ + dir = 1 + }, +/obj/machinery/light/directional/south, +/turf/open/floor/iron/smooth, +/area/template_noop) +"O" = ( +/obj/effect/turf_decal/stripes{ + dir = 1 + }, +/obj/effect/turf_decal/stripes, +/turf/open/floor/iron/smooth, +/area/template_noop) +"V" = ( +/obj/machinery/light/directional/east, +/obj/structure/sign/poster/official/moth_hardhat/directional/east, +/obj/item/clothing/head/utility/hardhat{ + pixel_y = 11; + pixel_x = 1 + }, +/obj/structure/reagent_dispensers/water_cooler, +/turf/open/floor/iron, +/area/template_noop) +"X" = ( +/obj/effect/turf_decal/stripes{ + dir = 1 + }, +/obj/effect/turf_decal/stripes, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/broken/directional/west, +/turf/open/floor/iron/smooth, +/area/template_noop) +"Z" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/smooth, +/area/template_noop) + +(1,1,1) = {" +h +h +h +h +h +h +h +h +g +"} +(2,1,1) = {" +h +t +t +t +t +t +t +t +h +"} +(3,1,1) = {" +h +t +b +X +r +o +l +x +h +"} +(4,1,1) = {" +h +t +e +O +r +r +c +J +h +"} +(5,1,1) = {" +h +t +s +O +z +z +L +t +d +"} +(6,1,1) = {" +h +t +f +B +u +K +p +t +h +"} +(7,1,1) = {" +h +t +j +V +w +q +H +t +h +"} +(8,1,1) = {" +h +t +t +t +Z +a +t +t +h +"} +(9,1,1) = {" +h +h +h +h +h +h +h +h +h +"} diff --git a/_maps/modular_generic/station_m_showroom.dmm b/_maps/modular_generic/station_m_showroom.dmm new file mode 100644 index 0000000000000..dc073e9465630 --- /dev/null +++ b/_maps/modular_generic/station_m_showroom.dmm @@ -0,0 +1,322 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/effect/decal/cleanable/blood/tracks{ + dir = 6 + }, +/turf/open/floor/iron/dark/corner{ + dir = 8 + }, +/area/template_noop) +"b" = ( +/obj/structure/chair/sofa/bench/tram/left{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light_switch/directional/south, +/turf/open/floor/iron, +/area/template_noop) +"c" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/plating, +/area/template_noop) +"d" = ( +/obj/effect/spawner/random/vending/colavend, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/template_noop) +"i" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/effect/decal/cleanable/blood/gibs/down, +/turf/open/floor/plating, +/area/template_noop) +"j" = ( +/obj/effect/decal/cleanable/glass, +/obj/effect/spawner/random/trash/box, +/turf/open/floor/iron/dark/side, +/area/template_noop) +"k" = ( +/obj/effect/decal/cleanable/glass, +/obj/item/shard, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/decal/cleanable/blood/tracks, +/turf/open/floor/iron, +/area/template_noop) +"l" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/moisture, +/turf/open/floor/iron/dark/side{ + dir = 1 + }, +/area/template_noop) +"m" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/dark/side{ + dir = 1 + }, +/area/template_noop) +"n" = ( +/obj/machinery/light/small/directional/west, +/turf/template_noop, +/area/template_noop) +"o" = ( +/obj/structure/window/spawner/directional/north, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/broken_flooring/pile/directional/west, +/turf/open/floor/iron, +/area/template_noop) +"q" = ( +/obj/structure/window/spawner/directional/north, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/template_noop) +"u" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = -6; + pixel_y = 5 + }, +/turf/open/floor/iron/dark/corner, +/area/template_noop) +"v" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"w" = ( +/obj/structure/chair/sofa/bench/tram/right{ + dir = 1 + }, +/obj/structure/sign/poster/random/directional/south, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/template_noop) +"y" = ( +/obj/effect/spawner/random/decoration/showcase, +/obj/structure/sign/poster/random/directional/north, +/obj/effect/turf_decal/box, +/turf/open/floor/iron/dark, +/area/template_noop) +"z" = ( +/turf/template_noop, +/area/template_noop) +"A" = ( +/obj/machinery/door/airlock/command{ + name = "Corporate Showroom" + }, +/turf/open/floor/iron, +/area/template_noop) +"B" = ( +/obj/structure/sign/poster/random/directional/west, +/obj/structure/broken_flooring/corner/directional/west, +/obj/effect/spawner/random/trash/cigbutt, +/obj/structure/railing, +/turf/open/floor/plating, +/area/template_noop) +"C" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/effect/decal/cleanable/blood/tracks{ + dir = 4 + }, +/turf/open/floor/plating, +/area/template_noop) +"D" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/structure/broken_flooring/pile/directional/east, +/turf/open/floor/plating, +/area/template_noop) +"E" = ( +/obj/item/shard, +/obj/effect/decal/cleanable/glass, +/obj/structure/table_frame, +/obj/effect/spawner/random/entertainment/cigarette_pack, +/turf/open/floor/iron, +/area/template_noop) +"H" = ( +/obj/structure/sign/poster/random/directional/north, +/obj/effect/spawner/random/structure/crate, +/obj/effect/turf_decal/box, +/turf/open/floor/iron/dark, +/area/template_noop) +"K" = ( +/turf/closed/wall, +/area/template_noop) +"L" = ( +/obj/effect/decal/cleanable/plastic, +/obj/structure/rack, +/obj/effect/turf_decal/box, +/obj/effect/spawner/random/exotic/antag_gear, +/obj/machinery/light/directional/north, +/obj/structure/sign/flag/terragov/directional/north, +/turf/open/floor/iron/dark, +/area/template_noop) +"N" = ( +/obj/structure/chair/stool/directional/west{ + pixel_x = 5 + }, +/obj/structure/sign/warning/yes_smoking/circle/directional/east, +/turf/open/floor/iron/dark/corner{ + dir = 1 + }, +/area/template_noop) +"O" = ( +/obj/effect/decal/cleanable/blood/tracks{ + dir = 1 + }, +/obj/effect/spawner/random/trash/garbage, +/obj/structure/sign/calendar/directional/east, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/railing, +/turf/open/floor/iron, +/area/template_noop) +"R" = ( +/obj/effect/spawner/random/trash/bin, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/template_noop) +"T" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/machinery/door/airlock/command{ + name = "Corporate Showroom" + }, +/turf/open/floor/iron, +/area/template_noop) +"V" = ( +/obj/structure/window/spawner/directional/west, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/item/kirbyplants/random/dead, +/obj/effect/decal/remains/human, +/turf/open/floor/iron, +/area/template_noop) +"Y" = ( +/obj/structure/window/spawner/directional/east, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/spawner/random/structure/closet_maintenance, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/cobweb, +/turf/open/floor/iron, +/area/template_noop) + +(1,1,1) = {" +z +z +z +z +z +z +z +z +v +"} +(2,1,1) = {" +z +K +K +K +K +T +K +K +z +"} +(3,1,1) = {" +z +K +Y +B +u +c +R +K +z +"} +(4,1,1) = {" +z +K +H +q +j +m +b +K +z +"} +(5,1,1) = {" +z +K +L +k +i +D +w +K +z +"} +(6,1,1) = {" +z +K +y +o +C +l +E +K +z +"} +(7,1,1) = {" +z +K +V +O +a +N +d +K +z +"} +(8,1,1) = {" +z +K +K +K +A +K +K +K +z +"} +(9,1,1) = {" +z +z +z +n +z +z +z +z +z +"} diff --git a/_maps/modular_generic/station_m_shuttle.dmm b/_maps/modular_generic/station_m_shuttle.dmm new file mode 100644 index 0000000000000..4f1a2ebc98dd7 --- /dev/null +++ b/_maps/modular_generic/station_m_shuttle.dmm @@ -0,0 +1,306 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"d" = ( +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/iron, +/area/template_noop) +"e" = ( +/obj/machinery/computer{ + dir = 8; + name = "shuttle console"; + icon_screen = "shuttle" + }, +/turf/open/floor/iron/white/textured_large, +/area/template_noop) +"f" = ( +/turf/open/floor/plating/rust, +/area/template_noop) +"h" = ( +/obj/effect/turf_decal/siding/dark{ + dir = 8 + }, +/obj/effect/turf_decal/tile/brown{ + dir = 8 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/item/stack/ore/gold, +/turf/open/floor/iron/white/textured_edge{ + dir = 1 + }, +/area/template_noop) +"i" = ( +/obj/effect/decal/cleanable/glass/titanium, +/obj/effect/decal/cleanable/dirt, +/obj/item/stack/ore/titanium, +/turf/open/floor/iron/white/textured_large, +/area/template_noop) +"k" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"l" = ( +/obj/effect/mapping_helpers/burnt_floor, +/obj/structure/broken_flooring/side/directional/north, +/turf/open/floor/plating/rust, +/area/template_noop) +"m" = ( +/obj/structure/grille/broken, +/turf/open/floor/plating, +/area/template_noop) +"n" = ( +/obj/effect/mapping_helpers/burnt_floor, +/turf/open/floor/iron, +/area/template_noop) +"o" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/crowbar/red, +/turf/open/floor/iron/white/textured_large, +/area/template_noop) +"q" = ( +/obj/structure/broken_flooring/corner/directional/east, +/turf/open/floor/plating, +/area/template_noop) +"s" = ( +/obj/effect/turf_decal/trimline/brown, +/obj/effect/turf_decal/trimline/brown/mid_joiner, +/obj/effect/turf_decal/trimline/brown/mid_joiner{ + dir = 1 + }, +/turf/open/floor/iron/white/textured_large, +/area/template_noop) +"t" = ( +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/iron, +/area/template_noop) +"u" = ( +/turf/closed/wall/mineral/titanium, +/area/template_noop) +"v" = ( +/obj/machinery/power/shuttle_engine/heater{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plating, +/area/template_noop) +"x" = ( +/turf/open/floor/iron, +/area/template_noop) +"z" = ( +/obj/structure/table/reinforced, +/obj/item/climbing_hook/emergency, +/obj/item/pickaxe/emergency, +/turf/open/floor/iron/white/textured_large, +/area/template_noop) +"A" = ( +/obj/machinery/door/airlock/shuttle/glass, +/turf/open/floor/iron/white/textured_large, +/area/template_noop) +"C" = ( +/obj/structure/grille, +/obj/item/shard/titanium, +/turf/open/floor/plating, +/area/template_noop) +"G" = ( +/obj/machinery/power/shuttle_engine/propulsion/burst{ + dir = 8 + }, +/obj/structure/window/reinforced/spawner/directional/east, +/turf/open/floor/plating, +/area/template_noop) +"H" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/turf/open/floor/iron/white/textured_large, +/area/template_noop) +"I" = ( +/obj/effect/turf_decal/tile/brown{ + dir = 1 + }, +/obj/effect/mob_spawn/corpse/human/miner, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/iron/white/textured_corner{ + dir = 1 + }, +/area/template_noop) +"K" = ( +/obj/effect/spawner/structure/window/reinforced/shuttle, +/turf/open/floor/plating, +/area/template_noop) +"M" = ( +/obj/effect/turf_decal/tile/brown/half{ + dir = 1 + }, +/turf/open/floor/iron/white/textured_half, +/area/template_noop) +"N" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/structure/ore_box, +/turf/open/floor/plating, +/area/template_noop) +"O" = ( +/turf/open/floor/plating, +/area/template_noop) +"P" = ( +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/template_noop) +"T" = ( +/obj/machinery/computer{ + dir = 1; + name = "shuttle console"; + icon_screen = "shuttle" + }, +/obj/structure/broken_flooring/corner/directional/south, +/turf/open/floor/plating, +/area/template_noop) +"V" = ( +/obj/effect/turf_decal/siding/dark{ + dir = 8 + }, +/obj/effect/turf_decal/tile/brown{ + dir = 1 + }, +/obj/effect/decal/cleanable/plasma, +/turf/open/floor/iron/white/textured_corner{ + dir = 1 + }, +/area/template_noop) +"W" = ( +/obj/effect/turf_decal/siding/dark{ + dir = 8 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/generic, +/obj/item/stack/ore/plasma, +/turf/open/floor/iron/white/textured_half{ + dir = 1 + }, +/area/template_noop) +"X" = ( +/obj/structure/table/reinforced, +/obj/item/flashlight/glowstick, +/obj/item/flashlight/glowstick{ + pixel_y = 3; + pixel_x = 3 + }, +/turf/open/floor/iron/white/textured_large, +/area/template_noop) +"Y" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/iron, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +k +"} +(2,1,1) = {" +a +O +u +G +K +G +u +x +a +"} +(3,1,1) = {" +a +f +P +v +N +v +P +q +a +"} +(4,1,1) = {" +a +T +P +h +W +V +K +f +a +"} +(5,1,1) = {" +a +d +A +M +s +o +C +f +a +"} +(6,1,1) = {" +a +Y +P +I +H +i +m +t +a +"} +(7,1,1) = {" +a +l +P +z +e +X +P +n +a +"} +(8,1,1) = {" +a +n +u +K +K +K +u +f +a +"} +(9,1,1) = {" +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/modular_generic/station_m_tools.dmm b/_maps/modular_generic/station_m_tools.dmm new file mode 100644 index 0000000000000..08c60a632f7b8 --- /dev/null +++ b/_maps/modular_generic/station_m_tools.dmm @@ -0,0 +1,323 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Auxiliary Tool Storage Maintenance" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plating, +/area/template_noop) +"c" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/spawner/random/trash/mess, +/turf/open/floor/iron, +/area/template_noop) +"d" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/yellow/anticorner{ + dir = 1 + }, +/obj/machinery/light/cold/directional/west, +/turf/open/floor/iron/corner, +/area/template_noop) +"e" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/rack, +/obj/item/storage/toolbox/emergency{ + pixel_y = 2 + }, +/obj/item/storage/toolbox/electrical{ + pixel_x = 3; + pixel_y = -2 + }, +/obj/structure/sign/poster/official/random/directional/east, +/turf/open/floor/iron/edge{ + dir = 4 + }, +/area/template_noop) +"g" = ( +/turf/closed/wall, +/area/template_noop) +"h" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron/edge{ + dir = 4 + }, +/area/template_noop) +"i" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/structure/table_or_rack, +/obj/item/stack/sheet/iron/five, +/obj/item/stack/rods/ten, +/turf/open/floor/iron/edge{ + dir = 1 + }, +/area/template_noop) +"k" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch" + }, +/turf/open/floor/plating, +/area/template_noop) +"l" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/template_noop) +"o" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/iron, +/area/template_noop) +"p" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/yellow/anticorner, +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/turf/open/floor/iron/corner{ + dir = 1 + }, +/area/template_noop) +"t" = ( +/obj/effect/spawner/random/structure/closet_maintenance, +/obj/effect/turf_decal/tile/yellow/anticorner{ + dir = 4 + }, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/corner{ + dir = 8 + }, +/area/template_noop) +"u" = ( +/obj/effect/spawner/random/structure/table_or_rack, +/obj/effect/spawner/random/maintenance/two, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/yellow/anticorner{ + dir = 8 + }, +/obj/machinery/light/cold/directional/west, +/turf/open/floor/iron/corner{ + dir = 4 + }, +/area/template_noop) +"w" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"y" = ( +/obj/structure/table, +/obj/effect/spawner/random/maintenance, +/obj/effect/spawner/random/engineering/flashlight, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/iron/edge{ + dir = 2 + }, +/area/template_noop) +"z" = ( +/obj/machinery/door/airlock/engineering/glass{ + name = "Auxiliary Tool Storage" + }, +/turf/open/floor/iron, +/area/template_noop) +"A" = ( +/obj/structure/reagent_dispensers/fueltank, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/yellow/half{ + dir = 4 + }, +/obj/effect/turf_decal/delivery, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/iron/edge{ + dir = 4 + }, +/area/template_noop) +"E" = ( +/obj/structure/rack, +/obj/item/clothing/gloves/color/fyellow{ + pixel_x = 4; + pixel_y = 2 + }, +/obj/item/clothing/gloves/color/fyellow{ + pixel_x = -1; + pixel_y = -3 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/tile/yellow/half{ + dir = 8 + }, +/turf/open/floor/iron/edge{ + dir = 8 + }, +/area/template_noop) +"F" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/iron, +/area/template_noop) +"H" = ( +/obj/item/stack/tile/iron{ + pixel_x = 6; + pixel_y = 4 + }, +/turf/open/floor/plating, +/area/template_noop) +"J" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/sign/poster/random/directional/east, +/turf/open/floor/iron, +/area/template_noop) +"M" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/iron, +/area/template_noop) +"N" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/spawner/random/trash/mess, +/turf/open/floor/plating, +/area/template_noop) +"O" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small/directional/east, +/turf/open/floor/iron, +/area/template_noop) +"Q" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/template_noop) +"R" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch" + }, +/turf/open/floor/plating, +/area/template_noop) +"T" = ( +/obj/machinery/door/airlock/engineering/glass{ + name = "Auxiliary Tool Storage" + }, +/obj/effect/decal/cleanable/fuel_pool, +/turf/open/floor/iron, +/area/template_noop) +"U" = ( +/turf/template_noop, +/area/template_noop) +"V" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/decal/cleanable/dirt, +/obj/structure/sign/poster/random/directional/west, +/turf/open/floor/plating, +/area/template_noop) + +(1,1,1) = {" +U +U +U +U +U +U +U +U +w +"} +(2,1,1) = {" +U +g +g +T +l +z +g +g +U +"} +(3,1,1) = {" +U +g +d +F +E +H +u +l +U +"} +(4,1,1) = {" +U +g +i +M +o +c +y +l +U +"} +(5,1,1) = {" +U +g +t +h +A +e +p +l +U +"} +(6,1,1) = {" +U +g +g +a +g +g +g +g +U +"} +(7,1,1) = {" +U +k +J +N +Q +O +V +R +U +"} +(8,1,1) = {" +U +g +g +g +g +g +g +g +U +"} +(9,1,1) = {" +U +U +U +U +U +U +U +U +U +"} diff --git a/_maps/modular_generic/station_s_chasm.dmm b/_maps/modular_generic/station_s_chasm.dmm new file mode 100644 index 0000000000000..2865aca985b45 --- /dev/null +++ b/_maps/modular_generic/station_s_chasm.dmm @@ -0,0 +1,146 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/mapping_helpers/burnt_floor, +/obj/item/transfer_valve{ + pixel_x = -5; + pixel_y = 3 + }, +/obj/structure/table_frame, +/turf/open/floor/iron, +/area/template_noop) +"b" = ( +/obj/structure/broken_flooring/side/directional/east, +/obj/effect/decal/cleanable/dirt, +/obj/item/stack/cable_coil{ + pixel_x = 5; + pixel_y = -2 + }, +/turf/open/floor/plating, +/area/template_noop) +"d" = ( +/obj/structure/holosign/wetsign, +/turf/open/floor/plating/rust, +/area/template_noop) +"e" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/plasma, +/turf/open/floor/iron, +/area/template_noop) +"f" = ( +/obj/structure/holosign/barrier/engineering, +/obj/effect/mapping_helpers/burnt_floor, +/turf/open/floor/plating/rust, +/area/template_noop) +"j" = ( +/obj/structure/lattice, +/obj/structure/broken_flooring/plating/directional/east, +/turf/open/chasm/true, +/area/template_noop) +"n" = ( +/obj/structure/holosign/barrier/engineering, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating/rust, +/area/template_noop) +"o" = ( +/obj/structure/lattice, +/turf/open/chasm/true, +/area/template_noop) +"t" = ( +/obj/structure/broken_flooring/pile/directional/west, +/obj/effect/decal/cleanable/plasma, +/turf/open/floor/plating, +/area/template_noop) +"C" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"D" = ( +/obj/structure/broken_flooring/corner/directional/north, +/obj/item/tank/internals/plasma/empty, +/turf/open/floor/plating, +/area/template_noop) +"E" = ( +/obj/effect/mapping_helpers/burnt_floor, +/obj/effect/decal/cleanable/oil/slippery, +/turf/open/floor/iron, +/area/template_noop) +"N" = ( +/turf/open/chasm/true, +/area/template_noop) +"P" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/ash, +/turf/open/floor/iron, +/area/template_noop) +"T" = ( +/obj/structure/lattice, +/obj/structure/broken_flooring/plating/directional/south, +/turf/open/chasm/true, +/area/template_noop) +"V" = ( +/turf/template_noop, +/area/template_noop) + +(1,1,1) = {" +V +V +V +V +V +V +C +"} +(2,1,1) = {" +V +P +N +n +D +e +V +"} +(3,1,1) = {" +V +b +N +N +j +E +V +"} +(4,1,1) = {" +V +N +N +N +o +d +V +"} +(5,1,1) = {" +V +N +T +N +N +N +V +"} +(6,1,1) = {" +V +f +t +N +N +a +V +"} +(7,1,1) = {" +V +V +V +V +V +V +V +"} diff --git a/_maps/modular_generic/station_s_garden.dmm b/_maps/modular_generic/station_s_garden.dmm new file mode 100644 index 0000000000000..6944f7138e81a --- /dev/null +++ b/_maps/modular_generic/station_s_garden.dmm @@ -0,0 +1,193 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"f" = ( +/obj/structure/flora/bush/jungle/a/style_2{ + pixel_y = 10; + pixel_x = 4 + }, +/obj/machinery/light/floor, +/turf/open/floor/grass, +/area/template_noop) +"m" = ( +/obj/structure/flora/grass/jungle/a/style_2, +/turf/open/misc/dirt/station, +/area/template_noop) +"n" = ( +/obj/structure/water_source/puddle, +/turf/open/misc/dirt/station, +/area/template_noop) +"o" = ( +/obj/machinery/hydroponics/soil, +/turf/open/floor/grass, +/area/template_noop) +"p" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"u" = ( +/obj/structure/flora/tree/jungle/small{ + pixel_x = -25 + }, +/turf/open/floor/grass, +/area/template_noop) +"B" = ( +/obj/structure/flora/bush/flowers_br/style_2{ + pixel_x = 6 + }, +/obj/item/plant_analyzer{ + pixel_y = -2; + pixel_x = -3 + }, +/turf/open/floor/grass, +/area/template_noop) +"G" = ( +/obj/effect/turf_decal/siding/thinplating_new/terracotta{ + dir = 10 + }, +/obj/structure/table/glass, +/obj/item/reagent_containers/cup/bottle/nutrient/ez{ + pixel_y = 6; + pixel_x = -5 + }, +/obj/item/reagent_containers/spray/pestspray{ + pixel_x = 10; + pixel_y = 5 + }, +/turf/open/floor/iron/terracotta/small, +/area/template_noop) +"H" = ( +/obj/structure/flora/bush/jungle/b/style_2, +/turf/open/misc/dirt/station, +/area/template_noop) +"I" = ( +/turf/closed/wall, +/area/template_noop) +"J" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/template_noop) +"O" = ( +/obj/structure/flora/rock/pile/jungle/style_2{ + pixel_y = -4 + }, +/obj/item/storage/bag/plants/portaseeder{ + pixel_y = 11 + }, +/turf/open/floor/grass, +/area/template_noop) +"P" = ( +/obj/structure/flora/grass/jungle/b/style_4{ + pixel_y = 8 + }, +/turf/open/misc/dirt/station, +/area/template_noop) +"Q" = ( +/obj/structure/flora/bush/flowers_br/style_3{ + pixel_x = 4 + }, +/turf/open/floor/grass, +/area/template_noop) +"R" = ( +/obj/structure/flora/rock/pile/jungle/style_5{ + pixel_y = -3 + }, +/turf/open/floor/grass, +/area/template_noop) +"U" = ( +/obj/item/reagent_containers/cup/bucket/wooden{ + pixel_x = -12; + pixel_y = -4 + }, +/obj/item/cultivator/rake{ + pixel_x = 6 + }, +/obj/structure/flora/bush/sparsegrass/style_2, +/turf/open/misc/dirt/station, +/area/template_noop) +"Y" = ( +/obj/effect/turf_decal/siding/thinplating_new/terracotta/corner{ + dir = 8 + }, +/obj/structure/table/glass, +/obj/effect/spawner/random/food_or_drink/seed{ + pixel_x = -5; + pixel_y = 2 + }, +/obj/effect/spawner/random/food_or_drink/seed_rare{ + pixel_y = 7; + pixel_x = 2 + }, +/turf/open/floor/iron/terracotta/small, +/area/template_noop) +"Z" = ( +/obj/effect/turf_decal/siding/thinplating_new/terracotta{ + dir = 10 + }, +/turf/open/floor/iron/terracotta/small, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +a +p +"} +(2,1,1) = {" +a +u +o +o +I +I +a +"} +(3,1,1) = {" +a +m +R +B +n +J +a +"} +(4,1,1) = {" +a +H +P +f +U +J +a +"} +(5,1,1) = {" +a +I +G +Q +O +o +a +"} +(6,1,1) = {" +a +I +Y +Z +o +o +a +"} +(7,1,1) = {" +a +a +a +a +a +a +a +"} diff --git a/_maps/modular_generic/station_s_kitchen.dmm b/_maps/modular_generic/station_s_kitchen.dmm new file mode 100644 index 0000000000000..95a65c1d4ab71 --- /dev/null +++ b/_maps/modular_generic/station_s_kitchen.dmm @@ -0,0 +1,204 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/structure/table, +/obj/item/kitchen/rollingpin{ + pixel_y = 6; + pixel_x = -5 + }, +/obj/item/knife/kitchen{ + pixel_y = 4; + pixel_x = 10 + }, +/turf/open/floor/iron/kitchen, +/area/template_noop) +"c" = ( +/obj/effect/turf_decal/siding/dark{ + dir = 1 + }, +/obj/effect/decal/cleanable/food/flour, +/turf/open/floor/iron/kitchen, +/area/template_noop) +"d" = ( +/obj/effect/turf_decal/siding/dark{ + dir = 4 + }, +/obj/structure/table, +/obj/machinery/microwave{ + pixel_y = 6 + }, +/turf/open/floor/iron/kitchen, +/area/template_noop) +"m" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/template_noop) +"q" = ( +/obj/structure/sink/directional/east, +/turf/open/floor/iron, +/area/template_noop) +"r" = ( +/obj/effect/turf_decal/siding/dark{ + dir = 6 + }, +/obj/machinery/grill, +/turf/open/floor/iron/kitchen, +/area/template_noop) +"u" = ( +/obj/effect/turf_decal/siding/dark, +/obj/item/storage/box/ingredients/random{ + pixel_y = 14; + pixel_x = -7 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/kitchen, +/area/template_noop) +"w" = ( +/obj/effect/turf_decal/trimline/green/warning{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/template_noop) +"y" = ( +/turf/closed/wall, +/area/template_noop) +"z" = ( +/obj/effect/turf_decal/siding/dark{ + dir = 1 + }, +/obj/structure/closet/secure_closet/freezer/fridge/all_access, +/turf/open/floor/iron/kitchen, +/area/template_noop) +"C" = ( +/obj/structure/table/reinforced, +/obj/item/reagent_containers/condiment/enzyme{ + pixel_y = 10; + pixel_x = -7 + }, +/obj/item/kitchen/tongs{ + pixel_y = 6; + pixel_x = 6 + }, +/turf/open/floor/iron, +/area/template_noop) +"D" = ( +/obj/effect/turf_decal/trimline/green/warning{ + dir = 10 + }, +/turf/open/floor/iron, +/area/template_noop) +"F" = ( +/obj/effect/turf_decal/siding/dark{ + dir = 5 + }, +/obj/structure/closet/crate/bin{ + pixel_y = 2 + }, +/turf/open/floor/iron/kitchen, +/area/template_noop) +"G" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"I" = ( +/obj/effect/turf_decal/trimline/green/corner{ + dir = 8 + }, +/turf/open/floor/iron, +/area/template_noop) +"L" = ( +/obj/structure/table/reinforced, +/obj/item/reagent_containers/condiment/ketchup{ + pixel_x = 8; + pixel_y = 8 + }, +/obj/item/plate/small{ + pixel_x = -8; + pixel_y = 3 + }, +/turf/open/floor/iron, +/area/template_noop) +"M" = ( +/obj/effect/turf_decal/trimline/green/warning{ + dir = 8 + }, +/turf/open/floor/iron, +/area/template_noop) +"P" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/template_noop) +"S" = ( +/turf/open/floor/iron/kitchen, +/area/template_noop) +"U" = ( +/obj/effect/turf_decal/siding/dark, +/turf/open/floor/iron/kitchen, +/area/template_noop) +"V" = ( +/turf/template_noop, +/area/template_noop) + +(1,1,1) = {" +V +V +V +V +V +V +G +"} +(2,1,1) = {" +V +y +m +m +m +y +V +"} +(3,1,1) = {" +V +q +z +a +u +C +V +"} +(4,1,1) = {" +V +P +c +S +U +L +V +"} +(5,1,1) = {" +V +D +F +d +r +y +V +"} +(6,1,1) = {" +V +I +w +M +w +D +V +"} +(7,1,1) = {" +V +V +V +V +V +V +V +"} diff --git a/_maps/modular_generic/station_s_mime.dmm b/_maps/modular_generic/station_s_mime.dmm new file mode 100644 index 0000000000000..60d6e4ca7ea63 --- /dev/null +++ b/_maps/modular_generic/station_s_mime.dmm @@ -0,0 +1,138 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"d" = ( +/obj/structure/table/wood/fancy/royalblack, +/obj/item/toy/crayon/spraycan/mimecan{ + pixel_x = 6; + pixel_y = 17 + }, +/obj/item/flashlight/lamp{ + pixel_x = -5; + pixel_y = 12 + }, +/obj/item/food/baguette, +/turf/open/floor/iron/checker, +/area/template_noop) +"i" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/checker, +/area/template_noop) +"o" = ( +/obj/structure/chair/stool/directional/east, +/turf/open/floor/iron/checker, +/area/template_noop) +"v" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/checker, +/area/template_noop) +"A" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"H" = ( +/obj/effect/forcefield/mime/advanced{ + initial_duration = 0 + }, +/turf/open/floor/iron/checker, +/area/template_noop) +"K" = ( +/obj/structure/dresser, +/obj/item/toy/figure/mime{ + pixel_y = 13; + pixel_x = -5 + }, +/obj/item/stamp/mime{ + pixel_y = 13; + pixel_x = 7 + }, +/turf/open/floor/iron/checker, +/area/template_noop) +"L" = ( +/obj/structure/table/wood, +/obj/item/clothing/accessory/mime_fan_pin{ + pixel_x = -5; + pixel_y = 3 + }, +/obj/effect/spawner/random/decoration/flower{ + pixel_y = 4; + pixel_x = 7 + }, +/turf/open/floor/iron/checker, +/area/template_noop) +"Q" = ( +/turf/open/floor/iron/checker, +/area/template_noop) +"Y" = ( +/obj/structure/closet/secure_closet/personal/cabinet{ + name = "mime's closet" + }, +/obj/item/clothing/mask/gas/mime, +/obj/item/book/granter/action/spell/mime/mimery, +/turf/open/floor/iron/checker, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +a +A +"} +(2,1,1) = {" +a +i +v +v +H +H +a +"} +(3,1,1) = {" +a +H +K +v +o +v +a +"} +(4,1,1) = {" +a +H +d +Q +L +H +a +"} +(5,1,1) = {" +a +v +Q +i +Y +H +a +"} +(6,1,1) = {" +a +v +v +H +H +H +a +"} +(7,1,1) = {" +a +a +a +a +a +a +a +"} diff --git a/_maps/modular_generic/station_s_vault.dmm b/_maps/modular_generic/station_s_vault.dmm new file mode 100644 index 0000000000000..774d50d31521c --- /dev/null +++ b/_maps/modular_generic/station_s_vault.dmm @@ -0,0 +1,205 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"d" = ( +/obj/effect/mapping_helpers/burnt_floor, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/dark_blue/corner, +/obj/machinery/light/small/broken/directional/west, +/turf/open/floor/iron/smooth_half{ + dir = 1 + }, +/area/template_noop) +"e" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 8 + }, +/turf/open/floor/iron/smooth_half{ + dir = 1 + }, +/area/template_noop) +"k" = ( +/obj/effect/mob_spawn/corpse/human/generic_assistant, +/obj/item/clothing/neck/stethoscope{ + pixel_y = 13; + pixel_x = 4 + }, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/dark_blue/corner, +/turf/open/floor/iron/smooth_corner{ + dir = 4 + }, +/area/template_noop) +"o" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/trimline/dark_blue/corner, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 8 + }, +/turf/open/floor/iron/smooth_half, +/area/template_noop) +"r" = ( +/obj/item/book{ + desc = "An undeniably handy book."; + icon_state = "bookknock"; + name = "\improper A Simpleton's Guide to Safe-cracking with Stethoscopes"; + pixel_x = -13; + pixel_y = 2 + }, +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/glass, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/dark_blue/warning, +/turf/open/floor/iron/smooth_half, +/area/template_noop) +"t" = ( +/obj/effect/spawner/random/structure/girder, +/turf/open/floor/plating, +/area/template_noop) +"y" = ( +/obj/structure/safe, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 8 + }, +/obj/item/ammo_box/a357, +/obj/item/gun/ballistic/revolver/golden, +/turf/open/floor/iron/smooth_corner{ + dir = 8 + }, +/area/template_noop) +"z" = ( +/obj/structure/closet/crate/preopen, +/obj/item/stack/sheet/mineral/gold, +/obj/item/stack/sheet/mineral/gold{ + pixel_y = 2; + pixel_x = 7 + }, +/obj/item/coin/gold/doubloon{ + pixel_x = -8 + }, +/obj/item/stack/ore/gold, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/turf_decal/trimline/dark_blue/corner, +/turf/open/floor/iron/smooth_corner, +/area/template_noop) +"J" = ( +/obj/modular_map_connector, +/turf/template_noop, +/area/template_noop) +"M" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/dark_blue/corner, +/obj/effect/turf_decal/trimline/white, +/turf/open/floor/iron/smooth, +/area/template_noop) +"Q" = ( +/turf/closed/wall/r_wall, +/area/template_noop) +"U" = ( +/obj/effect/spawner/random/structure/barricade, +/obj/structure/door_assembly/door_assembly_vault, +/turf/open/floor/iron/smooth_large, +/area/template_noop) +"Z" = ( +/obj/effect/decal/cleanable/generic, +/obj/effect/mapping_helpers/burnt_floor, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/dark_blue/corner{ + dir = 8 + }, +/obj/machinery/light/small/red/dim/directional/south, +/turf/open/floor/iron/smooth_corner{ + dir = 1 + }, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +a +J +"} +(2,1,1) = {" +a +Q +t +Q +Q +Q +a +"} +(3,1,1) = {" +a +Q +z +d +k +Q +a +"} +(4,1,1) = {" +a +Q +o +M +r +U +a +"} +(5,1,1) = {" +a +Q +y +e +Z +Q +a +"} +(6,1,1) = {" +a +Q +Q +Q +t +Q +a +"} +(7,1,1) = {" +a +a +a +a +a +a +a +"} diff --git a/_maps/safehouses/TEMPLATES/TEMPLATE.dmm b/_maps/safehouses/TEMPLATES/TEMPLATE.dmm index c8e5059f0d013..03eaca12fb139 100644 --- a/_maps/safehouses/TEMPLATES/TEMPLATE.dmm +++ b/_maps/safehouses/TEMPLATES/TEMPLATE.dmm @@ -13,11 +13,11 @@ /turf/open/floor/plating, /area/virtual_domain/safehouse) "v" = ( -/obj/effect/bitrunning/exit_spawn, +/obj/effect/landmark/bitrunning/hololadder_spawn, /turf/open/floor/plating, /area/virtual_domain/safehouse) "N" = ( -/obj/effect/bitrunning/goal_turf, +/obj/effect/landmark/bitrunning/cache_goal_turf, /turf/open/floor/plating, /area/virtual_domain/safehouse) "R" = ( diff --git a/_maps/templates/holodeck_medicalsim.dmm b/_maps/templates/holodeck_medicalsim.dmm index acc38d02c58dd..871e5461491a2 100644 --- a/_maps/templates/holodeck_medicalsim.dmm +++ b/_maps/templates/holodeck_medicalsim.dmm @@ -568,6 +568,8 @@ /obj/item/surgical_drapes, /obj/item/razor, /obj/item/hemostat, +/obj/item/bonesetter, +/obj/item/stack/medical/bone_gel, /obj/effect/turf_decal/tile/red/half/contrasted{ dir = 1 }, diff --git a/_maps/templates/lazy_templates/heretic_sacrifice.dmm b/_maps/templates/lazy_templates/heretic_sacrifice.dmm index 06ace91956c01..44300c13735fe 100644 --- a/_maps/templates/lazy_templates/heretic_sacrifice.dmm +++ b/_maps/templates/lazy_templates/heretic_sacrifice.dmm @@ -44,7 +44,7 @@ /obj/effect/decal/cleanable/blood/old, /obj/effect/decal/cleanable/dirt/dust, /turf/open/indestructible/plating, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "fO" = ( /turf/open/indestructible, /area/space) @@ -59,7 +59,7 @@ /obj/effect/decal/cleanable/dirt/dust, /obj/item/storage/toolbox/mechanical/old, /turf/open/indestructible/plating, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "hZ" = ( /obj/effect/decal/cleanable/blood/old, /turf/open/indestructible/necropolis/air, @@ -71,7 +71,7 @@ /area/centcom/heretic_sacrifice/rust) "jt" = ( /turf/closed/indestructible/reinforced, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "jB" = ( /obj/machinery/light/very_dim/directional/south, /turf/open/misc/asteroid, @@ -105,7 +105,7 @@ /obj/effect/decal/cleanable/dirt/dust, /obj/item/spear, /turf/open/indestructible/plating, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "mZ" = ( /obj/effect/decal/fakelattice{ density = 0 @@ -176,7 +176,7 @@ /obj/effect/decal/cleanable/dirt/dust, /obj/item/storage/toolbox/mechanical/old, /turf/open/indestructible/plating, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "qu" = ( /obj/effect/turf_decal/weather/dirt, /turf/open/misc/ashplanet/wateryrock{ @@ -234,7 +234,7 @@ /obj/effect/decal/cleanable/dirt/dust, /obj/item/clothing/under/color/grey/ancient, /turf/open/indestructible/plating, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "uT" = ( /obj/structure/cable, /turf/open/floor/plating/rust, @@ -260,7 +260,7 @@ /area/centcom/heretic_sacrifice/ash) "wo" = ( /turf/closed/indestructible/grille, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "wt" = ( /obj/structure/stone_tile/block{ dir = 1 @@ -285,7 +285,7 @@ start_on = 1 }, /turf/open/indestructible/plating, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "wS" = ( /turf/open/misc/dirt/jungle/dark{ planetary_atmos = 0; @@ -326,7 +326,7 @@ /obj/effect/decal/cleanable/dirt/dust, /obj/item/clothing/mask/gas, /turf/open/indestructible/plating, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "AH" = ( /obj/effect/turf_decal/trimline/brown/corner, /turf/open/floor/plating/rust, @@ -345,11 +345,11 @@ /obj/effect/decal/cleanable/dirt/dust, /obj/item/clothing/mask/gas/tiki_mask/yalp_elor, /turf/open/indestructible/plating, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "AY" = ( /obj/effect/decal/cleanable/dirt/dust, /turf/open/indestructible/plating, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "Bv" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/trimline/brown/line, @@ -405,7 +405,7 @@ /area/centcom/heretic_sacrifice/ash) "En" = ( /turf/closed/indestructible/fakedoor/maintenance, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "ER" = ( /turf/open/misc/ironsand, /area/centcom/heretic_sacrifice/rust) @@ -543,7 +543,7 @@ start_on = 1 }, /turf/open/indestructible/plating, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "Nh" = ( /obj/effect/turf_decal/trimline/brown/line{ dir = 1 @@ -589,7 +589,7 @@ /obj/effect/decal/cleanable/dirt/dust, /obj/item/clothing/under/color/grey/ancient, /turf/open/indestructible/plating, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "Pl" = ( /obj/effect/turf_decal/weather/dirt{ dir = 6 @@ -712,9 +712,9 @@ "Zw" = ( /obj/effect/decal/cleanable/blood/old, /obj/effect/decal/cleanable/dirt/dust, -/obj/effect/landmark/heretic/knock, +/obj/effect/landmark/heretic/lock, /turf/open/indestructible/plating, -/area/centcom/heretic_sacrifice/knock) +/area/centcom/heretic_sacrifice/lock) "ZA" = ( /turf/closed/indestructible/riveted/boss, /area/centcom/heretic_sacrifice/ash) diff --git a/_maps/virtual_domains/README.md b/_maps/virtual_domains/README.md index a02d43e1575ee..723af1b34c2c1 100644 --- a/_maps/virtual_domains/README.md +++ b/_maps/virtual_domains/README.md @@ -1,32 +1,33 @@ # Making new virtual domains -## From scratch - -1. Create a new map using TGM format. It can be any size, but please, consider limiting to 75x75 max. -2. Ensure that the map has ONE tile marked with the safehouse bottom left landmark. If you're using modular safehouses, it will need to be a 7x6 area. -4. Provide a way for players to enter your new map via the north door, which is 4th tile over. -5. Enclose your area with a single wall binary closed wall. - -## From an existing map - +## REQUIRED: +1. One way that the encrypted cache can spawn. This can be from a mob drop, a landmark (place a few, it'll pick one), or a signable landmark if you have a points system. +2. Place a virtual domain baseturf helper in each area. +3. Ensure that the map has ONE tile marked with the safehouse bottom left landmark. If you're using modular safehouses, it will need an open 7x6 area. +4. Placing a safehouse area is redundant, but it will ensure there is power in the starting safehouse. +5. Create the dm file that defines the map qualities. You can use the existing ones as a template. + +## Converting an existing map 1. Create a new map using the existing map's size - give yourself enough room to enclose it with a binary wall. There's no need for any space outside of it, so ensure that it fits and is enclosed, nothing outside of this. 2. Copy and paste the existing map into it. -3. Find an accessible area for a safehouse, 7x6 - or with a custom, just ensure the necessary landmarks are placed. +3. Find an accessible area for a safehouse, 7x6. 4. Place a bottom left safehouse landmark somewhere on the map to load the safehouse. -## BOTH. -1. You need to have one (1) way that the encrypted cache can spawn. This can be from a mob drop, a landmark (place a few, it'll pick one), or a signable landmark if you have a points system. -2. Make note of the size of the map. Make sure this is in the dm file. -3. Create the dm file that defines the map qualities. Examples are in the bitrunning file. +## Notes +You shouldn't need to fully enclose your map in 15 tiles of binary filler. Using one solid wall should do the trick. -### Notes +For areas, ideally just one on the map and one for the safehouse. Vdoms should never last so long as to need individual area power and atmos unless you're specifically going for a gimmick. -You shouldn't need to fully enclose your map in 15 tiles of binary filler. Using one solid wall should do the trick. +Use modular mob segments! Use modular map segments! Add some variety to your maps! Just make sure you've set your map to have "is_modular" afterwards. Adding some open tile padding around the safehouse is a good touch. About 7 tiles West/East for the visual effect of a larger map. If you want to add prep gear, you can do so within the safehouse's area as long you don't overlap with goal turfs or exit spawners. The top left corner is a good spot for this, with respect for the walls, therefore [1, 1], [1, 2], [1, 3] -You can also create safehouses if you find yourself needing the same gear over and over again. There is a readme for that as well. +You can also create a specific safehouse if you find yourself needing the same gear over and over again. There is a readme for that as well. Boss zones should give players pretty ample space, I've been using a 23x23 minimum area. + +While it's not a hard set rule, 75x75 is the guideline for max size. The main issue is keeping them in the domain for too long. + +You have the option of baking in your own safehouse and ignoring the 7x6 guideline. To do this, you will still need a safehouse landmark and a file to load - even if it's empty. Ensure that you have the necessary landmarks placed that normally go in a safehouse on the map itself. diff --git a/_maps/virtual_domains/beach_bar.dmm b/_maps/virtual_domains/beach_bar.dmm index 779b1b893c04e..628265552f12c 100644 --- a/_maps/virtual_domains/beach_bar.dmm +++ b/_maps/virtual_domains/beach_bar.dmm @@ -4,10 +4,10 @@ /obj/effect/turf_decal/sand, /obj/structure/sign/poster/contraband/have_a_puff/directional/west, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ag" = ( /turf/open/floor/carpet/red, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "as" = ( /obj/structure/closet/crate/bin, /obj/item/tank/internals/emergency_oxygen, @@ -16,14 +16,14 @@ /obj/effect/turf_decal/sand, /obj/machinery/light/directional/west, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "aw" = ( /obj/machinery/grill, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "aE" = ( /turf/open/floor/pod/light, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "aZ" = ( /obj/machinery/light/small/directional/east, /obj/structure/closet/crate{ @@ -32,57 +32,57 @@ /obj/item/stack/sheet/mineral/coal/ten, /obj/item/stack/sheet/mineral/coal/ten, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "bf" = ( /mob/living/basic/crab{ name = "Jonny" }, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "bC" = ( /obj/effect/turf_decal/sand, /mob/living/basic/crab{ name = "James" }, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "bM" = ( /mob/living/basic/crab{ name = "Jon" }, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "bQ" = ( /obj/structure/fluff/beach_umbrella/cap, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "bS" = ( /obj/machinery/chem_master/condimaster{ name = "CondiMaster Neo"; pixel_x = -4 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "cb" = ( /obj/structure/table/wood, /obj/item/reagent_containers/pill/lsd, /obj/item/reagent_containers/pill/lsd, /obj/item/reagent_containers/pill/lsd, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "cv" = ( /turf/open/floor/carpet/royalblue, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "cz" = ( /obj/effect/turf_decal/sand, /obj/machinery/jukebox, /obj/item/coin/gold, /turf/open/floor/sepia, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "cG" = ( /obj/structure/flora/bush/sparsegrass/style_random, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "db" = ( /obj/item/reagent_containers/cup/glass/bottle/beer/light, /obj/item/reagent_containers/cup/glass/bottle/beer/light, @@ -113,7 +113,7 @@ /obj/item/reagent_containers/cup/glass/colocup, /obj/item/reagent_containers/cup/glass/colocup, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "di" = ( /obj/machinery/vending/boozeomat, /obj/effect/mapping_helpers/atom_injector/obj_flag{ @@ -121,37 +121,37 @@ target_type = /obj/machinery/vending/boozeomat }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "dj" = ( /turf/open/misc/beach/coast{ dir = 1 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "dx" = ( /obj/effect/turf_decal/sand, /obj/effect/turf_decal/stripes/asteroid/line{ dir = 8 }, /turf/open/floor/sepia, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "dI" = ( /obj/machinery/light/directional/south, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "dZ" = ( /obj/structure/bookcase/random/reference, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ed" = ( /obj/machinery/atmospherics/components/tank/air{ dir = 1 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "er" = ( /obj/structure/noticeboard/staff, /turf/closed/wall/mineral/wood/nonmetal, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "fc" = ( /obj/structure/table/wood, /obj/item/reagent_containers/pill/happy, @@ -159,22 +159,18 @@ pixel_x = -8; pixel_y = -1 }, -/obj/item/reagent_containers/cup/glass/drinkingglass/filled/pina_colada{ - pixel_y = 5; - pixel_x = 6 - }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "fr" = ( /obj/item/melee/skateboard/hoverboard, /obj/machinery/light/directional/west, /turf/open/floor/pod/light, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "gh" = ( /obj/structure/flora/bush/stalky/style_random, /obj/structure/flora/bush/sparsegrass/style_random, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "gl" = ( /turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, /area/lavaland/surface/outdoors/virtual_domain) @@ -185,21 +181,21 @@ /turf/open/misc/beach/coast{ dir = 4 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "hk" = ( /obj/structure/reagent_dispensers/watertank, /turf/open/floor/pod/light, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "hE" = ( /obj/structure/sign/departments/restroom/directional/east, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "hG" = ( /obj/machinery/door/airlock/sandstone{ name = "Surfer Shack 1" }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "iz" = ( /turf/closed/indestructible/binary, /area/lavaland/surface/outdoors/virtual_domain) @@ -210,18 +206,18 @@ /obj/item/reagent_containers/cup/rag, /obj/machinery/light/small/directional/west, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "jc" = ( /turf/open/floor/iron/stairs/right, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "jg" = ( /obj/machinery/vending/hydronutrients, /turf/open/floor/iron/grimy, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "jl" = ( /obj/structure/flora/rock/pile/jungle/style_random, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "jy" = ( /obj/effect/turf_decal/sand{ density = 1 @@ -230,7 +226,7 @@ /turf/open/floor/pod/light{ density = 1 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ke" = ( /obj/structure/marker_beacon/bronze, /turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, @@ -242,7 +238,7 @@ }, /obj/structure/chair/stool/bar/directional/west, /turf/open/floor/sepia, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "kv" = ( /obj/effect/baseturf_helper/virtual_domain, /turf/closed/indestructible/binary, @@ -251,45 +247,45 @@ /obj/structure/table, /obj/machinery/reagentgrinder, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "kK" = ( /obj/structure/mirror/directional/west, /obj/structure/sink/kitchen/directional/south, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "kT" = ( /obj/structure/chair/stool/bar/directional/south, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "lq" = ( /obj/item/melee/skateboard/hoverboard, /turf/open/floor/pod/light, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "lB" = ( /obj/item/toy/seashell, /obj/effect/turf_decal/sand, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "lS" = ( /turf/open/floor/light/colour_cycle/dancefloor_a, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ml" = ( /turf/template_noop, /area/virtual_domain/safehouse) "mq" = ( /obj/structure/closet/secure_closet/freezer/kitchen/all_access, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "mG" = ( /obj/structure/easel, /obj/item/canvas/twentythree_twentythree, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "mP" = ( /turf/open/misc/beach/coast/corner{ dir = 1 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "mX" = ( /obj/structure/closet/secure_closet/freezer/meat/all_access, /obj/item/food/meat/rawbacon, @@ -299,15 +295,12 @@ /obj/item/food/meat/slab/rawcrab, /obj/item/food/meat/slab/rawcrab, /turf/open/floor/wood, -/area/virtual_domain/powered) -"no" = ( -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "nP" = ( /obj/item/stack/sheet/iron/fifty, /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "oE" = ( /obj/structure/railing/corner{ dir = 1 @@ -316,57 +309,57 @@ /turf/open/misc/beach/coast/corner{ dir = 8 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "oP" = ( /obj/structure/table/wood, /obj/machinery/reagentgrinder, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "pr" = ( /turf/template_noop, /area/template_noop) "pC" = ( /obj/machinery/computer/arcade/battle, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "pT" = ( /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "pZ" = ( /obj/machinery/light/directional/south, /turf/open/misc/beach/coast{ dir = 1 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "qc" = ( /obj/structure/extinguisher_cabinet/directional/south, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "qg" = ( /obj/structure/sign/poster/contraband/space_up/directional/west, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "qR" = ( /obj/effect/spawner/structure/window, /obj/structure/curtain, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "qW" = ( /obj/item/melee/skateboard/hoverboard, /mob/living/basic/chicken{ name = "Chicken Joe" }, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "rc" = ( /obj/machinery/light/directional/east, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ri" = ( /obj/structure/sign/poster/official/fruit_bowl, /turf/closed/wall/mineral/wood/nonmetal, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "rm" = ( /obj/item/storage/crayons, /obj/structure/closet/crate/wooden, @@ -374,11 +367,11 @@ /obj/item/canvas/twentythree_twentythree, /obj/item/canvas/twentythree_twentythree, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "rT" = ( /obj/item/toy/seashell, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "sT" = ( /obj/effect/baseturf_helper/virtual_domain, /turf/template_noop, @@ -388,19 +381,19 @@ name = "Resort Casino" }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "tF" = ( /obj/structure/extinguisher_cabinet/directional/east, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "tZ" = ( /obj/structure/toilet, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "uc" = ( /obj/machinery/light/small/directional/east, /turf/open/misc/asteroid/basalt/lava_land_surface, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ug" = ( /obj/structure/closet/secure_closet{ icon_state = "cabinet"; @@ -416,31 +409,33 @@ /obj/item/clothing/suit/costume/hawaiian, /obj/machinery/light/small/directional/east, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "uk" = ( /obj/structure/closet/crate/hydroponics, /obj/item/shovel/spade, /obj/item/reagent_containers/cup/bucket, /obj/item/cultivator, /turf/open/floor/iron/grimy, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "uq" = ( /obj/structure/table/wood, -/obj/item/reagent_containers/cup/glass/drinkingglass/filled/pina_colada, /obj/item/reagent_containers/cup/glass/drinkingglass/filled/pina_colada{ - pixel_x = -5; + pixel_x = 4 + }, +/obj/item/reagent_containers/cup/glass/drinkingglass/filled/pina_colada{ + pixel_x = -7; pixel_y = 5 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "uU" = ( /obj/effect/turf_decal/sand, /turf/open/floor/sepia, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "uV" = ( /obj/structure/flora/coconuts, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ve" = ( /obj/item/toy/dodgeball, /obj/item/toy/dodgeball, @@ -448,33 +443,33 @@ /obj/item/toy/dodgeball, /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "vp" = ( /obj/machinery/light/directional/east, /obj/structure/chair/stool/bar/directional/south, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "vq" = ( /obj/machinery/oven/range, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "vv" = ( /obj/structure/chair/stool/directional/south, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "vN" = ( /obj/structure/table/wood, /obj/item/reagent_containers/pill/morphine, /obj/item/reagent_containers/pill/morphine, /obj/item/reagent_containers/pill/morphine, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "vT" = ( /obj/structure/railing{ dir = 8 }, /turf/open/misc/beach/coast/corner, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "wb" = ( /obj/structure/closet/crate/freezer{ name = "Cooler" @@ -498,10 +493,10 @@ /obj/item/reagent_containers/cup/glass/bottle/beer/light, /obj/item/reagent_containers/cup/glass/bottle/beer/light, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "wD" = ( /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "xb" = ( /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors/virtual_domain) @@ -510,16 +505,16 @@ /obj/item/storage/dice, /obj/item/stack/spacecash/c1000, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "xq" = ( /obj/structure/window/reinforced/spawner/directional/west, /obj/structure/window/reinforced/spawner/directional/south, /obj/item/megaphone, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "xw" = ( /turf/open/floor/pod/dark, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "xJ" = ( /obj/structure/closet/cabinet, /obj/item/storage/backpack/duffelbag, @@ -531,7 +526,7 @@ /obj/item/clothing/glasses/sunglasses, /obj/item/clothing/neck/beads, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "xR" = ( /obj/structure/window/reinforced/spawner/directional/east, /obj/structure/window/reinforced/spawner/directional/north{ @@ -542,7 +537,7 @@ /obj/item/clothing/under/shorts/red, /obj/item/clothing/glasses/sunglasses, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "xW" = ( /turf/open/space/basic, /area/space) @@ -552,14 +547,14 @@ /obj/item/reagent_containers/pill/zoom, /obj/item/reagent_containers/pill/zoom, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "yi" = ( /obj/structure/sink/kitchen/directional/west{ desc = "A sink used for washing one's hands and face. It looks rusty and home-made"; name = "old sink" }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "yl" = ( /obj/item/reagent_containers/cup/glass/colocup{ pixel_x = -7; @@ -574,39 +569,39 @@ pixel_y = -3 }, /turf/open/floor/carpet/red, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ys" = ( /obj/effect/turf_decal/sand, /obj/machinery/light/directional/east, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "yv" = ( /obj/effect/turf_decal/sand, /obj/machinery/food_cart, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "yB" = ( /obj/item/instrument/guitar, /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "yU" = ( /obj/structure/sign/warning/gas_mask/directional/north, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "yX" = ( /obj/structure/chair/stool/bar/directional/south, /turf/open/floor/carpet/red, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "zn" = ( /obj/machinery/light/directional/east, /turf/open/misc/beach/coast{ dir = 8 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "zw" = ( /obj/structure/punching_bag, /turf/open/floor/pod/dark, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "zI" = ( /obj/structure/marker_beacon/indigo, /turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, @@ -614,7 +609,7 @@ "zU" = ( /obj/structure/flora/rock/pile/style_random, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Aa" = ( /obj/effect/turf_decal/sand, /obj/effect/turf_decal/stripes/asteroid/line{ @@ -622,11 +617,11 @@ }, /obj/machinery/light/directional/west, /turf/open/floor/sepia, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Ae" = ( /obj/structure/chair, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Al" = ( /turf/closed/mineral/random/volcanic, /area/lavaland/surface/outdoors/virtual_domain) @@ -637,19 +632,19 @@ "Au" = ( /obj/structure/fluff/beach_umbrella/science, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "AI" = ( /obj/structure/table/reinforced, /obj/machinery/reagentgrinder, /turf/open/floor/pod/light, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "AP" = ( /obj/machinery/chem_dispenser/drinks/beer/fullupgrade{ dir = 1 }, /obj/structure/table/wood, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Br" = ( /obj/structure/table/wood/poker, /obj/item/toy/cards/deck/cas{ @@ -660,73 +655,73 @@ pixel_y = 2 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Bu" = ( /turf/open/misc/beach/coast{ dir = 8 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Bw" = ( /obj/structure/flora/bush/sparsegrass/style_random, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "BD" = ( /obj/structure/table/wood, /obj/item/reagent_containers/condiment/saltshaker, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "BJ" = ( /obj/structure/table/wood/poker, /obj/item/toy/cards/deck, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "BM" = ( /turf/closed/wall/mineral/wood/nonmetal, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "BQ" = ( /obj/machinery/seed_extractor, /turf/open/floor/pod/light, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Cb" = ( /obj/machinery/light/directional/north, /mob/living/basic/crab{ name = "Eddie" }, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Cv" = ( /obj/machinery/hydroponics/constructable, /turf/open/floor/iron/grimy, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "CA" = ( /obj/structure/window/reinforced/spawner/directional/east, /obj/effect/mob_spawn/ghost_role/human/beach/lifeguard, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "CO" = ( /obj/machinery/vending/dinnerware, /obj/machinery/light/directional/east, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Db" = ( /obj/machinery/barsign/all_access, /turf/closed/wall/mineral/wood/nonmetal, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Ds" = ( /obj/machinery/door/airlock/public/glass{ name = "Resort Lobby" }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Dt" = ( /obj/machinery/light/directional/east, /obj/effect/turf_decal/sand, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "DL" = ( /obj/effect/baseturf_helper/virtual_domain, /turf/closed/wall/mineral/sandstone, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Em" = ( /obj/item/reagent_containers/condiment/enzyme{ layer = 5 @@ -736,28 +731,28 @@ }, /obj/structure/table, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Et" = ( /obj/machinery/light/small/directional/east, /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Ev" = ( /obj/structure/reagent_dispensers/beerkeg, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "EC" = ( /obj/structure/sign/warning/gas_mask/directional/west, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "EP" = ( /obj/machinery/light/directional/north, /obj/machinery/washing_machine, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Fn" = ( /turf/closed/wall/mineral/sandstone, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "FM" = ( /obj/effect/landmark/bitrunning/safehouse_spawn, /turf/template_noop, @@ -767,26 +762,26 @@ /obj/item/secateurs, /obj/item/reagent_containers/cup/bottle/nutrient/ez, /turf/open/floor/pod/light, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "FS" = ( /obj/effect/turf_decal/sand, /obj/structure/sign/warning/no_smoking/circle/directional/east, /obj/machinery/light/directional/east, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "FY" = ( /obj/structure/mineral_door/wood, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Gh" = ( /obj/effect/turf_decal/sand, /obj/structure/sign/poster/contraband/starkist/directional/north, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Gz" = ( /obj/structure/flora/tree/palm, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "GA" = ( /obj/structure/window/reinforced/spawner/directional/north, /obj/structure/window/reinforced/spawner/directional/west, @@ -795,56 +790,56 @@ /obj/item/storage/medkit/regular, /obj/item/storage/medkit/brute, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Hs" = ( /obj/machinery/shower/directional/west, /turf/open/floor/iron/white, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "HF" = ( /obj/machinery/deepfryer, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Ia" = ( /obj/structure/urinal/directional/north, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Ii" = ( /obj/machinery/light/directional/west, /turf/open/floor/iron/stairs/left, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Ir" = ( /obj/machinery/vending/cola, /obj/effect/turf_decal/sand, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Iv" = ( /obj/structure/table/wood, /obj/item/reagent_containers/condiment/peppermill, /obj/item/reagent_containers/condiment/soysauce, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "IH" = ( /obj/item/toy/beach_ball, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "IM" = ( /obj/machinery/hydroponics/constructable, /obj/machinery/light/directional/east, /turf/open/floor/iron/grimy, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "IP" = ( /obj/machinery/vending/snack, /obj/effect/turf_decal/sand, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Jt" = ( /obj/item/reagent_containers/cup/glass/bottle/beer, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "JC" = ( /obj/structure/fluff/beach_umbrella/engine, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "JE" = ( /obj/structure/closet/secure_closet/freezer/kitchen/all_access, /obj/item/reagent_containers/condiment/milk, @@ -852,53 +847,53 @@ /obj/item/reagent_containers/condiment/flour, /obj/item/reagent_containers/condiment/flour, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "JY" = ( /obj/structure/flora/rock/style_random, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Kd" = ( /obj/structure/sign/warning/secure_area, /turf/closed/wall/mineral/sandstone, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "KH" = ( /obj/structure/mineral_door/wood{ name = "Croupier's Booth" }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "KZ" = ( /obj/structure/flora/bush/stalky/style_random, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "LD" = ( /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "LW" = ( /obj/item/storage/cans/sixbeer, /turf/open/floor/carpet/orange, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Mp" = ( /obj/structure/table/wood, /obj/item/reagent_containers/cup/glass/drinkingglass/filled/pina_colada{ - pixel_x = 5; - pixel_y = 5 + pixel_x = 8; + pixel_y = 4 }, /obj/item/reagent_containers/cup/glass/drinkingglass/filled/pina_colada, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Mw" = ( /obj/structure/chair/sofa/right/brown, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Mz" = ( /obj/structure/chair/sofa/left/brown, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Nr" = ( /obj/machinery/light/directional/north, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Nw" = ( /obj/item/bedsheet/dorms{ dir = 4 @@ -907,7 +902,7 @@ dir = 4 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "NM" = ( /obj/structure/closet/crate/hydroponics, /obj/item/food/grown/ambrosia/vulgaris, @@ -921,32 +916,32 @@ /obj/item/food/grown/ambrosia/vulgaris, /obj/item/food/grown/ambrosia/vulgaris, /turf/open/floor/iron/grimy, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "NX" = ( /obj/effect/landmark/bitrunning/loot_signal, /turf/open/floor/light/colour_cycle/dancefloor_a, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "OE" = ( /obj/effect/mob_spawn/ghost_role/human/beach{ dir = 4 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "OK" = ( /obj/structure/sign/warning/gas_mask/directional/north, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "OR" = ( /obj/machinery/light/directional/south, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "OW" = ( /obj/structure/sink/kitchen/directional/east{ desc = "A sink used for washing one's hands and face. It looks rusty and home-made"; name = "old sink" }, /turf/open/floor/pod/light, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "OZ" = ( /obj/structure/marker_beacon/teal, /turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, @@ -955,30 +950,30 @@ /obj/structure/chair/wood, /obj/machinery/light/directional/west, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Pg" = ( /obj/structure/sign/poster/official/high_class_martini/directional/west, /obj/effect/mob_spawn/ghost_role/human/bartender{ dir = 4 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "PM" = ( /obj/machinery/door/airlock/external/ruin, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Qb" = ( /obj/machinery/griddle, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Qu" = ( /obj/structure/curtain, /turf/open/floor/iron/white, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "QP" = ( /obj/structure/extinguisher_cabinet/directional/north, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "QX" = ( /obj/machinery/chem_dispenser/drinks/fullupgrade{ dir = 1 @@ -986,10 +981,10 @@ /obj/structure/table/wood, /obj/machinery/light/small/directional/east, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Rx" = ( /turf/open/floor/iron/stairs/medium, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "RL" = ( /obj/structure/closet/cabinet, /obj/item/storage/backpack/duffelbag, @@ -1001,173 +996,173 @@ /obj/item/clothing/glasses/sunglasses/big, /obj/item/clothing/neck/beads, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Sg" = ( /obj/structure/flora/coconuts, /obj/machinery/light/directional/north, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "SB" = ( /obj/machinery/door/airlock/sandstone{ name = "Resort Bathroom" }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "SD" = ( /obj/machinery/door/airlock/sandstone{ name = "Bar Access" }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "SY" = ( /obj/machinery/door/airlock/sandstone{ name = "Surfer Shack 2" }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "TG" = ( /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "TJ" = ( /obj/structure/fluff/beach_umbrella/security, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "TX" = ( /obj/structure/sign/poster/contraband/ambrosia_vulgaris/directional/north, /turf/open/floor/iron/grimy, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Ud" = ( /obj/effect/turf_decal/sand, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Uh" = ( /turf/open/floor/iron/stairs/old, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Uq" = ( /obj/structure/weightmachine/weightlifter, /turf/open/floor/pod/dark, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "UU" = ( /obj/structure/flora/bush/large/style_random, /obj/structure/flora/bush/jungle/a/style_random, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Ve" = ( /obj/machinery/processor, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "VA" = ( /obj/machinery/computer/slot_machine, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "VH" = ( /obj/machinery/light/directional/west, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "VX" = ( /obj/structure/flora/bush/large/style_random, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "We" = ( /obj/structure/table/wood, /obj/item/book/manual/wiki/cooking_to_serve_man, /obj/item/clothing/suit/apron/chef, /obj/item/clothing/head/utility/chefhat, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Wg" = ( /obj/structure/dresser, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Ww" = ( /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "WL" = ( /obj/machinery/light/directional/north, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "WO" = ( /obj/structure/flora/bush/jungle/a/style_random, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "WW" = ( /obj/effect/turf_decal/sand, /obj/machinery/icecream_vat, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "WX" = ( /obj/item/toy/plush/lizard_plushie/green{ name = "Soaks-The-Rays" }, /turf/open/floor/carpet/orange, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Xt" = ( /turf/open/misc/beach/coast/corner{ dir = 4 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Xv" = ( /obj/structure/table/wood, /obj/structure/bedsheetbin, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "XL" = ( /obj/machinery/light/directional/east, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "XM" = ( /turf/open/misc/beach/coast, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "XP" = ( /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "XT" = ( /obj/effect/turf_decal/sand, /obj/structure/sign/departments/botany/directional/south, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Yi" = ( /obj/structure/flora/bush/sparsegrass/style_random, /obj/item/toy/seashell, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Yq" = ( /obj/machinery/portable_atmospherics/canister/air, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "YI" = ( /obj/machinery/door/airlock/maintenance{ name = "Supply Room" }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "YJ" = ( /turf/open/floor/carpet/purple, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "YN" = ( /obj/effect/turf_decal/sand, /obj/machinery/light/directional/west, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Zb" = ( /obj/structure/sign/poster/official/cohiba_robusto_ad/directional/west, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Zd" = ( /obj/structure/sign/poster/contraband/space_cola/directional/north, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Zg" = ( /obj/structure/table, /obj/machinery/microwave, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Zt" = ( /obj/structure/table/wood, /obj/item/reagent_containers/pill/morphine, /obj/item/storage/fancy/donut_box, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) (1,1,1) = {" pr @@ -2118,7 +2113,7 @@ iz (23,1,1) = {" iz Al -no +xb Fn Cb wD @@ -2161,7 +2156,7 @@ xW (24,1,1) = {" iz Al -no +xb Fn wD Gz @@ -2204,7 +2199,7 @@ xW (25,1,1) = {" iz Al -no +xb Fn OK Gz @@ -2247,7 +2242,7 @@ xW (26,1,1) = {" iz Al -no +xb Fn Sg wD diff --git a/_maps/virtual_domains/breeze_bay.dmm b/_maps/virtual_domains/breeze_bay.dmm index 6fe6f49ab3ab1..bf973fa2027ee 100644 --- a/_maps/virtual_domains/breeze_bay.dmm +++ b/_maps/virtual_domains/breeze_bay.dmm @@ -1,29 +1,33 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE "a" = ( /turf/closed/indestructible/binary, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "c" = ( /obj/structure/flora/coconuts, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "d" = ( /obj/structure/chair/wood, /turf/open/floor/wood/large, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "e" = ( /turf/open/floor/carpet/red, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "g" = ( /obj/item/toy/beach_ball/branded, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) +"h" = ( +/obj/machinery/light/small/directional/south, +/turf/open/misc/beach/sand, +/area/virtual_domain/fullbright) "i" = ( /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "k" = ( /obj/effect/landmark/bitrunning/loot_signal, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "m" = ( /obj/item/fishing_rod{ pixel_x = 5; @@ -36,22 +40,22 @@ }, /obj/structure/table/wood, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "o" = ( /obj/structure/flora/tree/jungle/style_5, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "p" = ( /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "s" = ( /obj/structure/fluff/beach_umbrella/cap, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "t" = ( /obj/structure/fluff/beach_umbrella/syndi, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "v" = ( /obj/effect/baseturf_helper/virtual_domain, /obj/effect/landmark/bitrunning/safehouse_spawn, @@ -60,44 +64,44 @@ "y" = ( /obj/structure/flora/bush/sparsegrass/style_random, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "z" = ( /mob/living/basic/crab, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "B" = ( /obj/structure/flora/tree/jungle/style_6, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "C" = ( /obj/structure/flora/tree/jungle/style_2, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "D" = ( /turf/open/floor/carpet/green, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "F" = ( /obj/structure/fluff/beach_umbrella/engine, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "G" = ( /obj/structure/flora/bush/jungle/a/style_random, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "H" = ( /obj/structure/flora/tree/jungle/style_4, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "I" = ( /turf/template_noop, /area/virtual_domain/safehouse) "J" = ( /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "K" = ( /obj/structure/flora/tree/jungle, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "L" = ( /obj/item/fishing_line, /obj/item/fishing_hook, @@ -105,19 +109,25 @@ /obj/item/fishing_hook, /obj/structure/closet/crate, /obj/item/bait_can/worm, +/obj/item/bait_can/worm, +/obj/item/bait_can/worm, +/turf/open/misc/beach/sand, +/area/virtual_domain/fullbright) +"N" = ( +/obj/machinery/light/small/directional/north, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "O" = ( /obj/structure/flora/rock/style_random, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "P" = ( /turf/open/misc/beach/coast, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Q" = ( /obj/structure/flora/bush/stalky/style_random, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "R" = ( /obj/structure/closet/crate/freezer{ name = "Cooler" @@ -142,22 +152,30 @@ /obj/item/reagent_containers/cup/glass/bottle/beer/light, /obj/item/clothing/head/soft/fishing_hat, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "S" = ( /obj/structure/flora/tree/jungle/style_3, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) +"T" = ( +/obj/machinery/light/small/directional/east, +/turf/open/misc/beach/sand, +/area/virtual_domain/fullbright) "U" = ( /obj/structure/flora/tree/palm/style_random, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "X" = ( /turf/open/floor/wood/large, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) +"Y" = ( +/obj/machinery/light/small/directional/west, +/turf/open/misc/beach/sand, +/area/virtual_domain/fullbright) "Z" = ( /obj/effect/baseturf_helper/virtual_domain, /turf/closed/indestructible/binary, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) (1,1,1) = {" a @@ -192,12 +210,12 @@ K G y J +T J J J J -J -J +T z P i @@ -218,14 +236,14 @@ a J O J -J +h I I I I I v -J +N P Q i @@ -380,14 +398,14 @@ a G y J -J +h I I I I I I -J +N P i i @@ -408,12 +426,12 @@ o J J J +Y J J J J -J -J +Y J P i diff --git a/_maps/virtual_domains/clown_planet.dmm b/_maps/virtual_domains/clown_planet.dmm index 01d7b88a5efb5..7dbeefe3043f9 100644 --- a/_maps/virtual_domains/clown_planet.dmm +++ b/_maps/virtual_domains/clown_planet.dmm @@ -7,15 +7,15 @@ /obj/machinery/light/small/directional/west, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "aI" = ( /obj/item/bikehorn/airhorn, /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "aM" = ( /obj/item/bikehorn, /turf/open/indestructible/honk, -/area/virtual_domain/powered) +/area/virtual_domain) "aP" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -23,7 +23,7 @@ /obj/effect/decal/cleanable/food/pie_smudge, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "ba" = ( /obj/structure/mecha_wreckage/honker, /obj/structure/disposalpipe/segment{ @@ -31,7 +31,7 @@ invisibility = 101 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "bi" = ( /obj/item/bikehorn, /obj/structure/disposalpipe/segment{ @@ -39,19 +39,19 @@ }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "bp" = ( /turf/open/indestructible/light, -/area/virtual_domain/powered) +/area/virtual_domain) "bq" = ( /obj/structure/disposalpipe/segment{ dir = 10 }, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "by" = ( /turf/closed/wall/r_wall, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "bQ" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -59,26 +59,26 @@ }, /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "bR" = ( /obj/item/paper/crumpled/bloody/ruins/lavaland/clown_planet/hope, /obj/effect/decal/cleanable/blood/old, /obj/effect/mapping_helpers/no_lava, /turf/open/floor/noslip, -/area/virtual_domain/powered) +/area/virtual_domain) "bU" = ( /obj/structure/disposalpipe/segment{ dir = 9 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "cw" = ( /obj/structure/disposalpipe/segment{ dir = 6 }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "cM" = ( /obj/structure/disposalpipe/trunk{ dir = 8 @@ -87,7 +87,7 @@ dir = 1 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "cW" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/disposalpipe/segment{ @@ -95,21 +95,21 @@ }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "ed" = ( /obj/structure/disposalpipe/segment{ invisibility = 101 }, /obj/machinery/light/small/directional/west, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "eE" = ( /obj/structure/window/reinforced/spawner/directional/south, /obj/structure/disposalpipe/segment{ invisibility = 101 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "fh" = ( /obj/effect/mob_spawn/corpse/human/damaged, /obj/effect/decal/cleanable/blood/old, @@ -118,7 +118,7 @@ }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "gr" = ( /obj/effect/baseturf_helper/virtual_domain, /turf/template_noop, @@ -129,23 +129,23 @@ }, /obj/effect/baseturf_helper/virtual_domain, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "gH" = ( /obj/item/bikehorn, /obj/effect/decal/cleanable/dirt, /turf/open/indestructible/honk, -/area/virtual_domain/powered) +/area/virtual_domain) "gK" = ( /obj/structure/disposalpipe/segment{ dir = 9 }, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "hK" = ( /obj/item/clothing/head/cone, /obj/effect/mapping_helpers/no_lava, /turf/open/floor/noslip, -/area/virtual_domain/powered) +/area/virtual_domain) "hY" = ( /turf/template_noop, /area/template_noop) @@ -157,24 +157,24 @@ dir = 4 }, /turf/open/floor/noslip, -/area/virtual_domain/powered) +/area/virtual_domain) "ik" = ( /turf/open/lava/smooth, -/area/virtual_domain/powered) +/area/virtual_domain) "iR" = ( /obj/structure/disposalpipe/segment{ dir = 4; invisibility = 101 }, /turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "ki" = ( /obj/structure/disposalpipe/segment{ dir = 4; invisibility = 101 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "kn" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -182,7 +182,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "lj" = ( /obj/structure/disposalpipe/trunk{ dir = 4 @@ -191,14 +191,14 @@ dir = 8 }, /turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "lm" = ( /obj/structure/disposalpipe/segment{ dir = 9 }, /obj/machinery/light/small/directional/east, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "lr" = ( /obj/item/bikehorn, /obj/effect/decal/cleanable/dirt, @@ -207,60 +207,60 @@ }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "lx" = ( /obj/structure/disposalpipe/segment{ dir = 9 }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "ly" = ( /obj/structure/disposalpipe/segment{ dir = 9 }, /turf/closed/indestructible/binary, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "lP" = ( /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "mD" = ( /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "mE" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "mF" = ( /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "nE" = ( /obj/effect/mapping_helpers/no_lava, /turf/closed/wall/r_wall, -/area/virtual_domain/powered) +/area/virtual_domain) "oA" = ( /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "oI" = ( /obj/structure/table/glass, /obj/item/grown/bananapeel/bluespace, /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "pl" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "ps" = ( /obj/structure/disposalpipe/segment{ dir = 6 }, /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "qM" = ( /obj/structure/disposalpipe/segment{ invisibility = 101 @@ -268,7 +268,7 @@ /obj/machinery/light/small/directional/north, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "rg" = ( /obj/item/coin/bananium, /obj/item/coin/bananium, @@ -276,19 +276,19 @@ /obj/item/coin/bananium, /obj/machinery/light/small/directional/west, /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "rh" = ( /obj/structure/disposalpipe/segment{ dir = 6 }, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "rr" = ( /obj/structure/disposalpipe/segment{ dir = 5 }, /turf/closed/indestructible/binary, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "rH" = ( /obj/structure/disposalpipe/junction/yjunction{ dir = 1; @@ -297,46 +297,46 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "rT" = ( /obj/structure/disposalpipe/segment{ dir = 6 }, /turf/closed/indestructible/binary, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "sq" = ( /obj/machinery/light/directional/north, /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "sT" = ( /obj/structure/disposalpipe/sorting/mail/flip{ dir = 1 }, /obj/effect/mapping_helpers/mail_sorting/supply/qm_office, /turf/closed/wall/r_wall, -/area/virtual_domain/powered) +/area/virtual_domain) "tq" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "tt" = ( /obj/structure/disposalpipe/segment{ dir = 4; invisibility = 101 }, /turf/open/indestructible/light, -/area/virtual_domain/powered) +/area/virtual_domain) "tv" = ( /obj/effect/mob_spawn/corpse/human/damaged, /obj/effect/decal/cleanable/blood/old, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "tF" = ( /obj/effect/baseturf_helper/virtual_domain, /turf/closed/indestructible/binary, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "tI" = ( /obj/item/coin/bananium, /obj/item/coin/bananium, @@ -344,15 +344,15 @@ /obj/item/coin/bananium, /obj/machinery/light/small/directional/east, /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "uX" = ( /obj/effect/mapping_helpers/no_lava, /mob/living/basic/clown, /turf/open/floor/noslip, -/area/virtual_domain/powered) +/area/virtual_domain) "uY" = ( /turf/closed/mineral/bananium, -/area/virtual_domain/powered) +/area/virtual_domain) "uZ" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -362,13 +362,13 @@ /obj/item/paper/crumpled/bloody/ruins/lavaland/clown_planet/escape, /obj/item/pen/fourcolor, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "wz" = ( /obj/machinery/light/small/directional/south, /obj/effect/mapping_helpers/no_lava, /mob/living/basic/clown, /turf/open/floor/noslip, -/area/virtual_domain/powered) +/area/virtual_domain) "xt" = ( /obj/effect/landmark/bitrunning/safehouse_spawn, /turf/template_noop, @@ -377,17 +377,17 @@ /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "yz" = ( /obj/structure/disposalpipe/segment{ dir = 10 }, /turf/closed/wall/r_wall, -/area/virtual_domain/powered) +/area/virtual_domain) "yS" = ( /obj/structure/marker_beacon/yellow, /turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "yZ" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -395,16 +395,16 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "zm" = ( /obj/effect/decal/cleanable/cobweb, /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "zA" = ( /obj/structure/statue/bananium/clown, /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "zF" = ( /obj/structure/disposalpipe/trunk{ dir = 4 @@ -413,14 +413,14 @@ dir = 8 }, /turf/open/floor/noslip, -/area/virtual_domain/powered) +/area/virtual_domain) "Aa" = ( /obj/structure/disposalpipe/segment{ dir = 9 }, /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "Bi" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -429,7 +429,7 @@ /obj/effect/decal/cleanable/cobweb, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "Cp" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -437,7 +437,7 @@ }, /obj/machinery/light/small/directional/west, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "Cs" = ( /obj/item/bikehorn, /obj/structure/disposalpipe/segment{ @@ -446,10 +446,7 @@ }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) -"Dh" = ( -/turf/closed/wall/r_wall, -/area/virtual_domain/powered) +/area/virtual_domain) "Do" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -457,7 +454,7 @@ }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "DL" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -465,35 +462,35 @@ /obj/item/bikehorn, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "Ex" = ( /obj/structure/disposalpipe/segment{ dir = 10 }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "FI" = ( /obj/item/reagent_containers/cup/glass/trophy/gold_cup, /obj/structure/table/glass, /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "Gg" = ( /obj/structure/table/glass, /obj/item/gun/magic/staff/honk, /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "Hq" = ( /obj/structure/disposalpipe/segment{ dir = 6 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Hr" = ( /obj/structure/table/glass, /obj/item/clothing/shoes/clown_shoes/banana_shoes, /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "HQ" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -501,10 +498,10 @@ /obj/machinery/light/small/directional/east, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "Ie" = ( /turf/closed/indestructible/binary, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "Iz" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -512,20 +509,20 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "IN" = ( /obj/structure/disposalpipe/segment{ dir = 6 }, /turf/closed/wall/r_wall, -/area/virtual_domain/powered) +/area/virtual_domain) "IY" = ( /turf/open/indestructible/honk, -/area/virtual_domain/powered) +/area/virtual_domain) "Jv" = ( /obj/effect/decal/cleanable/dirt, /turf/open/indestructible/honk, -/area/virtual_domain/powered) +/area/virtual_domain) "JB" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -534,28 +531,28 @@ /obj/machinery/light/small/directional/north, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "Ka" = ( /obj/effect/decal/cleanable/food/pie_smudge, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "Kh" = ( /obj/effect/mob_spawn/corpse/human/damaged, /obj/effect/decal/cleanable/blood/old, /turf/open/indestructible/honk, -/area/virtual_domain/powered) +/area/virtual_domain) "KG" = ( /obj/item/pickaxe, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "KI" = ( /obj/structure/disposalpipe/segment{ dir = 4; invisibility = 101 }, /turf/closed/wall/r_wall, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "Lv" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -563,18 +560,18 @@ }, /obj/machinery/light/small/directional/east, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "Nv" = ( /obj/effect/decal/cleanable/cobweb, /turf/open/indestructible/honk, -/area/virtual_domain/powered) +/area/virtual_domain) "NB" = ( /obj/machinery/disposal/delivery_chute, /obj/structure/disposalpipe/trunk{ dir = 1 }, /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "NL" = ( /obj/machinery/disposal/delivery_chute{ desc = "The following is engraved upon the chute: A FATE WORSE THAN DEATH LIES WITHIN"; @@ -584,12 +581,12 @@ /obj/structure/disposalpipe/trunk, /obj/effect/mapping_helpers/no_lava, /turf/open/floor/noslip, -/area/virtual_domain/powered) +/area/virtual_domain) "NW" = ( /obj/structure/table/glass, /obj/item/reagent_containers/spray/waterflower/superlube, /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "Ok" = ( /obj/item/bikehorn, /obj/structure/disposalpipe/segment{ @@ -597,7 +594,7 @@ }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "Ov" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -605,7 +602,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "PJ" = ( /obj/structure/disposalpipe/trunk, /obj/structure/disposaloutlet{ @@ -613,10 +610,10 @@ }, /obj/effect/mapping_helpers/no_lava, /turf/open/floor/noslip, -/area/virtual_domain/powered) +/area/virtual_domain) "PM" = ( /turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "PQ" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -624,20 +621,20 @@ }, /obj/item/pickaxe, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "QP" = ( /turf/template_noop, /area/virtual_domain/safehouse) "QX" = ( /obj/structure/closet/crate/secure/bitrunning/encrypted, /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "Rh" = ( /obj/structure/disposalpipe/segment{ dir = 5 }, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "Rx" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -646,13 +643,13 @@ /obj/structure/table, /obj/item/flashlight/lamp/bananalamp, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "RU" = ( /obj/structure/disposalpipe/segment{ invisibility = 101 }, /turf/closed/indestructible/binary, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "Sg" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -661,13 +658,13 @@ /obj/effect/decal/cleanable/food/pie_smudge, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "Sm" = ( /obj/structure/disposalpipe/segment{ dir = 5 }, /turf/closed/wall/r_wall, -/area/virtual_domain/powered) +/area/virtual_domain) "Tm" = ( /obj/effect/decal/cleanable/food/pie_smudge, /obj/structure/disposalpipe/segment{ @@ -675,13 +672,13 @@ }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "Tx" = ( /obj/structure/disposalpipe/segment{ invisibility = 101 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "TH" = ( /obj/structure/disposalpipe/trunk{ dir = 4 @@ -690,67 +687,60 @@ dir = 8 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "TK" = ( /obj/structure/disposalpipe/segment{ invisibility = 101 }, /turf/closed/wall/r_wall, -/area/virtual_domain/powered) +/area/virtual_domain) "Ug" = ( /obj/machinery/light/small/directional/north, /turf/open/floor/carpet, -/area/virtual_domain/powered) +/area/virtual_domain) "UL" = ( /obj/effect/decal/cleanable/oil, /obj/structure/disposalpipe/segment{ dir = 10 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "UN" = ( /obj/structure/disposalpipe/segment{ dir = 10 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "UQ" = ( /obj/structure/disposalpipe/segment{ invisibility = 101 }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "UY" = ( /obj/structure/disposalpipe/segment{ dir = 5 }, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) -"Vv" = ( -/obj/structure/disposalpipe/segment{ - dir = 4; - invisibility = 101 - }, -/turf/closed/wall/r_wall, -/area/virtual_domain/powered) +/area/virtual_domain) "Vx" = ( /obj/structure/disposalpipe/segment{ dir = 4; invisibility = 101 }, /turf/closed/indestructible/binary, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "VI" = ( /obj/structure/disposalpipe/segment{ dir = 10 }, /turf/closed/indestructible/binary, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) "VQ" = ( /turf/open/floor/noslip, -/area/virtual_domain/powered) +/area/virtual_domain) "Ww" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -759,40 +749,40 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/indestructible/permalube, -/area/virtual_domain/powered) +/area/virtual_domain) "WB" = ( /obj/machinery/disposal/delivery_chute{ dir = 1 }, /obj/structure/disposalpipe/trunk, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "WT" = ( /obj/machinery/door/airlock/bananium, /turf/open/indestructible/honk, -/area/virtual_domain/powered) +/area/virtual_domain) "WX" = ( /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "Xp" = ( /obj/machinery/light/directional/south, /turf/open/indestructible/honk, -/area/virtual_domain/powered) +/area/virtual_domain) "XB" = ( /obj/machinery/light/directional/north, /turf/open/indestructible/honk, -/area/virtual_domain/powered) +/area/virtual_domain) "Yb" = ( /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/open/indestructible/honk, -/area/virtual_domain/powered) +/area/virtual_domain) "YP" = ( /obj/structure/disposalpipe/segment{ dir = 4; invisibility = 101 }, /turf/open/indestructible/white, -/area/virtual_domain/powered) +/area/virtual_domain) "ZR" = ( /obj/structure/disposalpipe/trunk{ dir = 8 @@ -801,7 +791,7 @@ dir = 4 }, /turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) +/area/virtual_domain) (1,1,1) = {" Ie @@ -904,13 +894,13 @@ Ie Ie Ie Ie -Dh -Dh -Dh -Dh -Dh -Dh -Dh +by +by +by +by +by +by +by Ie Ie Ie @@ -918,11 +908,11 @@ Ie Ie Ie Ie -Dh -Dh -Dh -Dh -Dh +by +by +by +by +by Ie Ie Ie @@ -948,29 +938,29 @@ Vx Ie Ie Ie -Dh -Dh -Dh +by +by +by ik ik ik ik ik -Dh -Dh +by +by Ie Ie Ie Ie Ie -Dh -Dh +by +by ik ik ik -Dh -Dh -Dh +by +by +by Ie Ie Ie @@ -993,8 +983,8 @@ Ie Vx Ie Ie -Dh -Dh +by +by ik ik ik @@ -1003,21 +993,21 @@ Sm Hq Sm ik -Dh -Dh +by +by Ie Ie Ie -Dh -Dh +by +by ik ik tq mD ik ik -Dh -Dh +by +by Ie Ie Ie @@ -1038,8 +1028,8 @@ Ie Ie Vx Ie -Dh -Dh +by +by ik ik IN @@ -1050,11 +1040,11 @@ yZ aP Sm ik -Dh -Dh -Dh -Dh -Dh +by +by +by +by +by Nv IY tq @@ -1063,8 +1053,8 @@ ik ik ik ik -Dh -Dh +by +by Ie Ie Vx @@ -1084,23 +1074,23 @@ Ie Ie Vx Ie -Dh +by ik ik -Dh +by Bi cw UQ lr UQ UY -Vv +KI ik -Dh +by IY Jv IY -Dh +by IY Jv Kh @@ -1110,7 +1100,7 @@ ik tq ik ik -Dh +by Ie Ie Vx @@ -1129,8 +1119,8 @@ hY Ie Ie Vx -Dh -Dh +by +by ik IN Tm @@ -1139,9 +1129,9 @@ Ww cw UQ Sm -Vv -Vv -Dh +KI +KI +by zm oA IY @@ -1152,12 +1142,12 @@ Jv IY IY IY -Dh +by ik mD ik -Dh -Dh +by +by Ie Vx hY @@ -1175,27 +1165,27 @@ hY Ie Ie Vx -Dh +by ik ik UN UQ UY Ww -Vv +KI TH -Vv +KI YP Cp uY -Dh +by sq oA IY -Dh -Dh +by +by Jv -Dh +by IY IY IY @@ -1203,7 +1193,7 @@ tq ik ik ik -Dh +by Ie Vx Ie @@ -1221,7 +1211,7 @@ tF Ie Ie Vx -Dh +by ik IN UQ @@ -1229,14 +1219,14 @@ UQ yZ Do Do -Vv +KI YP YP YP KG uY -Dh -Dh +by +by oA IY IY @@ -1246,10 +1236,10 @@ IY gH Jv Xp -Dh +by ik ik -Dh +by by KI by @@ -1267,15 +1257,15 @@ Ie Ie Ie Vx -Dh +by ik yz fh UQ UY -Vv +KI Ww -Vv +KI YP YP tt @@ -1285,7 +1275,7 @@ oA oA oA IY -Dh +by IY IY Jv @@ -1295,7 +1285,7 @@ IY ik tq ik -Dh +by by iR PM @@ -1313,7 +1303,7 @@ Ie Ie Ie Vx -Dh +by ik Hq TK @@ -1321,18 +1311,18 @@ qM yZ Ww Ww -Vv +KI YP PQ tt bp uY -Dh +by oA oA IY IY -Dh +by IY IY IY @@ -1359,7 +1349,7 @@ Ie Ie Ie Vx -Dh +by ik UN UQ @@ -1368,20 +1358,20 @@ DL Ww yz lx -Vv +KI YP Lv WX -Dh -Dh +by +by oA IY IY -Dh -Dh +by +by IY IY -Dh +by IY Jv ik @@ -1403,8 +1393,8 @@ Ie "} (14,1,1) = {" Ie -Dh -Vv +by +KI nE nE mD @@ -1415,17 +1405,17 @@ Ex Tm UQ lx -Vv -Vv +KI +KI ps TK Sm -Dh -Dh -Dh +by +by +by zA rg -Dh +by XB IY Jv @@ -1449,11 +1439,11 @@ Ie "} (15,1,1) = {" Ie -Dh +by ij hK nE -Dh +by yz UQ UQ @@ -1466,13 +1456,13 @@ Do Iz kn Ww -Dh -Dh +by +by FI mF mF mF -Dh +by IY Jv Jv @@ -1495,7 +1485,7 @@ Ie "} (16,1,1) = {" Ie -Dh +by VQ uX NL @@ -1513,13 +1503,13 @@ pl Do Ex UY -Dh +by Ug oI NW mF -Dh -Dh +by +by Jv IY IY @@ -1541,11 +1531,11 @@ Ie "} (17,1,1) = {" Ie -Dh +by VQ bR wz -Dh +by Hq UQ Sm @@ -1568,7 +1558,7 @@ WT IY Jv IY -Dh +by ik tq ik @@ -1587,7 +1577,7 @@ Ie "} (18,1,1) = {" Ie -Dh +by VQ uX PJ @@ -1596,7 +1586,7 @@ sT kn Do Do -Vv +KI Do Ov UQ @@ -1605,12 +1595,12 @@ Ok mE rH pl -Dh +by mF Hr Gg mF -Dh +by IY IY IY @@ -1633,12 +1623,12 @@ Ie "} (19,1,1) = {" Ie -Dh +by zF uX nE -Dh -Dh +by +by Ww Ww Ww @@ -1649,14 +1639,14 @@ lP Ex UY Ka -Vv +KI tv -Dh +by FI mF mF QX -Dh +by IY IY IY @@ -1679,29 +1669,29 @@ Ie "} (20,1,1) = {" Ie -Dh -Vv +by +KI nE nE ik -Dh +by Ww Ww Cs Do Do -Vv -Dh -Dh +KI +by +by bQ -Dh +by ba -Dh +by IY -Dh +by zA tI -Dh +by XB IY Jv @@ -1727,26 +1717,26 @@ Ie Ie Ie Vx -Dh +by ik -Dh -Dh +by +by Do Do Do Ww Do -Vv +KI rh ed gK -Dh +by UL Sm IY IY -Dh -Dh +by +by Kh IY IY @@ -1773,26 +1763,26 @@ Ie Ie Ie Vx -Dh +by ik -Dh -Dh +by +by JB Sg -Vv +KI Ww -Vv +KI uZ YP bp bp uY -Dh +by bQ oA IY IY -Dh +by IY Jv IY @@ -1819,15 +1809,15 @@ Ie Ie Ie Vx -Dh +by ik cM eE lx -Vv +KI ki Ww -Vv +KI Rx YP bp @@ -1835,7 +1825,7 @@ bp WB TK Aa -Dh +by IY IY Jv @@ -1844,10 +1834,10 @@ Jv IY aM Xp -Dh +by tq ik -Dh +by by iR PM @@ -1865,10 +1855,10 @@ Ie Ie Ie Vx -Dh +by ik -Dh -Dh +by +by lP Do Do @@ -1879,7 +1869,7 @@ bq Rh WX uY -Dh +by oA oA IY @@ -1888,12 +1878,12 @@ Jv Jv IY IY -Dh -Dh +by +by ik mD ik -Dh +by by KI by @@ -1911,20 +1901,20 @@ Ie Ie Ie Vx -Dh +by ik -Dh -Dh +by +by pl Do -Vv +KI Do -Vv -Vv +KI +KI rh lm uY -Dh +by sq oA IY @@ -1932,14 +1922,14 @@ IY IY IY IY -Dh +by IY IY ik mD ik ik -Dh +by Ie Vx Ie @@ -1957,19 +1947,19 @@ Ie Ie Ie Vx -Dh +by ik ik -Dh +by yd Do Do Do Ex lx -Vv -Dh -Dh +KI +by +by oA oA IY @@ -1980,12 +1970,12 @@ aM IY IY IY -Dh +by ik tq ik -Dh -Dh +by +by Ie Vx hY @@ -2003,34 +1993,34 @@ hY Ie Ie Vx -Dh -Dh +by +by ik -Dh -Dh +by +by Ex lx HQ UQ UQ bU -Dh +by ik -Dh +by Yb IY IY -Dh +by IY IY -Dh +by IY IY ik mD ik ik -Dh +by Ie Ie Vx @@ -2050,23 +2040,23 @@ Ie Ie Vx Ie -Dh -Dh +by +by ik ik -Dh +by mD -Dh +by Ka lP mD -Dh +by ik -Dh -Dh -Dh -Dh -Dh +by +by +by +by +by IY IY IY @@ -2075,8 +2065,8 @@ ik ik ik ik -Dh -Dh +by +by Ie Ie Vx @@ -2097,31 +2087,31 @@ Ie Vx Ie Ie -Dh -Dh +by +by ik ik ik tq tq tq -Dh +by ik -Dh -Dh +by +by Ie Ie Ie -Dh -Dh +by +by ik ik mD tq ik ik -Dh -Dh +by +by Ie Ie Ie @@ -2144,29 +2134,29 @@ Vx Ie Ie Ie -Dh -Dh -Dh +by +by +by ik ik ik ik ik -Dh -Dh +by +by Ie Ie Ie Ie Ie -Dh -Dh +by +by ik ik ik -Dh -Dh -Dh +by +by +by Ie Ie Ie @@ -2192,13 +2182,13 @@ Ie Ie Ie Ie -Dh -Dh -Dh -Dh -Dh -Dh -Dh +by +by +by +by +by +by +by Ie Ie Ie @@ -2206,11 +2196,11 @@ Ie Ie Ie Ie -Dh -Dh -Dh -Dh -Dh +by +by +by +by +by Ie Ie Ie diff --git a/_maps/virtual_domains/legion.dmm b/_maps/virtual_domains/legion.dmm deleted file mode 100644 index 55843177ad0f1..0000000000000 --- a/_maps/virtual_domains/legion.dmm +++ /dev/null @@ -1,6370 +0,0 @@ -//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE -"ah" = ( -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/obj/structure/stone_tile, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"ak" = ( -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"aI" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"aR" = ( -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"bd" = ( -/obj/structure/stone_tile/block, -/obj/structure/stone_tile/block{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"be" = ( -/obj/structure/stone_tile/block{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"bt" = ( -/obj/effect/decal/cleanable/blood, -/obj/effect/decal/cleanable/blood/drip, -/obj/effect/decal/cleanable/blood/footprints{ - dir = 1 - }, -/turf/open/floor/pod/dark, -/area/lavaland/surface/outdoors/virtual_domain) -"bu" = ( -/obj/structure/marker_beacon/bronze, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"ca" = ( -/obj/effect/mob_spawn/corpse/human/legioninfested, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"cf" = ( -/obj/structure/stone_tile/block{ - dir = 1 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"cp" = ( -/turf/template_noop, -/area/template_noop) -"dm" = ( -/obj/structure/stone_tile/block{ - dir = 1 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"dn" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/obj/effect/mob_spawn/corpse/human/legioninfested, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"dr" = ( -/obj/structure/stone_tile/block{ - dir = 1 - }, -/obj/structure/stone_tile/block/cracked, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"dx" = ( -/obj/effect/decal/cleanable/blood/footprints{ - dir = 8 - }, -/obj/effect/decal/cleanable/blood/drip, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"dL" = ( -/obj/structure/stone_tile/block{ - dir = 4 - }, -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"dQ" = ( -/turf/closed/wall/mineral/titanium/survival/pod, -/area/lavaland/surface/outdoors/virtual_domain) -"et" = ( -/obj/structure/stone_tile/block/cracked, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"ew" = ( -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"eJ" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"fA" = ( -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"fG" = ( -/obj/structure/marker_beacon/violet, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"gh" = ( -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 8 - }, -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"gk" = ( -/obj/structure/necropolis_gate/locked, -/obj/structure/stone_tile/slab, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"gK" = ( -/obj/effect/decal/cleanable/blood/footprints, -/obj/effect/decal/cleanable/blood/drip, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"gQ" = ( -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 8 - }, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/obj/structure/stone_tile, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"hc" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"hw" = ( -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 8 - }, -/obj/structure/stone_tile/block/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"hx" = ( -/obj/structure/stone_tile, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"hU" = ( -/obj/structure/stone_tile/block{ - dir = 4 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"ib" = ( -/turf/closed/mineral/volcanic/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"ie" = ( -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile/block{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"iP" = ( -/obj/structure/fluff/drake_statue/falling, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"iR" = ( -/obj/structure/stone_tile/block{ - dir = 1 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"iV" = ( -/obj/structure/stone_tile/block{ - dir = 8 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"jk" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"jt" = ( -/obj/structure/stone_tile/slab/cracked, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"jw" = ( -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"jN" = ( -/obj/machinery/sleeper/survival_pod, -/turf/open/floor/pod/dark, -/area/lavaland/surface/outdoors/virtual_domain) -"ka" = ( -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"kg" = ( -/turf/closed/indestructible/riveted/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"kT" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"kZ" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"ll" = ( -/obj/structure/stone_tile/cracked, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"lz" = ( -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"lC" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"lO" = ( -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"lT" = ( -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"mz" = ( -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"mG" = ( -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"nm" = ( -/obj/structure/stone_tile{ - dir = 8 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"nu" = ( -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"nv" = ( -/obj/structure/stone_tile/block{ - dir = 8 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"ny" = ( -/obj/structure/stone_tile, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"nI" = ( -/obj/structure/stone_tile/block, -/obj/structure/stone_tile{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"nO" = ( -/obj/structure/stone_tile/surrounding_tile, -/obj/structure/stone_tile/surrounding_tile{ - dir = 1 - }, -/obj/structure/stone_tile/center, -/obj/structure/stone_tile/surrounding_tile/cracked{ - dir = 8 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"ob" = ( -/obj/structure/necropolis_gate/legion_gate, -/obj/structure/necropolis_arch, -/obj/structure/stone_tile/slab, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"og" = ( -/obj/effect/landmark/bitrunning/safehouse_spawn, -/turf/template_noop, -/area/virtual_domain/safehouse) -"oo" = ( -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 8 - }, -/obj/structure/stone_tile/block/cracked{ - dir = 1 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"ox" = ( -/turf/closed/indestructible/binary, -/area/lavaland/surface/outdoors/virtual_domain) -"oS" = ( -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"pP" = ( -/obj/structure/stone_tile/block{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"qo" = ( -/obj/structure/stone_tile/slab/cracked, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"qs" = ( -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"qW" = ( -/obj/effect/decal/cleanable/blood/footprints{ - dir = 1 - }, -/obj/machinery/door/airlock/survival_pod/glass, -/turf/open/floor/pod/dark, -/area/lavaland/surface/outdoors/virtual_domain) -"rt" = ( -/obj/effect/mob_spawn/corpse/human/miner, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"rU" = ( -/obj/structure/stone_tile/block{ - dir = 1 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"sd" = ( -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/obj/structure/stone_tile/block{ - dir = 4 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"sk" = ( -/obj/structure/stone_tile{ - dir = 8 - }, -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"sz" = ( -/obj/structure/stone_tile/center, -/obj/structure/stone_tile/surrounding_tile, -/obj/structure/stone_tile/surrounding_tile{ - dir = 4 - }, -/obj/structure/stone_tile/surrounding_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"sA" = ( -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"tk" = ( -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"tF" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/block{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"uK" = ( -/obj/structure/stone_tile/block{ - dir = 8 - }, -/obj/structure/stone_tile/block{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"vf" = ( -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"wq" = ( -/obj/structure/marker_beacon/teal, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"wy" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"xd" = ( -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"xm" = ( -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"xw" = ( -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"xD" = ( -/obj/structure/stone_tile/cracked, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"yu" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 1 - }, -/obj/structure/stone_tile/block, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"yZ" = ( -/obj/structure/stone_tile{ - dir = 4 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"zg" = ( -/obj/machinery/light/small/directional/south, -/obj/effect/baseturf_helper/virtual_domain, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/virtual_domain/powered) -"zo" = ( -/obj/effect/turf_decal/mining/survival, -/turf/closed/wall/mineral/titanium/survival/pod, -/area/lavaland/surface/outdoors/virtual_domain) -"zW" = ( -/obj/structure/stone_tile/surrounding_tile{ - dir = 8 - }, -/obj/structure/stone_tile/surrounding_tile{ - dir = 4 - }, -/obj/structure/stone_tile/surrounding_tile, -/obj/structure/stone_tile/center/cracked, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Ah" = ( -/obj/effect/baseturf_helper/virtual_domain, -/turf/closed/indestructible/binary, -/area/lavaland/surface/outdoors/virtual_domain) -"Aj" = ( -/obj/structure/marker_beacon/burgundy, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Ak" = ( -/obj/structure/stone_tile/surrounding_tile{ - dir = 8 - }, -/obj/structure/stone_tile/surrounding_tile, -/obj/structure/stone_tile/center/cracked, -/obj/structure/stone_tile/surrounding_tile/cracked{ - dir = 4 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"As" = ( -/obj/structure/marker_beacon/cerulean, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"AY" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Bo" = ( -/obj/structure/marker_beacon/indigo, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"BO" = ( -/turf/template_noop, -/area/virtual_domain/safehouse) -"CX" = ( -/obj/effect/decal/cleanable/blood/drip, -/obj/effect/decal/cleanable/blood/footprints{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Dm" = ( -/turf/closed/mineral/random/volcanic, -/area/lavaland/surface/outdoors/virtual_domain) -"DP" = ( -/obj/structure/stone_tile/surrounding_tile{ - dir = 4 - }, -/obj/structure/stone_tile/surrounding_tile{ - dir = 8 - }, -/obj/structure/stone_tile/surrounding_tile/cracked{ - dir = 1 - }, -/obj/structure/stone_tile/center, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Ek" = ( -/obj/structure/stone_tile/block, -/obj/structure/stone_tile/block/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Ep" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"Ez" = ( -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 8 - }, -/obj/structure/stone_tile/cracked, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"EC" = ( -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 1 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Fg" = ( -/obj/structure/stone_tile/surrounding/cracked{ - dir = 6 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Fp" = ( -/obj/effect/baseturf_helper/virtual_domain, -/turf/template_noop, -/area/virtual_domain/safehouse) -"Fq" = ( -/obj/structure/marker_beacon/fuchsia, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"FV" = ( -/obj/structure/stone_tile/block, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Gj" = ( -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Gn" = ( -/turf/closed/indestructible/riveted/boss/see_through, -/area/lavaland/surface/outdoors/virtual_domain) -"Go" = ( -/obj/structure/stone_tile/block{ - dir = 8 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 1 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"GH" = ( -/obj/structure/fans, -/turf/open/floor/pod/dark, -/area/lavaland/surface/outdoors/virtual_domain) -"GM" = ( -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Hi" = ( -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Hu" = ( -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"Hw" = ( -/obj/structure/stone_tile/surrounding_tile, -/obj/structure/stone_tile/surrounding_tile{ - dir = 1 - }, -/obj/structure/stone_tile/center/cracked, -/obj/structure/stone_tile/surrounding_tile/cracked{ - dir = 8 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"HK" = ( -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 8 - }, -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"HQ" = ( -/obj/structure/stone_tile/block/cracked, -/obj/structure/stone_tile/block{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"HZ" = ( -/obj/structure/stone_tile{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Ii" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Io" = ( -/obj/structure/marker_beacon/jade, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Ip" = ( -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"IB" = ( -/obj/structure/stone_tile, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"IG" = ( -/obj/structure/stone_tile{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"IL" = ( -/obj/structure/stone_tile/surrounding, -/obj/structure/stone_tile/center/cracked, -/mob/living/simple_animal/hostile/megafauna/legion/virtual_domain, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"IQ" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Jc" = ( -/obj/structure/stone_tile/slab, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Jp" = ( -/obj/structure/stone_tile/block/cracked, -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Jt" = ( -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/obj/structure/stone_tile, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Jw" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"JD" = ( -/obj/structure/fluff/drake_statue, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"KG" = ( -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Le" = ( -/obj/structure/stone_tile, -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Lx" = ( -/obj/effect/decal/cleanable/blood/footprints{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"LH" = ( -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/obj/structure/stone_tile/block{ - dir = 8 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Ml" = ( -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Mm" = ( -/obj/structure/stone_tile/surrounding_tile, -/obj/structure/stone_tile/surrounding_tile{ - dir = 4 - }, -/obj/structure/stone_tile/center/cracked, -/obj/structure/stone_tile/surrounding_tile/cracked{ - dir = 1 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Mo" = ( -/obj/structure/stone_tile/block/cracked, -/obj/structure/stone_tile/block/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"MH" = ( -/obj/structure/stone_tile/cracked, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"MP" = ( -/obj/structure/stone_tile/block{ - dir = 8 - }, -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"MW" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Nl" = ( -/obj/structure/stone_tile/surrounding_tile{ - dir = 4 - }, -/obj/structure/stone_tile/surrounding_tile{ - dir = 1 - }, -/obj/structure/stone_tile/surrounding_tile{ - dir = 8 - }, -/obj/structure/stone_tile/center, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"Ot" = ( -/obj/structure/stone_tile/surrounding_tile{ - dir = 4 - }, -/obj/structure/stone_tile/surrounding_tile{ - dir = 1 - }, -/obj/structure/stone_tile/surrounding_tile{ - dir = 8 - }, -/obj/structure/stone_tile/center, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Pv" = ( -/obj/effect/turf_decal/mining/survival{ - dir = 4 - }, -/turf/closed/wall/mineral/titanium/survival/pod, -/area/lavaland/surface/outdoors/virtual_domain) -"Px" = ( -/obj/structure/stone_tile{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"PO" = ( -/obj/structure/stone_tile/block{ - dir = 8 - }, -/obj/structure/stone_tile/block{ - dir = 4 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"Qi" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/obj/structure/stone_tile/cracked, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Qx" = ( -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/marker_beacon/burgundy, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"QD" = ( -/obj/item/pickaxe, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/pod/dark, -/area/lavaland/surface/outdoors/virtual_domain) -"RC" = ( -/obj/effect/turf_decal/mining/survival{ - dir = 1 - }, -/turf/closed/wall/mineral/titanium/survival/pod, -/area/lavaland/surface/outdoors/virtual_domain) -"RV" = ( -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"So" = ( -/obj/structure/stone_tile/cracked, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Sw" = ( -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"SI" = ( -/obj/effect/turf_decal/mining, -/turf/closed/wall/mineral/titanium/survival/pod, -/area/lavaland/surface/outdoors/virtual_domain) -"SJ" = ( -/obj/structure/stone_tile/slab/cracked, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"SX" = ( -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Ti" = ( -/turf/closed/mineral/random/high_chance/volcanic, -/area/lavaland/surface/outdoors/virtual_domain) -"Tm" = ( -/obj/structure/bed/pod, -/obj/item/bedsheet/black, -/obj/structure/tubes, -/obj/machinery/light/small/broken/directional/east, -/turf/open/floor/pod/dark, -/area/lavaland/surface/outdoors/virtual_domain) -"TC" = ( -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"TJ" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Ud" = ( -/obj/machinery/light/small/directional/north, -/obj/effect/baseturf_helper/virtual_domain, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/virtual_domain/powered) -"UD" = ( -/obj/structure/stone_tile/surrounding_tile{ - dir = 1 - }, -/obj/structure/stone_tile/surrounding_tile, -/obj/structure/stone_tile/surrounding_tile{ - dir = 4 - }, -/obj/structure/stone_tile/center/cracked, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"UM" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Vc" = ( -/obj/structure/tubes, -/obj/item/crowbar, -/obj/effect/decal/cleanable/blood/drip, -/turf/open/floor/pod/dark, -/area/lavaland/surface/outdoors/virtual_domain) -"VI" = ( -/obj/structure/stone_tile/surrounding_tile{ - dir = 1 - }, -/obj/structure/stone_tile/surrounding_tile/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/surrounding_tile, -/obj/structure/stone_tile/center, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"Wa" = ( -/obj/structure/stone_tile/surrounding_tile{ - dir = 4 - }, -/obj/structure/stone_tile/surrounding_tile/cracked{ - dir = 1 - }, -/obj/structure/stone_tile/surrounding_tile{ - dir = 8 - }, -/obj/structure/stone_tile/center/cracked, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Wm" = ( -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"WM" = ( -/obj/structure/stone_tile/block, -/obj/structure/stone_tile/cracked{ - dir = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"WR" = ( -/obj/structure/stone_tile/block, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"WS" = ( -/obj/item/gps/computer, -/obj/structure/tubes, -/turf/open/floor/pod/dark, -/area/lavaland/surface/outdoors/virtual_domain) -"Xb" = ( -/obj/structure/marker_beacon/yellow, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Xn" = ( -/obj/structure/stone_tile, -/obj/structure/stone_tile/cracked{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Xo" = ( -/obj/structure/stone_tile/block, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Xv" = ( -/obj/structure/stone_tile{ - dir = 1 - }, -/obj/structure/stone_tile/cracked, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"XO" = ( -/obj/effect/turf_decal/mining/survival{ - dir = 8 - }, -/turf/closed/wall/mineral/titanium/survival/pod, -/area/lavaland/surface/outdoors/virtual_domain) -"Yu" = ( -/obj/structure/stone_tile/block{ - dir = 4 - }, -/obj/structure/stone_tile/block{ - dir = 8 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"YN" = ( -/obj/structure/stone_tile/block/cracked, -/obj/structure/stone_tile/block/cracked{ - dir = 1 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"YV" = ( -/obj/structure/stone_tile{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Zc" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 4 - }, -/obj/structure/stone_tile/block{ - dir = 8 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"Zh" = ( -/obj/structure/marker_beacon/purple, -/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, -/area/lavaland/surface/outdoors/virtual_domain) -"Zj" = ( -/obj/structure/stone_tile/block/cracked{ - dir = 8 - }, -/obj/structure/stone_tile/block{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"Zq" = ( -/obj/structure/stone_tile/block{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 4 - }, -/obj/structure/stone_tile{ - dir = 8 - }, -/turf/open/indestructible/boss, -/area/lavaland/surface/outdoors/virtual_domain) -"Zu" = ( -/obj/machinery/smartfridge/survival_pod{ - desc = "A heated storage unit. This one's seen better days."; - name = "dusty survival pod storage" - }, -/turf/open/floor/pod/dark, -/area/lavaland/surface/outdoors/virtual_domain) -"ZM" = ( -/obj/structure/stone_tile/cracked{ - dir = 4 - }, -/obj/structure/stone_tile, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors/virtual_domain) -"ZN" = ( -/obj/structure/table/survival_pod, -/obj/item/knife/combat/survival, -/turf/open/floor/pod/dark, -/area/lavaland/surface/outdoors/virtual_domain) - -(1,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -Ah -"} -(2,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ox -"} -(3,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -ib -nu -nu -ib -ib -ib -ib -nu -nu -nu -nu -nu -nu -nu -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ib -nu -nu -nu -nu -nu -nu -ib -ib -nu -nu -ib -ox -"} -(4,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(5,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(6,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -wq -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(7,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ox -"} -(8,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -ib -nu -nu -nu -nu -nu -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -rt -nu -nu -ib -ib -ox -"} -(9,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -ib -nu -nu -nu -nu -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ox -"} -(10,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ib -ib -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ox -"} -(11,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ib -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(12,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -fA -fA -fA -nu -nu -nu -nu -ib -ox -"} -(13,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -ib -nu -fG -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -fA -fA -fA -nu -nu -nu -nu -ib -ox -"} -(14,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -fA -fA -nu -nu -nu -nu -ib -ox -"} -(15,1,1) = {" -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(16,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -nu -nu -nu -nu -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(17,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -Ti -Ti -Ti -Ti -GM -nu -nu -nu -nu -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -Io -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -Xb -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(18,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -et -Ti -GM -GM -GM -nu -nu -nu -nu -GM -GM -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(19,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -GM -nu -nu -nu -nu -nu -nu -nu -nu -GM -GM -GM -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -wq -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(20,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -Ti -nu -nu -nu -nu -nu -nu -nu -nu -GM -GM -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(21,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -Ti -nu -nu -nu -nu -GM -Ti -GM -GM -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -Zh -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(22,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -FV -nu -nu -nu -nu -Ti -Dm -Dm -GM -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(23,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -Ti -GM -GM -GM -Ti -Ti -Dm -Dm -Ti -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(24,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -FV -Ml -Ti -Dm -Dm -Ti -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ox -"} -(25,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -GM -GM -Ti -Dm -Dm -IB -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -GM -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ox -"} -(26,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -GM -GM -GM -GM -GM -GM -fA -fA -fA -fA -RV -fA -fA -fA -fA -fA -fA -Xn -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -As -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ox -"} -(27,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -Ek -Le -be -be -kT -GM -GM -GM -GM -fA -fA -xm -fA -fA -fA -GM -ZM -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(28,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -dr -KG -mz -KG -KG -jt -GM -GM -GM -GM -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -HZ -nu -bu -nu -nu -nu -MH -nu -nu -lz -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -nu -nu -ib -ox -"} -(29,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -bd -mG -Hw -hU -Mm -lO -et -GM -tk -fA -fA -fA -fA -ak -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -YV -nu -nu -So -nu -nu -nu -nu -nu -nu -bu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -nu -nu -ib -ox -"} -(30,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -Ez -WR -JD -rU -KG -dm -GM -GM -fA -Hi -fA -fA -fA -ll -fA -fA -Wm -fA -fA -YV -qs -MH -nu -nu -nu -ny -ca -oS -nu -nu -Qx -nu -nu -hx -nu -nu -nu -nu -nu -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -nu -nu -ib -ox -"} -(31,1,1) = {" -ox -kg -kg -kg -Hu -Zq -wy -Zq -lT -kg -kg -Gn -Gn -KG -Ak -nv -Ot -mG -hw -kg -kg -Wm -fA -fA -fA -fA -fA -fA -fA -fA -fA -ak -nu -nu -qs -nu -nu -TC -nu -YV -nu -ny -nu -oS -nu -nu -nu -SX -nu -nu -nu -zg -BO -BO -BO -BO -BO -og -Ud -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -nu -nu -ib -ox -"} -(32,1,1) = {" -ox -kg -kg -Gn -VI -xw -gQ -ka -iR -kg -kg -Gn -Gn -sz -KG -KG -KG -KG -mz -kg -kZ -kZ -sd -kZ -lC -kZ -TJ -UM -kZ -IQ -UM -UM -AY -nu -nI -nu -nu -nu -nu -oS -nu -nu -nu -nu -nu -qs -nu -nu -nu -nu -nu -nu -BO -BO -BO -BO -BO -BO -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -nu -nu -ib -ox -"} -(33,1,1) = {" -ox -PO -PO -gk -PO -Zc -IL -Yu -SJ -Yu -Yu -Yu -ob -dL -uK -MP -uK -uK -dL -Jc -Mo -eJ -Mo -hc -yu -eJ -Fg -eJ -YN -tF -Mo -Zj -HQ -qo -Jp -nu -aR -nu -TC -nu -YV -nu -nu -oS -nu -nu -ny -Sw -nu -nu -nu -nu -BO -BO -BO -BO -BO -BO -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -Io -ib -ib -nu -nu -ib -ox -"} -(34,1,1) = {" -ox -kg -kg -Gn -Nl -gh -jw -lT -oo -kg -kg -Gn -Gn -Wa -KG -xd -Ez -mz -HK -kg -ie -Jw -Jw -jk -Jw -jk -dn -Jw -Jw -LH -Ii -Qi -aI -nu -Xo -nu -nu -YV -Sw -nu -nu -nu -sA -nu -Gj -nu -nu -HZ -nu -YV -nu -nu -BO -BO -BO -BO -BO -BO -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -nu -nu -ib -ox -"} -(35,1,1) = {" -ox -kg -kg -kg -Hu -Ep -iV -Go -Ip -kg -kg -Gn -Gn -lO -nO -hU -UD -KG -dm -kg -kg -ll -fA -fA -fA -ak -fA -fA -fA -fA -ll -fA -nu -nu -ny -nu -nu -Aj -HZ -nu -ew -nu -nu -bu -nu -nu -nu -nu -nu -Aj -nu -nu -BO -BO -BO -BO -BO -BO -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -nu -nu -ib -ox -"} -(36,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -KG -WR -iP -rU -Ez -cf -GM -GM -fA -fA -yZ -vf -ll -fA -fA -fA -ak -fA -fA -oS -ny -qs -YV -qs -nu -nu -nu -nu -nu -nu -Sw -nu -qs -oS -nu -nu -Sw -nu -nu -BO -BO -BO -BO -BO -BO -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -nu -nu -ib -ox -"} -(37,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -bd -xd -zW -nv -DP -KG -FV -GM -GM -fA -fA -fA -GM -Px -fA -IG -GM -Hi -fA -fA -nu -nu -nu -nu -TC -nu -ah -nu -nu -nm -nu -nu -nu -nu -nu -nu -sk -nu -nu -zg -BO -BO -BO -BO -BO -Fp -Ud -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -nu -nu -ib -ox -"} -(38,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -bd -KG -KG -KG -lO -Jc -GM -GM -GM -fA -fA -fA -fA -fA -fA -GM -Jt -fA -fA -fA -nu -TC -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(39,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -Ek -KG -lO -MW -pP -GM -GM -GM -GM -fA -fA -fA -fA -fA -fA -fA -xD -fA -fA -fA -oS -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(40,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -IB -nu -nu -nu -nu -GM -RV -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(41,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -GM -nu -nu -Sw -Xv -GM -fA -fA -fA -fA -fA -fA -fA -fA -fA -GM -GM -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(42,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -GM -nu -nu -nu -ny -GM -fA -fA -fA -fA -fA -fA -fA -fA -fA -EC -GM -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -Bo -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ox -"} -(43,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -WM -GM -Px -ny -nu -nu -nu -nu -nu -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ox -"} -(44,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -GM -GM -GM -nu -nu -nu -nu -nu -nu -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(45,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -GM -GM -GM -nu -nu -nu -nu -nu -nu -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(46,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -Ti -GM -GM -nu -nu -nu -nu -nu -nu -fA -fA -ak -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -wq -nu -nu -nu -nu -nu -nu -nu -nu -nu -fA -ib -ox -"} -(47,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -Ti -GM -nu -nu -nu -nu -nu -nu -fA -fA -fA -xD -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -fA -fA -ib -ox -"} -(48,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -Ti -GM -nu -nu -nu -nu -nu -nu -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -fA -fA -ib -ox -"} -(49,1,1) = {" -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -Ti -GM -nu -nu -nu -nu -nu -nu -fA -fA -fA -GM -fA -fA -fA -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -Fq -nu -ib -ib -ib -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -fA -ib -ox -"} -(50,1,1) = {" -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -kg -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -rt -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(51,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -dQ -dQ -XO -dQ -dQ -GM -nu -nu -nu -ib -ox -"} -(52,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -Fq -nu -nu -nu -nu -nu -nu -nu -nu -nu -dQ -GH -jN -ZN -zo -GM -nu -nu -nu -ib -ox -"} -(53,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -RC -Zu -QD -bt -qW -CX -nu -nu -nu -ib -ox -"} -(54,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -dQ -WS -Tm -Vc -SI -Lx -nu -nu -nu -ib -ox -"} -(55,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -dQ -dQ -Pv -dQ -dQ -Lx -nu -nu -nu -ib -ox -"} -(56,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -ib -nu -nu -nu -fA -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -GM -GM -GM -GM -dx -gK -nu -nu -nu -ib -ox -"} -(57,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -Io -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(58,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ox -"} -(59,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -fA -fA -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -ox -"} -(60,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -fA -fA -fA -fA -nu -nu -nu -nu -nu -nu -Xb -nu -nu -nu -ib -ox -"} -(61,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -nu -nu -ib -ox -"} -(62,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -nu -ib -ox -"} -(63,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -ib -nu -nu -nu -ib -ib -ib -nu -nu -nu -nu -nu -ib -ib -nu -nu -nu -nu -ib -ib -ib -nu -nu -nu -nu -nu -nu -nu -nu -ib -ib -nu -nu -nu -nu -ib -ib -ox -"} -(64,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ib -ox -"} -(65,1,1) = {" -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -ox -"} diff --git a/_maps/virtual_domains/pipedream.dmm b/_maps/virtual_domains/pipedream.dmm index 44bd845477a18..779af98c98813 100644 --- a/_maps/virtual_domains/pipedream.dmm +++ b/_maps/virtual_domains/pipedream.dmm @@ -4,13 +4,13 @@ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "aw" = ( /obj/structure/disposalpipe/sorting/mail/flip{ dir = 1 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "ax" = ( /obj/effect/turf_decal/tile/yellow/fourcorners, /obj/structure/frame/computer{ @@ -21,24 +21,24 @@ icon_state = "medium" }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "aK" = ( /turf/open/space/basic, -/area/space) +/area/virtual_domain) "aL" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "bq" = ( /obj/machinery/light/small/red/dim{ dir = 1 }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "bs" = ( /turf/open/floor/carpet/orange, -/area/virtual_domain/powered) +/area/virtual_domain) "bw" = ( /obj/structure/disposalpipe/broken{ dir = 1 @@ -46,18 +46,18 @@ /obj/effect/decal/cleanable/dirt/dust, /obj/structure/closet/crate/preopen, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "bx" = ( /obj/structure/frame/computer, /obj/item/shard, /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-12" }, -/area/virtual_domain/powered) +/area/virtual_domain) "bA" = ( /obj/structure/chair/plastic, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "bG" = ( /obj/structure/lattice/catwalk{ name = "industrial lift" @@ -65,7 +65,7 @@ /obj/structure/closet/crate/preopen, /obj/structure/railing, /turf/open/chasm, -/area/virtual_domain/powered) +/area/virtual_domain) "bS" = ( /obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ dir = 1 @@ -80,7 +80,7 @@ pixel_y = -2 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "cw" = ( /obj/effect/turf_decal/trimline/yellow/warning{ dir = 9 @@ -89,7 +89,7 @@ dir = 1 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "cB" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 10 @@ -99,18 +99,18 @@ }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "cF" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 9 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "dx" = ( /obj/effect/turf_decal/trimline/yellow/line, /obj/item/shard, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "dz" = ( /obj/machinery/light/broken, /obj/effect/decal/cleanable/dirt, @@ -119,22 +119,22 @@ dir = 8 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "dA" = ( /obj/machinery/light/dim{ dir = 4 }, /obj/structure/disposalpipe/segment, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "dP" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "eg" = ( /turf/closed/wall, -/area/virtual_domain/powered) +/area/virtual_domain) "ei" = ( /obj/machinery/conveyor/auto{ dir = 6; @@ -145,17 +145,17 @@ dir = 5 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "ev" = ( /obj/effect/baseturf_helper/virtual_domain, /turf/template_noop, -/area/virtual_domain/safehouse) +/area/virtual_domain) "eJ" = ( /obj/structure/disposalpipe/sorting{ dir = 2 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "eN" = ( /obj/effect/turf_decal/trimline/yellow/arrow_cw{ dir = 1 @@ -165,42 +165,42 @@ dir = 1 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "eY" = ( /turf/closed/wall/r_wall, -/area/virtual_domain/powered) +/area/virtual_domain) "fe" = ( /obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ dir = 8 }, /obj/structure/table/reinforced, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "fg" = ( /turf/open/floor/iron/stairs/left{ dir = 8 }, -/area/virtual_domain/powered) +/area/virtual_domain) "fj" = ( /obj/structure/closet/crate/preopen, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "fl" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 1 }, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "fw" = ( /obj/structure/door_assembly/door_assembly_eng, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "fK" = ( /obj/structure/chair/stool/bar/directional/west, /turf/open/floor/iron/cafeteria, -/area/virtual_domain/powered) +/area/virtual_domain) "fR" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 8 @@ -210,52 +210,52 @@ }, /obj/structure/sign/poster/official/random/directional/west, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "fZ" = ( /obj/effect/turf_decal/tile/yellow/fourcorners, /obj/structure/chair/office{ dir = 8 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "gc" = ( /obj/structure/disposalpipe/broken, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "gj" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "gs" = ( /obj/machinery/door/airlock/external/glass/ruin, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "gN" = ( /obj/structure/disposalpipe/sorting{ dir = 8 }, /turf/open/floor/catwalk_floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "gV" = ( /obj/effect/turf_decal/trimline/yellow/warning{ dir = 8 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "hg" = ( /obj/effect/turf_decal/caution{ dir = 1 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "hi" = ( /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "hk" = ( /obj/effect/turf_decal/tile/yellow/anticorner/contrasted, /obj/effect/decal/cleanable/dirt/dust, @@ -263,24 +263,24 @@ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "ho" = ( /obj/effect/turf_decal/siding/white{ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "iw" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "iz" = ( /obj/structure/broken_flooring/corner, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "iI" = ( /obj/effect/turf_decal/trimline/yellow/corner{ dir = 8 @@ -288,7 +288,7 @@ /obj/effect/turf_decal/trimline/yellow/corner, /obj/effect/decal/cleanable/blood/drip, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "jv" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 8 @@ -297,53 +297,53 @@ dir = 8 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "jw" = ( /obj/effect/turf_decal/delivery, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "jH" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, /turf/open/floor/catwalk_floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "jQ" = ( /obj/structure/disposalpipe/segment, /obj/machinery/light/small/red/dim{ dir = 1 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "jS" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/corner{ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "jW" = ( /obj/effect/decal/cleanable/generic, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "kh" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "ki" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/landmark/bitrunning/cache_spawn, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "kn" = ( /obj/machinery/light/small/red/dim{ dir = 1 }, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "kJ" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -353,67 +353,64 @@ id = "factorylockdown" }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "kU" = ( /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "lp" = ( /obj/machinery/door/airlock/maintenance, /obj/effect/mapping_helpers/airlock/locked, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "lt" = ( -/obj/structure/disposalpipe/sorting{ - dir = 8 - }, -/mob/living/basic/hivebot/range, +/obj/effect/landmark/bitrunning/mob_segment, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "lx" = ( /obj/machinery/door/poddoor/shutters/indestructible{ dir = 4; id = "factorylockdown" }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "lB" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 5 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "lC" = ( /obj/machinery/door/airlock/glass, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "lI" = ( /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "lN" = ( /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "lW" = ( /obj/structure/disposalpipe/sorting{ dir = 8 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "mh" = ( /obj/structure/broken_flooring/pile{ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "mu" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "mE" = ( /obj/machinery/door/airlock/maintenance, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "mY" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 1 @@ -422,7 +419,7 @@ dir = 1 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "nc" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 1 @@ -432,30 +429,30 @@ }, /obj/structure/sign/poster/official/safety_internals/directional/south, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "nz" = ( /obj/structure/broken_flooring/side/directional/north, /obj/structure/disposalpipe/segment{ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "nD" = ( /obj/structure/disposalpipe/trunk/multiz, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "nL" = ( /obj/effect/turf_decal/tile/dark/half, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "nS" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/disposalpipe/segment{ dir = 5 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "op" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/machinery/light/dim{ @@ -463,62 +460,62 @@ }, /obj/structure/sign/warning/doors/directional/north, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "oN" = ( /obj/machinery/conveyor/auto, /obj/structure/window/reinforced/spawner/directional/west, /obj/structure/window/reinforced/spawner/directional/east, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "oX" = ( /obj/structure/broken_flooring/corner/directional/north, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "pa" = ( /obj/machinery/light/small/red/dim{ dir = 1 }, /turf/open/floor/carpet/orange, -/area/virtual_domain/powered) +/area/virtual_domain) "pb" = ( /obj/structure/broken_flooring/corner{ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "pf" = ( /obj/effect/spawner/structure/window/reinforced, /obj/effect/mapping_helpers/damaged_window, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "pi" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "po" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/closet/crate/maint, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "pv" = ( /obj/structure/broken_flooring/side{ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "pI" = ( /obj/effect/turf_decal/tile/yellow/fourcorners, /obj/machinery/light/small/red/dim{ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "pJ" = ( /obj/structure/broken_flooring/pile{ dir = 1 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "qc" = ( /obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ dir = 8 @@ -526,18 +523,18 @@ /obj/structure/table/reinforced, /obj/effect/spawner/random/bureaucracy/briefcase, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "qk" = ( /obj/structure/disposalpipe/segment{ dir = 10 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "qK" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/structure/sign/warning/secure_area/directional/north, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "qN" = ( /obj/effect/turf_decal/siding/white{ dir = 4 @@ -545,7 +542,7 @@ /obj/effect/mob_spawn/corpse/human/factory, /obj/effect/decal/cleanable/blood/old, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "qT" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -554,13 +551,13 @@ dir = 1 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "qV" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "qW" = ( /obj/machinery/light/dim{ dir = 1 @@ -569,45 +566,44 @@ dir = 1 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "rc" = ( /obj/structure/disposalpipe/segment, /obj/structure/sign/poster/contraband/random/directional/north, /obj/effect/landmark/bitrunning/cache_spawn, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "rz" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 1 }, /obj/machinery/light/small/red/dim, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "rG" = ( /obj/machinery/light/dim, /obj/effect/turf_decal/trimline/yellow/line, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "rJ" = ( /obj/structure/railing, /obj/effect/decal/cleanable/oil, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "rM" = ( /obj/structure/disposalpipe/broken{ dir = 1 }, -/mob/living/basic/hivebot/strong, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "rO" = ( /turf/closed/mineral, -/area/space) +/area/virtual_domain) "sn" = ( /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-38" }, -/area/virtual_domain/powered) +/area/virtual_domain) "sB" = ( /obj/machinery/light/broken{ dir = 8 @@ -617,7 +613,7 @@ dir = 8 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "sW" = ( /obj/effect/decal/cleanable/oil/streak, /obj/effect/turf_decal/trimline/yellow/corner{ @@ -629,39 +625,41 @@ /obj/effect/decal/cleanable/blood/drip, /obj/effect/decal/cleanable/blood/drip, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "tl" = ( /obj/machinery/door/poddoor/shutters/indestructible{ id = "factorylockdown" }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "tr" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "tE" = ( -/obj/structure/disposalpipe/segment, -/mob/living/basic/hivebot/range, -/turf/open/floor/iron, -/area/virtual_domain/powered) +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/landmark/bitrunning/mob_segment, +/turf/open/floor/plating, +/area/virtual_domain) "ud" = ( /obj/effect/decal/cleanable/blood/drip, /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-110" }, -/area/virtual_domain/powered) +/area/virtual_domain) "uk" = ( /obj/effect/spawner/structure/window/reinforced, /obj/effect/decal/cleanable/blood/splatter/over_window, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "um" = ( /obj/machinery/light/dim{ dir = 1 }, /turf/open/floor/iron/cafeteria, -/area/virtual_domain/powered) +/area/virtual_domain) "uv" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -670,29 +668,29 @@ dir = 1 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "uz" = ( /obj/effect/spawner/random/trash/mess, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "uC" = ( /obj/structure/falsewall, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "uF" = ( /obj/structure/disposalpipe/segment, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "uP" = ( /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-55" }, -/area/virtual_domain/powered) +/area/virtual_domain) "uU" = ( /obj/structure/broken_flooring/side, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "vb" = ( /obj/effect/turf_decal/trimline/yellow/line, /obj/effect/turf_decal/trimline/yellow/line{ @@ -700,7 +698,7 @@ }, /obj/machinery/light/broken, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "ve" = ( /obj/machinery/mass_driver/trash{ dir = 1 @@ -709,26 +707,26 @@ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "vA" = ( /obj/structure/closet/crate/maint, /obj/effect/turf_decal/stripes{ dir = 9 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "vL" = ( /obj/effect/decal/cleanable/glass, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "vQ" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "vU" = ( /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "wg" = ( /obj/machinery/light/small/red/dim{ dir = 4 @@ -736,24 +734,24 @@ /obj/effect/decal/cleanable/dirt, /obj/structure/closet/crate/preopen, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "wh" = ( /obj/structure/table/wood, /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-207" }, -/area/virtual_domain/powered) +/area/virtual_domain) "wl" = ( /obj/item/shard, /turf/open/space/basic, -/area/space) +/area/virtual_domain) "wm" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 1 }, /obj/structure/sign/clock/directional/north, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "wq" = ( /obj/structure/table/wood, /obj/machinery/button/door{ @@ -763,7 +761,7 @@ /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-63" }, -/area/virtual_domain/powered) +/area/virtual_domain) "ws" = ( /obj/effect/turf_decal/trimline/yellow/corner{ dir = 1 @@ -772,57 +770,56 @@ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "ww" = ( /obj/effect/turf_decal/stripes{ dir = 8 }, /obj/effect/decal/cleanable/dirt, -/mob/living/basic/hivebot, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "wU" = ( /obj/structure/disposalpipe/segment{ dir = 9 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "wW" = ( /obj/effect/turf_decal/tile/yellow/fourcorners, /obj/structure/disposalpipe/segment, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "xa" = ( /obj/machinery/door/poddoor/shutters/indestructible{ dir = 8; id = "factorylockdown" }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "xj" = ( /obj/structure/railing/corner/end{ dir = 4 }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "xk" = ( /obj/machinery/light/dim{ dir = 4 }, /obj/effect/landmark/bitrunning/cache_spawn, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "xl" = ( /obj/structure/disposalpipe/segment{ dir = 5 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "xA" = ( /obj/effect/decal/cleanable/generic, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "xE" = ( /obj/effect/turf_decal/trimline/yellow/line, /obj/effect/turf_decal/trimline/yellow/line{ @@ -830,11 +827,11 @@ }, /obj/machinery/light/broken, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "xF" = ( /obj/effect/baseturf_helper/virtual_domain, /turf/closed/indestructible/binary, -/area/virtual_domain/powered) +/area/virtual_domain) "xM" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 4 @@ -844,28 +841,28 @@ name = "cat bed" }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "xT" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "yB" = ( /obj/machinery/door/airlock/maintenance, /obj/effect/mapping_helpers/airlock/welded, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "yM" = ( /turf/closed/indestructible/fakedoor{ name = "Stairwell Access" }, -/area/virtual_domain/powered) +/area/virtual_domain) "yQ" = ( /turf/template_noop, /area/template_noop) "yX" = ( /obj/structure/fans/tiny, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "zp" = ( /obj/structure/chair/sofa/corp/right{ dir = 1 @@ -873,13 +870,13 @@ /obj/effect/decal/cleanable/dirt, /obj/machinery/light/broken, /turf/open/floor/carpet/orange, -/area/virtual_domain/powered) +/area/virtual_domain) "zB" = ( /obj/structure/closet/crate/bin, /obj/item/trash/tray, /obj/effect/spawner/random/trash/garbage, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "zE" = ( /obj/structure/disposalpipe/broken{ dir = 1 @@ -888,7 +885,7 @@ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "zO" = ( /obj/effect/turf_decal/siding/white{ dir = 4 @@ -896,30 +893,29 @@ /obj/effect/decal/cleanable/dirt/dust, /obj/machinery/light/broken, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Av" = ( /obj/item/stack/rods/two, /turf/open/space/basic, -/area/space) +/area/virtual_domain) "Aw" = ( /obj/structure/lattice/catwalk{ name = "industrial lift" }, -/mob/living/basic/hivebot/rapid, /turf/open/chasm, -/area/virtual_domain/powered) +/area/virtual_domain) "AJ" = ( /obj/effect/decal/cleanable/generic, /obj/structure/disposalpipe/segment, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "AP" = ( /obj/structure/railing, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "AU" = ( /turf/open/misc/asteroid/airless, -/area/space) +/area/virtual_domain) "Bd" = ( /obj/structure/closet/secure_closet/tac{ req_access = null @@ -928,11 +924,11 @@ /obj/item/ammo_casing/shotgun/buckshot, /obj/item/ammo_casing/shotgun/buckshot, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Bh" = ( /obj/structure/broken_flooring/corner/directional/east, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Bx" = ( /obj/structure/table/reinforced, /obj/machinery/microwave{ @@ -940,11 +936,11 @@ desc = "No longer cooks and boils stuff." }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "BA" = ( /obj/structure/broken_flooring/corner/directional/south, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "BI" = ( /obj/machinery/door/airlock/command/glass{ name = "Quartermaster's Office" @@ -957,28 +953,28 @@ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "BN" = ( /obj/structure/flora/rock/pile/style_random, /turf/open/misc/asteroid/airless, -/area/space) +/area/virtual_domain) "BW" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/trimline/yellow/warning{ dir = 1 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "BX" = ( /obj/effect/decal/cleanable/robot_debris/old, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Ci" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 8 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Ct" = ( /obj/machinery/conveyor/auto{ dir = 6 @@ -989,7 +985,7 @@ /obj/structure/sign/warning/vacuum/directional/north, /obj/structure/window/reinforced/spawner/directional/east, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Cv" = ( /obj/structure/chair/office{ dir = 8 @@ -997,30 +993,26 @@ /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-157" }, -/area/virtual_domain/powered) +/area/virtual_domain) "CA" = ( /obj/structure/disposalpipe/segment, /obj/structure/broken_flooring/side{ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "CQ" = ( /obj/effect/spawner/random/trash/botanical_waste, /obj/item/trash/chips, /obj/structure/closet/secure_closet/freezer/empty/open, /turf/open/floor/iron, -/area/virtual_domain/powered) -"CR" = ( -/obj/structure/flora/rock/pile/style_random, -/turf/open/misc/asteroid/airless, -/area/virtual_domain/powered) +/area/virtual_domain) "CX" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 1 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Dr" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -1029,37 +1021,37 @@ dir = 8 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "DA" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/catwalk_floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "DE" = ( /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "DP" = ( /obj/structure/table/reinforced, /obj/effect/spawner/random/food_or_drink/snack, /turf/open/floor/iron/cafeteria, -/area/virtual_domain/powered) +/area/virtual_domain) "Ex" = ( /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-137" }, -/area/virtual_domain/powered) +/area/virtual_domain) "Ez" = ( /obj/structure/flora/rock/style_random, /turf/open/misc/asteroid/airless, -/area/space) +/area/virtual_domain) "EI" = ( /obj/effect/turf_decal/stripes{ dir = 8 }, /obj/effect/decal/cleanable/oil, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "EJ" = ( /obj/machinery/recycler/deathtrap{ dir = 8 @@ -1069,28 +1061,28 @@ }, /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Fa" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/structure/closet/crate/maint, /obj/effect/turf_decal/delivery, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Ff" = ( /obj/structure/disposalpipe/trunk/multiz{ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Fo" = ( /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/cafeteria, -/area/virtual_domain/powered) +/area/virtual_domain) "Fr" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/structure/closet/crate/preopen, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Fw" = ( /obj/structure/flora/bush/fullgrass/style_random, /obj/structure/flora/rock/pile/style_random, @@ -1098,34 +1090,31 @@ /obj/structure/window/reinforced/spawner/directional/north, /obj/structure/window/reinforced/spawner/directional/west, /turf/open/floor/grass, -/area/virtual_domain/powered) +/area/virtual_domain) "FK" = ( /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/iron, -/area/virtual_domain/powered) -"FO" = ( -/turf/open/misc/asteroid/airless, -/area/virtual_domain/powered) +/area/virtual_domain) "FP" = ( /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-110" }, -/area/virtual_domain/powered) +/area/virtual_domain) "Gb" = ( /obj/effect/turf_decal/stripes{ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Ge" = ( /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-21" }, -/area/virtual_domain/powered) +/area/virtual_domain) "Gh" = ( /obj/machinery/door/airlock/maintenance, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Gi" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 9 @@ -1133,7 +1122,7 @@ /obj/effect/turf_decal/trimline/yellow/corner, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Gs" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 1 @@ -1142,7 +1131,7 @@ dir = 1 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Gy" = ( /obj/machinery/conveyor/auto{ dir = 9; @@ -1152,11 +1141,11 @@ /obj/effect/turf_decal/stripes/line, /obj/structure/window/reinforced/spawner/directional/west, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "GI" = ( /obj/effect/turf_decal/trimline/yellow/arrow_ccw, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "GV" = ( /obj/machinery/light/small/red/dim{ dir = 8 @@ -1166,57 +1155,57 @@ }, /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Hn" = ( /turf/open/floor/iron/cafeteria, -/area/virtual_domain/powered) +/area/virtual_domain) "HI" = ( /obj/structure/broken_flooring/pile/directional/north, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Ib" = ( /obj/structure/chair/sofa/corp/left{ dir = 1 }, /turf/open/floor/carpet/orange, -/area/virtual_domain/powered) +/area/virtual_domain) "Ip" = ( /obj/machinery/door/airlock/engineering/glass, /obj/effect/mapping_helpers/airlock/access/any/away/supply, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Is" = ( /obj/machinery/door/airlock/engineering/glass, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "IF" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "IK" = ( /obj/effect/turf_decal/trimline/yellow/line, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "IZ" = ( /obj/structure/lattice/catwalk{ name = "industrial lift" }, /obj/structure/closet/crate, /turf/open/chasm, -/area/virtual_domain/powered) +/area/virtual_domain) "Jl" = ( /obj/effect/decal/cleanable/blood/old, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Jm" = ( /obj/structure/broken_flooring/pile/directional/north, /obj/machinery/light/dim, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Jn" = ( /obj/effect/turf_decal/stripes{ dir = 4 @@ -1227,63 +1216,62 @@ }, /obj/structure/sign/warning/doors/directional/east, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Jq" = ( /obj/structure/broken_flooring/pile{ dir = 1 }, /obj/structure/sign/poster/contraband/random/directional/west, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "JE" = ( /obj/machinery/light/small/red/dim{ dir = 1 }, /obj/structure/sign/warning/chem_diamond/directional/west, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "JR" = ( /turf/template_noop, -/area/virtual_domain/safehouse) +/area/virtual_domain) "JT" = ( /obj/structure/lattice/catwalk{ name = "industrial lift" }, /obj/effect/spawner/random/trash/grime, /turf/open/chasm, -/area/virtual_domain/powered) +/area/virtual_domain) "Kb" = ( /obj/effect/mob_spawn/corpse/human/factory/guard, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Kt" = ( /obj/structure/disposalpipe/segment{ dir = 6 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "KO" = ( /obj/structure/broken_flooring/side/directional/north, /obj/machinery/light/small/red/dim, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "KX" = ( -/obj/structure/lattice/catwalk{ - name = "industrial lift" - }, -/turf/open/chasm, -/area/virtual_domain/powered) +/obj/structure/disposalpipe/broken, +/obj/effect/landmark/bitrunning/mob_segment, +/turf/open/floor/plating, +/area/virtual_domain) "Ln" = ( /obj/structure/disposalpipe/broken{ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Lp" = ( /obj/effect/turf_decal/trimline/yellow/line, /obj/machinery/light/broken, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "LN" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 4 @@ -1295,7 +1283,7 @@ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "LU" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 6 @@ -1303,12 +1291,13 @@ /obj/effect/turf_decal/trimline/yellow/corner{ dir = 1 }, +/obj/effect/landmark/bitrunning/cache_spawn, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Mc" = ( /obj/effect/turf_decal/trimline/yellow/warning, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Mh" = ( /obj/machinery/conveyor/auto{ dir = 8 @@ -1317,14 +1306,11 @@ dir = 1 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Mi" = ( /obj/effect/mob_spawn/corpse/human/factory, /turf/open/floor/plating, -/area/virtual_domain/powered) -"Mj" = ( -/turf/closed/mineral, -/area/virtual_domain/powered) +/area/virtual_domain) "Mu" = ( /obj/effect/turf_decal/trimline/yellow/corner{ dir = 4 @@ -1333,14 +1319,14 @@ dir = 1 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Mx" = ( /obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ dir = 1 }, /obj/structure/filingcabinet, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "My" = ( /obj/machinery/conveyor/auto{ dir = 1 @@ -1349,12 +1335,12 @@ dir = 8 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "MI" = ( /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-74" }, -/area/virtual_domain/powered) +/area/virtual_domain) "MN" = ( /obj/effect/turf_decal/tile/dark, /obj/effect/decal/cleanable/dirt, @@ -1362,29 +1348,29 @@ dir = 5 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Nc" = ( /obj/structure/chair/plastic{ dir = 8 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Nu" = ( /obj/effect/turf_decal/trimline/yellow/line, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "NW" = ( /obj/effect/decal/cleanable/dirt, /mob/living/basic/hivebot/strong, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Ok" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 1 }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "On" = ( /obj/structure/broken_flooring/side{ dir = 4 @@ -1393,30 +1379,30 @@ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "OJ" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/stripes{ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "OL" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "OQ" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/structure/sign/poster/ripped/directional/west, /turf/open/floor/carpet/orange, -/area/virtual_domain/powered) +/area/virtual_domain) "OR" = ( /obj/machinery/light/broken, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Po" = ( /obj/machinery/light/small/red/dim{ dir = 4 @@ -1425,7 +1411,7 @@ /obj/structure/broken_flooring/corner, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Pr" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 5 @@ -1435,14 +1421,14 @@ }, /obj/structure/sign/poster/official/random/directional/east, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "PH" = ( /obj/structure/railing/corner/end/flip{ dir = 8 }, /obj/structure/disposalpipe/segment, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Qd" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 8 @@ -1454,29 +1440,29 @@ dir = 8 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Qh" = ( /obj/structure/disposalpipe/segment, /obj/machinery/light/broken{ dir = 8 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Qj" = ( /obj/machinery/light/dim{ dir = 8 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Qo" = ( /obj/effect/landmark/bitrunning/safehouse_spawn, /turf/template_noop, -/area/virtual_domain/safehouse) +/area/virtual_domain) "Qr" = ( /turf/closed/indestructible/fakedoor/maintenance{ name = "maintenance access" }, -/area/virtual_domain/powered) +/area/virtual_domain) "Qv" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 4 @@ -1488,7 +1474,7 @@ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Qy" = ( /obj/structure/disposalpipe/trunk{ dir = 8 @@ -1497,39 +1483,39 @@ dir = 1 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "QI" = ( /obj/structure/sign/calendar/directional/north, /obj/effect/spawner/random/trash/garbage, /turf/open/floor/iron/cafeteria, -/area/virtual_domain/powered) +/area/virtual_domain) "QK" = ( /obj/structure/table, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "QN" = ( /obj/structure/disposalpipe/segment{ dir = 9 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "QP" = ( /obj/structure/sign/poster/contraband/random/directional/east, /obj/effect/decal/cleanable/blood/old, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "QW" = ( /obj/machinery/conveyor/auto{ dir = 5 }, /obj/effect/decal/cleanable/cobweb, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Ru" = ( /obj/machinery/door/airlock/external/glass/ruin, /obj/effect/mapping_helpers/airlock/cyclelink_helper, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Ry" = ( /obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ dir = 4 @@ -1539,14 +1525,14 @@ }, /obj/machinery/disposal/bin, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "RJ" = ( /turf/closed/indestructible/binary, -/area/virtual_domain/powered) +/area/virtual_domain) "RK" = ( /obj/effect/decal/cleanable/blood/drip, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "RZ" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 1 @@ -1555,7 +1541,7 @@ dir = 6 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Sg" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 1 @@ -1564,7 +1550,7 @@ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Sl" = ( /obj/effect/turf_decal/trimline/yellow/corner{ dir = 4 @@ -1573,53 +1559,42 @@ dir = 8 }, /turf/open/floor/iron, -/area/virtual_domain/powered) -"SC" = ( -/mob/living/basic/hivebot/strong, -/turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "SR" = ( /obj/effect/turf_decal/trimline/yellow/line, /obj/effect/decal/cleanable/glass, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "SS" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, /turf/closed/mineral, -/area/virtual_domain/powered) +/area/virtual_domain) "SU" = ( /obj/effect/spawner/structure/window, /obj/item/stack/rods/two, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "SZ" = ( /obj/structure/table/reinforced, /obj/effect/spawner/random/food_or_drink/booze, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Te" = ( /obj/effect/decal/cleanable/blood/tracks{ dir = 5 }, /obj/effect/mob_spawn/corpse/human/factory/qm, /turf/open/floor/iron, -/area/virtual_domain/powered) -"Tn" = ( -/obj/structure/broken_flooring/corner{ - dir = 4 - }, -/mob/living/basic/hivebot, -/turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Tp" = ( /obj/machinery/door/poddoor/shutters/indestructible{ dir = 4; id = "factorylockdown" }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Tt" = ( /obj/machinery/conveyor/auto{ dir = 9 @@ -1628,12 +1603,12 @@ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "TH" = ( /obj/structure/broken_flooring/corner/directional/south, /obj/item/ammo_casing/shotgun/buckshot/spent, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Ue" = ( /obj/structure/table/reinforced, /obj/machinery/light/small/red/dim{ @@ -1641,17 +1616,17 @@ }, /obj/structure/sign/poster/official/cleanliness/directional/west, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Uw" = ( /obj/machinery/light/dim{ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "UO" = ( /obj/structure/broken_flooring/side/directional/north, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "UV" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 1 @@ -1660,18 +1635,18 @@ dir = 6 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "UX" = ( /obj/effect/turf_decal/trimline/yellow/line, /obj/machinery/light/small/red/dim, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "UY" = ( /obj/effect/decal/cleanable/blood/tracks{ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Vb" = ( /obj/effect/turf_decal/trimline/yellow/corner{ dir = 4 @@ -1681,7 +1656,7 @@ }, /obj/machinery/light/broken, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Vg" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 1 @@ -1691,60 +1666,60 @@ }, /obj/machinery/light/small/red/dim, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Vh" = ( /obj/structure/table/reinforced, /turf/open/floor/iron/cafeteria, -/area/virtual_domain/powered) +/area/virtual_domain) "Vy" = ( /obj/structure/broken_flooring/singular{ dir = 4 }, /obj/effect/mob_spawn/corpse/human/factory/guard, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "VA" = ( /obj/machinery/light/small/red/dim{ dir = 1 }, /obj/structure/table, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "VJ" = ( /obj/structure/broken_flooring/corner{ dir = 1 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "VL" = ( /obj/structure/sign/warning/secure_area/directional/south, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "VO" = ( /obj/machinery/light/broken{ dir = 1 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Wd" = ( /obj/structure/lattice/catwalk{ name = "industrial lift" }, /obj/structure/railing, /turf/open/chasm, -/area/virtual_domain/powered) +/area/virtual_domain) "Wp" = ( /obj/effect/turf_decal/trimline/yellow/warning{ dir = 1 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "WT" = ( /obj/effect/turf_decal/stripes{ dir = 8 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "WV" = ( /obj/machinery/conveyor/auto{ dir = 10; @@ -1755,32 +1730,32 @@ dir = 6 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Xb" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, /turf/closed/wall, -/area/virtual_domain/powered) +/area/virtual_domain) "Xc" = ( /obj/effect/turf_decal/trimline/yellow/line, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Xm" = ( /obj/item/gun/ballistic/shotgun/lethal, /obj/machinery/light/broken{ dir = 1 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Xo" = ( /obj/machinery/conveyor/auto{ dir = 4 }, /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Xw" = ( /obj/effect/turf_decal/trimline/yellow/line{ dir = 1 @@ -1789,7 +1764,7 @@ dir = 10 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "XL" = ( /obj/effect/turf_decal/trimline/yellow/warning{ dir = 5 @@ -1799,26 +1774,26 @@ }, /obj/structure/sign/warning/vacuum/external/directional/south, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "XN" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/disposalpipe/segment{ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "XO" = ( /obj/effect/turf_decal/delivery, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "XP" = ( /obj/structure/disposalpipe/segment, /obj/structure/railing/corner/end{ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "XQ" = ( /obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ dir = 4 @@ -1827,22 +1802,22 @@ dir = 4 }, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "XR" = ( /obj/effect/turf_decal/trimline/yellow/warning{ dir = 1 }, /obj/structure/disposalpipe/segment, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Yc" = ( /obj/item/gun/ballistic/revolver, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Yl" = ( /obj/structure/broken_flooring/corner/directional/west, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Ym" = ( /mob/living/simple_animal/pet/cat/space, /obj/structure/bed/dogbed{ @@ -1855,61 +1830,61 @@ /obj/machinery/light/small/dim/directional/south, /obj/structure/sign/poster/official/moth_hardhat/directional/west, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Yt" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/disposalpipe/segment{ dir = 4 }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Yz" = ( /obj/structure/disposalpipe/segment, /obj/machinery/door/poddoor/shutters/indestructible{ id = "factorylockdown" }, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "YF" = ( /obj/machinery/light/small/red/dim, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "YL" = ( /obj/effect/turf_decal/tile/yellow/anticorner/contrasted, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "YP" = ( /obj/effect/turf_decal/trimline/yellow/corner{ dir = 1 }, /obj/machinery/light/dim, /turf/open/floor/iron, -/area/virtual_domain/powered) +/area/virtual_domain) "Zb" = ( /obj/effect/decal/cleanable/oil, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "Zg" = ( /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-157" }, -/area/virtual_domain/powered) +/area/virtual_domain) "Zy" = ( /obj/structure/table, /obj/item/flashlight/lantern, /turf/open/floor/plating, -/area/virtual_domain/powered) +/area/virtual_domain) "ZI" = ( /turf/open/floor/carpet/royalblue{ icon_state = "carpet_royalblue-203" }, -/area/virtual_domain/powered) +/area/virtual_domain) "ZP" = ( /obj/structure/railing, /turf/open/floor/iron/stairs/right{ dir = 8 }, -/area/virtual_domain/powered) +/area/virtual_domain) (1,1,1) = {" yQ @@ -1989,8 +1964,8 @@ yQ yQ yQ RJ -Mj -Mj +rO +rO eg eg SS @@ -1998,8 +1973,8 @@ eg eg eg Xb -Mj -Mj +rO +rO RJ yQ yQ @@ -2039,7 +2014,7 @@ yQ yQ yQ RJ -Mj +rO Bx SZ Ue @@ -2049,7 +2024,7 @@ eg OQ bs Ib -Mj +rO RJ RJ RJ @@ -2102,7 +2077,7 @@ zp eY RJ RJ -Mj +rO RJ RJ rO @@ -2150,9 +2125,9 @@ fg ZP Fw eY -Mj -Mj -Mj +rO +rO +rO AU AU AU @@ -2200,7 +2175,7 @@ hi FK eY eY -Mj +rO Ez AU aK @@ -2233,7 +2208,7 @@ yQ RJ eg jQ -lt +lW kU vU lN @@ -2249,8 +2224,8 @@ tr hi Ln eY -Mj -Mj +rO +rO AU AU BN @@ -2284,8 +2259,8 @@ RJ eg uU gj -kU -Tn +lt +pb OR eg RJ @@ -2531,7 +2506,7 @@ kU pv AP IZ -KX +Aw Wd uv DE @@ -2580,14 +2555,14 @@ mu uF xl AP -KX +Aw JT bG -qk +tE DA DA zE -gc +KX mu Yz lW @@ -2630,7 +2605,7 @@ iz jS gj rJ -KX +Aw Aw Wd Ff @@ -2638,7 +2613,7 @@ lN XO gj DE -SC +kU tl qk mu @@ -2664,10 +2639,10 @@ RJ (16,1,1) = {" yQ RJ -Mj -Mj -Mj -Mj +rO +rO +rO +rO RJ eg eg @@ -2714,12 +2689,12 @@ RJ (17,1,1) = {" yQ RJ -Mj +rO BN AU -Mj -Mj -Mj +rO +rO +rO eg QW My @@ -2884,7 +2859,7 @@ eg kn pb kU -kU +lt kU Fa kU @@ -2919,7 +2894,7 @@ aK aK aK Av -CR +BN tr kU ei @@ -2936,7 +2911,7 @@ mu rM gc vQ -tE +vQ mu mu eg @@ -2969,7 +2944,7 @@ aK aK aK aK -FO +AU eg eg wg @@ -2988,7 +2963,7 @@ kU On pi kU -Mj +rO eg wm xA @@ -3019,12 +2994,12 @@ aK aK aK AU -FO -Mj +AU +rO eg eg -Mj -Mj +rO +rO eY eY UO @@ -3035,10 +3010,10 @@ eg eg eg eg -Mj -Mj -Mj -Mj +rO +rO +rO +rO eg RZ vQ @@ -3069,11 +3044,11 @@ aK aK AU Ez -Mj -Mj +rO +rO RJ -Mj -Mj +rO +rO Vy hi eY @@ -3086,7 +3061,7 @@ Qd jv fR cB -Mj +rO RJ RJ eg @@ -3098,10 +3073,10 @@ YL eg bq hi -Mj +rO eY -Mj -Mj +rO +rO AU AU aK @@ -3118,8 +3093,8 @@ aK AU BN AU -Mj -Mj +rO +rO RJ RJ eY @@ -3140,25 +3115,25 @@ eg RJ RJ eg -Mj -Mj +rO +rO eg eg eg eg eg -Mj -Mj +rO +rO RJ RJ -Mj -Mj -Mj +rO +rO +rO RJ RJ -Mj -Mj -Mj +rO +rO +rO RJ "} (26,1,1) = {" @@ -3168,7 +3143,7 @@ RJ RJ RJ rO -Mj +rO RJ RJ RJ @@ -3386,7 +3361,7 @@ LN xM Qv LU -Mj +rO RJ yQ yQ @@ -3434,9 +3409,9 @@ eg eg eg eg -Mj -Mj -Mj +rO +rO +rO RJ yQ yQ @@ -3526,7 +3501,7 @@ yQ yQ yQ RJ -Mj +rO CX hi Nu @@ -3576,7 +3551,7 @@ yQ yQ yQ RJ -Mj +rO CX RJ Lp diff --git a/_maps/virtual_domains/pirates.dmm b/_maps/virtual_domains/pirates.dmm index 9868ab8e9b32e..145b633bed993 100644 --- a/_maps/virtual_domains/pirates.dmm +++ b/_maps/virtual_domains/pirates.dmm @@ -3,13 +3,13 @@ /obj/effect/mapping_helpers/burnt_floor, /obj/effect/decal/cleanable/garbage, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "by" = ( /obj/effect/turf_decal/weather/sand{ dir = 5 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "bz" = ( /obj/structure/flora/bush/grassy{ pixel_y = 8 @@ -18,25 +18,25 @@ pixel_y = -10 }, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "bP" = ( /obj/structure/flora/bush/flowers_br/style_random, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "cl" = ( /obj/structure/flora/rock/style_3, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ct" = ( /obj/structure/closet/cabinet, /obj/item/clothing/head/costume/pirate/armored, /obj/item/clothing/suit/costume/pirate/captain/armored, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/wood/parquet, -/area/virtual_domain/powered) +/area/virtual_domain) "cx" = ( -/turf/closed/indestructible/binary, -/area/virtual_domain/powered) +/turf/template_noop, +/area/virtual_domain/safehouse) "cJ" = ( /obj/item/stack/cannonball/shellball{ pixel_x = 13; @@ -48,7 +48,7 @@ }, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "cQ" = ( /obj/structure/flora/grass/jungle/b{ pixel_x = -15; @@ -59,22 +59,22 @@ pixel_y = -1 }, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "dp" = ( /turf/closed/wall/mineral/wood/nonmetal, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "dA" = ( /obj/structure/bonfire/prelit, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "dQ" = ( /obj/structure/flora/rock/style_4, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "eb" = ( /obj/structure/flora/bush/sparsegrass, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "eD" = ( /obj/structure/flora/coconuts{ pixel_x = 9; @@ -82,38 +82,38 @@ }, /obj/structure/flora/tree/palm/style_2, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "eQ" = ( /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain) "eW" = ( /obj/effect/turf_decal/weather/sand{ dir = 6 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "fx" = ( /obj/structure/fluff/beach_umbrella{ pixel_x = -7; pixel_y = -10 }, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "gk" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/effect/landmark/bitrunning/cache_spawn, /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain) "gw" = ( /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ht" = ( /obj/structure/bookcase/random/fiction, /turf/open/floor/wood/parquet, -/area/virtual_domain/powered) +/area/virtual_domain) "hH" = ( /obj/item/clothing/suit/armor/militia{ pixel_x = -5; @@ -144,18 +144,18 @@ }, /obj/structure/closet/cabinet, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "hM" = ( /obj/structure/closet/crate/goldcrate, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "hW" = ( /obj/structure/chair/comfy/carp{ dir = 1 }, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain) "iM" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -163,13 +163,13 @@ /obj/effect/decal/cleanable/dirt/dust, /mob/living/basic/trooper/pirate/ranged/space, /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain) "iO" = ( /obj/effect/turf_decal/weather/sand{ dir = 4 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "jl" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -188,13 +188,13 @@ pixel_x = -5 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "jz" = ( /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "jB" = ( /obj/effect/turf_decal/weather/sand{ dir = 4 @@ -204,7 +204,7 @@ /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "jC" = ( /obj/structure/table/wood, /obj/effect/turf_decal/siding/wood{ @@ -225,19 +225,19 @@ pixel_y = 7 }, /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain) "jQ" = ( /obj/item/gun/energy/laser/hellgun{ pixel_y = 10 }, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "kg" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "kl" = ( /obj/structure/cannon, /obj/effect/turf_decal/siding/wood, @@ -246,7 +246,7 @@ pixel_x = 8 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "lC" = ( /obj/item/stack/cannonball{ pixel_x = 7; @@ -261,71 +261,71 @@ }, /obj/effect/decal/cleanable/oil/streak, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "me" = ( /obj/effect/turf_decal/siding/wood, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "mw" = ( /obj/structure/flora/grass/jungle/b/style_random{ pixel_x = -13; pixel_y = 18 }, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "mP" = ( /obj/structure/flora/bush/fullgrass, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "nz" = ( /obj/effect/mob_spawn/corpse/human/pirate, /turf/open/misc/beach/coast{ dir = 8 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "nQ" = ( /obj/machinery/loot_locator, /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain) "nS" = ( /obj/structure/flora/rock/pile/jungle/large, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "nX" = ( /obj/effect/decal/cleanable/dirt/dust, /mob/living/basic/trooper/pirate/melee/space, /turf/open/floor/wood/parquet, -/area/virtual_domain/powered) +/area/virtual_domain) "oo" = ( /obj/machinery/smartfridge/drying_rack, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "oU" = ( /turf/open/misc/beach/coast{ dir = 10 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "pq" = ( /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "px" = ( /obj/structure/headpike/bone{ pixel_y = 24 }, /turf/open/misc/beach/coast, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "pP" = ( /turf/open/misc/beach/coast, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "pU" = ( /obj/effect/mob_spawn/corpse/human/pirate, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "qj" = ( /obj/structure/barricade/wooden, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "qm" = ( /obj/effect/turf_decal/siding/wood, /obj/item/melee/sabre{ @@ -335,7 +335,7 @@ /obj/item/gun/energy/laser/retro, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "qx" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -344,13 +344,16 @@ /obj/effect/decal/cleanable/dirt/dust, /mob/living/basic/trooper/pirate/ranged, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "qN" = ( /obj/structure/flora/bush/sunny/style_3{ pixel_y = 22 }, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) +"qQ" = ( +/turf/closed/indestructible/binary, +/area/virtual_domain/fullbright) "qX" = ( /obj/effect/turf_decal/weather/sand{ dir = 9 @@ -363,34 +366,34 @@ /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "sn" = ( /obj/structure/table/wood, /obj/item/book/manual/wiki/ordnance, /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain) "so" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 }, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain) "th" = ( /obj/effect/turf_decal/weather/sand, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "tk" = ( /obj/structure/flora/bush/flowers_pp, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "to" = ( /mob/living/basic/trooper/pirate/melee, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ub" = ( /turf/template_noop, -/area/virtual_domain/safehouse) +/area/virtual_domain/fullbright) "uw" = ( /obj/structure/barricade/sandbags, /obj/effect/turf_decal/weather/sand{ @@ -399,39 +402,39 @@ /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "uM" = ( /obj/structure/flora/bush/stalky{ pixel_y = 13; pixel_x = -8 }, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "uT" = ( /obj/structure/closet/crate/grave, /obj/structure/flora/grass/jungle/b, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "wb" = ( /obj/structure/flora/rock, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "we" = ( /obj/effect/mine/explosive/light, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "xc" = ( /turf/open/misc/beach/coast{ dir = 4 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "xg" = ( /turf/template_noop, /area/template_noop) "xm" = ( /obj/structure/barricade/wooden/crude, /turf/closed/wall/mineral/wood/nonmetal, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "xB" = ( /obj/structure/fermenting_barrel/gunpowder{ pixel_x = -4; @@ -452,33 +455,33 @@ pixel_y = -10 }, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "xC" = ( /obj/effect/turf_decal/weather/dirt{ dir = 1 }, /obj/effect/turf_decal/weather/dirt, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "xI" = ( /obj/structure/flora/rock/pile/style_2, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "yc" = ( /obj/effect/turf_decal/weather/dirt, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ye" = ( /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "yi" = ( /mob/living/basic/trooper/pirate/melee, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "yq" = ( /obj/structure/barricade/sandbags, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "yw" = ( /obj/effect/mapping_helpers/burnt_floor, /mob/living/basic/trooper/pirate/ranged, @@ -486,21 +489,21 @@ /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "yA" = ( /obj/item/bedsheet/rainbow/double, /obj/structure/bed/double, /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain) "zf" = ( /obj/structure/flora/bush/flowers_br/style_random, /obj/structure/flora/bush/ferny, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "zg" = ( /obj/structure/flora/rock/pile/style_3, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "zR" = ( /obj/effect/baseturf_helper/virtual_domain, /turf/template_noop, @@ -509,30 +512,34 @@ /obj/effect/turf_decal/weather/dirt, /obj/effect/turf_decal/weather/dirt, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "AU" = ( /obj/effect/turf_decal/weather/dirt{ dir = 1 }, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "BC" = ( /obj/effect/turf_decal/siding/wood, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) +"BL" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/wall/mineral/wood/nonmetal, +/area/virtual_domain) "BO" = ( /obj/structure/bookcase/random/adult, /obj/effect/decal/cleanable/cobweb, /turf/open/floor/wood/parquet, -/area/virtual_domain/powered) +/area/virtual_domain) "Cc" = ( /obj/structure/flora/tree/palm, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Ct" = ( /turf/open/misc/beach/coast/corner, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Dm" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/structure/table/wood, @@ -546,7 +553,7 @@ /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "DJ" = ( /obj/effect/mapping_helpers/burnt_floor, /obj/structure/bed/maint{ @@ -555,11 +562,11 @@ }, /obj/effect/decal/cleanable/wrapping, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "DL" = ( /obj/structure/flora/bush/sunny, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ED" = ( /obj/effect/turf_decal/siding/wood, /obj/effect/turf_decal/weather/sand{ @@ -569,7 +576,7 @@ dir = 9 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "EZ" = ( /obj/effect/turf_decal/weather/sand{ dir = 9 @@ -577,7 +584,7 @@ /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "FG" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/item/claymore/cutlass, @@ -592,15 +599,15 @@ /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "FT" = ( /turf/closed/mineral/random/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "GF" = ( /obj/effect/turf_decal/weather/dirt, /obj/structure/flora/rock/pile, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "GG" = ( /obj/structure/barricade/sandbags, /obj/effect/turf_decal/weather/sand{ @@ -613,38 +620,38 @@ /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Hp" = ( /obj/effect/turf_decal/siding/wood, /mob/living/basic/trooper/pirate/ranged, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "HY" = ( /turf/open/misc/beach/coast{ dir = 6 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "It" = ( /obj/structure/flora/bush/sparsegrass, /obj/structure/flora/bush/lavendergrass, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Iz" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/structure/bed/maint, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "IF" = ( /obj/effect/turf_decal/weather/dirt{ dir = 4 }, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "IG" = ( /obj/effect/mob_spawn/corpse/human/pirate, /obj/effect/decal/cleanable/blood/gibs/old, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "IM" = ( /obj/effect/turf_decal/weather/sand{ dir = 10 @@ -652,24 +659,24 @@ /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Jo" = ( /obj/effect/landmark/bitrunning/cache_spawn, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Jr" = ( /obj/structure/headpike/bone, /turf/open/misc/beach/coast, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Jv" = ( /obj/effect/turf_decal/siding/wood, /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "JT" = ( /obj/effect/decal/cleanable/ants, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Kb" = ( /obj/structure/railing{ color = "#4C3117"; @@ -680,23 +687,23 @@ dir = 1 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Kl" = ( /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Kw" = ( /obj/machinery/door/airlock/vault{ color = "#825427"; name = "Ye Olde Strong Door" }, /turf/open/floor/wood/parquet, -/area/virtual_domain/powered) +/area/virtual_domain) "KC" = ( /obj/effect/turf_decal/weather/dirt{ dir = 5 }, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "KG" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -712,19 +719,19 @@ pixel_y = -3 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "KQ" = ( /obj/structure/flora/rock/style_2, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Ld" = ( /obj/structure/flora/rock/pile, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Ma" = ( /obj/structure/flora/bush/sparsegrass/style_random, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Mi" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -732,28 +739,28 @@ /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/oil, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "MW" = ( /obj/effect/turf_decal/weather/sand{ dir = 5 }, /obj/effect/decal/cleanable/glass, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Nh" = ( /obj/structure/flora/rock/pile/jungle/style_3{ pixel_x = -15; pixel_y = -4 }, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Nk" = ( /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Nz" = ( /obj/structure/flora/bush/jungle, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "NI" = ( /obj/structure/railing{ color = "#4C3117"; @@ -763,7 +770,7 @@ dir = 9 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ON" = ( /obj/item/kirbyplants/organic/plant21{ pixel_x = -8 @@ -772,11 +779,11 @@ pixel_x = 11 }, /turf/open/floor/wood/parquet, -/area/virtual_domain/powered) +/area/virtual_domain) "OP" = ( /obj/structure/flora/bush/stalky, /turf/open/misc/beach/coast, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Pq" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -788,24 +795,24 @@ pixel_y = 13 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Pz" = ( /obj/structure/table/wood, /mob/living/simple_animal/parrot{ name = "pepper" }, /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain) "PQ" = ( /obj/structure/flora/grass/jungle/b, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Qb" = ( /obj/structure/flora/rock{ pixel_x = 7 }, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Rr" = ( /obj/structure/bed/maint{ pixel_x = -5; @@ -815,18 +822,18 @@ dir = 6 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "RR" = ( /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Sm" = ( /obj/structure/flora/tree/jungle, /obj/structure/flora/bush/fullgrass/style_random, /turf/open/misc/grass, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "St" = ( /obj/structure/table/wood, /obj/item/melee/energy/sword/pirate{ @@ -841,12 +848,12 @@ }, /obj/machinery/light/small/directional/north, /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain) "Tp" = ( /turf/open/misc/beach/coast/corner{ dir = 1 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Tt" = ( /obj/structure/cannon{ dir = 1 @@ -855,7 +862,7 @@ dir = 1 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "TO" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -863,7 +870,7 @@ /obj/machinery/light/small/directional/south, /obj/effect/landmark/bitrunning/cache_spawn, /turf/open/floor/carpet/blue, -/area/virtual_domain/powered) +/area/virtual_domain) "TP" = ( /obj/effect/turf_decal/weather/dirt{ dir = 4 @@ -871,7 +878,7 @@ /turf/open/misc/beach/coast{ dir = 6 }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "TQ" = ( /obj/effect/mapping_helpers/broken_floor, /obj/effect/decal/cleanable/dirt/dust, @@ -882,11 +889,11 @@ /obj/effect/decal/cleanable/cobweb, /obj/item/toy/plush/beeplushie, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Uy" = ( /obj/effect/baseturf_helper/virtual_domain, /turf/closed/indestructible/binary, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "UE" = ( /obj/structure/barricade/sandbags, /obj/effect/turf_decal/weather/sand{ @@ -895,25 +902,28 @@ /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Vg" = ( /obj/effect/mob_spawn/corpse/human/pirate/melee, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Vk" = ( /obj/structure/barricade/sandbags, /obj/effect/turf_decal/weather/sand, /turf/open/floor/wood{ icon_state = "wood_large" }, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) +"Vw" = ( +/turf/closed/wall/mineral/wood/nonmetal, +/area/virtual_domain) "VC" = ( /obj/effect/mob_spawn/corpse/human/damaged, /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "VF" = ( /turf/open/water/beach, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "VX" = ( /obj/effect/mapping_helpers/burnt_floor, /obj/structure/rack{ @@ -925,14 +935,14 @@ pixel_y = 13 }, /turf/open/floor/wood/parquet, -/area/virtual_domain/powered) +/area/virtual_domain) "WM" = ( /obj/structure/flora/rock/pile/jungle/style_2, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "WP" = ( /turf/open/floor/wood/parquet, -/area/virtual_domain/powered) +/area/virtual_domain) "Xn" = ( /obj/effect/landmark/bitrunning/safehouse_spawn, /turf/template_noop, @@ -944,32 +954,32 @@ }, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Yj" = ( /obj/effect/landmark/bitrunning/cache_spawn, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Yk" = ( /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/wood/parquet, -/area/virtual_domain/powered) +/area/virtual_domain) "Yq" = ( /obj/effect/turf_decal/siding/wood{ dir = 10 }, /turf/open/floor/wood, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "Zk" = ( /obj/structure/flora/coconuts{ pixel_x = 12 }, /obj/structure/flora/tree/palm, /turf/open/misc/beach/sand, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) "ZZ" = ( /obj/structure/flora/grass/jungle, /turf/open/misc/dirt/jungle, -/area/virtual_domain/powered) +/area/virtual_domain/fullbright) (1,1,1) = {" xg @@ -986,14 +996,14 @@ xg xg xg xg -cx -cx -cx -cx -cx -cx -cx -cx +qQ +qQ +qQ +qQ +qQ +qQ +qQ +qQ xg xg xg @@ -1029,17 +1039,17 @@ xg xg xg xg -cx -cx +qQ +qQ FT FT FT FT FT FT -cx -cx -cx +qQ +qQ +qQ xg xg xg @@ -1071,9 +1081,9 @@ xg xg xg xg -cx -cx -cx +qQ +qQ +qQ FT FT FT @@ -1083,7 +1093,7 @@ FT FT FT FT -cx +qQ xg xg xg @@ -1114,8 +1124,8 @@ xg xg xg xg -cx -cx +qQ +qQ FT FT FT @@ -1127,7 +1137,7 @@ FT FT FT FT -cx +qQ xg xg xg @@ -1158,7 +1168,7 @@ xg xg xg xg -cx +qQ FT FT FT @@ -1171,7 +1181,7 @@ we FT FT FT -cx +qQ xg xg xg @@ -1200,9 +1210,9 @@ xg xg xg xg -cx -cx -cx +qQ +qQ +qQ FT FT FT @@ -1215,13 +1225,13 @@ Kl Kl FT FT -cx -cx -cx -cx -cx -cx -cx +qQ +qQ +qQ +qQ +qQ +qQ +qQ xg xg xg @@ -1241,10 +1251,10 @@ xg xg xg xg -cx -cx -cx -cx +qQ +qQ +qQ +qQ FT FT FT @@ -1259,13 +1269,13 @@ Cc Kl IG FT -cx -cx +qQ +qQ FT FT FT FT -cx +qQ xg xg xg @@ -1284,8 +1294,8 @@ xg xg xg xg -cx -cx +qQ +qQ FT FT FT @@ -1303,13 +1313,13 @@ Kl Kl Kl we -cx -cx +qQ +qQ FT FT FT FT -cx +qQ xg xg xg @@ -1327,8 +1337,8 @@ xg xg xg xg -cx -cx +qQ +qQ FT dp dp @@ -1353,10 +1363,10 @@ VF VF VF VF -cx -cx -cx -cx +qQ +qQ +qQ +qQ xg xg xg @@ -1371,7 +1381,7 @@ xg xg xg xg -cx +qQ FT dp dp @@ -1400,9 +1410,9 @@ VF VF VF dp -cx -cx -cx +qQ +qQ +qQ xg xg xg @@ -1414,8 +1424,8 @@ xg (11,1,1) = {" xg xg -cx -cx +qQ +qQ FT dp TQ @@ -1446,19 +1456,19 @@ VF dp KG pq -cx -cx -cx -cx -cx -cx -cx +qQ +qQ +qQ +qQ +qQ +qQ +qQ Uy "} (12,1,1) = {" xg xg -cx +qQ FT FT dp @@ -1491,18 +1501,18 @@ dp jl pq BC -ub -ub -ub -ub -ub -Xn cx -"} -(13,1,1) = {" cx cx cx +cx +Xn +qQ +"} +(13,1,1) = {" +qQ +qQ +qQ FT FT FT @@ -1535,22 +1545,22 @@ dp hH Nk qm -ub -ub -ub -ub -ub -ub cx +cx +cx +cx +cx +cx +qQ "} (14,1,1) = {" -cx -dp -dp -dp -dp -dp -dp +qQ +Vw +Vw +Vw +Vw +Vw +BL oo Kl Kl @@ -1579,22 +1589,22 @@ dp dp Nk Jv -ub -ub -ub -ub -ub -ub cx +cx +cx +cx +cx +cx +qQ "} (15,1,1) = {" -cx -dp +qQ +Vw BO ht VX ct -dp +Vw yi Kl dA @@ -1623,17 +1633,17 @@ VF VF VF me -ub -ub -ub -ub -ub -ub cx +cx +cx +cx +cx +cx +qQ "} (16,1,1) = {" -cx -dp +qQ +Vw ON WP nX @@ -1667,22 +1677,22 @@ VF VF VF VF -ub -ub -ub -ub -ub -ub cx +cx +cx +cx +cx +cx +qQ "} (17,1,1) = {" -cx -dp +qQ +Vw jC iM so TO -dp +Vw Kl Kl EZ @@ -1711,22 +1721,22 @@ VF VF VF VF -ub -ub -ub -ub -ub -ub cx +cx +cx +cx +cx +cx +qQ "} (18,1,1) = {" -cx -dp +qQ +Vw sn hW eQ gk -dp +Vw dp qX gw @@ -1755,22 +1765,22 @@ VF VF me VF -ub -ub -ub -ub -ub -zR cx +cx +cx +cx +cx +zR +qQ "} (19,1,1) = {" -cx -dp +qQ +Vw St Pz nQ yA -dp +Vw dp Dm jz @@ -1804,17 +1814,17 @@ VF VF VF VF -cx -cx +qQ +qQ "} (20,1,1) = {" -cx -dp -dp -dp -dp -dp -dp +qQ +Vw +Vw +Vw +Vw +Vw +Vw xm FG RR @@ -1848,13 +1858,13 @@ VF VF VF VF -cx +qQ xg "} (21,1,1) = {" -cx -cx -cx +qQ +qQ +qQ FT FT Kl @@ -1892,13 +1902,13 @@ VF VF VF VF -cx +qQ xg "} (22,1,1) = {" xg xg -cx +qQ FT FT fx @@ -1936,13 +1946,13 @@ VF VF VF VF -cx +qQ xg "} (23,1,1) = {" xg xg -cx +qQ FT FT FT @@ -1980,13 +1990,13 @@ VF VF FT FT -cx +qQ xg "} (24,1,1) = {" xg xg -cx +qQ FT FT FT @@ -2024,14 +2034,14 @@ VF VF FT FT -cx +qQ xg "} (25,1,1) = {" xg xg -cx -cx +qQ +qQ FT FT FT @@ -2068,16 +2078,16 @@ VF FT FT FT -cx +qQ xg "} (26,1,1) = {" xg xg xg -cx -cx -cx +qQ +qQ +qQ FT FT FT @@ -2093,8 +2103,8 @@ TP VF FT FT -cx -cx +qQ +qQ VF VF VF @@ -2107,12 +2117,12 @@ VF VF VF VF -cx +qQ FT FT FT FT -cx +qQ xg "} (27,1,1) = {" @@ -2120,8 +2130,8 @@ xg xg xg xg -xg -cx +ub +qQ FT FT FT @@ -2138,8 +2148,8 @@ AU FT FT FT -cx -cx +qQ +qQ VF VF VF @@ -2150,13 +2160,13 @@ VF VF VF VF -cx -cx +qQ +qQ FT FT FT -cx -cx +qQ +qQ xg "} (28,1,1) = {" @@ -2165,8 +2175,8 @@ xg xg xg xg -cx -cx +qQ +qQ FT FT FT @@ -2183,23 +2193,23 @@ FT FT FT FT -cx -cx -cx -cx +qQ +qQ +qQ +qQ VF VF VF VF VF VF -cx -cx -cx -cx -cx -cx -cx +qQ +qQ +qQ +qQ +qQ +qQ +qQ xg xg "} @@ -2210,12 +2220,12 @@ xg xg xg xg -cx -cx -cx -cx -cx -cx +qQ +qQ +qQ +qQ +qQ +qQ FT FT FT @@ -2230,14 +2240,14 @@ FT FT FT FT -cx -cx -cx -cx -cx -cx -cx -cx +qQ +qQ +qQ +qQ +qQ +qQ +qQ +qQ xg xg xg @@ -2258,8 +2268,8 @@ xg xg xg xg -cx -cx +qQ +qQ FT FT FT @@ -2275,8 +2285,8 @@ FT FT FT FT -cx -cx +qQ +qQ xg xg xg @@ -2303,8 +2313,8 @@ xg xg xg xg -cx -cx +qQ +qQ FT FT FT @@ -2320,8 +2330,8 @@ WM FT FT FT -cx -cx +qQ +qQ xg xg xg @@ -2348,8 +2358,8 @@ xg xg xg xg -cx -cx +qQ +qQ FT FT FT @@ -2365,7 +2375,7 @@ hM FT FT FT -cx +qQ xg xg xg @@ -2393,8 +2403,8 @@ xg xg xg xg -cx -cx +qQ +qQ FT FT FT @@ -2409,7 +2419,7 @@ ye hM FT FT -cx +qQ xg xg xg @@ -2438,8 +2448,8 @@ xg xg xg xg -cx -cx +qQ +qQ FT FT FT @@ -2453,7 +2463,7 @@ jQ Jo FT FT -cx +qQ xg xg xg @@ -2483,9 +2493,9 @@ xg xg xg xg -cx -cx -cx +qQ +qQ +qQ FT FT FT @@ -2497,7 +2507,7 @@ FT FT FT FT -cx +qQ xg xg xg @@ -2529,7 +2539,7 @@ xg xg xg xg -cx +qQ FT FT FT @@ -2541,7 +2551,7 @@ FT FT FT FT -cx +qQ xg xg xg @@ -2573,19 +2583,19 @@ xg xg xg xg -cx -cx -cx -cx -cx -cx -cx -cx -cx -cx -cx -cx -cx +qQ +qQ +qQ +qQ +qQ +qQ +qQ +qQ +qQ +qQ +qQ +qQ +qQ xg xg xg diff --git a/_maps/virtual_domains/syndicate_assault.dmm b/_maps/virtual_domains/syndicate_assault.dmm index 05014331406e2..9718dc01b3009 100644 --- a/_maps/virtual_domains/syndicate_assault.dmm +++ b/_maps/virtual_domains/syndicate_assault.dmm @@ -5,11 +5,11 @@ /turf/open/floor/plastic, /area/ruin/space/has_grav/powered/virtual_domain) "aw" = ( -/obj/structure/table/reinforced, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, +/obj/effect/landmark/bitrunning/mob_segment, /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/powered/virtual_domain) "aN" = ( @@ -31,28 +31,9 @@ /obj/machinery/recharge_station, /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/powered/virtual_domain) -"aZ" = ( -/obj/structure/chair/comfy/shuttle{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ - dir = 4 - }, -/mob/living/basic/trooper/syndicate/ranged/shotgun/space/stormtrooper, -/turf/open/floor/mineral/plastitanium, -/area/ruin/space/has_grav/powered/virtual_domain) "bh" = ( /turf/open/floor/carpet/royalblack, /area/ruin/space/has_grav/powered/virtual_domain) -"bo" = ( -/obj/structure/chair/comfy/shuttle{ - dir = 1 - }, -/turf/open/floor/mineral/plastitanium, -/area/ruin/space/has_grav/powered/virtual_domain) "bD" = ( /obj/structure/table/reinforced, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -199,12 +180,6 @@ /obj/machinery/light/small/directional/north, /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/powered/virtual_domain) -"fM" = ( -/obj/machinery/computer/crew/syndie{ - dir = 8 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/ruin/space/has_grav/powered/virtual_domain) "fV" = ( /obj/machinery/atmospherics/components/unary/vent_pump, /turf/open/floor/mineral/plastitanium/red, @@ -236,7 +211,7 @@ /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/powered/virtual_domain) "ip" = ( -/mob/living/basic/trooper/syndicate/melee/sword/space/stormtrooper, +/obj/effect/landmark/bitrunning/mob_segment, /turf/open/floor/plastic, /area/ruin/space/has_grav/powered/virtual_domain) "iB" = ( @@ -274,7 +249,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 4 }, -/mob/living/basic/trooper/syndicate/ranged/smg/space/stormtrooper, /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/powered/virtual_domain) "ja" = ( @@ -411,10 +385,6 @@ /obj/structure/cable, /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/powered/virtual_domain) -"oZ" = ( -/mob/living/basic/trooper/syndicate/melee/sword/space/stormtrooper, -/turf/open/floor/carpet/royalblack, -/area/ruin/space/has_grav/powered/virtual_domain) "pl" = ( /obj/machinery/atmospherics/components/tank/air{ dir = 8 @@ -468,6 +438,7 @@ /area/ruin/space/has_grav/powered/virtual_domain) "qY" = ( /obj/machinery/light/small/directional/south, +/obj/effect/landmark/bitrunning/cache_spawn, /turf/open/floor/iron/dark, /area/ruin/space/has_grav/powered/virtual_domain) "rm" = ( @@ -622,12 +593,6 @@ /obj/item/ammo_box/c9mm, /turf/open/floor/mineral/plastitanium/red, /area/ruin/space/has_grav/powered/virtual_domain) -"xZ" = ( -/obj/machinery/computer/camera_advanced/syndie{ - dir = 8 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/ruin/space/has_grav/powered/virtual_domain) "yl" = ( /obj/machinery/door/airlock/grunge{ name = "Captain's Room" @@ -640,10 +605,6 @@ }, /turf/open/floor/mineral/plastitanium/red, /area/ruin/space/has_grav/powered/virtual_domain) -"yD" = ( -/mob/living/basic/trooper/syndicate/ranged/smg/space/stormtrooper, -/turf/open/floor/mineral/plastitanium, -/area/ruin/space/has_grav/powered/virtual_domain) "yJ" = ( /obj/structure/table/reinforced, /obj/machinery/atmospherics/components/unary/vent_scrubber/layer2, @@ -688,13 +649,6 @@ /obj/structure/chair/comfy/shuttle, /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/powered/virtual_domain) -"AN" = ( -/obj/structure/chair/comfy/shuttle{ - dir = 4 - }, -/mob/living/basic/trooper/syndicate/ranged/smg/space/stormtrooper, -/turf/open/floor/mineral/plastitanium, -/area/ruin/space/has_grav/powered/virtual_domain) "Bm" = ( /obj/effect/baseturf_helper/virtual_domain, /turf/closed/indestructible/syndicate, @@ -787,10 +741,6 @@ }, /turf/open/floor/mineral/plastitanium/red, /area/ruin/space/has_grav/powered/virtual_domain) -"EX" = ( -/mob/living/basic/trooper/syndicate/ranged/shotgun/space/stormtrooper, -/turf/open/floor/mineral/plastitanium, -/area/ruin/space/has_grav/powered/virtual_domain) "Fp" = ( /obj/structure/tank_dispenser/oxygen, /turf/open/floor/mineral/plastitanium, @@ -863,6 +813,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 9 }, +/obj/effect/landmark/bitrunning/mob_segment, /turf/open/floor/mineral/plastitanium/red, /area/ruin/space/has_grav/powered/virtual_domain) "Ig" = ( @@ -1009,11 +960,6 @@ /obj/machinery/light/small/directional/south, /turf/open/floor/pod/dark, /area/ruin/space/has_grav/powered/virtual_domain) -"Nt" = ( -/obj/structure/table/reinforced, -/obj/machinery/atmospherics/components/unary/vent_pump, -/turf/open/floor/mineral/plastitanium, -/area/ruin/space/has_grav/powered/virtual_domain) "Of" = ( /obj/structure/closet/crate/secure/gear{ req_access = list("syndicate") @@ -1077,7 +1023,7 @@ /turf/closed/mineral/random, /area/space) "QX" = ( -/mob/living/basic/trooper/syndicate/ranged/space/stormtrooper, +/obj/effect/landmark/bitrunning/mob_segment, /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/powered/virtual_domain) "Ra" = ( @@ -2016,14 +1962,14 @@ ru Sv vD uP -uP +Io Yj vD uP Wy DA +Io uP -QX vD cc ru @@ -2082,9 +2028,9 @@ uP uP lN uP +QX uP -uP -uP +Io hA qx qx @@ -2255,8 +2201,8 @@ sz Kz ru Mc -gD -yD +uP +uP uP rP ru @@ -2305,7 +2251,7 @@ ru sH Kz yl -oZ +bh bh Yk pS @@ -2314,7 +2260,7 @@ Jz vK uP uP -uP +Io sL hy ru @@ -2372,7 +2318,7 @@ pM vK uP uP -EX +QX sL Im ru @@ -2429,7 +2375,7 @@ JN MR ru Sd -gD +uP uP uP gD @@ -2887,7 +2833,7 @@ dw ru rH uP -AN +JA JA iX JA @@ -3002,13 +2948,13 @@ uP uP dd uP -Aa -hD -Nt +uP +uP +Ox aw -hD -hD -bo +uP +uP +uP uP dd uP @@ -3062,9 +3008,9 @@ ru XS uP uP -hD -aZ -hD +uP +FN +uP uP uP Cf @@ -3466,14 +3412,14 @@ ru Kz ru Kz -pz Kz -xZ Kz -fM +pz Kz kI Kz +Kz +Kz ru Mm ru @@ -3531,7 +3477,7 @@ Kz Kz Kz Kz -Kz +dz ru ru ru diff --git a/_maps/virtual_domains/test_only.dmm b/_maps/virtual_domains/test_only.dmm index 22b647188b6e1..1fc9cfba0fd50 100644 --- a/_maps/virtual_domains/test_only.dmm +++ b/_maps/virtual_domains/test_only.dmm @@ -1,15 +1,15 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE "a" = ( /turf/open/floor, -/area/virtual_domain/powered) +/area/virtual_domain) "D" = ( /obj/effect/mob_spawn/corpse/human/miner, /turf/open/floor, -/area/virtual_domain/powered) +/area/virtual_domain) "I" = ( /mob/living/basic/pet/dog/corgi, /turf/open/floor, -/area/virtual_domain/powered) +/area/virtual_domain) "U" = ( /obj/effect/landmark/bitrunning/safehouse_spawn, /turf/open/floor, diff --git a/_maps/virtual_domains/xeno_nest.dmm b/_maps/virtual_domains/xeno_nest.dmm index fcbd7cc116c91..7e16c48a2497f 100644 --- a/_maps/virtual_domains/xeno_nest.dmm +++ b/_maps/virtual_domains/xeno_nest.dmm @@ -24,7 +24,7 @@ /area/ruin/space/has_grav/powered/virtual_domain) "h" = ( /obj/structure/alien/weeds, -/mob/living/simple_animal/hostile/alien/sentinel, +/obj/effect/landmark/bitrunning/mob_segment, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/ruin/space/has_grav/powered/virtual_domain) "i" = ( @@ -106,6 +106,11 @@ /obj/effect/landmark/bitrunning/cache_spawn, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/ruin/space/has_grav/powered/virtual_domain) +"y" = ( +/obj/structure/alien/weeds/node, +/obj/effect/landmark/bitrunning/mob_segment, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) "z" = ( /obj/structure/alien/weeds, /obj/structure/alien/resin/wall, @@ -246,14 +251,6 @@ /obj/structure/alien/egg/burst, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/ruin/space/has_grav/powered/virtual_domain) -"Y" = ( -/obj/structure/alien/weeds, -/obj/effect/decal/cleanable/blood, -/mob/living/simple_animal/hostile/alien/drone{ - plants_off = 1 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/ruin/space/has_grav/powered/virtual_domain) "Z" = ( /obj/structure/alien/weeds, /obj/structure/bed/nest, @@ -477,7 +474,7 @@ a E z e -e +h m K J @@ -518,13 +515,13 @@ a E z W -h +e e e e B o -e +K z E a @@ -564,7 +561,7 @@ z e V e -h +e W z E @@ -683,12 +680,12 @@ E z z e -h e e -h e e +h +e z E a @@ -786,8 +783,8 @@ z z W o -Y -e +B +K z E a @@ -826,7 +823,7 @@ E z I e -V +y e W z @@ -973,7 +970,7 @@ E z e e -p +e z z z @@ -1130,7 +1127,7 @@ E E G t -S +h e z z @@ -1260,7 +1257,7 @@ E E E z -p +e z z E @@ -1383,7 +1380,7 @@ z z T e -e +h V W z @@ -1423,7 +1420,7 @@ E z N f -S +e e W I @@ -1873,8 +1870,8 @@ E E z I -p e +h e e e diff --git a/code/__DEFINES/achievements.dm b/code/__DEFINES/achievements.dm index 4a0299d835ac3..7af89f2673a97 100644 --- a/code/__DEFINES/achievements.dm +++ b/code/__DEFINES/achievements.dm @@ -6,11 +6,6 @@ #define ACHIEVEMENT_DEFAULT "default" #define ACHIEVEMENT_SCORE "score" -///the priority for which awards are orded on [/datum/achievement_data/load_all_achievements()] -#define AWARD_PRIORITY_DEFAULT 100 -///the priority of the achievements score. NO achievement should have a priority equal or lower than this. -#define AWARD_PRIORITY_LAST 0 - /// preferences for the sound played when unlocking an achievement #define CHEEVO_SOUND_TADA "Tada Fanfare" #define CHEEVO_SOUND_JINGLE "Beeps Jingle" @@ -46,7 +41,7 @@ #define MEDAL_VOID_ASCENSION "Void" #define MEDAL_BLADE_ASCENSION "Blade" #define MEDAL_COSMOS_ASCENSION "Cosmos" -#define MEDAL_KNOCK_ASCENSION "Knock" +#define MEDAL_LOCK_ASCENSION "Knock" #define MEDAL_TOOLBOX_SOUL "Toolsoul" #define MEDAL_CHEM_TUT "Beginner Chemist" #define MEDAL_HOT_DAMN "Hot Damn!" diff --git a/code/__DEFINES/ai/ai.dm b/code/__DEFINES/ai/ai.dm index 53cbf117af410..5e0b979b2f8c8 100644 --- a/code/__DEFINES/ai/ai.dm +++ b/code/__DEFINES/ai/ai.dm @@ -1,4 +1,5 @@ #define GET_AI_BEHAVIOR(behavior_type) SSai_behaviors.ai_behaviors[behavior_type] +#define GET_TARGETING_STRATEGY(targeting_type) SSai_behaviors.targeting_strategies[targeting_type] #define HAS_AI_CONTROLLER_TYPE(thing, type) istype(thing?.ai_controller, type) #define AI_STATUS_ON 1 diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index 484b38b0fd16b..91ad49975fe17 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -10,6 +10,12 @@ #define BB_PATH_TO_USE "BB_path_to_use" ///How close a mob must be for us to select it as a target, if that is less than how far we can maintain it as a target #define BB_AGGRO_RANGE "BB_aggro_range" +///are we hungry? determined by the udder compnent +#define BB_CHECK_HUNGRY "BB_check_hungry" +///are we ready to breed? +#define BB_BREED_READY "BB_breed_ready" +///maximum kids we can have +#define BB_MAX_CHILDREN "BB_max_children" /// Store a single or list of emotes at this key #define BB_EMOTE_KEY "BB_emotes" @@ -40,31 +46,33 @@ ///Basic Mob Keys -///Targetting subtrees +///Targeting subtrees #define BB_BASIC_MOB_CURRENT_TARGET "BB_basic_current_target" #define BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION "BB_basic_current_target_hiding_location" -#define BB_TARGETTING_DATUM "targetting_datum" +#define BB_TARGETING_STRATEGY "targeting_strategy" ///some behaviors that check current_target also set this on deep crit mobs #define BB_BASIC_MOB_EXECUTION_TARGET "BB_basic_execution_target" ///Blackboard key for a whitelist typecache of "things we can target while trying to move" -#define BB_OBSTACLE_TARGETTING_WHITELIST "BB_targetting_whitelist" +#define BB_OBSTACLE_TARGETING_WHITELIST "BB_targeting_whitelist" /// Key for the minimum status at which we want to target mobs (does not need to be specified if CONSCIOUS) #define BB_TARGET_MINIMUM_STAT "BB_target_minimum_stat" /// Flag for whether to target only wounded mobs #define BB_TARGET_WOUNDED_ONLY "BB_target_wounded_only" +/// What typepath the holding object targeting strategy should look for +#define BB_TARGET_HELD_ITEM "BB_target_held_item" -/// Blackboard key storing how long your targetting datum has held a particular target +/// Blackboard key storing how long your targeting strategy has held a particular target #define BB_BASIC_MOB_HAS_TARGET_TIME "BB_basic_mob_has_target_time" -///Targetting keys for something to run away from, if you need to store this separately from current target +///Targeting keys for something to run away from, if you need to store this separately from current target #define BB_BASIC_MOB_FLEE_TARGET "BB_basic_flee_target" #define BB_BASIC_MOB_FLEE_TARGET_HIDING_LOCATION "BB_basic_flee_target_hiding_location" -#define BB_FLEE_TARGETTING_DATUM "flee_targetting_datum" +#define BB_FLEE_TARGETING_STRATEGY "flee_targeting_strategy" #define BB_BASIC_MOB_FLEE_DISTANCE "BB_basic_flee_distance" #define DEFAULT_BASIC_FLEE_DISTANCE 9 -/// Generic key for a non-specific targetted action -#define BB_TARGETTED_ACTION "BB_targetted_action" +/// Generic key for a non-specific targeted action +#define BB_TARGETED_ACTION "BB_TARGETED_action" /// Generic key for a non-specific action #define BB_GENERIC_ACTION "BB_generic_action" @@ -115,9 +123,9 @@ ///Range for a MOD AI controller. #define MOD_AI_RANGE 200 -///should we skip the faction check for the targetting datum? +///should we skip the faction check for the targeting strategy? #define BB_ALWAYS_IGNORE_FACTION "BB_always_ignore_factions" -///are we in some kind of temporary state of ignoring factions when targetting? can result in volatile results if multiple behaviours touch this +///are we in some kind of temporary state of ignoring factions when targeting? can result in volatile results if multiple behaviours touch this #define BB_TEMPORARILY_IGNORE_FACTION "BB_temporarily_ignore_factions" ///currently only used by clowns, a list of what can the mob speak randomly diff --git a/code/__DEFINES/ai/carp.dm b/code/__DEFINES/ai/carp.dm index 8286f32620774..459b98ffb0204 100644 --- a/code/__DEFINES/ai/carp.dm +++ b/code/__DEFINES/ai/carp.dm @@ -7,9 +7,9 @@ /// Current target turf in your migration #define BB_CARP_MIGRATION_TARGET "BB_carp_migration_target" -/// Targetting keys for magicarp spells +/// Targeting keys for magicarp spells #define BB_MAGICARP_SPELL_TARGET "BB_magicarp_spell_target" -#define BB_MAGICARP_SPELL_SPECIAL_TARGETTING "BB_magicarp_spell_special_targetting" +#define BB_MAGICARP_SPELL_SPECIAL_TARGETING "BB_magicarp_spell_special_targeting" #define MAGICARP_SPELL_CORPSES "magicarp_spell_corpses" #define MAGICARP_SPELL_WALLS "magicarp_spell_walls" #define MAGICARP_SPELL_OBJECTS "magicarp_spell_objects" diff --git a/code/__DEFINES/ai/monsters.dm b/code/__DEFINES/ai/monsters.dm index 750d65e6eb33e..6f5f0364bec16 100644 --- a/code/__DEFINES/ai/monsters.dm +++ b/code/__DEFINES/ai/monsters.dm @@ -190,6 +190,9 @@ /// the bonfire we will light up #define BB_MOOK_BONFIRE_TARGET "bonfire_target" +//gutlunch keys +///the trough we will eat from +#define BB_TROUGH_TARGET "trough_target" //leaper keys ///key holds our volley ability #define BB_LEAPER_VOLLEY "leaper_volley" @@ -216,3 +219,7 @@ #define BB_WIZARD_BLINK_SPELL "BB_wizard_blink_spell" /// Key for the next time we can cast a spell #define BB_WIZARD_SPELL_COOLDOWN "BB_wizard_spell_cooldown" + +//netguardians +/// rocket launcher +#define BB_NETGUARDIAN_ROCKET_ABILITY "netguardian_rocket" diff --git a/code/__DEFINES/ai/pet_commands.dm b/code/__DEFINES/ai/pet_commands.dm index 5894aedff14d0..1e692b9f805aa 100644 --- a/code/__DEFINES/ai/pet_commands.dm +++ b/code/__DEFINES/ai/pet_commands.dm @@ -4,6 +4,6 @@ /// Blackboard field for what we actually want the pet to target #define BB_CURRENT_PET_TARGET "BB_current_pet_target" /// Blackboard field for how we target things, as usually we want to be more permissive than normal -#define BB_PET_TARGETTING_DATUM "BB_pet_targetting" +#define BB_PET_TARGETING_STRATEGY "BB_pet_targeting" /// Typecache of weakrefs to mobs this mob is friends with, will follow their instructions and won't attack them #define BB_FRIENDS_LIST "BB_friends_list" diff --git a/code/__DEFINES/ai/ventcrawling.dm b/code/__DEFINES/ai/ventcrawling.dm index f981ef3bba5d6..a60b7fd594017 100644 --- a/code/__DEFINES/ai/ventcrawling.dm +++ b/code/__DEFINES/ai/ventcrawling.dm @@ -3,7 +3,7 @@ /// Key that holds a vent that we want to exit out of (when we're already in a pipenet) #define BB_EXIT_VENT_TARGET "BB_exit_vent_target" /// Do we plan on going inside a vent? Boolean. -#define BB_CURRENTLY_TARGETTING_VENT "BB_currently_targetting_vent" +#define BB_CURRENTLY_TARGETING_VENT "BB_currently_targeting_vent" /// How long should we wait before we try and enter a vent again? #define BB_VENTCRAWL_COOLDOWN "BB_ventcrawl_cooldown" /// The least amount of time (in seconds) we take to go through the vents. diff --git a/code/__DEFINES/alerts.dm b/code/__DEFINES/alerts.dm index 6f25e61e7c558..cfb408898ec45 100644 --- a/code/__DEFINES/alerts.dm +++ b/code/__DEFINES/alerts.dm @@ -68,5 +68,6 @@ #define ALERT_BITRUNNER_INTEGRITY "bitrunning_integrity" #define ALERT_BITRUNNER_SHUTDOWN "bitrunning_shutdown" #define ALERT_BITRUNNER_RESET "bitrunning_reset" -#define ALERT_BITRUNNER_SPAWN_CYBERCOP "bitrunning_spawn_cybercop" #define ALERT_BITRUNNER_THREAT "bitrunning_threat" +#define ALERT_BITRUNNER_BREACH "bitrunning_breach" +#define ALERT_BITRUNNER_GLITCH "bitrunning_glitch" diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index c0ff62c0b585d..3048ec84593cb 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -80,7 +80,7 @@ #define PATH_VOID "Void Path" #define PATH_BLADE "Blade Path" #define PATH_COSMIC "Cosmic Path" -#define PATH_KNOCK "Knock Path" +#define PATH_LOCK "Lock Path" /// Defines are used in /proc/has_living_heart() to report if the heretic has no heart period, no living heart, or has a living heart. #define HERETIC_NO_HEART_ORGAN -1 @@ -317,8 +317,8 @@ GLOBAL_LIST_INIT(human_invader_antagonists, list( #define ANTAG_GROUP_ASHWALKERS "Ash Walkers" #define ANTAG_GROUP_BIOHAZARDS "Biohazards" #define ANTAG_GROUP_CLOWNOPS "Clown Operatives" -#define ANTAG_GROUP_CYBERAUTH "Cyber Authority" #define ANTAG_GROUP_ERT "Emergency Response Team" +#define ANTAG_GROUP_GLITCH "Digital Anomalies" #define ANTAG_GROUP_HORRORS "Eldritch Horrors" #define ANTAG_GROUP_LEVIATHANS "Spaceborne Leviathans" #define ANTAG_GROUP_NINJAS "Ninja Clan" diff --git a/code/__DEFINES/atmospherics/atmos_mapping_helpers.dm b/code/__DEFINES/atmospherics/atmos_mapping_helpers.dm index dd794cbf0539f..9a040f0c160a0 100644 --- a/code/__DEFINES/atmospherics/atmos_mapping_helpers.dm +++ b/code/__DEFINES/atmospherics/atmos_mapping_helpers.dm @@ -7,6 +7,8 @@ #define OPENTURF_DEFAULT_ATMOS GAS_O2 + "=22;" + GAS_N2 + "=82;TEMP=293.15" /// the default low-pressure air mix used mostly for mining areas. #define OPENTURF_LOW_PRESSURE GAS_O2 + "=14;" + GAS_N2 + "=30;TEMP=293.15" +/// breathable air that causes disease +#define OPENTURF_DIRTY_ATMOS GAS_MIASMA + "=15;" + GAS_O2 + "=88;TEMP=293.15" /// -193,15°C telecommunications. also used for xenobiology slime killrooms #define TCOMMS_ATMOS GAS_N2 + "=100;TEMP=80" /// space diff --git a/code/__DEFINES/atmospherics/atmos_mob_interaction.dm b/code/__DEFINES/atmospherics/atmos_mob_interaction.dm index 260a80190e71d..dbd8bbc5610b0 100644 --- a/code/__DEFINES/atmospherics/atmos_mob_interaction.dm +++ b/code/__DEFINES/atmospherics/atmos_mob_interaction.dm @@ -96,6 +96,9 @@ /// The temperature the blue icon is displayed. #define BODYTEMP_COLD_WARNING_3 (BODYTEMP_COLD_DAMAGE_LIMIT - 150) //120k +/// Beyond this temperature, being on fire will increase body temperature by less and less +#define BODYTEMP_FIRE_TEMP_SOFTCAP 1200 + /// The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE #define PRESSURE_DAMAGE_COEFFICIENT 2 #define MAX_HIGH_PRESSURE_DAMAGE 2 diff --git a/code/__DEFINES/bitrunning.dm b/code/__DEFINES/bitrunning.dm index 343801c477e97..bdb02b4d79220 100644 --- a/code/__DEFINES/bitrunning.dm +++ b/code/__DEFINES/bitrunning.dm @@ -4,17 +4,22 @@ #define BITRUNNER_COST_HIGH 3 #define BITRUNNER_COST_EXTREME 20 +/// Yay you did it #define BITRUNNER_REWARD_MIN 1 +/// You faced some decent odds #define BITRUNNER_REWARD_LOW 3 +/// One of your teammates might've died #define BITRUNNER_REWARD_MEDIUM 4 +/// Heroic effort #define BITRUNNER_REWARD_HIGH 5 +/// For the priciest domains, free loot basically #define BITRUNNER_REWARD_EXTREME 6 -/// Blue in ui +/// Blue in ui. Basically the only threat is rogue ghosts roles #define BITRUNNER_DIFFICULTY_NONE 0 -/// Yellow +/// Yellow. Mobs are kinda dumb and largely avoidable #define BITRUNNER_DIFFICULTY_LOW 1 -/// Orange +/// Orange. Mobs will shoot at you or are pretty aggressive #define BITRUNNER_DIFFICULTY_MEDIUM 2 -/// Red with skull +/// Red with skull. I am trying to kill bitrunners. #define BITRUNNER_DIFFICULTY_HIGH 3 diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index eae18813fae22..6a71a8d6c3c07 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -283,6 +283,8 @@ #define LIGHT_COLOR_TUNGSTEN "#FFD6AA" /// Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250) #define LIGHT_COLOR_HALOGEN "#F0FAFA" +/// Nearly red. rgb(226, 78, 118) +#define LIGHT_COLOR_BUBBLEGUM "#e24e76" //The GAGS greyscale_colors for each department's computer/machine circuits #define CIRCUIT_COLOR_GENERIC "#1A7A13" diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index cc9412208fb85..116b933c6ae22 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -169,6 +169,9 @@ DEFINE_BITFIELD(status_flags, list( GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( /obj/item/gun))) +//The define for base unarmed miss chance +#define UNARMED_MISS_CHANCE_BASE 20 +#define UNARMED_MISS_CHANCE_MAX 80 //Combat object defines diff --git a/code/__DEFINES/dcs/signals/signals_bitrunning.dm b/code/__DEFINES/dcs/signals/signals_bitrunning.dm index 3bca73db596b3..74d418182d597 100644 --- a/code/__DEFINES/dcs/signals/signals_bitrunning.dm +++ b/code/__DEFINES/dcs/signals/signals_bitrunning.dm @@ -44,7 +44,3 @@ // Ladder /// from /obj/structure/hololadder/disconnect() #define COMSIG_BITRUNNER_LADDER_SEVER "bitrunner_ladder_sever" - - -/// deprecated -#define COMSIG_BITRUNNER_SPAWN_GLITCH "bitrunner_spawn_glitch" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_guardian.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_guardian.dm new file mode 100644 index 0000000000000..9f4819de79749 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_guardian.dm @@ -0,0 +1,7 @@ +/// Sent when a guardian is manifested +#define COMSIG_GUARDIAN_MANIFESTED "guardian_manifested" +/// Sent when a guardian is recalled +#define COMSIG_GUARDIAN_RECALLED "guardian_recalled" + +/// Sent when an assassin guardian is forced to exit stealth +#define COMSIG_GUARDIAN_ASSASSIN_REVEALED "guardian_assassin_revealed" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index ceebe7f304be7..b919f94a1c122 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -139,6 +139,9 @@ #define COMSIG_LIVING_EARLY_UNARMED_ATTACK "human_pre_attack_hand" /// from mob/living/*/UnarmedAttack(): (mob/living/source, atom/target, proximity, modifiers) #define COMSIG_LIVING_UNARMED_ATTACK "living_unarmed_attack" +///From base of mob/living/MobBump(): (mob/bumped, mob/living/bumper) +#define COMSIG_LIVING_PRE_MOB_BUMP "movable_pre_bump" + #define COMPONENT_LIVING_BLOCK_PRE_MOB_BUMP (1<<0) ///From base of mob/living/MobBump() (mob/living) #define COMSIG_LIVING_MOB_BUMP "living_mob_bump" ///From base of mob/living/Bump() (turf/closed) @@ -225,3 +228,8 @@ #define COMSIG_MOB_LOST_CHAIN_TAIL "living_detached_chain_tail" /// Sent from a 'contract chain' button on a mob chain #define COMSIG_MOB_CHAIN_CONTRACT "living_chain_contracted" + +/// Sent from a mob to their loc when starting to remove cuffs on itself +#define COMSIG_MOB_REMOVING_CUFFS "living_removing_cuffs" +/// Sent as a reply to above from any atom that wishs to stop self-cuff removal +#define COMSIG_MOB_BLOCK_CUFF_REMOVAL (1<<0) diff --git a/code/__DEFINES/dcs/signals/signals_turf.dm b/code/__DEFINES/dcs/signals/signals_turf.dm index 65709f4e446d9..04a2648773adc 100644 --- a/code/__DEFINES/dcs/signals/signals_turf.dm +++ b/code/__DEFINES/dcs/signals/signals_turf.dm @@ -31,5 +31,7 @@ ///from /datum/element/footstep/prepare_step(): (list/steps) #define COMSIG_TURF_PREPARE_STEP_SOUND "turf_prepare_step_sound" + //stops element/footstep/proc/prepare_step() from returning null if the turf itself has no sound + #define FOOTSTEP_OVERRIDEN (1<<0) ///from base of datum/thrownthing/finalize(): (turf/turf, atom/movable/thrownthing) when something is thrown and lands on us #define COMSIG_TURF_MOVABLE_THROW_LANDED "turf_movable_throw_landed" diff --git a/code/__DEFINES/exosuit_fab.dm b/code/__DEFINES/exosuit_fab.dm index 706daf6e2dec2..4cc21f210d61d 100644 --- a/code/__DEFINES/exosuit_fab.dm +++ b/code/__DEFINES/exosuit_fab.dm @@ -33,10 +33,12 @@ #define EXOSUIT_MODULE_RETICENCE (1<<9) /// Module is compatible with Marauder models #define EXOSUIT_MODULE_MARAUDER (1<<10) +/// Module is compatible with Paddy models +#define EXOSUIT_MODULE_PADDY (1<<11) /// Module is compatible with "Working" Exosuit models - Ripley and Clarke #define EXOSUIT_MODULE_WORKING (EXOSUIT_MODULE_RIPLEY | EXOSUIT_MODULE_CLARKE) /// Module is compatible with "Combat" Exosuit models - Gygax, H.O.N.K, Durand and Phazon, or any Exosuit with an empty Concealed Weapon Bay -#define EXOSUIT_MODULE_COMBAT (EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_HONK | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON | EXOSUIT_MODULE_SAVANNAH | EXOSUIT_MODULE_RETICENCE | EXOSUIT_MODULE_MARAUDER | EXOSUIT_MODULE_CONCEALED_WEP_BAY) +#define EXOSUIT_MODULE_COMBAT (EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_HONK | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON | EXOSUIT_MODULE_SAVANNAH | EXOSUIT_MODULE_RETICENCE | EXOSUIT_MODULE_MARAUDER | EXOSUIT_MODULE_PADDY | EXOSUIT_MODULE_CONCEALED_WEP_BAY) /// Module is compatible with "Medical" Exosuit modelsm - Odysseus #define EXOSUIT_MODULE_MEDICAL EXOSUIT_MODULE_ODYSSEUS diff --git a/code/__DEFINES/guardian_defines.dm b/code/__DEFINES/guardian_defines.dm index e7961368feee0..ae2c3175b4a61 100644 --- a/code/__DEFINES/guardian_defines.dm +++ b/code/__DEFINES/guardian_defines.dm @@ -3,5 +3,28 @@ #define GUARDIAN_THEME_CARP "carp" #define GUARDIAN_THEME_MINER "miner" -#define GUARDIAN_COLOR_LAYER 1 -#define GUARDIAN_TOTAL_LAYERS 1 +#define GUARDIAN_MAGIC "magic" +#define GUARDIAN_TECH "tech" + +#define GUARDIAN_ASSASSIN "assassin" +#define GUARDIAN_CHARGER "charger" +#define GUARDIAN_DEXTROUS "dextrous" +#define GUARDIAN_EXPLOSIVE "explosive" +#define GUARDIAN_GASEOUS "gaseous" +#define GUARDIAN_GRAVITOKINETIC "gravitokinetic" +#define GUARDIAN_LIGHTNING "lightning" +#define GUARDIAN_PROTECTOR "protector" +#define GUARDIAN_RANGED "ranged" +#define GUARDIAN_STANDARD "standard" +#define GUARDIAN_SUPPORT "support" + +/// List of all guardians currently extant +GLOBAL_LIST_EMPTY(parasites) + +/// Assoc list of guardian theme singletons +GLOBAL_LIST_INIT(guardian_themes, list( + GUARDIAN_THEME_TECH = new /datum/guardian_fluff/tech, + GUARDIAN_THEME_MAGIC = new /datum/guardian_fluff, + GUARDIAN_THEME_CARP = new /datum/guardian_fluff/carp, + GUARDIAN_THEME_MINER = new /datum/guardian_fluff/miner, +)) diff --git a/code/__DEFINES/interaction_flags.dm b/code/__DEFINES/interaction_flags.dm index 0b4e958872943..55732f2364bb1 100644 --- a/code/__DEFINES/interaction_flags.dm +++ b/code/__DEFINES/interaction_flags.dm @@ -36,9 +36,8 @@ #define INTERACT_MACHINE_OPEN_SILICON (1<<4) /// must be silicon to interact #define INTERACT_MACHINE_REQUIRES_SILICON (1<<5) -/// MACHINES HAVE THIS BY DEFAULT, SOMEONE SHOULD RUN THROUGH MACHINES AND REMOVE IT FROM THINGS LIKE LIGHT SWITCHES WHEN POSSIBLE!!-------------------------- /// This flag determines if a machine set_machine's the user when the user uses it, making updateUsrDialog make the user re-call interact() on it. -/// THIS FLAG IS ON ALL MACHINES BY DEFAULT, NEEDS TO BE RE-EVALUATED LATER!! +/// This is exclusively used for non-TGUI UIs, and its instances should be removed when moved to TGUI. #define INTERACT_MACHINE_SET_MACHINE (1<<6) /// the user must have vision to interact (blind people need not apply) #define INTERACT_MACHINE_REQUIRES_SIGHT (1<<7) diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 5676a6aaa8e5c..e9963ca1f6a29 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -188,7 +188,7 @@ GLOBAL_LIST_INIT(turfs_pass_meteor, typecacheof(list( #define isregalrat(A) (istype(A, /mob/living/basic/regal_rat)) -#define isguardian(A) (istype(A, /mob/living/simple_animal/hostile/guardian)) +#define isguardian(A) (istype(A, /mob/living/basic/guardian)) #define ismegafauna(A) (istype(A, /mob/living/simple_animal/hostile/megafauna)) diff --git a/code/__DEFINES/mecha.dm b/code/__DEFINES/mecha.dm index db65b0b6ee8d3..5a37f60aba6fb 100644 --- a/code/__DEFINES/mecha.dm +++ b/code/__DEFINES/mecha.dm @@ -46,6 +46,7 @@ #define MECHA_SNOWFLAKE_ID_AIR_TANK "air_tank_snowflake" #define MECHA_SNOWFLAKE_ID_WEAPON_BALLISTIC "ballistic_weapon_snowflake" #define MECHA_SNOWFLAKE_ID_GENERATOR "generator_snowflake" +#define MECHA_SNOWFLAKE_ID_CLAW "lawclaw_snowflake" #define MECHA_AMMO_INCENDIARY "Incendiary bullet" #define MECHA_AMMO_BUCKSHOT "Buckshot shell" diff --git a/code/__DEFINES/movement.dm b/code/__DEFINES/movement.dm index f71871f964a2e..540e5f7914c24 100644 --- a/code/__DEFINES/movement.dm +++ b/code/__DEFINES/movement.dm @@ -39,6 +39,14 @@ GLOBAL_VAR_INIT(glide_size_multiplier, 1.0) ///Is the loop moving the movable outside its control, like it's an external force? e.g. footsteps won't play if enabled. #define MOVEMENT_LOOP_OUTSIDE_CONTROL (1<<4) +// Movement loop status flags +/// Has the loop been paused, soon to be resumed? +#define MOVELOOP_STATUS_PAUSED (1<<0) +/// Is the loop running? (Is true even when paused) +#define MOVELOOP_STATUS_RUNNING (1<<1) +/// Is the loop queued in a subsystem? +#define MOVELOOP_STATUS_QUEUED (1<<2) + /** * Returns a bitfield containing flags both present in `flags` arg and the `processing_move_loop_flags` move_packet variable. * Has no use outside of procs called within the movement proc chain. diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index 7f2ddaa334b56..c7daddd2970ae 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -131,6 +131,9 @@ /// such as hair color being affixed to hair. #define PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES "supplemental_features" +/// These preferences will not be rendered on the preferences page, and are practically invisible unless specifically rendered. Used for quirks, currently. +#define PREFERENCE_CATEGORY_MANUALLY_RENDERED "manually_rendered_features" + // Playtime is tracked in minutes /// The time needed to unlock hardcore random mode in preferences #define PLAYTIME_HARDCORE_RANDOM 120 // 2 hours diff --git a/code/__DEFINES/projectiles.dm b/code/__DEFINES/projectiles.dm index a82ac8422c5ae..58f25ac39f112 100644 --- a/code/__DEFINES/projectiles.dm +++ b/code/__DEFINES/projectiles.dm @@ -52,6 +52,14 @@ #define CALIBER_ARROW "arrow" /// The caliber used by the harpoon gun. #define CALIBER_HARPOON "harpoon" +/// The caliber used by the rebar crossbow. +#define CALIBER_REBAR "sharpened iron rod" +/// The caliber used by the rebar crossbow when forced to hold 2 rods. +#define CALIBER_REBAR_FORCED "sharpened iron rod" +/// The caliber used by the syndicate rebar crossbow. +#define CALIBER_REBAR_SYNDIE "jagged iron rod" +/// The caliber used by the syndicate rebar crossbow. +#define CALIBER_REBAR_SYNDIE_NORMAL "sharpened iron rod" /// The caliber used by the meat hook. #define CALIBER_HOOK "hook" /// The caliber used by the changeling tentacle mutation. diff --git a/code/__DEFINES/research.dm b/code/__DEFINES/research.dm index c1427fcb67a06..005c67ae1a3ee 100644 --- a/code/__DEFINES/research.dm +++ b/code/__DEFINES/research.dm @@ -1,10 +1,6 @@ -#define RDSCREEN_NOBREAK "" - /// For instances where we don't want a design showing up due to it being for debug/sanity purposes #define DESIGN_ID_IGNORE "IGNORE_THIS_DESIGN" -#define RESEARCH_MATERIAL_DESTROY_ID "__destroy" - //! Techweb names for new point types. Can be used to define specific point values for specific types of research (science, security, engineering, etc.) #define TECHWEB_POINT_TYPE_GENERIC "General Research" diff --git a/code/__DEFINES/research/research_categories.dm b/code/__DEFINES/research/research_categories.dm index e8d426fcfc5a7..9ebdb44c8a58c 100644 --- a/code/__DEFINES/research/research_categories.dm +++ b/code/__DEFINES/research/research_categories.dm @@ -126,6 +126,7 @@ #define RND_SUBCATEGORY_EXOSUIT_BOARDS_SAVANNAH_IVANOV "/Savannah-Ivanov" #define RND_CATEGORY_MECHFAB_RIPLEY "/Ripley" +#define RND_CATEGORY_MECHFAB_PADDY "/Paddy" #define RND_CATEGORY_MECHFAB_ODYSSEUS "/Odysseus" #define RND_CATEGORY_MECHFAB_GYGAX "/Gygax" #define RND_CATEGORY_MECHFAB_DURAND "/Durand" diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index e16493d4d9d7b..09ba57c4ad367 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -23,7 +23,6 @@ #define ROLE_BLOB "Blob" #define ROLE_BLOB_INFECTION "Blob Infection" #define ROLE_CHANGELING_MIDROUND "Changeling (Midround)" -#define ROLE_CYBER_POLICE "Cyber Police" #define ROLE_FUGITIVE "Fugitive" #define ROLE_LONE_OPERATIVE "Lone Operative" #define ROLE_MALF_MIDROUND "Malf AI (Midround)" @@ -107,6 +106,11 @@ #define ROLE_VENUSHUMANTRAP "Venus Human Trap" #define ROLE_ZOMBIE "Zombie" +// Virtual dom related +#define ROLE_GLITCH "Glitch" // the parent type of all vdom roles +#define ROLE_CYBER_POLICE "Cyber Police" +#define ROLE_CYBER_TAC "Cyber Tac" +#define ROLE_NETGUARDIAN "NetGuardian Prime" /// This defines the antagonists you can operate with in the settings. /// Keys are the antagonist, values are the number of days since the player's @@ -130,7 +134,6 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_BLOB = 0, ROLE_BLOB_INFECTION = 0, ROLE_CHANGELING_MIDROUND = 0, - ROLE_CYBER_POLICE = 0, ROLE_FUGITIVE = 0, ROLE_LONE_OPERATIVE = 14, ROLE_MALF_MIDROUND = 0, @@ -153,6 +156,7 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_STOWAWAY_CHANGELING = 0, // I'm not too sure why these are here, but they're not moving. + ROLE_GLITCH = 0, ROLE_PAI = 0, ROLE_SENTIENCE = 0, )) diff --git a/code/__DEFINES/span.dm b/code/__DEFINES/span.dm index 76ab9ccf84114..ab8ff969e307f 100644 --- a/code/__DEFINES/span.dm +++ b/code/__DEFINES/span.dm @@ -23,6 +23,7 @@ #define span_bold(str) ("" + str + "") #define span_boldannounce(str) ("" + str + "") #define span_bolddanger(str) ("" + str + "") +#define span_bolditalic(str) ("" + str + "") #define span_boldnicegreen(str) ("" + str + "") #define span_boldnotice(str) ("" + str + "") #define span_boldwarning(str) ("" + str + "") diff --git a/code/__DEFINES/text.dm b/code/__DEFINES/text.dm index 8a7731618bbff..ffac885bf4c88 100644 --- a/code/__DEFINES/text.dm +++ b/code/__DEFINES/text.dm @@ -100,3 +100,5 @@ #define NINJA_FILE "ninja.json" /// File loation for title splashes #define SPLASH_FILE "splashes.json" +///File location for mother hallucination lines +#define MOTHER_FILE "mother.json" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index ffcb72b92ae5a..d1b47c6a57c8e 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -669,7 +669,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_TENTACLE_IMMUNE "tentacle_immune" /// Currently under the effect of overwatch #define TRAIT_OVERWATCHED "watcher_overwatched" -/// Cannot be targetted by watcher overwatch +/// Cannot be targeted by watcher overwatch #define TRAIT_OVERWATCH_IMMUNE "overwatch_immune" //non-mob traits @@ -1056,6 +1056,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai */ #define TRAIT_UNIQUE_IMMERSE "unique_immerse" +/// This item is currently under the control of telekinesis +#define TRAIT_TELEKINESIS_CONTROLLED "telekinesis_controlled" // unique trait sources, still defines #define EMP_TRAIT "emp_trait" @@ -1352,5 +1354,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Trait given to a dragon who fails to defend their rifts #define TRAIT_RIFT_FAILURE "fail_dragon_loser" +///trait determines if this mob can breed given by /datum/component/breeding +#define TRAIT_MOB_BREEDER "mob_breeder" /// Trait given to mobs that we do not want to mindswap #define TRAIT_NO_MINDSWAP "no_mindswap" diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm index 1cc9025b82164..f6cb654b1d549 100644 --- a/code/__DEFINES/vv.dm +++ b/code/__DEFINES/vv.dm @@ -57,7 +57,7 @@ // VV HREF KEYS #define VV_HK_TARGET "target" -#define VV_HK_VARNAME "targetvar" //name or index of var for 1 variable targetting hrefs. +#define VV_HK_VARNAME "targetvar" //name or index of var for 1 variable targeting hrefs. // vv_do_list() keys #define VV_HK_LIST_ADD "listadd" diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm index bfe94ff85047d..dbb11a3295b65 100644 --- a/code/__DEFINES/wounds.dm +++ b/code/__DEFINES/wounds.dm @@ -91,7 +91,7 @@ GLOBAL_LIST_INIT(wound_severities_chronological, list( // "Where" a specific biostate is within a given limb // Interior is hard shit, the last line, shit like bones -// Exterior is soft shit, targetted by slashes and pierces (usually), protects exterior +// Exterior is soft shit, targeted by slashes and pierces (usually), protects exterior // A limb needs both mangled interior and exterior to be dismembered, but slash/pierce must mangle exterior to attack the interior // Not having exterior/interior counts as mangled exterior/interior for the purposes of dismemberment /// The given biostate is on the "interior" of the limb - hard shit, protected by exterior diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 4ab974dd4a8a9..918428daf77e1 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -900,7 +900,7 @@ ///Gets the total amount of everything in the associative list. /proc/assoc_value_sum(list/input) - var/list/keys = list() + var/keys = 0 for(var/key in input) keys += input[key] return keys diff --git a/code/__HELPERS/animations.dm b/code/__HELPERS/animations.dm deleted file mode 100644 index cae8d3a8f52b1..0000000000000 --- a/code/__HELPERS/animations.dm +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Causes the passed atom / image to appear floating, - * playing a simple animation where they move up and down by 2 pixels (looping) - * - * In most cases you should NOT call this manually, instead use [/datum/element/movetype_handler]! - * This is just so you can apply the animation to things which can be animated but are not movables (like images) - */ -#define DO_FLOATING_ANIM(target) \ - animate(target, pixel_y = 2, time = 1 SECONDS, loop = -1, flags = ANIMATION_RELATIVE); \ - animate(pixel_y = -2, time = 1 SECONDS, flags = ANIMATION_RELATIVE) - -/** - * Stops the passed atom / image from appearing floating - * (Living mobs also have a 'body_position_pixel_y_offset' variable that has to be taken into account here) - * - * In most cases you should NOT call this manually, instead use [/datum/element/movetype_handler]! - * This is just so you can apply the animation to things which can be animated but are not movables (like images) - */ -#define STOP_FLOATING_ANIM(target) \ - var/final_pixel_y = 0; \ - if(ismovable(target)) { \ - var/atom/movable/movable_target = target; \ - final_pixel_y = movable_target.base_pixel_y; \ - }; \ - if(isliving(target)) { \ - var/mob/living/living_target = target; \ - final_pixel_y += living_target.body_position_pixel_y_offset; \ - }; \ - animate(target, pixel_y = final_pixel_y, time = 1 SECONDS) - -/// The duration of the animate call in mob/living/update_transform -#define UPDATE_TRANSFORM_ANIMATION_TIME (0.2 SECONDS) - -///Animates source spinning around itself. For docmentation on the args, check atom/proc/SpinAnimation() -/atom/proc/do_spin_animation(speed = 1 SECONDS, loops = -1, segments = 3, angle = 120, parallel = TRUE) - var/list/matrices = list() - for(var/i in 1 to segments-1) - var/matrix/segment_matrix = matrix(transform) - segment_matrix.Turn(angle*i) - matrices += segment_matrix - var/matrix/last = matrix(transform) - matrices += last - - speed /= segments - - if(parallel) - animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL) - else - animate(src, transform = matrices[1], time = speed, loops) - for(var/i in 2 to segments) //2 because 1 is covered above - animate(transform = matrices[i], time = speed) - //doesn't have an object argument because this is "Stacking" with the animate call above - //3 billion% intentional - -/// Similar to shake but more spasm-y and jerk-y -/atom/proc/spasm_animation(loops = -1) - var/list/transforms = list( - matrix(transform).Translate(-1, 0), - matrix(transform).Translate(0, 1), - matrix(transform).Translate(1, 0), - matrix(transform).Translate(0, -1), - ) - - animate(src, transform = transforms[1], time = 0.2, loop = loops) - animate(transform = transforms[2], time = 0.1) - animate(transform = transforms[3], time = 0.2) - animate(transform = transforms[4], time = 0.3) diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index e1303882b1aa1..0210c44ee57ba 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -189,12 +189,6 @@ /proc/cmp_assoc_list_name(list/A, list/B) return sorttext(B["name"], A["name"]) -/// Used by /datum/achievement_data/load_all_achievements() to determine in which order awards have to be loaded. -/proc/cmp_award_priority(type_a, type_b) - var/datum/award/award_a = SSachievements.awards[type_a] - var/datum/award/award_b = SSachievements.awards[type_b] - return award_b?.load_priority - award_a?.load_priority - /// Orders mobs by health /proc/cmp_mob_health(mob/living/mob_a, mob/living/mob_b) return mob_b.health - mob_a.health diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm index 7d716e5eaf6bb..f36ab36becbd5 100644 --- a/code/__HELPERS/priority_announce.dm +++ b/code/__HELPERS/priority_announce.dm @@ -37,7 +37,7 @@ * * encode_title - if TRUE, the title will be HTML encoded * * encode_text - if TRUE, the text will be HTML encoded */ -/proc/priority_announce(text, title = "", sound, type, sender_override, has_important_message = FALSE, list/mob/players, encode_title = TRUE, encode_text = TRUE, color_override) +/proc/priority_announce(text, title = "", sound, type, sender_override, has_important_message = FALSE, list/mob/players = GLOB.player_list, encode_title = TRUE, encode_text = TRUE, color_override) if(!text) return @@ -85,7 +85,7 @@ dispatch_announcement_to_players(finalized_announcement, players, sound) - if(isnull(sender_override)) + if(isnull(sender_override) && players == GLOB.player_list) if(length(title) > 0) GLOB.news_network.submit_article(title + "

" + text, "[command_name()]", "Station Announcements", null) else @@ -185,10 +185,7 @@ return jointext(returnable_strings, "") /// Proc that just dispatches the announcement to our applicable audience. Only the announcement is a mandatory arg. -/proc/dispatch_announcement_to_players(announcement, list/players, sound_override = null, should_play_sound = TRUE) - if(!players) - players = GLOB.player_list - +/proc/dispatch_announcement_to_players(announcement, list/players = GLOB.player_list, sound_override = null, should_play_sound = TRUE) var/sound_to_play = !isnull(sound_override) ? sound_override : 'sound/misc/notice2.ogg' for(var/mob/target in players) diff --git a/code/__HELPERS/visual_effects.dm b/code/__HELPERS/visual_effects.dm new file mode 100644 index 0000000000000..b7855ade45f55 --- /dev/null +++ b/code/__HELPERS/visual_effects.dm @@ -0,0 +1,125 @@ +/** + * Causes the passed atom / image to appear floating, + * playing a simple animation where they move up and down by 2 pixels (looping) + * + * In most cases you should NOT call this manually, instead use [/datum/element/movetype_handler]! + * This is just so you can apply the animation to things which can be animated but are not movables (like images) + */ +#define DO_FLOATING_ANIM(target) \ + animate(target, pixel_y = 2, time = 1 SECONDS, loop = -1, flags = ANIMATION_RELATIVE); \ + animate(pixel_y = -2, time = 1 SECONDS, flags = ANIMATION_RELATIVE) + +/** + * Stops the passed atom / image from appearing floating + * (Living mobs also have a 'body_position_pixel_y_offset' variable that has to be taken into account here) + * + * In most cases you should NOT call this manually, instead use [/datum/element/movetype_handler]! + * This is just so you can apply the animation to things which can be animated but are not movables (like images) + */ +#define STOP_FLOATING_ANIM(target) \ + var/final_pixel_y = 0; \ + if(ismovable(target)) { \ + var/atom/movable/movable_target = target; \ + final_pixel_y = movable_target.base_pixel_y; \ + }; \ + if(isliving(target)) { \ + var/mob/living/living_target = target; \ + final_pixel_y += living_target.body_position_pixel_y_offset; \ + }; \ + animate(target, pixel_y = final_pixel_y, time = 1 SECONDS) + +/// The duration of the animate call in mob/living/update_transform +#define UPDATE_TRANSFORM_ANIMATION_TIME (0.2 SECONDS) + +///Animates source spinning around itself. For docmentation on the args, check atom/proc/SpinAnimation() +/atom/proc/do_spin_animation(speed = 1 SECONDS, loops = -1, segments = 3, angle = 120, parallel = TRUE) + var/list/matrices = list() + for(var/i in 1 to segments-1) + var/matrix/segment_matrix = matrix(transform) + segment_matrix.Turn(angle*i) + matrices += segment_matrix + var/matrix/last = matrix(transform) + matrices += last + + speed /= segments + + if(parallel) + animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL) + else + animate(src, transform = matrices[1], time = speed, loops) + for(var/i in 2 to segments) //2 because 1 is covered above + animate(transform = matrices[i], time = speed) + //doesn't have an object argument because this is "Stacking" with the animate call above + //3 billion% intentional + +/// Similar to shake but more spasm-y and jerk-y +/atom/proc/spasm_animation(loops = -1) + var/list/transforms = list( + matrix(transform).Translate(-1, 0), + matrix(transform).Translate(0, 1), + matrix(transform).Translate(1, 0), + matrix(transform).Translate(0, -1), + ) + + animate(src, transform = transforms[1], time = 0.2, loop = loops) + animate(transform = transforms[2], time = 0.1) + animate(transform = transforms[3], time = 0.2) + animate(transform = transforms[4], time = 0.3) + +/** + * Proc called when you want the atom to spin around the center of its icon (or where it would be if its transform var is translated) + * By default, it makes the atom spin forever and ever at a speed of 60 rpm. + * + * Arguments: + * * speed: how much it takes for the atom to complete one 360° rotation + * * loops: how many times do we want the atom to rotate + * * clockwise: whether the atom ought to spin clockwise or counter-clockwise + * * segments: in how many animate calls the rotation is split. Probably unnecessary, but you shouldn't set it lower than 3 anyway. + * * parallel: whether the animation calls have the ANIMATION_PARALLEL flag, necessary for it to run alongside concurrent animations. + */ +/atom/proc/SpinAnimation(speed = 1 SECONDS, loops = -1, clockwise = TRUE, segments = 3, parallel = TRUE) + if(!segments) + return + var/segment = 360/segments + if(!clockwise) + segment = -segment + SEND_SIGNAL(src, COMSIG_ATOM_SPIN_ANIMATION, speed, loops, segments, segment) + do_spin_animation(speed, loops, segments, segment, parallel) + +/// Makes this atom look like a "hologram" +/// So transparent, blue, with a scanline and an emissive glow +/// This is acomplished using a combination of filters and render steps/overlays +/// The degree of the opacity is optional, based off the opacity arg (0 -> 1) +/atom/proc/makeHologram(opacity = 0.5) + // First, we'll make things blue (roughly) and sorta transparent + add_filter("HOLO: Color and Transparent", 1, color_matrix_filter(rgb(125,180,225, opacity * 255))) + // Now we're gonna do a scanline effect + // Gonna take this atom and give it a render target, then use it as a source for a filter + // (We use an atom because it seems as if setting render_target on an MA is just invalid. I hate this engine) + var/atom/movable/scanline = new(null) + scanline.icon = 'icons/effects/effects.dmi' + scanline.icon_state = "scanline" + scanline.appearance_flags |= RESET_TRANSFORM + // * so it doesn't render + var/static/uid_scan = 0 + scanline.render_target = "*HoloScanline [uid_scan]" + uid_scan++ + // Now we add it as a filter, and overlay the appearance so the render source is always around + add_filter("HOLO: Scanline", 2, alpha_mask_filter(render_source = scanline.render_target)) + add_overlay(scanline) + qdel(scanline) + // Annd let's make the sucker emissive, so it glows in the dark + if(!render_target) + var/static/uid = 0 + render_target = "HOLOGRAM [uid]" + uid++ + // I'm using static here to reduce the overhead, it does mean we need to do plane stuff manually tho + var/static/atom/movable/render_step/emissive/glow = new(null) + glow.render_source = render_target + SET_PLANE_EXPLICIT(glow, initial(glow.plane), src) + // We're creating a render step that copies ourselves, and draws it to the emissive plane + // Then we overlay it, and release "ownership" back to this proc, since we get to keep the appearance it generates + // We can't just use an MA from the start cause render_source setting starts going fuckey REALLY quick + var/mutable_appearance/glow_appearance = new(glow) + add_overlay(glow_appearance) + LAZYADD(update_overlays_on_z, glow_appearance) diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index d72ca6fb5c95b..1e775dd49ae40 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -10,6 +10,7 @@ GLOBAL_LIST_EMPTY(stealthminID) //reference list with IDs that store ckeys, for GLOBAL_LIST_INIT(abstract_mob_types, list( /mob/living/basic/blob_minion, /mob/living/basic/construct, + /mob/living/basic/guardian, /mob/living/basic/heretic_summon, /mob/living/basic/mining, /mob/living/basic/pet, @@ -26,7 +27,6 @@ GLOBAL_LIST_INIT(abstract_mob_types, list( /mob/living/simple_animal/bot, /mob/living/simple_animal/hostile/asteroid/elite, /mob/living/simple_animal/hostile/asteroid, - /mob/living/simple_animal/hostile/guardian, /mob/living/simple_animal/hostile/megafauna, /mob/living/simple_animal/hostile/mimic, // Cannot exist if spawned without being passed an item reference /mob/living/simple_animal/hostile/retaliate, diff --git a/code/_globalvars/lists/names.dm b/code/_globalvars/lists/names.dm index b2662b5e804a6..52af61db88ac9 100644 --- a/code/_globalvars/lists/names.dm +++ b/code/_globalvars/lists/names.dm @@ -25,6 +25,9 @@ GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1. GLOBAL_LIST_INIT(megacarp_last_names, world.file2list("strings/names/megacarp2.txt")) GLOBAL_LIST_INIT(cyberauth_names, world.file2list("strings/names/cyberauth.txt")) GLOBAL_LIST_INIT(syndicate_monkey_names, world.file2list("strings/names/syndicate_monkey.txt")) +GLOBAL_LIST_INIT(guardian_first_names, world.file2list("strings/names/guardian_descriptions.txt")) +GLOBAL_LIST_INIT(guardian_tech_surnames, world.file2list("strings/names/guardian_gamepieces.txt")) +GLOBAL_LIST_INIT(guardian_fantasy_surnames, world.file2list("strings/names/guardian_tarot.txt")) GLOBAL_LIST_INIT(verbs, world.file2list("strings/names/verbs.txt")) GLOBAL_LIST_INIT(ing_verbs, world.file2list("strings/names/ing_verbs.txt")) diff --git a/code/_globalvars/lists/poll_ignore.dm b/code/_globalvars/lists/poll_ignore.dm index 7d532ec3aea3d..b65ec230d37b3 100644 --- a/code/_globalvars/lists/poll_ignore.dm +++ b/code/_globalvars/lists/poll_ignore.dm @@ -7,11 +7,12 @@ #define POLL_IGNORE_BLOB "blob" #define POLL_IGNORE_BOTS "bots" #define POLL_IGNORE_CARGORILLA "cargorilla" -#define POLL_IGNORE_CONTRACTOR_SUPPORT "contractor_support" #define POLL_IGNORE_CONSTRUCT "construct" +#define POLL_IGNORE_CONTRACTOR_SUPPORT "contractor_support" #define POLL_IGNORE_DRONE "drone" #define POLL_IGNORE_FIRE_SHARK "fire_shark" #define POLL_IGNORE_FUGITIVE "fugitive" +#define POLL_IGNORE_GLITCH "glitch" #define POLL_IGNORE_GOLEM "golem" #define POLL_IGNORE_HERETIC_MONSTER "heretic_monster" #define POLL_IGNORE_HOLOPARASITE "holoparasite" @@ -36,7 +37,6 @@ #define POLL_IGNORE_SYNDICATE "syndicate" #define POLL_IGNORE_VENUSHUMANTRAP "venus_human_trap" - GLOBAL_LIST_INIT(poll_ignore_desc, list( POLL_IGNORE_ACADEMY_WIZARD = "Academy Wizard Defender", POLL_IGNORE_ALIEN_LARVA = "Xenomorph larva", @@ -45,11 +45,12 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list( POLL_IGNORE_BLOB = "Blob spores", POLL_IGNORE_BOTS = "Bots", POLL_IGNORE_CARGORILLA = "Cargorilla", - POLL_IGNORE_CONTRACTOR_SUPPORT = "Contractor Support Unit", POLL_IGNORE_CONSTRUCT = "Construct", + POLL_IGNORE_CONTRACTOR_SUPPORT = "Contractor Support Unit", POLL_IGNORE_DRONE = "Drone shells", POLL_IGNORE_FIRE_SHARK = "Fire Shark", POLL_IGNORE_FUGITIVE = "Fugitive Hunter", + POLL_IGNORE_GLITCH = "Glitch", POLL_IGNORE_GOLEM = "Golems", POLL_IGNORE_HERETIC_MONSTER = "Heretic Monster", POLL_IGNORE_HOLOPARASITE = "Holoparasite", @@ -62,8 +63,8 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list( POLL_IGNORE_POSSESSED_BLADE = "Possessed blade", POLL_IGNORE_PYROSLIME = "Slime", POLL_IGNORE_RAW_PROPHET = "Raw Prophet", - POLL_IGNORE_RUST_SPIRIT = "Rust Spirit", POLL_IGNORE_REGAL_RAT = "Regal rat", + POLL_IGNORE_RUST_SPIRIT = "Rust Spirit", POLL_IGNORE_SENTIENCE_POTION = "Sentience potion", POLL_IGNORE_SHADE = "Shade", POLL_IGNORE_SHUTTLE_DENIZENS = "Shuttle denizens", diff --git a/code/_globalvars/lists/reagents.dm b/code/_globalvars/lists/reagents.dm index 0a9bb7fd7f037..685eda9357610 100644 --- a/code/_globalvars/lists/reagents.dm +++ b/code/_globalvars/lists/reagents.dm @@ -54,8 +54,6 @@ GLOBAL_LIST_INIT(blacklisted_metalgen_types, typecacheof(list( /turf/closed/indestructible, //indestructible turfs should be indestructible, metalgen transmutation to plasma allows them to be destroyed /turf/open/indestructible ))) -/// Names of human readable reagents used by plumbing UI. -GLOBAL_LIST_INIT(chemical_name_list, init_chemical_name_list()) /// Map of reagent names to its datum path GLOBAL_LIST_INIT(name2reagent, build_name2reagentlist()) @@ -72,16 +70,6 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagentlist()) return reagent_list -/// Creates an list which is indexed by reagent name . used by plumbing reaction chamber and chemical filter UI -/proc/init_chemical_name_list() - var/list/name_list = list() - - for(var/X in GLOB.chemical_reagents_list) - var/datum/reagent/Reagent = GLOB.chemical_reagents_list[X] - name_list += Reagent.name - - return sort_list(name_list) - /** * Chemical Reactions - Initialises all /datum/chemical_reaction into a list * It is filtered into multiple lists within a list. @@ -187,7 +175,19 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagentlist()) /// Builds map of reagent name to its datum path /proc/build_name2reagentlist() . = list() - for (var/datum/reagent/R as anything in subtypesof(/datum/reagent)) - var/name = initial(R.name) + + //build map with keys stored seperatly + var/list/name_to_reagent = list() + var/list/only_names = list() + for (var/datum/reagent/reagent as anything in GLOB.chemical_reagents_list) + var/name = initial(reagent.name) if (length(name)) - .[ckey(name)] = R + name_to_reagent[name] = reagent + only_names += name + + //sort keys + only_names = sort_list(only_names) + + //build map with sorted keys + for(var/name as anything in only_names) + .[name] = name_to_reagent[name] diff --git a/code/_globalvars/phobias.dm b/code/_globalvars/phobias.dm index 36a4329ffbf72..5bb8b4bf31498 100644 --- a/code/_globalvars/phobias.dm +++ b/code/_globalvars/phobias.dm @@ -57,7 +57,7 @@ GLOBAL_LIST_INIT(phobia_mobs, list( /mob/living/carbon/alien, /mob/living/simple_animal/slime, )), - "anime" = typecacheof(list(/mob/living/simple_animal/hostile/guardian)), + "anime" = typecacheof(list(/mob/living/basic/guardian)), "birds" = typecacheof(list( /mob/living/basic/chick, /mob/living/basic/chicken, @@ -367,7 +367,7 @@ GLOBAL_LIST_INIT(phobia_objs, list( /obj/effect/forcefield/wizard/heretic, /obj/effect/heretic_influence, /obj/effect/heretic_rune, - /obj/effect/knock_portal, + /obj/effect/lock_portal, /obj/effect/visible_heretic_influence, /obj/item/ammo_box/strilka310/lionhunter, /obj/item/ammo_casing/strilka310/lionhunter, @@ -379,7 +379,7 @@ GLOBAL_LIST_INIT(phobia_objs, list( /obj/item/codex_cicatrix, /obj/item/coin/eldritch, /obj/item/gun/ballistic/rifle/lionhunter, - /obj/item/heretic_lintel, + /obj/item/heretic_labyrinth_handbook, /obj/item/melee/rune_carver, /obj/item/melee/sickly_blade, /obj/item/melee/touch_attack/mansus_fist, @@ -388,7 +388,7 @@ GLOBAL_LIST_INIT(phobia_objs, list( /obj/item/toy/reality_pierce, /obj/projectile/curse_hand, /obj/structure/destructible/eldritch_crucible, - /obj/structure/knock_tear, + /obj/structure/lock_tear, )), "insects" = typecacheof(list( /obj/item/clothing/mask/animal/small/bee, diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index 1db45879260f7..44925cc2eae60 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -86,6 +86,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_BLOOD_DEFICIENCY" = TRAIT_BLOOD_DEFICIENCY, "TRAIT_JOLLY" = TRAIT_JOLLY, "TRAIT_NO_GLIDE" = TRAIT_NO_GLIDE, + "TRAIT_NO_FLOATING_ANIM" = TRAIT_NO_FLOATING_ANIM, "TRAIT_NOCRITDAMAGE" = TRAIT_NOCRITDAMAGE, "TRAIT_NO_SLIP_WATER" = TRAIT_NO_SLIP_WATER, "TRAIT_NO_SLIP_ICE" = TRAIT_NO_SLIP_ICE, diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index f68776f5ec9da..c1c22091593a2 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -17,13 +17,17 @@ if(!category || QDELETED(src)) return + var/datum/weakref/master_ref + if(isdatum(new_master)) + master_ref = WEAKREF(new_master) var/atom/movable/screen/alert/thealert if(alerts[category]) thealert = alerts[category] if(thealert.override_alerts) return thealert - if(new_master && new_master != thealert.master) - WARNING("[src] threw alert [category] with new_master [new_master] while already having that alert with master [thealert.master]") + if(master_ref && thealert.master_ref && master_ref != thealert.master_ref) + var/datum/current_master = thealert.master_ref.resolve() + WARNING("[src] threw alert [category] with new_master [new_master] while already having that alert with master [current_master]") clear_alert(category) return .() @@ -55,7 +59,7 @@ new_master.layer = old_layer new_master.plane = old_plane thealert.icon_state = "template" // We'll set the icon to the client's ui pref in reorganize_alerts() - thealert.master = new_master + thealert.master_ref = master_ref else thealert.icon_state = "[initial(thealert.icon_state)][severity]" thealert.severity = severity @@ -294,13 +298,17 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." /atom/movable/screen/alert/fire/Click() . = ..() if(!.) - return + return FALSE var/mob/living/living_owner = owner + if(!living_owner.can_resist()) + return FALSE living_owner.changeNext_move(CLICK_CD_RESIST) - if(living_owner.mobility_flags & MOBILITY_MOVE) - return living_owner.resist_fire() + if(!(living_owner.mobility_flags & MOBILITY_MOVE)) + return FALSE + + return living_owner.resist_fire() /atom/movable/screen/alert/give // information set when the give alert is made icon_state = "default" @@ -607,19 +615,13 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." //GUARDIANS -/atom/movable/screen/alert/cancharge - name = "Charge Ready" - desc = "You are ready to charge at a location!" - icon_state = "guardian_charge" - alerttooltipstyle = "parasite" - /atom/movable/screen/alert/canstealth name = "Stealth Ready" desc = "You are ready to enter stealth!" icon_state = "guardian_canstealth" alerttooltipstyle = "parasite" -/atom/movable/screen/alert/instealth +/atom/movable/screen/alert/status_effect/instealth name = "In Stealth" desc = "You are in stealth and your next attack will do bonus damage!" icon_state = "guardian_instealth" @@ -780,13 +782,14 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." desc = "This can be clicked on to perform an action." icon_state = "template" timeout = 30 SECONDS - /// The target to use the action on - var/atom/target + /// Weakref to the target atom to use the action on + var/datum/weakref/target_ref /// Which on click action to use var/action = NOTIFY_JUMP /atom/movable/screen/alert/notify_action/Click() . = ..() + var/atom/target = target_ref?.resolve() if(isnull(target)) return @@ -916,14 +919,15 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." if(LAZYACCESS(modifiers, SHIFT_CLICK)) // screen objects don't do the normal Click() stuff so we'll cheat to_chat(usr, span_boldnotice("[name] - [desc]")) return FALSE - if(master && click_master) - return usr.client.Click(master, location, control, params) + var/datum/our_master = master_ref?.resolve() + if(our_master && click_master) + return usr.client.Click(our_master, location, control, params) return TRUE /atom/movable/screen/alert/Destroy() . = ..() severity = 0 - master = null + master_ref = null owner = null screen_loc = "" diff --git a/code/_onclick/hud/guardian.dm b/code/_onclick/hud/guardian.dm index f9963c1fa3a91..ba1d8f4565e64 100644 --- a/code/_onclick/hud/guardian.dm +++ b/code/_onclick/hud/guardian.dm @@ -1,7 +1,7 @@ /datum/hud/guardian ui_style = 'icons/hud/guardian.dmi' -/datum/hud/guardian/New(mob/living/simple_animal/hostile/guardian/owner) +/datum/hud/guardian/New(mob/living/basic/guardian/owner) ..() var/atom/movable/screen/using @@ -34,10 +34,10 @@ using.screen_loc = ui_back static_inventory += using -/datum/hud/dextrous/guardian/New(mob/living/simple_animal/hostile/guardian/owner) //for a dextrous guardian +/datum/hud/dextrous/guardian/New(mob/living/basic/guardian/owner) //for a dextrous guardian ..() var/atom/movable/screen/using - if(istype(owner, /mob/living/simple_animal/hostile/guardian/dextrous)) + if(istype(owner, /mob/living/basic/guardian/dextrous)) var/atom/movable/screen/inventory/inv_box inv_box = new /atom/movable/screen/inventory(null, src) @@ -86,8 +86,8 @@ /datum/hud/dextrous/guardian/persistent_inventory_update() if(!mymob) return - if(istype(mymob, /mob/living/simple_animal/hostile/guardian/dextrous)) - var/mob/living/simple_animal/hostile/guardian/dextrous/dex_guardian = mymob + if(istype(mymob, /mob/living/basic/guardian/dextrous)) + var/mob/living/basic/guardian/dextrous/dex_guardian = mymob if(hud_shown) if(dex_guardian.internal_storage) @@ -109,7 +109,7 @@ /atom/movable/screen/guardian/manifest/Click() if(isguardian(usr)) - var/mob/living/simple_animal/hostile/guardian/user = usr + var/mob/living/basic/guardian/user = usr user.manifest() @@ -120,7 +120,7 @@ /atom/movable/screen/guardian/recall/Click() if(isguardian(usr)) - var/mob/living/simple_animal/hostile/guardian/user = usr + var/mob/living/basic/guardian/user = usr user.recall() /atom/movable/screen/guardian/toggle_mode @@ -130,7 +130,7 @@ /atom/movable/screen/guardian/toggle_mode/Click() if(isguardian(usr)) - var/mob/living/simple_animal/hostile/guardian/user = usr + var/mob/living/basic/guardian/user = usr user.toggle_modes() /atom/movable/screen/guardian/toggle_mode/inactive @@ -153,7 +153,7 @@ /atom/movable/screen/guardian/communicate/Click() if(isguardian(usr)) - var/mob/living/simple_animal/hostile/guardian/user = usr + var/mob/living/basic/guardian/user = usr user.communicate() @@ -164,5 +164,5 @@ /atom/movable/screen/guardian/toggle_light/Click() if(isguardian(usr)) - var/mob/living/simple_animal/hostile/guardian/user = usr + var/mob/living/basic/guardian/user = usr user.toggle_light() diff --git a/code/_onclick/hud/ooze.dm b/code/_onclick/hud/ooze.dm index 1b466f7ff9796..0962b58126af9 100644 --- a/code/_onclick/hud/ooze.dm +++ b/code/_onclick/hud/ooze.dm @@ -1,4 +1,4 @@ -///Hud type with targetting dol and a nutrition bar +///Hud type with targeting dol and a nutrition bar /datum/hud/ooze/New(mob/living/owner) . = ..() diff --git a/code/_onclick/hud/rendering/plane_master.dm b/code/_onclick/hud/rendering/plane_master.dm deleted file mode 100644 index 4ae1c573ad4af..0000000000000 --- a/code/_onclick/hud/rendering/plane_master.dm +++ /dev/null @@ -1,684 +0,0 @@ -// I hate this place -INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) - -/atom/movable/screen/plane_master - screen_loc = "CENTER" - icon_state = "blank" - appearance_flags = PLANE_MASTER - blend_mode = BLEND_OVERLAY - plane = LOWEST_EVER_PLANE - /// Will be sent to the debug ui as a description for each plane - /// Also useful as a place to explain to coders how/why your plane works, and what it's meant to do - /// Plaintext and basic html are fine to use here. - /// I'll bonk you if I find you putting "lmao stuff" in here, make this useful. - var/documentation = "" - /// Our real alpha value, so alpha can persist through being hidden/shown - var/true_alpha = 255 - /// Tracks if we're using our true alpha, or being manipulated in some other way - var/alpha_enabled = TRUE - - /// The plane master group we're a member of, our "home" - var/datum/plane_master_group/home - - /// If our plane master allows for offsetting - /// Mostly used for planes that really don't need to be duplicated, like the hud planes - var/allows_offsetting = TRUE - /// Our offset from our "true" plane, see below - var/offset - /// When rendering multiz, lower levels get their own set of plane masters - /// Real plane here represents the "true" plane value of something, ignoring the offset required to handle lower levels - var/real_plane - - //--rendering relay vars-- - /// list of planes we will relay this plane's render to - var/list/render_relay_planes = list(RENDER_PLANE_GAME) - /// blend mode to apply to the render relay in case you dont want to use the plane_masters blend_mode - var/blend_mode_override - /// list of current relays this plane is utilizing to render - var/list/atom/movable/render_plane_relay/relays = list() - /// if render relays have already be generated - var/relays_generated = FALSE - - /// If this plane master should be hidden from the player at roundstart - /// We do this so PMs can opt into being temporary, to reduce load on clients - var/start_hidden = FALSE - /// If this plane master is being forced to hide. - /// Hidden PMs will dump ANYTHING relayed or drawn onto them. Be careful with this - /// Remember: a hidden plane master will dump anything drawn directly to it onto the output render. It does NOT hide its contents - /// Use alpha for that - var/force_hidden = FALSE - - /// If this plane should be scaled by multiz - /// Planes with this set should NEVER be relay'd into each other, as that will cause visual fuck - var/multiz_scaled = TRUE - - /// Bitfield that describes how this plane master will render if its z layer is being "optimized" - /// If a plane master is NOT critical, it will be completely dropped if we start to render outside a client's multiz boundary prefs - /// Of note: most of the time we will relay renders to non critical planes in this stage. so the plane master will end up drawing roughly "in order" with its friends - /// This is NOT done for parallax and other problem children, because the rules of BLEND_MULTIPLY appear to not behave as expected :( - /// This will also just make debugging harder, because we do fragile things in order to ensure things operate as epected. I'm sorry - /// Compile time - /// See [code\__DEFINES\layers.dm] for our bitflags - var/critical = NONE - - /// If this plane master is outside of our visual bounds right now - var/is_outside_bounds = FALSE - -/atom/movable/screen/plane_master/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset = 0) - . = ..() - src.offset = offset - true_alpha = alpha - real_plane = plane - - if(!set_home(home)) - return INITIALIZE_HINT_QDEL - update_offset() - if(!documentation && !(istype(src, /atom/movable/screen/plane_master) || istype(src, /atom/movable/screen/plane_master/rendering_plate))) - stack_trace("Plane master created without a description. Document how your thing works so people will know in future, and we can display it in the debug menu") - if(start_hidden) - hide_plane(home.our_hud?.mymob) - generate_render_relays() - -/atom/movable/screen/plane_master/Destroy() - if(home) - // NOTE! We do not clear ourselves from client screens - // We relay on whoever qdel'd us to reset our hud, and properly purge us - home.plane_masters -= "[plane]" - home = null - . = ..() - QDEL_LIST(relays) - -/// Sets the plane group that owns us, it also determines what screen we render to -/// Returns FALSE if the set_home fails, TRUE otherwise -/atom/movable/screen/plane_master/proc/set_home(datum/plane_master_group/home) - if(!istype(home, /datum/plane_master_group)) - return FALSE - src.home = home - if(home.map) - screen_loc = "[home.map]:[screen_loc]" - assigned_map = home.map - return TRUE - -/// Updates our "offset", basically what layer of multiz we're meant to render -/// Top is 0, goes up as you go down -/// It's taken into account by render targets and relays, so we gotta make sure they're on the same page -/atom/movable/screen/plane_master/proc/update_offset() - name = "[initial(name)] #[offset]" - SET_PLANE_W_SCALAR(src, real_plane, offset) - for(var/i in 1 to length(render_relay_planes)) - render_relay_planes[i] = GET_NEW_PLANE(render_relay_planes[i], offset) - if(initial(render_target)) - render_target = OFFSET_RENDER_TARGET(initial(render_target), offset) - -/atom/movable/screen/plane_master/proc/set_alpha(new_alpha) - true_alpha = new_alpha - if(!alpha_enabled) - return - alpha = new_alpha - -/atom/movable/screen/plane_master/proc/disable_alpha() - alpha_enabled = FALSE - alpha = 0 - -/atom/movable/screen/plane_master/proc/enable_alpha() - alpha_enabled = TRUE - alpha = true_alpha - -/// Shows a plane master to the passed in mob -/// Override this to apply unique effects and such -/// Returns TRUE if the call is allowed, FALSE otherwise -/atom/movable/screen/plane_master/proc/show_to(mob/mymob) - SHOULD_CALL_PARENT(TRUE) - if(force_hidden) - return FALSE - - var/client/our_client = mymob?.canon_client - // Alright, let's get this out of the way - // Mobs can move z levels without their client. If this happens, we need to ensure critical display settings are respected - // This is done here. Mild to severe pain but it's nessesary - if(check_outside_bounds()) - if(!(critical & PLANE_CRITICAL_DISPLAY)) - return FALSE - if(!our_client) - return TRUE - our_client.screen += src - - if(!(critical & PLANE_CRITICAL_NO_RELAY)) - our_client.screen += relays - return TRUE - return TRUE - - if(!our_client) - return TRUE - - our_client.screen += src - our_client.screen += relays - return TRUE - -/// Hook to allow planes to work around is_outside_bounds -/// Return false to allow a show, true otherwise -/atom/movable/screen/plane_master/proc/check_outside_bounds() - return is_outside_bounds - -/// Hides a plane master from the passeed in mob -/// Do your effect cleanup here -/atom/movable/screen/plane_master/proc/hide_from(mob/oldmob) - SHOULD_CALL_PARENT(TRUE) - var/client/their_client = oldmob?.client - if(!their_client) - return - their_client.screen -= src - their_client.screen -= relays - - -/// Forces this plane master to hide, until unhide_plane is called -/// This allows us to disable unused PMs without breaking anything else -/atom/movable/screen/plane_master/proc/hide_plane(mob/cast_away) - force_hidden = TRUE - hide_from(cast_away) - -/// Disables any forced hiding, allows the plane master to be used as normal -/atom/movable/screen/plane_master/proc/unhide_plane(mob/enfold) - force_hidden = FALSE - show_to(enfold) - -/// Mirrors our force hidden state to the hidden state of the plane that came before, assuming it's valid -/// This allows us to mirror any hidden sets from before we were created, no matter how low that chance is -/atom/movable/screen/plane_master/proc/mirror_parent_hidden() - var/mob/our_mob = home?.our_hud?.mymob - var/atom/movable/screen/plane_master/true_plane = our_mob?.hud_used?.get_plane_master(plane) - if(true_plane == src || !true_plane) - return - - if(true_plane.force_hidden == force_hidden) - return - - // If one of us already exists and it's not hidden, unhide ourselves - if(true_plane.force_hidden) - hide_plane(our_mob) - else - unhide_plane(our_mob) - -/atom/movable/screen/plane_master/proc/outside_bounds(mob/relevant) - if(force_hidden || is_outside_bounds) - return - is_outside_bounds = TRUE - // If we're of critical importance, AND we're below the rendering layer - if(critical & PLANE_CRITICAL_DISPLAY) - // We here assume that your render target starts with * - if(critical & PLANE_CRITICAL_CUT_RENDER && render_target) - render_target = copytext_char(render_target, 2) - if(!(critical & PLANE_CRITICAL_NO_RELAY)) - return - var/client/our_client = relevant.client - if(our_client) - for(var/atom/movable/render_plane_relay/relay as anything in relays) - our_client.screen -= relay - - return - hide_from(relevant) - -/atom/movable/screen/plane_master/proc/inside_bounds(mob/relevant) - is_outside_bounds = FALSE - if(critical & PLANE_CRITICAL_DISPLAY) - // We here assume that your render target starts with * - if(critical & PLANE_CRITICAL_CUT_RENDER && render_target) - render_target = "*[render_target]" - - if(!(critical & PLANE_CRITICAL_NO_RELAY)) - return - var/client/our_client = relevant.client - if(our_client) - for(var/atom/movable/render_plane_relay/relay as anything in relays) - our_client.screen += relay - - return - show_to(relevant) - -/atom/movable/screen/plane_master/clickcatcher - name = "Click Catcher" - documentation = "Contains the screen object we use as a backdrop to catch clicks on portions of the screen that would otherwise contain nothing else. \ -
Will always be below almost everything else" - plane = CLICKCATCHER_PLANE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - multiz_scaled = FALSE - critical = PLANE_CRITICAL_DISPLAY - -/atom/movable/screen/plane_master/clickcatcher/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) - . = ..() - RegisterSignal(SSmapping, COMSIG_PLANE_OFFSET_INCREASE, PROC_REF(offset_increased)) - offset_increased(SSmapping, 0, SSmapping.max_plane_offset) - -/atom/movable/screen/plane_master/clickcatcher/proc/offset_increased(datum/source, old_off, new_off) - SIGNAL_HANDLER - // We only want need the lowest level - // If my system better supported changing PM plane values mid op I'd do that, but I do NOT so - if(new_off > offset) - hide_plane(home?.our_hud?.mymob) - -/atom/movable/screen/plane_master/parallax_white - name = "Parallax whitifier" - documentation = "Essentially a backdrop for the parallax plane. We're rendered just below it, so we'll be multiplied by its well, parallax.\ -
If you want something to look as if it has parallax on it, draw it to this plane." - plane = PLANE_SPACE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - render_relay_planes = list(RENDER_PLANE_GAME, LIGHT_MASK_PLANE) - critical = PLANE_CRITICAL_FUCKO_PARALLAX // goes funny when touched. no idea why I don't trust byond - -/atom/movable/screen/plane_master/parallax_white/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) - . = ..() - add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_SPACE_LAYER) - -///Contains space parallax -/atom/movable/screen/plane_master/parallax - name = "Parallax" - documentation = "Contains parallax, or to be more exact the screen objects that hold parallax.\ -
Note the BLEND_MULTIPLY. The trick here is how low our plane value is. Because of that, we draw below almost everything in the game.\ -
We abuse this to ensure we multiply against the Parallax whitifier plane, or space's plane. It's set to full white, so when you do the multiply you just get parallax out where it well, makes sense to be.\ -
Also notice that the parent parallax plane is mirrored down to all children. We want to support viewing parallax across all z levels at once." - plane = PLANE_SPACE_PARALLAX - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - blend_mode = BLEND_MULTIPLY - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - multiz_scaled = FALSE - -/atom/movable/screen/plane_master/parallax/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) - . = ..() - if(offset != 0) - // You aren't the source? don't change yourself - return - RegisterSignal(SSmapping, COMSIG_PLANE_OFFSET_INCREASE, PROC_REF(on_offset_increase)) - RegisterSignal(SSdcs, COMSIG_NARSIE_SUMMON_UPDATE, PROC_REF(narsie_modified)) - if(GLOB.narsie_summon_count >= 1) - narsie_start_midway(GLOB.narsie_effect_last_modified) // We assume we're on the start, so we can use this number - offset_increase(0, SSmapping.max_plane_offset) - -/atom/movable/screen/plane_master/parallax/proc/on_offset_increase(datum/source, old_offset, new_offset) - SIGNAL_HANDLER - offset_increase(old_offset, new_offset) - -/atom/movable/screen/plane_master/parallax/proc/offset_increase(old_offset, new_offset) - // Parallax will be mirrored down to any new planes that are added, so it will properly render across mirage borders - for(var/offset in old_offset to new_offset) - if(offset != 0) - // Overlay so we don't multiply twice, and thus fuck up our rendering - add_relay_to(GET_NEW_PLANE(plane, offset), BLEND_OVERLAY) - -// Hacky shit to ensure parallax works in perf mode -/atom/movable/screen/plane_master/parallax/outside_bounds(mob/relevant) - if(offset == 0) - remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_GAME, 0)) - is_outside_bounds = TRUE // I'm sorry :( - return - // If we can't render, and we aren't the bottom layer, don't render us - // This way we only multiply against stuff that's not fullwhite space - var/atom/movable/screen/plane_master/parent_parallax = home.our_hud.get_plane_master(PLANE_SPACE_PARALLAX) - var/turf/viewing_turf = get_turf(relevant) - if(!viewing_turf || offset != GET_LOWEST_STACK_OFFSET(viewing_turf.z)) - parent_parallax.remove_relay_from(plane) - else - parent_parallax.add_relay_to(plane, BLEND_OVERLAY) - return ..() - -/atom/movable/screen/plane_master/parallax/inside_bounds(mob/relevant) - if(offset == 0) - add_relay_to(GET_NEW_PLANE(RENDER_PLANE_GAME, 0)) - is_outside_bounds = FALSE - return - // Always readd, just in case we lost it - var/atom/movable/screen/plane_master/parent_parallax = home.our_hud.get_plane_master(PLANE_SPACE_PARALLAX) - parent_parallax.add_relay_to(plane, BLEND_OVERLAY) - return ..() - -// Needs to handle rejoining on a lower z level, so we NEED to readd old planes -/atom/movable/screen/plane_master/parallax/check_outside_bounds() - // If we're outside bounds AND we're the 0th plane, we need to show cause parallax is hacked to hell - return offset != 0 && is_outside_bounds - -/// Starts the narsie animation midway, so we can catch up to everyone else quickly -/atom/movable/screen/plane_master/parallax/proc/narsie_start_midway(start_time) - var/time_elapsed = world.time - start_time - narsie_summoned_effect(max(16 SECONDS - time_elapsed, 0)) - -/// Starts the narsie animation, make us grey, then red -/atom/movable/screen/plane_master/parallax/proc/narsie_modified(datum/source, new_count) - SIGNAL_HANDLER - if(new_count >= 1) - narsie_summoned_effect(16 SECONDS) - else - narsie_unsummoned() - -/atom/movable/screen/plane_master/parallax/proc/narsie_summoned_effect(animate_time) - if(GLOB.narsie_summon_count >= 2) - var/static/list/nightmare_parallax = list(255,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, -130,0,0,0) - animate(src, color = nightmare_parallax, time = animate_time) - return - - var/static/list/grey_parallax = list(0.4,0.4,0.4,0, 0.4,0.4,0.4,0, 0.4,0.4,0.4,0, 0,0,0,1, -0.1,-0.1,-0.1,0) - // We're gonna animate ourselves grey - // Then, once it's done, about 40 seconds into the event itself, we're gonna start doin some shit. see below - animate(src, color = grey_parallax, time = animate_time) - -/atom/movable/screen/plane_master/parallax/proc/narsie_unsummoned() - animate(src, color = null, time = 8 SECONDS) - -/atom/movable/screen/plane_master/gravpulse - name = "Gravpulse" - documentation = "Ok so this one's fun. Basically, we want to be able to distort the game plane when a grav annom is around.\ -
So we draw the pattern we want to use to this plane, and it's then used as a render target by a distortion filter on the game plane.\ -
Note the blend mode and lack of relay targets. This plane exists only to distort, it's never rendered anywhere." - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - plane = GRAVITY_PULSE_PLANE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - blend_mode = BLEND_ADD - render_target = GRAVITY_PULSE_RENDER_TARGET - render_relay_planes = list() - -///Contains just the floor -/atom/movable/screen/plane_master/floor - name = "Floor" - documentation = "The well, floor. This is mostly used as a sorting mechanism, but it also lets us create a \"border\" around the game world plane, so its drop shadow will actually work." - plane = FLOOR_PLANE - render_relay_planes = list(RENDER_PLANE_GAME, LIGHT_MASK_PLANE) - -/atom/movable/screen/plane_master/transparent_floor - name = "Transparent Floor" - documentation = "Really just openspace, stuff that is a turf but has no color or alpha whatsoever.\ -
We use this to draw to just the light mask plane, cause if it's not there we get holes of blackness over openspace" - plane = TRANSPARENT_FLOOR_PLANE - render_relay_planes = list(LIGHT_MASK_PLANE) - // Needs to be critical or it uh, it'll look white - critical = PLANE_CRITICAL_DISPLAY|PLANE_CRITICAL_NO_RELAY - -/atom/movable/screen/plane_master/floor/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) - . = ..() - add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_FLOOR_LAYER, relay_color = GLOB.em_block_color) - -/atom/movable/screen/plane_master/wall - name = "Wall" - documentation = "Holds all walls. We render this onto the game world. Separate so we can use this + space and floor planes as a guide for where byond blackness is NOT." - plane = WALL_PLANE - render_relay_planes = list(RENDER_PLANE_GAME_WORLD, LIGHT_MASK_PLANE) - -/atom/movable/screen/plane_master/wall/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) - . = ..() - add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_WALL_LAYER, relay_color = GLOB.em_block_color) - -/atom/movable/screen/plane_master/game - name = "Lower game world" - documentation = "Exists mostly because of FOV shit. Basically, if you've just got a normal not ABOVE fov thing, and you don't want it masked, stick it here yeah?" - plane = GAME_PLANE - render_relay_planes = list(RENDER_PLANE_GAME_WORLD) - -/atom/movable/screen/plane_master/game_world_fov_hidden - name = "lower game world fov hidden" - documentation = "If you want something to be hidden by fov, stick it on this plane. We're masked by the fov blocker plane, so the items on us can actually well, disappear." - plane = GAME_PLANE_FOV_HIDDEN - render_relay_planes = list(RENDER_PLANE_GAME_WORLD) - -/atom/movable/screen/plane_master/game_world_fov_hidden/Initialize(mapload, datum/hud/hud_owner) - . = ..() - add_filter("vision_cone", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(FIELD_OF_VISION_BLOCKER_RENDER_TARGET, offset), flags = MASK_INVERSE)) - -/atom/movable/screen/plane_master/field_of_vision_blocker - name = "Field of vision blocker" - documentation = "This is one of those planes that's only used as a filter. It masks out things that want to be hidden by fov.\ -
Literally just contains FOV images, or masks." - plane = FIELD_OF_VISION_BLOCKER_PLANE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - render_target = FIELD_OF_VISION_BLOCKER_RENDER_TARGET - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - render_relay_planes = list() - // We do NOT allow offsetting, because there's no case where you would want to block only one layer, at least currently - allows_offsetting = FALSE - start_hidden = TRUE - // We mark as multiz_scaled FALSE so transforms don't effect us, and we draw to the planes below us as if they were us. - // This is safe because we will ALWAYS be on the top z layer, so it DON'T MATTER - multiz_scaled = FALSE - -/atom/movable/screen/plane_master/field_of_vision_blocker/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) - . = ..() - mirror_parent_hidden() - -/atom/movable/screen/plane_master/game_world_upper - name = "Upper game world" - documentation = "Ok so fov is kinda fucky, because planes in byond serve both as effect groupings and as rendering orderers. Since that's true, we need a plane that we can stick stuff that draws above fov blocked stuff on." - plane = GAME_PLANE_UPPER - render_relay_planes = list(RENDER_PLANE_GAME_WORLD) - -/atom/movable/screen/plane_master/wall_upper - name = "Upper wall" - documentation = "There are some walls that want to render above most things (mostly minerals since they shift over.\ -
We draw them to their own plane so we can hijack them for our emissive mask stuff" - plane = WALL_PLANE_UPPER - render_relay_planes = list(RENDER_PLANE_GAME_WORLD, LIGHT_MASK_PLANE) - -/atom/movable/screen/plane_master/wall_upper/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) - . = ..() - add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_WALL_LAYER, relay_color = GLOB.em_block_color) - -/atom/movable/screen/plane_master/game_world_upper_fov_hidden - name = "Upper game world fov hidden" - documentation = "Just as we need a place to draw things \"above\" the hidden fov plane, we also need to be able to hide stuff that draws over the upper game plane." - plane = GAME_PLANE_UPPER_FOV_HIDDEN - render_relay_planes = list(RENDER_PLANE_GAME_WORLD) - -/atom/movable/screen/plane_master/game_world_upper_fov_hidden/Initialize(mapload, datum/hud/hud_owner) - . = ..() - // Dupe of the other hidden plane - add_filter("vision_cone", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(FIELD_OF_VISION_BLOCKER_RENDER_TARGET, offset), flags = MASK_INVERSE)) - -/atom/movable/screen/plane_master/seethrough - name = "Seethrough" - documentation = "Holds the seethrough versions (done using image overrides) of large objects. Mouse transparent, so you can click through them." - plane = SEETHROUGH_PLANE - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - render_relay_planes = list(RENDER_PLANE_GAME_WORLD) - start_hidden = TRUE - -/atom/movable/screen/plane_master/game_world_above - name = "Above game world" - documentation = "We need a place that's unmasked by fov that also draws above the upper game world fov hidden plane. I told you fov was hacky man." - plane = ABOVE_GAME_PLANE - render_relay_planes = list(RENDER_PLANE_GAME_WORLD) - -/** - * Plane master that byond will by default draw to - * Shouldn't be used, exists to prevent people using plane 0 - * NOTE: If we used SEE_BLACKNESS on a map format that wasn't SIDE_MAP, this is where its darkness would land - * This would allow us to control it and do fun things. But we can't because side map doesn't support it, so this is just a stub - */ -/atom/movable/screen/plane_master/default - name = "Default" - documentation = "This is quite fiddly, so bear with me. By default (in byond) everything in the game is rendered onto plane 0. It's the default plane. \ -
But, because we've moved everything we control off plane 0, all that's left is stuff byond internally renders. \ -
What I'd like to do with this is capture byond blackness by giving mobs the SEE_BLACKNESS sight flag. \ -
But we CAN'T because SEE_BLACKNESS does not work with our rendering format. So I just eat it I guess" - plane = DEFAULT_PLANE - multiz_scaled = FALSE - start_hidden = TRUE // Doesn't DO anything, exists to hold this place - -/atom/movable/screen/plane_master/area - name = "Area" - documentation = "Holds the areas themselves, which ends up meaning it holds any overlays/effects we apply to areas. NOT snow or rad storms, those go on above lighting" - plane = AREA_PLANE - -/atom/movable/screen/plane_master/massive_obj - name = "Massive object" - documentation = "Huge objects need to render above everything else on the game plane, otherwise they'd well, get clipped and look not that huge. This does that." - plane = MASSIVE_OBJ_PLANE - -/atom/movable/screen/plane_master/point - name = "Point" - documentation = "I mean like, what do you want me to say? Points draw over pretty much everything else, so they get their own plane. Remember we layer render relays to draw planes in their proper order on render plates." - plane = POINT_PLANE - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - -///Contains all turf lighting -/atom/movable/screen/plane_master/turf_lighting - name = "Turf Lighting" - documentation = "Contains all lighting drawn to turfs. Not so complex, draws directly onto the lighting plate." - plane = LIGHTING_PLANE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - render_relay_planes = list(RENDER_PLANE_LIGHTING) - blend_mode_override = BLEND_ADD - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - critical = PLANE_CRITICAL_DISPLAY - -/// This will not work through multiz, because of a byond bug with BLEND_MULTIPLY -/// Bug report is up, waiting on a fix -/atom/movable/screen/plane_master/o_light_visual - name = "Overlight light visual" - documentation = "Holds overlay lighting objects, or the sort of lighting that's a well, overlay stuck to something.\ -
Exists because lighting updating is really slow, and movement needs to feel smooth.\ -
We draw to the game plane, and mask out space for ourselves on the lighting plane so any color we have has the chance to display." - plane = O_LIGHTING_VISUAL_PLANE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - render_target = O_LIGHTING_VISUAL_RENDER_TARGET - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - blend_mode = BLEND_MULTIPLY - critical = PLANE_CRITICAL_DISPLAY - -/atom/movable/screen/plane_master/above_lighting - name = "Above lighting" - plane = ABOVE_LIGHTING_PLANE - documentation = "Anything on the game plane that needs a space to draw on that will be above the lighting plane.\ -
Mostly little alerts and effects, also sometimes contains things that are meant to look as if they glow." - -/** - * Handles emissive overlays and emissive blockers. - */ -/atom/movable/screen/plane_master/emissive - name = "Emissive" - documentation = "Holds things that will be used to mask the lighting plane later on. Masked by the Emissive Mask plane to ensure we don't emiss out under a wall.\ -
Relayed onto the Emissive render plane to do the actual masking of lighting, since we need to be transformed and other emissive stuff needs to be transformed too.\ -
Don't want to double scale now." - plane = EMISSIVE_PLANE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - render_relay_planes = list(EMISSIVE_RENDER_PLATE) - critical = PLANE_CRITICAL_DISPLAY - -/atom/movable/screen/plane_master/pipecrawl - name = "Pipecrawl" - documentation = "Holds pipecrawl images generated during well, pipecrawling.\ -
Has a few effects and a funky color matrix designed to make things a bit more visually readable." - plane = PIPECRAWL_IMAGES_PLANE - start_hidden = TRUE - -/atom/movable/screen/plane_master/pipecrawl/Initialize(mapload, datum/hud/hud_owner) - . = ..() - // Makes everything on this plane slightly brighter - // Has a nice effect, makes thing stand out - color = list(1.2,0,0,0, 0,1.2,0,0, 0,0,1.2,0, 0,0,0,1, 0,0,0,0) - // This serves a similar purpose, I want the pipes to pop - add_filter("pipe_dropshadow", 1, drop_shadow_filter(x = -1, y= -1, size = 1, color = "#0000007A")) - mirror_parent_hidden() - -/atom/movable/screen/plane_master/camera_static - name = "Camera static" - documentation = "Holds camera static images. Usually only visible to people who can well, see static.\ -
We use images rather then vis contents because they're lighter on maptick, and maptick sucks butt." - plane = CAMERA_STATIC_PLANE - -/atom/movable/screen/plane_master/camera_static/show_to(mob/mymob) - . = ..() - if(!.) - return - var/datum/hud/our_hud = home.our_hud - if(isnull(our_hud)) - return - - // We'll hide the slate if we're not seeing through a camera eye - // This can call on a cycle cause we don't clear in hide_from - // Yes this is the best way of hooking into the hud, I hate myself too - RegisterSignal(our_hud, COMSIG_HUD_EYE_CHANGED, PROC_REF(eye_changed), override = TRUE) - eye_changed(our_hud, null, our_hud.mymob?.canon_client?.eye) - -/atom/movable/screen/plane_master/camera_static/proc/eye_changed(datum/hud/source, atom/old_eye, atom/new_eye) - SIGNAL_HANDLER - - if(!isaicamera(new_eye)) - if(!force_hidden) - hide_plane(source.mymob) - return - - if(force_hidden) - unhide_plane(source.mymob) - -/atom/movable/screen/plane_master/high_game - name = "High Game" - documentation = "Holds anything that wants to be displayed above the rest of the game plane, and doesn't want to be clickable. \ -
This includes atmos debug overlays, blind sound images, and mining scanners. \ -
Really only exists for its layering potential, we don't use this for any vfx" - plane = HIGH_GAME_PLANE - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - -/atom/movable/screen/plane_master/ghost - name = "Ghost" - documentation = "Ghosts draw here, so they don't get mixed up in the visuals of the game world. Note, this is not not how we HIDE ghosts from people, that's done with invisible and see_invisible." - plane = GHOST_PLANE - render_relay_planes = list(RENDER_PLANE_NON_GAME) - -/atom/movable/screen/plane_master/fullscreen - name = "Fullscreen" - documentation = "Holds anything that applies to or above the full screen. \ -
Note, it's still rendered underneath hud objects, but this lets us control the order that things like death/damage effects render in." - plane = FULLSCREEN_PLANE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - render_relay_planes = list(RENDER_PLANE_NON_GAME) - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - allows_offsetting = FALSE - -/atom/movable/screen/plane_master/runechat - name = "Runechat" - documentation = "Holds runechat images, that text that pops up when someone say something. Uses a dropshadow to well, look nice." - plane = RUNECHAT_PLANE - render_relay_planes = list(RENDER_PLANE_NON_GAME) - -/atom/movable/screen/plane_master/runechat/show_to(mob/mymob) - . = ..() - if(!.) - return - remove_filter("AO") - if(istype(mymob) && mymob.canon_client?.prefs?.read_preference(/datum/preference/toggle/ambient_occlusion)) - add_filter("AO", 1, drop_shadow_filter(x = 0, y = -2, size = 4, color = "#04080FAA")) - -/atom/movable/screen/plane_master/balloon_chat - name = "Balloon chat" - documentation = "Holds ballon chat images, those little text bars that pop up for a second when you do some things. NOT runechat." - plane = BALLOON_CHAT_PLANE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - render_relay_planes = list(RENDER_PLANE_NON_GAME) - -/atom/movable/screen/plane_master/hud - name = "HUD" - documentation = "Contains anything that want to be rendered on the hud. Typically is just screen elements." - plane = HUD_PLANE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - render_relay_planes = list(RENDER_PLANE_NON_GAME) - allows_offsetting = FALSE - -/atom/movable/screen/plane_master/above_hud - name = "Above HUD" - documentation = "Anything that wants to be drawn ABOVE the rest of the hud. Typically close buttons and other elements that need to be always visible. Think preventing draggable action button memes." - plane = ABOVE_HUD_PLANE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - render_relay_planes = list(RENDER_PLANE_NON_GAME) - allows_offsetting = FALSE - -/atom/movable/screen/plane_master/splashscreen - name = "Splashscreen" - documentation = "Cinematics and the splash screen." - plane = SPLASHSCREEN_PLANE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - render_relay_planes = list(RENDER_PLANE_NON_GAME) - allows_offsetting = FALSE - -/atom/movable/screen/plane_master/escape_menu - name = "Escape Menu" - documentation = "Anything relating to the escape menu." - plane = ESCAPE_MENU_PLANE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - render_relay_planes = list(RENDER_PLANE_MASTER) - allows_offsetting = FALSE diff --git a/code/_onclick/hud/rendering/plane_masters/_plane_master.dm b/code/_onclick/hud/rendering/plane_masters/_plane_master.dm new file mode 100644 index 0000000000000..13f94fa9f5aa0 --- /dev/null +++ b/code/_onclick/hud/rendering/plane_masters/_plane_master.dm @@ -0,0 +1,236 @@ +// I hate this place +INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) + +/atom/movable/screen/plane_master + screen_loc = "CENTER" + icon_state = "blank" + appearance_flags = PLANE_MASTER + blend_mode = BLEND_OVERLAY + plane = LOWEST_EVER_PLANE + /// Will be sent to the debug ui as a description for each plane + /// Also useful as a place to explain to coders how/why your plane works, and what it's meant to do + /// Plaintext and basic html are fine to use here. + /// I'll bonk you if I find you putting "lmao stuff" in here, make this useful. + var/documentation = "" + /// Our real alpha value, so alpha can persist through being hidden/shown + var/true_alpha = 255 + /// Tracks if we're using our true alpha, or being manipulated in some other way + var/alpha_enabled = TRUE + + /// The plane master group we're a member of, our "home" + var/datum/plane_master_group/home + + /// If our plane master allows for offsetting + /// Mostly used for planes that really don't need to be duplicated, like the hud planes + var/allows_offsetting = TRUE + /// Our offset from our "true" plane, see below + var/offset + /// When rendering multiz, lower levels get their own set of plane masters + /// Real plane here represents the "true" plane value of something, ignoring the offset required to handle lower levels + var/real_plane + + //--rendering relay vars-- + /// list of planes we will relay this plane's render to + var/list/render_relay_planes = list(RENDER_PLANE_GAME) + /// blend mode to apply to the render relay in case you dont want to use the plane_masters blend_mode + var/blend_mode_override + /// list of current relays this plane is utilizing to render + var/list/atom/movable/render_plane_relay/relays = list() + /// if render relays have already be generated + var/relays_generated = FALSE + + /// If this plane master should be hidden from the player at roundstart + /// We do this so PMs can opt into being temporary, to reduce load on clients + var/start_hidden = FALSE + /// If this plane master is being forced to hide. + /// Hidden PMs will dump ANYTHING relayed or drawn onto them. Be careful with this + /// Remember: a hidden plane master will dump anything drawn directly to it onto the output render. It does NOT hide its contents + /// Use alpha for that + var/force_hidden = FALSE + + /// If this plane should be scaled by multiz + /// Planes with this set should NEVER be relay'd into each other, as that will cause visual fuck + var/multiz_scaled = TRUE + + /// Bitfield that describes how this plane master will render if its z layer is being "optimized" + /// If a plane master is NOT critical, it will be completely dropped if we start to render outside a client's multiz boundary prefs + /// Of note: most of the time we will relay renders to non critical planes in this stage. so the plane master will end up drawing roughly "in order" with its friends + /// This is NOT done for parallax and other problem children, because the rules of BLEND_MULTIPLY appear to not behave as expected :( + /// This will also just make debugging harder, because we do fragile things in order to ensure things operate as epected. I'm sorry + /// Compile time + /// See [code\__DEFINES\layers.dm] for our bitflags + var/critical = NONE + + /// If this plane master is outside of our visual bounds right now + var/is_outside_bounds = FALSE + +/atom/movable/screen/plane_master/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset = 0) + . = ..() + src.offset = offset + true_alpha = alpha + real_plane = plane + + if(!set_home(home)) + return INITIALIZE_HINT_QDEL + update_offset() + if(!documentation && !(istype(src, /atom/movable/screen/plane_master) || istype(src, /atom/movable/screen/plane_master/rendering_plate))) + stack_trace("Plane master created without a description. Document how your thing works so people will know in future, and we can display it in the debug menu") + if(start_hidden) + hide_plane(home.our_hud?.mymob) + generate_render_relays() + +/atom/movable/screen/plane_master/Destroy() + if(home) + // NOTE! We do not clear ourselves from client screens + // We relay on whoever qdel'd us to reset our hud, and properly purge us + home.plane_masters -= "[plane]" + home = null + . = ..() + QDEL_LIST(relays) + +/// Sets the plane group that owns us, it also determines what screen we render to +/// Returns FALSE if the set_home fails, TRUE otherwise +/atom/movable/screen/plane_master/proc/set_home(datum/plane_master_group/home) + if(!istype(home, /datum/plane_master_group)) + return FALSE + src.home = home + if(home.map) + screen_loc = "[home.map]:[screen_loc]" + assigned_map = home.map + return TRUE + +/// Updates our "offset", basically what layer of multiz we're meant to render +/// Top is 0, goes up as you go down +/// It's taken into account by render targets and relays, so we gotta make sure they're on the same page +/atom/movable/screen/plane_master/proc/update_offset() + name = "[initial(name)] #[offset]" + SET_PLANE_W_SCALAR(src, real_plane, offset) + for(var/i in 1 to length(render_relay_planes)) + render_relay_planes[i] = GET_NEW_PLANE(render_relay_planes[i], offset) + if(initial(render_target)) + render_target = OFFSET_RENDER_TARGET(initial(render_target), offset) + +/atom/movable/screen/plane_master/proc/set_alpha(new_alpha) + true_alpha = new_alpha + if(!alpha_enabled) + return + alpha = new_alpha + +/atom/movable/screen/plane_master/proc/disable_alpha() + alpha_enabled = FALSE + alpha = 0 + +/atom/movable/screen/plane_master/proc/enable_alpha() + alpha_enabled = TRUE + alpha = true_alpha + +/// Shows a plane master to the passed in mob +/// Override this to apply unique effects and such +/// Returns TRUE if the call is allowed, FALSE otherwise +/atom/movable/screen/plane_master/proc/show_to(mob/mymob) + SHOULD_CALL_PARENT(TRUE) + if(force_hidden) + return FALSE + + var/client/our_client = mymob?.canon_client + // Alright, let's get this out of the way + // Mobs can move z levels without their client. If this happens, we need to ensure critical display settings are respected + // This is done here. Mild to severe pain but it's nessesary + if(check_outside_bounds()) + if(!(critical & PLANE_CRITICAL_DISPLAY)) + return FALSE + if(!our_client) + return TRUE + our_client.screen += src + + if(!(critical & PLANE_CRITICAL_NO_RELAY)) + our_client.screen += relays + return TRUE + return TRUE + + if(!our_client) + return TRUE + + our_client.screen += src + our_client.screen += relays + return TRUE + +/// Hook to allow planes to work around is_outside_bounds +/// Return false to allow a show, true otherwise +/atom/movable/screen/plane_master/proc/check_outside_bounds() + return is_outside_bounds + +/// Hides a plane master from the passeed in mob +/// Do your effect cleanup here +/atom/movable/screen/plane_master/proc/hide_from(mob/oldmob) + SHOULD_CALL_PARENT(TRUE) + var/client/their_client = oldmob?.client + if(!their_client) + return + their_client.screen -= src + their_client.screen -= relays + + +/// Forces this plane master to hide, until unhide_plane is called +/// This allows us to disable unused PMs without breaking anything else +/atom/movable/screen/plane_master/proc/hide_plane(mob/cast_away) + force_hidden = TRUE + hide_from(cast_away) + +/// Disables any forced hiding, allows the plane master to be used as normal +/atom/movable/screen/plane_master/proc/unhide_plane(mob/enfold) + force_hidden = FALSE + show_to(enfold) + +/// Mirrors our force hidden state to the hidden state of the plane that came before, assuming it's valid +/// This allows us to mirror any hidden sets from before we were created, no matter how low that chance is +/atom/movable/screen/plane_master/proc/mirror_parent_hidden() + var/mob/our_mob = home?.our_hud?.mymob + var/atom/movable/screen/plane_master/true_plane = our_mob?.hud_used?.get_plane_master(plane) + if(true_plane == src || !true_plane) + return + + if(true_plane.force_hidden == force_hidden) + return + + // If one of us already exists and it's not hidden, unhide ourselves + if(true_plane.force_hidden) + hide_plane(our_mob) + else + unhide_plane(our_mob) + +/atom/movable/screen/plane_master/proc/outside_bounds(mob/relevant) + if(force_hidden || is_outside_bounds) + return + is_outside_bounds = TRUE + // If we're of critical importance, AND we're below the rendering layer + if(critical & PLANE_CRITICAL_DISPLAY) + // We here assume that your render target starts with * + if(critical & PLANE_CRITICAL_CUT_RENDER && render_target) + render_target = copytext_char(render_target, 2) + if(!(critical & PLANE_CRITICAL_NO_RELAY)) + return + var/client/our_client = relevant.client + if(our_client) + for(var/atom/movable/render_plane_relay/relay as anything in relays) + our_client.screen -= relay + + return + hide_from(relevant) + +/atom/movable/screen/plane_master/proc/inside_bounds(mob/relevant) + is_outside_bounds = FALSE + if(critical & PLANE_CRITICAL_DISPLAY) + // We here assume that your render target starts with * + if(critical & PLANE_CRITICAL_CUT_RENDER && render_target) + render_target = "*[render_target]" + + if(!(critical & PLANE_CRITICAL_NO_RELAY)) + return + var/client/our_client = relevant.client + if(our_client) + for(var/atom/movable/render_plane_relay/relay as anything in relays) + our_client.screen += relay + + return + show_to(relevant) diff --git a/code/_onclick/hud/rendering/plane_masters/camera_static.dm b/code/_onclick/hud/rendering/plane_masters/camera_static.dm new file mode 100644 index 0000000000000..4cb3436a7a490 --- /dev/null +++ b/code/_onclick/hud/rendering/plane_masters/camera_static.dm @@ -0,0 +1,30 @@ +/atom/movable/screen/plane_master/camera_static + name = "Camera static" + documentation = "Holds camera static images. Usually only visible to people who can well, see static.\ +
We use images rather then vis contents because they're lighter on maptick, and maptick sucks butt." + plane = CAMERA_STATIC_PLANE + +/atom/movable/screen/plane_master/camera_static/show_to(mob/mymob) + . = ..() + if(!.) + return + var/datum/hud/our_hud = home.our_hud + if(isnull(our_hud)) + return + + // We'll hide the slate if we're not seeing through a camera eye + // This can call on a cycle cause we don't clear in hide_from + // Yes this is the best way of hooking into the hud, I hate myself too + RegisterSignal(our_hud, COMSIG_HUD_EYE_CHANGED, PROC_REF(eye_changed), override = TRUE) + eye_changed(our_hud, null, our_hud.mymob?.canon_client?.eye) + +/atom/movable/screen/plane_master/camera_static/proc/eye_changed(datum/hud/source, atom/old_eye, atom/new_eye) + SIGNAL_HANDLER + + if(!isaicamera(new_eye)) + if(!force_hidden) + hide_plane(source.mymob) + return + + if(force_hidden) + unhide_plane(source.mymob) diff --git a/code/_onclick/hud/rendering/plane_masters/clickcatcher.dm b/code/_onclick/hud/rendering/plane_masters/clickcatcher.dm new file mode 100644 index 0000000000000..8e581dc081c82 --- /dev/null +++ b/code/_onclick/hud/rendering/plane_masters/clickcatcher.dm @@ -0,0 +1,20 @@ +/atom/movable/screen/plane_master/clickcatcher + name = "Click Catcher" + documentation = "Contains the screen object we use as a backdrop to catch clicks on portions of the screen that would otherwise contain nothing else. \ +
Will always be below almost everything else" + plane = CLICKCATCHER_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + multiz_scaled = FALSE + critical = PLANE_CRITICAL_DISPLAY + +/atom/movable/screen/plane_master/clickcatcher/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + RegisterSignal(SSmapping, COMSIG_PLANE_OFFSET_INCREASE, PROC_REF(offset_increased)) + offset_increased(SSmapping, 0, SSmapping.max_plane_offset) + +/atom/movable/screen/plane_master/clickcatcher/proc/offset_increased(datum/source, old_off, new_off) + SIGNAL_HANDLER + // We only want need the lowest level + // If my system better supported changing PM plane values mid op I'd do that, but I do NOT so + if(new_off > offset) + hide_plane(home?.our_hud?.mymob) diff --git a/code/_onclick/hud/rendering/plane_masters/core_game_planes.dm b/code/_onclick/hud/rendering/plane_masters/core_game_planes.dm new file mode 100644 index 0000000000000..89379070b3500 --- /dev/null +++ b/code/_onclick/hud/rendering/plane_masters/core_game_planes.dm @@ -0,0 +1,122 @@ +//-------------------- FLOOR PLANE -------------------- + +///Contains just the floor +/atom/movable/screen/plane_master/floor + name = "Floor" + documentation = "The well, floor. This is mostly used as a sorting mechanism, but it also lets us create a \"border\" around the game world plane, so its drop shadow will actually work." + plane = FLOOR_PLANE + render_relay_planes = list(RENDER_PLANE_GAME, LIGHT_MASK_PLANE) + +/atom/movable/screen/plane_master/transparent_floor + name = "Transparent Floor" + documentation = "Really just openspace, stuff that is a turf but has no color or alpha whatsoever.\ +
We use this to draw to just the light mask plane, cause if it's not there we get holes of blackness over openspace" + plane = TRANSPARENT_FLOOR_PLANE + render_relay_planes = list(LIGHT_MASK_PLANE) + // Needs to be critical or it uh, it'll look white + critical = PLANE_CRITICAL_DISPLAY|PLANE_CRITICAL_NO_RELAY + +/atom/movable/screen/plane_master/floor/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_FLOOR_LAYER, relay_color = GLOB.em_block_color) + +//-------------------- WALL PLANE -------------------- + +/atom/movable/screen/plane_master/wall + name = "Wall" + documentation = "Holds all walls. We render this onto the game world. Separate so we can use this + space and floor planes as a guide for where byond blackness is NOT." + plane = WALL_PLANE + render_relay_planes = list(RENDER_PLANE_GAME_WORLD, LIGHT_MASK_PLANE) + +/atom/movable/screen/plane_master/wall/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_WALL_LAYER, relay_color = GLOB.em_block_color) + +/atom/movable/screen/plane_master/wall_upper + name = "Upper wall" + documentation = "There are some walls that want to render above most things (mostly minerals since they shift over.\ +
We draw them to their own plane so we can hijack them for our emissive mask stuff" + plane = WALL_PLANE_UPPER + render_relay_planes = list(RENDER_PLANE_GAME_WORLD, LIGHT_MASK_PLANE) + +/atom/movable/screen/plane_master/wall_upper/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_WALL_LAYER, relay_color = GLOB.em_block_color) + +//-------------------- AREA PLANE -------------------- + +/atom/movable/screen/plane_master/area + name = "Area" + documentation = "Holds the areas themselves, which ends up meaning it holds any overlays/effects we apply to areas. NOT snow or rad storms, those go on above lighting" + plane = AREA_PLANE + +//-------------------- GAME PLANES -------------------- + +/atom/movable/screen/plane_master/game + name = "Lower game world" + documentation = "Exists mostly because of FOV shit. Basically, if you've just got a normal not ABOVE fov thing, and you don't want it masked, stick it here yeah?" + plane = GAME_PLANE + render_relay_planes = list(RENDER_PLANE_GAME_WORLD) + +/atom/movable/screen/plane_master/high_game + name = "High Game" + documentation = "Holds anything that wants to be displayed above the rest of the game plane, and doesn't want to be clickable. \ +
This includes atmos debug overlays, blind sound images, and mining scanners. \ +
Really only exists for its layering potential, we don't use this for any vfx" + plane = HIGH_GAME_PLANE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + +//-------------------- FOV PLANES -------------------- + +/atom/movable/screen/plane_master/game_world_fov_hidden + name = "lower game world fov hidden" + documentation = "If you want something to be hidden by fov, stick it on this plane. We're masked by the fov blocker plane, so the items on us can actually well, disappear." + plane = GAME_PLANE_FOV_HIDDEN + render_relay_planes = list(RENDER_PLANE_GAME_WORLD) + +/atom/movable/screen/plane_master/game_world_fov_hidden/Initialize(mapload, datum/hud/hud_owner) + . = ..() + add_filter("vision_cone", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(FIELD_OF_VISION_BLOCKER_RENDER_TARGET, offset), flags = MASK_INVERSE)) + +/atom/movable/screen/plane_master/field_of_vision_blocker + name = "Field of vision blocker" + documentation = "This is one of those planes that's only used as a filter. It masks out things that want to be hidden by fov.\ +
Literally just contains FOV images, or masks." + plane = FIELD_OF_VISION_BLOCKER_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + render_target = FIELD_OF_VISION_BLOCKER_RENDER_TARGET + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + render_relay_planes = list() + // We do NOT allow offsetting, because there's no case where you would want to block only one layer, at least currently + allows_offsetting = FALSE + start_hidden = TRUE + // We mark as multiz_scaled FALSE so transforms don't effect us, and we draw to the planes below us as if they were us. + // This is safe because we will ALWAYS be on the top z layer, so it DON'T MATTER + multiz_scaled = FALSE + +/atom/movable/screen/plane_master/field_of_vision_blocker/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + mirror_parent_hidden() + +/atom/movable/screen/plane_master/game_world_above + name = "Above game world" + documentation = "We need a place that's unmasked by fov that also draws above the upper game world fov hidden plane. I told you fov was hacky man." + plane = ABOVE_GAME_PLANE + render_relay_planes = list(RENDER_PLANE_GAME_WORLD) + +/atom/movable/screen/plane_master/game_world_upper + name = "Upper game world" + documentation = "Ok so fov is kinda fucky, because planes in byond serve both as effect groupings and as rendering orderers. Since that's true, we need a plane that we can stick stuff that draws above fov blocked stuff on." + plane = GAME_PLANE_UPPER + render_relay_planes = list(RENDER_PLANE_GAME_WORLD) + +/atom/movable/screen/plane_master/game_world_upper_fov_hidden + name = "Upper game world fov hidden" + documentation = "Just as we need a place to draw things \"above\" the hidden fov plane, we also need to be able to hide stuff that draws over the upper game plane." + plane = GAME_PLANE_UPPER_FOV_HIDDEN + render_relay_planes = list(RENDER_PLANE_GAME_WORLD) + +/atom/movable/screen/plane_master/game_world_upper_fov_hidden/Initialize(mapload, datum/hud/hud_owner) + . = ..() + // Dupe of the other hidden plane + add_filter("vision_cone", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(FIELD_OF_VISION_BLOCKER_RENDER_TARGET, offset), flags = MASK_INVERSE)) diff --git a/code/_onclick/hud/rendering/plane_masters/default.dm b/code/_onclick/hud/rendering/plane_masters/default.dm new file mode 100644 index 0000000000000..f4f49f5bdd86b --- /dev/null +++ b/code/_onclick/hud/rendering/plane_masters/default.dm @@ -0,0 +1,15 @@ +/** + * Plane master that byond will by default draw to + * Shouldn't be used, exists to prevent people using plane 0 + * NOTE: If we used SEE_BLACKNESS on a map format that wasn't SIDE_MAP, this is where its darkness would land + * This would allow us to control it and do fun things. But we can't because side map doesn't support it, so this is just a stub + */ +/atom/movable/screen/plane_master/default + name = "Default" + documentation = "This is quite fiddly, so bear with me. By default (in byond) everything in the game is rendered onto plane 0. It's the default plane. \ +
But, because we've moved everything we control off plane 0, all that's left is stuff byond internally renders. \ +
What I'd like to do with this is capture byond blackness by giving mobs the SEE_BLACKNESS sight flag. \ +
But we CAN'T because SEE_BLACKNESS does not work with our rendering format. So I just eat it I guess" + plane = DEFAULT_PLANE + multiz_scaled = FALSE + start_hidden = TRUE // Doesn't DO anything, exists to hold this place diff --git a/code/_onclick/hud/rendering/plane_masters/in_world_chat.dm b/code/_onclick/hud/rendering/plane_masters/in_world_chat.dm new file mode 100644 index 0000000000000..bc7d327b8fb95 --- /dev/null +++ b/code/_onclick/hud/rendering/plane_masters/in_world_chat.dm @@ -0,0 +1,20 @@ +/atom/movable/screen/plane_master/runechat + name = "Runechat" + documentation = "Holds runechat images, that text that pops up when someone say something. Uses a dropshadow to well, look nice." + plane = RUNECHAT_PLANE + render_relay_planes = list(RENDER_PLANE_NON_GAME) + +/atom/movable/screen/plane_master/runechat/show_to(mob/mymob) + . = ..() + if(!.) + return + remove_filter("AO") + if(istype(mymob) && mymob.canon_client?.prefs?.read_preference(/datum/preference/toggle/ambient_occlusion)) + add_filter("AO", 1, drop_shadow_filter(x = 0, y = -2, size = 4, color = "#04080FAA")) + +/atom/movable/screen/plane_master/balloon_chat + name = "Balloon chat" + documentation = "Holds ballon chat images, those little text bars that pop up for a second when you do some things. NOT runechat." + plane = BALLOON_CHAT_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + render_relay_planes = list(RENDER_PLANE_NON_GAME) diff --git a/code/_onclick/hud/rendering/plane_masters/lighting.dm b/code/_onclick/hud/rendering/plane_masters/lighting.dm new file mode 100644 index 0000000000000..2ac4139b78f49 --- /dev/null +++ b/code/_onclick/hud/rendering/plane_masters/lighting.dm @@ -0,0 +1,44 @@ +///Contains all turf lighting +/atom/movable/screen/plane_master/turf_lighting + name = "Turf Lighting" + documentation = "Contains all lighting drawn to turfs. Not so complex, draws directly onto the lighting plate." + plane = LIGHTING_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + render_relay_planes = list(RENDER_PLANE_LIGHTING) + blend_mode_override = BLEND_ADD + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + critical = PLANE_CRITICAL_DISPLAY + +/// This will not work through multiz, because of a byond bug with BLEND_MULTIPLY +/// Bug report is up, waiting on a fix +/atom/movable/screen/plane_master/o_light_visual + name = "Overlight light visual" + documentation = "Holds overlay lighting objects, or the sort of lighting that's a well, overlay stuck to something.\ +
Exists because lighting updating is really slow, and movement needs to feel smooth.\ +
We draw to the game plane, and mask out space for ourselves on the lighting plane so any color we have has the chance to display." + plane = O_LIGHTING_VISUAL_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + render_target = O_LIGHTING_VISUAL_RENDER_TARGET + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + blend_mode = BLEND_MULTIPLY + critical = PLANE_CRITICAL_DISPLAY + +/atom/movable/screen/plane_master/above_lighting + name = "Above lighting" + plane = ABOVE_LIGHTING_PLANE + documentation = "Anything on the game plane that needs a space to draw on that will be above the lighting plane.\ +
Mostly little alerts and effects, also sometimes contains things that are meant to look as if they glow." + +/** + * Handles emissive overlays and emissive blockers. + */ +/atom/movable/screen/plane_master/emissive + name = "Emissive" + documentation = "Holds things that will be used to mask the lighting plane later on. Masked by the Emissive Mask plane to ensure we don't emiss out under a wall.\ +
Relayed onto the Emissive render plane to do the actual masking of lighting, since we need to be transformed and other emissive stuff needs to be transformed too.\ +
Don't want to double scale now." + plane = EMISSIVE_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + render_relay_planes = list(EMISSIVE_RENDER_PLATE) + critical = PLANE_CRITICAL_DISPLAY diff --git a/code/_onclick/hud/rendering/plane_masters/parallax.dm b/code/_onclick/hud/rendering/plane_masters/parallax.dm new file mode 100644 index 0000000000000..ee49ab177007e --- /dev/null +++ b/code/_onclick/hud/rendering/plane_masters/parallax.dm @@ -0,0 +1,105 @@ +/atom/movable/screen/plane_master/parallax_white + name = "Parallax whitifier" + documentation = "Essentially a backdrop for the parallax plane. We're rendered just below it, so we'll be multiplied by its well, parallax.\ +
If you want something to look as if it has parallax on it, draw it to this plane." + plane = PLANE_SPACE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + render_relay_planes = list(RENDER_PLANE_GAME, LIGHT_MASK_PLANE) + critical = PLANE_CRITICAL_FUCKO_PARALLAX // goes funny when touched. no idea why I don't trust byond + +/atom/movable/screen/plane_master/parallax_white/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_SPACE_LAYER) + +///Contains space parallax +/atom/movable/screen/plane_master/parallax + name = "Parallax" + documentation = "Contains parallax, or to be more exact the screen objects that hold parallax.\ +
Note the BLEND_MULTIPLY. The trick here is how low our plane value is. Because of that, we draw below almost everything in the game.\ +
We abuse this to ensure we multiply against the Parallax whitifier plane, or space's plane. It's set to full white, so when you do the multiply you just get parallax out where it well, makes sense to be.\ +
Also notice that the parent parallax plane is mirrored down to all children. We want to support viewing parallax across all z levels at once." + plane = PLANE_SPACE_PARALLAX + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + blend_mode = BLEND_MULTIPLY + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + multiz_scaled = FALSE + +/atom/movable/screen/plane_master/parallax/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + if(offset != 0) + // You aren't the source? don't change yourself + return + RegisterSignal(SSmapping, COMSIG_PLANE_OFFSET_INCREASE, PROC_REF(on_offset_increase)) + RegisterSignal(SSdcs, COMSIG_NARSIE_SUMMON_UPDATE, PROC_REF(narsie_modified)) + if(GLOB.narsie_summon_count >= 1) + narsie_start_midway(GLOB.narsie_effect_last_modified) // We assume we're on the start, so we can use this number + offset_increase(0, SSmapping.max_plane_offset) + +/atom/movable/screen/plane_master/parallax/proc/on_offset_increase(datum/source, old_offset, new_offset) + SIGNAL_HANDLER + offset_increase(old_offset, new_offset) + +/atom/movable/screen/plane_master/parallax/proc/offset_increase(old_offset, new_offset) + // Parallax will be mirrored down to any new planes that are added, so it will properly render across mirage borders + for(var/offset in old_offset to new_offset) + if(offset != 0) + // Overlay so we don't multiply twice, and thus fuck up our rendering + add_relay_to(GET_NEW_PLANE(plane, offset), BLEND_OVERLAY) + +// Hacky shit to ensure parallax works in perf mode +/atom/movable/screen/plane_master/parallax/outside_bounds(mob/relevant) + if(offset == 0) + remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_GAME, 0)) + is_outside_bounds = TRUE // I'm sorry :( + return + // If we can't render, and we aren't the bottom layer, don't render us + // This way we only multiply against stuff that's not fullwhite space + var/atom/movable/screen/plane_master/parent_parallax = home.our_hud.get_plane_master(PLANE_SPACE_PARALLAX) + var/turf/viewing_turf = get_turf(relevant) + if(!viewing_turf || offset != GET_LOWEST_STACK_OFFSET(viewing_turf.z)) + parent_parallax.remove_relay_from(plane) + else + parent_parallax.add_relay_to(plane, BLEND_OVERLAY) + return ..() + +/atom/movable/screen/plane_master/parallax/inside_bounds(mob/relevant) + if(offset == 0) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_GAME, 0)) + is_outside_bounds = FALSE + return + // Always readd, just in case we lost it + var/atom/movable/screen/plane_master/parent_parallax = home.our_hud.get_plane_master(PLANE_SPACE_PARALLAX) + parent_parallax.add_relay_to(plane, BLEND_OVERLAY) + return ..() + +// Needs to handle rejoining on a lower z level, so we NEED to readd old planes +/atom/movable/screen/plane_master/parallax/check_outside_bounds() + // If we're outside bounds AND we're the 0th plane, we need to show cause parallax is hacked to hell + return offset != 0 && is_outside_bounds + +/// Starts the narsie animation midway, so we can catch up to everyone else quickly +/atom/movable/screen/plane_master/parallax/proc/narsie_start_midway(start_time) + var/time_elapsed = world.time - start_time + narsie_summoned_effect(max(16 SECONDS - time_elapsed, 0)) + +/// Starts the narsie animation, make us grey, then red +/atom/movable/screen/plane_master/parallax/proc/narsie_modified(datum/source, new_count) + SIGNAL_HANDLER + if(new_count >= 1) + narsie_summoned_effect(16 SECONDS) + else + narsie_unsummoned() + +/atom/movable/screen/plane_master/parallax/proc/narsie_summoned_effect(animate_time) + if(GLOB.narsie_summon_count >= 2) + var/static/list/nightmare_parallax = list(255,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, -130,0,0,0) + animate(src, color = nightmare_parallax, time = animate_time) + return + + var/static/list/grey_parallax = list(0.4,0.4,0.4,0, 0.4,0.4,0.4,0, 0.4,0.4,0.4,0, 0,0,0,1, -0.1,-0.1,-0.1,0) + // We're gonna animate ourselves grey + // Then, once it's done, about 40 seconds into the event itself, we're gonna start doin some shit. see below + animate(src, color = grey_parallax, time = animate_time) + +/atom/movable/screen/plane_master/parallax/proc/narsie_unsummoned() + animate(src, color = null, time = 8 SECONDS) diff --git a/code/_onclick/hud/rendering/plane_masters/pipecrawl.dm b/code/_onclick/hud/rendering/plane_masters/pipecrawl.dm new file mode 100644 index 0000000000000..cb75135e1a491 --- /dev/null +++ b/code/_onclick/hud/rendering/plane_masters/pipecrawl.dm @@ -0,0 +1,15 @@ +/atom/movable/screen/plane_master/pipecrawl + name = "Pipecrawl" + documentation = "Holds pipecrawl images generated during well, pipecrawling.\ +
Has a few effects and a funky color matrix designed to make things a bit more visually readable." + plane = PIPECRAWL_IMAGES_PLANE + start_hidden = TRUE + +/atom/movable/screen/plane_master/pipecrawl/Initialize(mapload, datum/hud/hud_owner) + . = ..() + // Makes everything on this plane slightly brighter + // Has a nice effect, makes thing stand out + color = list(1.2,0,0,0, 0,1.2,0,0, 0,0,1.2,0, 0,0,0,1, 0,0,0,0) + // This serves a similar purpose, I want the pipes to pop + add_filter("pipe_dropshadow", 1, drop_shadow_filter(x = -1, y= -1, size = 1, color = "#0000007A")) + mirror_parent_hidden() diff --git a/code/_onclick/hud/rendering/plane_masters/simple_plane_masters.dm b/code/_onclick/hud/rendering/plane_masters/simple_plane_masters.dm new file mode 100644 index 0000000000000..ea0ad21a77355 --- /dev/null +++ b/code/_onclick/hud/rendering/plane_masters/simple_plane_masters.dm @@ -0,0 +1,82 @@ +/* + * Put plane masters that are just a simple type def in here, anything more complex should get its own file + */ + +/atom/movable/screen/plane_master/gravpulse + name = "Gravpulse" + documentation = "Ok so this one's fun. Basically, we want to be able to distort the game plane when a grav annom is around.\ +
So we draw the pattern we want to use to this plane, and it's then used as a render target by a distortion filter on the game plane.\ +
Note the blend mode and lack of relay targets. This plane exists only to distort, it's never rendered anywhere." + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + plane = GRAVITY_PULSE_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + blend_mode = BLEND_ADD + render_target = GRAVITY_PULSE_RENDER_TARGET + render_relay_planes = list() + +/atom/movable/screen/plane_master/seethrough + name = "Seethrough" + documentation = "Holds the seethrough versions (done using image overrides) of large objects. Mouse transparent, so you can click through them." + plane = SEETHROUGH_PLANE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + render_relay_planes = list(RENDER_PLANE_GAME_WORLD) + start_hidden = TRUE + +/atom/movable/screen/plane_master/massive_obj + name = "Massive object" + documentation = "Huge objects need to render above everything else on the game plane, otherwise they'd well, get clipped and look not that huge. This does that." + plane = MASSIVE_OBJ_PLANE + +/atom/movable/screen/plane_master/point + name = "Point" + documentation = "I mean like, what do you want me to say? Points draw over pretty much everything else, so they get their own plane. Remember we layer render relays to draw planes in their proper order on render plates." + plane = POINT_PLANE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + +/atom/movable/screen/plane_master/ghost + name = "Ghost" + documentation = "Ghosts draw here, so they don't get mixed up in the visuals of the game world. Note, this is not not how we HIDE ghosts from people, that's done with invisible and see_invisible." + plane = GHOST_PLANE + render_relay_planes = list(RENDER_PLANE_NON_GAME) + +/atom/movable/screen/plane_master/fullscreen + name = "Fullscreen" + documentation = "Holds anything that applies to or above the full screen. \ +
Note, it's still rendered underneath hud objects, but this lets us control the order that things like death/damage effects render in." + plane = FULLSCREEN_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + render_relay_planes = list(RENDER_PLANE_NON_GAME) + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + allows_offsetting = FALSE + +/atom/movable/screen/plane_master/hud + name = "HUD" + documentation = "Contains anything that want to be rendered on the hud. Typically is just screen elements." + plane = HUD_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + render_relay_planes = list(RENDER_PLANE_NON_GAME) + allows_offsetting = FALSE + +/atom/movable/screen/plane_master/above_hud + name = "Above HUD" + documentation = "Anything that wants to be drawn ABOVE the rest of the hud. Typically close buttons and other elements that need to be always visible. Think preventing draggable action button memes." + plane = ABOVE_HUD_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + render_relay_planes = list(RENDER_PLANE_NON_GAME) + allows_offsetting = FALSE + +/atom/movable/screen/plane_master/splashscreen + name = "Splashscreen" + documentation = "Cinematics and the splash screen." + plane = SPLASHSCREEN_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + render_relay_planes = list(RENDER_PLANE_NON_GAME) + allows_offsetting = FALSE + +/atom/movable/screen/plane_master/escape_menu + name = "Escape Menu" + documentation = "Anything relating to the escape menu." + plane = ESCAPE_MENU_PLANE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + render_relay_planes = list(RENDER_PLANE_MASTER) + allows_offsetting = FALSE diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 1a345038a2b5a..160a296abfca8 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -15,8 +15,8 @@ animate_movement = SLIDE_STEPS speech_span = SPAN_ROBOT appearance_flags = APPEARANCE_UI - /// A reference to the object in the slot. Grabs or items, generally. - var/obj/master = null + /// A reference to the object in the slot. Grabs or items, generally, but any datum will do. + var/datum/weakref/master_ref = null /// A reference to the owner HUD, if any. VAR_PRIVATE/datum/hud/hud = null /** @@ -42,7 +42,7 @@ hud = hud_owner /atom/movable/screen/Destroy() - master = null + master_ref = null hud = null return ..() @@ -249,10 +249,12 @@ /atom/movable/screen/close/Initialize(mapload, datum/hud/hud_owner, new_master) . = ..() - master = new_master + master_ref = WEAKREF(new_master) /atom/movable/screen/close/Click() - var/datum/storage/storage = master + var/datum/storage/storage = master_ref?.resolve() + if(!storage) + return storage.hide_contents(usr) return TRUE @@ -394,10 +396,10 @@ /atom/movable/screen/storage/Initialize(mapload, datum/hud/hud_owner, new_master) . = ..() - master = new_master + master_ref = WEAKREF(new_master) /atom/movable/screen/storage/Click(location, control, params) - var/datum/storage/storage_master = master + var/datum/storage/storage_master = master_ref?.resolve() if(!istype(storage_master)) return FALSE diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index 3de27ee7e10e9..c0ef2b6001f44 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -110,6 +110,8 @@ /obj/item/tk_grab/Destroy() STOP_PROCESSING(SSfastprocess, src) + if(!QDELETED(focus)) + REMOVE_TRAIT(focus, TRAIT_TELEKINESIS_CONTROLLED, REF(tk_user)) focus = null tk_user = null return ..() @@ -259,6 +261,7 @@ if(!check_if_focusable(target)) return focus = target + ADD_TRAIT(focus, TRAIT_TELEKINESIS_CONTROLLED, REF(tk_user)) update_appearance() apply_focus_overlay() return TRUE diff --git a/code/controllers/subsystem/economy.dm b/code/controllers/subsystem/economy.dm index 68fb43d7c2e2d..bf77acb065374 100644 --- a/code/controllers/subsystem/economy.dm +++ b/code/controllers/subsystem/economy.dm @@ -52,10 +52,6 @@ SUBSYSTEM_DEF(economy) */ var/list/audit_log = list() - /// Total value of exported materials. - var/export_total = 0 - /// Total value of imported goods. - var/import_total = 0 /// Number of mail items generated. var/mail_waiting = 0 /// Mail Holiday: AKA does mail arrive today? Always blocked on Sundays. diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 88112f9322676..d21e2da97d2e7 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -359,75 +359,80 @@ SUBSYSTEM_DEF(garbage) /datum/qdel_item/New(mytype) name = "[mytype]" - /// Should be treated as a replacement for the 'del' keyword. /// /// Datums passed to this will be given a chance to clean up references to allow the GC to collect them. -/proc/qdel(datum/D, force=FALSE, ...) - if(!istype(D)) - del(D) +/proc/qdel(datum/to_delete, force = FALSE, ...) + if(!istype(to_delete)) + del(to_delete) return - var/datum/qdel_item/I = SSgarbage.items[D.type] - if (!I) - I = SSgarbage.items[D.type] = new /datum/qdel_item(D.type) - I.qdels++ + var/datum/qdel_item/trash = SSgarbage.items[to_delete.type] + if (isnull(trash)) + trash = SSgarbage.items[to_delete.type] = new /datum/qdel_item(to_delete.type) + trash.qdels++ - if(isnull(D.gc_destroyed)) - if (SEND_SIGNAL(D, COMSIG_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted - return - D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED - var/start_time = world.time - var/start_tick = world.tick_usage - SEND_SIGNAL(D, COMSIG_QDELETING, force) // Let the (remaining) components know about the result of Destroy - var/hint = D.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up. - if(world.time != start_time) - I.slept_destroy++ - else - I.destroy_time += TICK_USAGE_TO_MS(start_tick) - if(!D) + if(!isnull(to_delete.gc_destroyed)) + if(to_delete.gc_destroyed == GC_CURRENTLY_BEING_QDELETED) + CRASH("[to_delete.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic") + return + + if (SEND_SIGNAL(to_delete, COMSIG_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted + return + + to_delete.gc_destroyed = GC_CURRENTLY_BEING_QDELETED + var/start_time = world.time + var/start_tick = world.tick_usage + SEND_SIGNAL(to_delete, COMSIG_QDELETING, force) // Let the (remaining) components know about the result of Destroy + var/hint = to_delete.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up. + + if(world.time != start_time) + trash.slept_destroy++ + else + trash.destroy_time += TICK_USAGE_TO_MS(start_tick) + + if(isnull(to_delete)) + return + + switch(hint) + if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion. + SSgarbage.Queue(to_delete) + if (QDEL_HINT_IWILLGC) + to_delete.gc_destroyed = world.time return - switch(hint) - if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion. - SSgarbage.Queue(D) - if (QDEL_HINT_IWILLGC) - D.gc_destroyed = world.time + if (QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory. + if(!force) + to_delete.gc_destroyed = null //clear the gc variable (important!) return - if (QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory. - if(!force) - D.gc_destroyed = null //clear the gc variable (important!) - return - // Returning LETMELIVE after being told to force destroy - // indicates the objects Destroy() does not respect force - #ifdef TESTING - if(!I.no_respect_force) - testing("WARNING: [D.type] has been force deleted, but is \ - returning an immortal QDEL_HINT, indicating it does \ - not respect the force flag for qdel(). It has been \ - placed in the queue, further instances of this type \ - will also be queued.") - #endif - I.no_respect_force++ + // Returning LETMELIVE after being told to force destroy + // indicates the objects Destroy() does not respect force + #ifdef TESTING + if(!trash.no_respect_force) + testing("WARNING: [to_delete.type] has been force deleted, but is \ + returning an immortal QDEL_HINT, indicating it does \ + not respect the force flag for qdel(). It has been \ + placed in the queue, further instances of this type \ + will also be queued.") + #endif + trash.no_respect_force++ - SSgarbage.Queue(D) - if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete - SSgarbage.Queue(D, GC_QUEUE_HARDDELETE) - if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste. - SSgarbage.HardDelete(D) - #ifdef REFERENCE_TRACKING - if (QDEL_HINT_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled, display all references to this object, then queue the object for deletion. - SSgarbage.Queue(D) - INVOKE_ASYNC(D, TYPE_PROC_REF(/datum, find_references)) - if (QDEL_HINT_IFFAIL_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled and the object fails to collect, display all references to this object. - SSgarbage.Queue(D) - SSgarbage.reference_find_on_fail[text_ref(D)] = TRUE + SSgarbage.Queue(to_delete) + if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete + SSgarbage.Queue(to_delete, GC_QUEUE_HARDDELETE) + if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste. + SSgarbage.HardDelete(to_delete) + #ifdef REFERENCE_TRACKING + if (QDEL_HINT_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled, display all references to this object, then queue the object for deletion. + SSgarbage.Queue(to_delete) + INVOKE_ASYNC(to_delete, TYPE_PROC_REF(/datum, find_references)) + if (QDEL_HINT_IFFAIL_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled and the object fails to collect, display all references to this object. + SSgarbage.Queue(to_delete) + SSgarbage.reference_find_on_fail[text_ref(to_delete)] = TRUE + #endif + else + #ifdef TESTING + if(!trash.no_hint) + testing("WARNING: [to_delete.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.") #endif - else - #ifdef TESTING - if(!I.no_hint) - testing("WARNING: [D.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.") - #endif - I.no_hint++ - SSgarbage.Queue(D) - else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED) - CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic") + trash.no_hint++ + SSgarbage.Queue(to_delete) diff --git a/code/controllers/subsystem/movement/move_handler.dm b/code/controllers/subsystem/movement/move_handler.dm index 90266dd3139d5..fcc5c1c65048b 100644 --- a/code/controllers/subsystem/movement/move_handler.dm +++ b/code/controllers/subsystem/movement/move_handler.dm @@ -121,9 +121,12 @@ SUBSYSTEM_DEF(move_manager) var/datum/controller/subsystem/movement/current_subsystem = running_loop.controller - current_subsystem.remove_loop(running_loop) - contesting_subsystem.add_loop(contestant) + var/current_running_loop = running_loop running_loop = contestant + current_subsystem.remove_loop(current_running_loop) + if(running_loop != contestant) // A signal registrant could have messed with things + return FALSE + contesting_subsystem.add_loop(contestant) return TRUE ///Tries to figure out the current favorite loop to run. More complex then just deciding between two different loops, assumes no running loop currently exists @@ -138,7 +141,7 @@ SUBSYSTEM_DEF(move_manager) var/datum/move_loop/checking = existing_loops[owner] if(checking.flags & MOVEMENT_LOOP_IGNORE_PRIORITY) continue - if(favorite && favorite.priority < checking.priority) + if(favorite && favorite.priority > checking.priority) continue favorite = checking @@ -152,8 +155,8 @@ SUBSYSTEM_DEF(move_manager) /datum/movement_packet/proc/remove_loop(datum/controller/subsystem/movement/remove_from, datum/move_loop/loop_to_remove) if(loop_to_remove == running_loop) - remove_from.remove_loop(loop_to_remove) running_loop = null + remove_from.remove_loop(loop_to_remove) if(loop_to_remove.flags & MOVEMENT_LOOP_IGNORE_PRIORITY) remove_from.remove_loop(loop_to_remove) if(QDELETED(src)) diff --git a/code/controllers/subsystem/movement/movement.dm b/code/controllers/subsystem/movement/movement.dm index c43debda5439d..425c67a0c474f 100644 --- a/code/controllers/subsystem/movement/movement.dm +++ b/code/controllers/subsystem/movement/movement.dm @@ -52,8 +52,11 @@ SUBSYSTEM_DEF(movement) while(processing.len) var/datum/move_loop/loop = processing[processing.len] processing.len-- + // No longer queued since we just got removed from the loop + loop.queued_time = null loop.process() //This shouldn't get nulls, if it does, runtime - if(!QDELETED(loop)) //Re-Insert the loop + if(!QDELETED(loop) && loop.status & MOVELOOP_STATUS_QUEUED) //Re-Insert the loop + loop.status &= ~MOVELOOP_STATUS_QUEUED loop.timer = world.time + loop.delay queue_loop(loop) if (MC_TICK_CHECK) @@ -86,26 +89,42 @@ SUBSYSTEM_DEF(movement) buckets -= "[bucket_time]" /datum/controller/subsystem/movement/proc/queue_loop(datum/move_loop/loop) - var/target_time = loop.timer - var/string_time = "[target_time]" + if(loop.status & MOVELOOP_STATUS_QUEUED) + stack_trace("A move loop attempted to queue while already queued") + return + loop.queued_time = loop.timer + loop.status |= MOVELOOP_STATUS_QUEUED + var/list/our_bucket = buckets["[loop.queued_time]"] // If there's no bucket for this, lets set them up - if(!buckets[string_time]) - buckets[string_time] = list() + if(!our_bucket) + buckets["[loop.queued_time]"] = list() + our_bucket = buckets["[loop.queued_time]"] // This makes assoc buckets and sorted buckets point to the same place, allowing for quicker inserts - var/list/new_bucket = list(list(target_time, buckets[string_time])) - BINARY_INSERT_DEFINE(new_bucket, sorted_buckets, SORT_VAR_NO_TYPE, list(target_time), SORT_FIRST_INDEX, COMPARE_KEY) + var/list/new_bucket = list(list(loop.queued_time, our_bucket)) + var/list/compare_item = list(loop.queued_time) + BINARY_INSERT_DEFINE(new_bucket, sorted_buckets, SORT_VAR_NO_TYPE, compare_item, SORT_FIRST_INDEX, COMPARE_KEY) - buckets[string_time] += loop + our_bucket += loop /datum/controller/subsystem/movement/proc/dequeue_loop(datum/move_loop/loop) - var/list/our_entries = buckets["[loop.timer]"] + // Go home, you're not here anyway + if(!(loop.status & MOVELOOP_STATUS_QUEUED)) + return + if(isnull(loop.queued_time)) // This happens if a moveloop is dequeued while handling process() + loop.status &= ~MOVELOOP_STATUS_QUEUED + return + var/list/our_entries = buckets["[loop.queued_time]"] our_entries -= loop if(!length(our_entries)) - smash_bucket(bucket_time = loop.timer) // We can't pass an index in for context because we don't know our position + smash_bucket(bucket_time = loop.queued_time) // We can't pass an index in for context because we don't know our position + loop.queued_time = null + loop.status &= ~MOVELOOP_STATUS_QUEUED /datum/controller/subsystem/movement/proc/add_loop(datum/move_loop/add) + if(add.status & MOVELOOP_STATUS_QUEUED) + CRASH("Loop being added that is already queued.") add.loop_started() - if(QDELETED(add)) + if(QDELETED(add) || add.status & MOVELOOP_STATUS_QUEUED) return queue_loop(add) diff --git a/code/controllers/subsystem/movement/movement_types.dm b/code/controllers/subsystem/movement/movement_types.dm index 6e18d35dd8ff4..de8e4531236cf 100644 --- a/code/controllers/subsystem/movement/movement_types.dm +++ b/code/controllers/subsystem/movement/movement_types.dm @@ -21,12 +21,12 @@ var/delay = 1 ///The next time we should process ///Used primarially as a hint to be reasoned about by our [controller], and as the id of our bucket - ///Should not be modified directly outside of [start_loop] var/timer = 0 - ///Is this loop running or not - var/running = FALSE - ///Track if we're currently paused - var/paused = FALSE + ///The time we are CURRENTLY queued for processing + ///Do not modify this directly + var/queued_time = -1 + /// Status bitfield for what state the move loop is currently in + var/status = NONE /datum/move_loop/New(datum/movement_packet/owner, datum/controller/subsystem/movement/controller, atom/moving, priority, flags, datum/extra_info) src.owner = owner @@ -57,7 +57,7 @@ /datum/move_loop/proc/loop_started() SHOULD_CALL_PARENT(TRUE) SEND_SIGNAL(src, COMSIG_MOVELOOP_START) - running = TRUE + status |= MOVELOOP_STATUS_RUNNING //If this is our first time starting to move with this loop //And we're meant to start instantly if(!timer && flags & MOVEMENT_LOOP_START_FAST) @@ -68,7 +68,7 @@ ///Called when a loop is stopped, doesn't stop the loop itself /datum/move_loop/proc/loop_stopped() SHOULD_CALL_PARENT(TRUE) - running = FALSE + status &= ~MOVELOOP_STATUS_RUNNING SEND_SIGNAL(src, COMSIG_MOVELOOP_STOP) /datum/move_loop/proc/info_deleted(datum/source) @@ -91,7 +91,7 @@ ///Pauses the move loop for some passed in period ///This functionally means shifting its timer up, and clearing it from its current bucket /datum/move_loop/proc/pause_for(time) - if(!controller || !running) //No controller or not running? go away + if(!controller || !(status & MOVELOOP_STATUS_RUNNING)) //No controller or not running? go away return //Dequeue us from our current bucket controller.dequeue_loop(src) @@ -141,21 +141,21 @@ ///Pause our loop untill restarted with resume_loop() /datum/move_loop/proc/pause_loop() - if(!controller || !running || paused) //we dead + if(!controller || !(status & MOVELOOP_STATUS_RUNNING) || (status & MOVELOOP_STATUS_PAUSED)) //we dead return //Dequeue us from our current bucket controller.dequeue_loop(src) - paused = TRUE + status |= MOVELOOP_STATUS_PAUSED ///Resume our loop after being paused by pause_loop() /datum/move_loop/proc/resume_loop() - if(!controller || !running || !paused) + if(!controller || (status & MOVELOOP_STATUS_RUNNING|MOVELOOP_STATUS_PAUSED) != (MOVELOOP_STATUS_RUNNING|MOVELOOP_STATUS_PAUSED)) return - controller.queue_loop(src) timer = world.time - paused = FALSE + controller.queue_loop(src) + status &= ~MOVELOOP_STATUS_PAUSED ///Removes the atom from some movement subsystem. Defaults to SSmovement /datum/controller/subsystem/move_manager/proc/stop_looping(atom/movable/moving, datum/controller/subsystem/movement/subsystem = SSmovement) diff --git a/code/controllers/subsystem/processing/ai_behaviors.dm b/code/controllers/subsystem/processing/ai_behaviors.dm index 4ec698db32bbc..e92da2474bb73 100644 --- a/code/controllers/subsystem/processing/ai_behaviors.dm +++ b/code/controllers/subsystem/processing/ai_behaviors.dm @@ -8,9 +8,12 @@ PROCESSING_SUBSYSTEM_DEF(ai_behaviors) wait = 1 ///List of all ai_behavior singletons, key is the typepath while assigned value is a newly created instance of the typepath. See SetupAIBehaviors() var/list/ai_behaviors + ///List of all targeting_strategy singletons, key is the typepath while assigned value is a newly created instance of the typepath. See SetupAIBehaviors() + var/list/targeting_strategies /datum/controller/subsystem/processing/ai_behaviors/Initialize() SetupAIBehaviors() + SetupTargetingStrats() return SS_INIT_SUCCESS /datum/controller/subsystem/processing/ai_behaviors/proc/SetupAIBehaviors() @@ -18,3 +21,9 @@ PROCESSING_SUBSYSTEM_DEF(ai_behaviors) for(var/behavior_type in subtypesof(/datum/ai_behavior)) var/datum/ai_behavior/ai_behavior = new behavior_type ai_behaviors[behavior_type] = ai_behavior + +/datum/controller/subsystem/processing/ai_behaviors/proc/SetupTargetingStrats() + targeting_strategies = list() + for(var/target_type in subtypesof(/datum/targeting_strategy)) + var/datum/targeting_strategy/target_start = new target_type + targeting_strategies[target_type] = target_start diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm index 1cc3468fb7db4..1d31582fc5fff 100644 --- a/code/controllers/subsystem/research.dm +++ b/code/controllers/subsystem/research.dm @@ -27,15 +27,15 @@ SUBSYSTEM_DEF(research) var/list/techweb_nodes_starting = list() ///category name = list(node.id = TRUE) var/list/techweb_categories = list() - ///associative double-layer path = list(id = list(point_type = point_discount)) - var/list/techweb_boost_items = list() + ///List of all items that can unlock a node. (node.id = list(items)) + var/list/techweb_unlock_items = list() ///Node ids that should be hidden by default. var/list/techweb_nodes_hidden = list() ///Node ids that are exclusive to the BEPIS. var/list/techweb_nodes_experimental = list() ///path = list(point type = value) var/list/techweb_point_items = list( - /obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 10000) + /obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 10000) ) var/list/errored_datums = list() var/list/point_types = list() //typecache style type = TRUE list @@ -64,7 +64,7 @@ SUBSYSTEM_DEF(research) /// Lookup list for ordnance briefers. var/list/ordnance_experiments = list() /// Lookup list for scipaper partners. - var/list/scientific_partners = list() + var/list/datum/scientific_partner/scientific_partners = list() /datum/controller/subsystem/research/Initialize() point_types = TECHWEB_POINT_TYPE_LIST_ASSOCIATIVE_NAMES @@ -153,7 +153,7 @@ SUBSYSTEM_DEF(research) if (!verify_techweb_nodes()) //Verify all nodes have ids and such. stack_trace("Invalid techweb nodes detected") calculate_techweb_nodes() - calculate_techweb_boost_list() + calculate_techweb_item_unlocking_requirements() if (!verify_techweb_nodes()) //Verify nodes and designs have been crosslinked properly. CRASH("Invalid techweb nodes detected") @@ -209,25 +209,15 @@ SUBSYSTEM_DEF(research) N.unlock_ids -= u research_node_id_error(u) . = FALSE - for(var/p in N.boost_item_paths) + for(var/p in N.required_items_to_unlock) if(!ispath(p)) - N.boost_item_paths -= p + N.required_items_to_unlock -= p WARNING("[p] is not a valid path.") node_boost_error(N.id, "[p] is not a valid path.") . = FALSE - var/list/points = N.boost_item_paths[p] - if(islist(points)) - for(var/i in points) - if(!isnum(points[i])) - WARNING("[points[i]] is not a valid number.") - node_boost_error(N.id, "[points[i]] is not a valid number.") - . = FALSE - else if(!point_types[i]) - WARNING("[i] is not a valid point type.") - node_boost_error(N.id, "[i] is not a valid point type.") - . = FALSE - else if(!isnull(points)) - N.boost_item_paths -= p + var/list/points = N.required_items_to_unlock[p] + if(!isnull(points)) + N.required_items_to_unlock -= p node_boost_error(N.id, "No valid list.") WARNING("No valid list.") . = FALSE @@ -281,18 +271,16 @@ SUBSYSTEM_DEF(research) var/datum/techweb_node/prereq_node = techweb_node_by_id(prereq_id) prereq_node.unlock_ids[node.id] = node -/datum/controller/subsystem/research/proc/calculate_techweb_boost_list(clearall = FALSE) - if(clearall) - techweb_boost_items = list() +/datum/controller/subsystem/research/proc/calculate_techweb_item_unlocking_requirements() for(var/node_id in techweb_nodes) var/datum/techweb_node/node = techweb_nodes[node_id] - for(var/path in node.boost_item_paths) + for(var/path in node.required_items_to_unlock) if(!ispath(path)) continue - if(length(techweb_boost_items[path])) - techweb_boost_items[path][node.id] = node.boost_item_paths[path] + if(length(techweb_unlock_items[path])) + techweb_unlock_items[path][node.id] = node.required_items_to_unlock[path] else - techweb_boost_items[path] = list(node.id = node.boost_item_paths[path]) + techweb_unlock_items[path] = list(node.id = node.required_items_to_unlock[path]) CHECK_TICK /datum/controller/subsystem/research/proc/populate_ordnance_experiments() diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 7665a51f30c06..d0d9cea7fa764 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -100,9 +100,6 @@ SUBSYSTEM_DEF(shuttle) /// Wishlist items made by crew for cargo to purchase at their leisure. var/list/request_list = list() - /// A listing of previously delivered supply packs. - var/list/order_history = list() - /// A list of job accesses that are able to purchase any shuttles. var/list/has_purchase_shuttle_access @@ -729,8 +726,6 @@ SUBSYSTEM_DEF(shuttle) shopping_list = SSshuttle.shopping_list if (istype(SSshuttle.request_list)) request_list = SSshuttle.request_list - if (istype(SSshuttle.order_history)) - order_history = SSshuttle.order_history if (istype(SSshuttle.shuttle_loan)) shuttle_loan = SSshuttle.shuttle_loan diff --git a/code/controllers/subsystem/stock_market.dm b/code/controllers/subsystem/stock_market.dm index 7c2cb71dc4972..c0d85eaf85dc8 100644 --- a/code/controllers/subsystem/stock_market.dm +++ b/code/controllers/subsystem/stock_market.dm @@ -51,6 +51,7 @@ SUBSYSTEM_DEF(stock_market) price_minimum = round(initial(mat.minimum_value_override) * SHEET_MATERIAL_AMOUNT) var/price_maximum = round(initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 3) var/price_baseline = initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT + var/quantity_baseline = initial(mat.tradable_base_quantity) var/stock_quantity = materials_quantity[mat] @@ -84,15 +85,15 @@ SUBSYSTEM_DEF(stock_market) switch(trend) if(MARKET_TREND_UPWARD) price_change = ROUND_UP(gaussian(price_units * 0.1, price_baseline * 0.05)) //If we don't ceil, small numbers will get trapped at low values - quantity_change = -round(gaussian(stock_quantity * 0.1, stock_quantity * 0.05)) + quantity_change = -round(gaussian(quantity_baseline * 0.05, quantity_baseline * 0.05)) if(MARKET_TREND_STABLE) price_change = round(gaussian(0, price_baseline * 0.01)) - quantity_change = round(gaussian(0, stock_quantity * 0.01)) + quantity_change = round(gaussian(0, quantity_baseline * 0.01)) if(MARKET_TREND_DOWNWARD) price_change = -ROUND_UP(gaussian(price_units * 0.1, price_baseline * 0.05)) - quantity_change = round(gaussian(stock_quantity * 0.1, stock_quantity * 0.05)) + quantity_change = round(gaussian(quantity_baseline * 0.05, quantity_baseline * 0.05)) materials_prices[mat] = round(clamp(price_units + price_change, price_minimum, price_maximum)) - materials_quantity[mat] = round(clamp(stock_quantity + quantity_change, 0, initial(mat.tradable_base_quantity) * 2)) + materials_quantity[mat] = round(clamp(stock_quantity + quantity_change, 0, quantity_baseline * 2)) /** * Market events are a way to spice up the market and make it more interesting. diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 15a4aed4adbf7..e68ee9ee1f2f4 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -66,7 +66,7 @@ SUBSYSTEM_DEF(vote) // Remove AFK or clientless non-voters. for(var/non_voter_ckey in non_voters) var/client/non_voter_client = non_voters[non_voter_ckey] - if(!non_voter_client || non_voter_client.is_afk()) + if(!istype(non_voter_client) || non_voter_client.is_afk()) non_voters -= non_voter_ckey // Now get the result of the vote. diff --git a/code/datums/achievements/_achievement_data.dm b/code/datums/achievements/_achievement_data.dm index aa47d8e9fc846..295770b89b5b7 100644 --- a/code/datums/achievements/_achievement_data.dm +++ b/code/datums/achievements/_achievement_data.dm @@ -45,7 +45,7 @@ kv[key] = value qdel(Query) - for(var/award_type in sortTim(subtypesof(/datum/award), GLOBAL_PROC_REF(cmp_award_priority))) + for(var/award_type in subtypesof(/datum/award)) var/datum/award/award = SSachievements.awards[award_type] if(!award || !award.name) //Skip abstract achievements types continue @@ -116,7 +116,7 @@ "icon_class" = assets.icon_class_name(award.icon), "value" = data[achievement_type], ) - award_data += award.get_ui_data() + award_data += award.get_ui_data(user.ckey) .["achievements"] += list(award_data) for(var/score in SSachievements.scores) diff --git a/code/datums/achievements/_awards.dm b/code/datums/achievements/_awards.dm index 7a7701e0cf1e0..23ab5e81001c9 100644 --- a/code/datums/achievements/_awards.dm +++ b/code/datums/achievements/_awards.dm @@ -15,9 +15,6 @@ //Value returned on db connection failure, in case we want to differ 0 and nonexistent later on var/default_value = FALSE - ///Whether the award has to be loaded before or after other awards on [/datum/achievement_data/load_all_achievements()] - var/load_priority = AWARD_PRIORITY_DEFAULT - ///This proc loads the achievement data from the hub. /datum/award/proc/load(key) if(!SSdbcore.Connect()) @@ -109,7 +106,6 @@ /datum/award/achievement/on_unlock(mob/user) . = ..() to_chat(user, span_greenannounce("Achievement unlocked: [name]!")) - user.client.give_award(/datum/award/score/achievements_score, user, 1) var/sound/sound_to_send = LAZYACCESS(GLOB.achievement_sounds, user.client.prefs.read_preference(/datum/preference/choiced/sound_achievement)) if(sound_to_send) SEND_SOUND(user, sound_to_send) @@ -177,20 +173,45 @@ desc = "Don't worry, metagaming is all that matters." icon = "elephant" //Obey the reference database_id = ACHIEVEMENTS_SCORE - load_priority = AWARD_PRIORITY_LAST //See below -/** - * If the raw value is not numerical, it's likely this is the first time the score is being loaded for a ckey. - * So, let's start counting how many achievements have been unlocked so far and return its value instead, - * which is why this award should always be loaded last. - */ +/datum/award/score/achievements_score/get_ui_data(key) + . = ..() + var/datum/db_query/get_unlocked_count = SSdbcore.NewQuery( + "SELECT COUNT(m.achievement_key) FROM [format_table_name("achievements")] AS a JOIN [format_table_name("achievement_metadata")] m ON a.achievement_key = m.achievement_key AND m.achievement_type = 'Achievement' WHERE a.ckey = :ckey", + list("ckey" = key) + ) + if(!get_unlocked_count.Execute(async = TRUE)) + qdel(get_unlocked_count) + .["value"] = default_value + return . + if(get_unlocked_count.NextRow()) + .["value"] = text2num(get_unlocked_count.item[1]) + qdel(get_unlocked_count) + return . + +/datum/award/score/achievements_score/LoadHighScores() + var/datum/db_query/get_unlocked_highscore = SSdbcore.NewQuery( + "SELECT ckey, COUNT(ckey) AS c FROM [format_table_name("achievements")] AS a JOIN [format_table_name("achievement_metadata")] m ON a.achievement_key = m.achievement_key AND m.achievement_type = 'Achievement' GROUP BY ckey ORDER BY c DESC LIMIT 50", + ) + if(!get_unlocked_highscore.Execute(async = TRUE)) + qdel(get_unlocked_highscore) + return + else + while(get_unlocked_highscore.NextRow()) + var/key = get_unlocked_highscore.item[1] + var/score = text2num(get_unlocked_highscore.item[2]) + high_scores[key] = score + qdel(get_unlocked_highscore) + /datum/award/score/achievements_score/on_achievement_data_init(datum/achievement_data/holder, database_value) - if(isnum(database_value)) - return ..() - //We need to keep the value differents so that it's properly saved at the end of the round. - holder.original_cached_data[type] = 0 - var/value = 0 - for(var/award_type in holder.data) - if(ispath(award_type, /datum/award/achievement) && holder.data[award_type]) - value++ - holder.data[type] = value + var/datum/db_query/get_unlocked_load = SSdbcore.NewQuery( + "SELECT COUNT(m.achievement_key) FROM [format_table_name("achievements")] AS a JOIN [format_table_name("achievement_metadata")] m ON a.achievement_key = m.achievement_key AND m.achievement_type = 'Achievement' WHERE a.ckey = :ckey", + list("ckey" = holder.owner_ckey) + ) + if(!get_unlocked_load.Execute(async = TRUE)) + qdel(get_unlocked_load) + return + if(get_unlocked_load.NextRow()) + holder.data[type] = text2num(get_unlocked_load.item[1]) || 0 + holder.original_cached_data[type] = 0 + qdel(get_unlocked_load) diff --git a/code/datums/achievements/misc_achievements.dm b/code/datums/achievements/misc_achievements.dm index f83f2cde7b0a1..8ae3da33e3a3a 100644 --- a/code/datums/achievements/misc_achievements.dm +++ b/code/datums/achievements/misc_achievements.dm @@ -135,11 +135,11 @@ database_id = MEDAL_COSMOS_ASCENSION icon = "cosmicascend" -/datum/award/achievement/misc/knock_ascension - name = "Secrets behind the Spider Door" +/datum/award/achievement/misc/lock_ascension + name = "Secrets of the Locked Labyrinth" desc = "You managed to open a gate into the mansus." - database_id = MEDAL_KNOCK_ASCENSION - icon = "knockascend" + database_id = MEDAL_LOCK_ASCENSION + icon = "lockascend" /datum/award/achievement/misc/grand_ritual_finale name = "Archmage" diff --git a/code/datums/actions/cooldown_action.dm b/code/datums/actions/cooldown_action.dm index a7e0603461a77..ed4309c36e1cb 100644 --- a/code/datums/actions/cooldown_action.dm +++ b/code/datums/actions/cooldown_action.dm @@ -177,6 +177,8 @@ /// Starts a cooldown time for other abilities that share a cooldown with this. Has some niche usage with more complicated attack ai! /// Will use default cooldown time if an override is not specified /datum/action/cooldown/proc/StartCooldownOthers(override_cooldown_time) + if(!length(owner.actions)) + return // Possible if they have an action they don't control for(var/datum/action/cooldown/shared_ability in owner.actions - src) if(!(shared_cooldown & shared_ability.shared_cooldown)) continue diff --git a/code/datums/actions/mobs/charge.dm b/code/datums/actions/mobs/charge.dm index 7fb5620977712..0c73145770ea4 100644 --- a/code/datums/actions/mobs/charge.dm +++ b/code/datums/actions/mobs/charge.dm @@ -156,17 +156,23 @@ SSexplosions.med_mov_atom += target INVOKE_ASYNC(src, PROC_REF(DestroySurroundings), source) - hit_target(source, target, charge_damage) - -/datum/action/cooldown/mob_cooldown/charge/proc/hit_target(atom/movable/source, atom/target, damage_dealt) - if(!isliving(target)) - return - var/mob/living/living_target = target - living_target.visible_message("[source] slams into [living_target]!", "[source] tramples you into the ground!") - source.forceMove(get_turf(living_target)) - living_target.apply_damage(damage_dealt, BRUTE, wound_bonus = CANT_WOUND) - playsound(get_turf(living_target), 'sound/effects/meteorimpact.ogg', 100, TRUE) - shake_camera(living_target, 4, 3) + try_hit_target(source, target) + +/// Attempt to hit someone with our charge +/datum/action/cooldown/mob_cooldown/charge/proc/try_hit_target(atom/movable/source, atom/target) + if (can_hit_target(source, target)) + hit_target(source, target, charge_damage) + +/// Returns true if we're allowed to charge into this target +/datum/action/cooldown/mob_cooldown/charge/proc/can_hit_target(atom/movable/source, atom/target) + return isliving(target) + +/// Actually hit someone +/datum/action/cooldown/mob_cooldown/charge/proc/hit_target(atom/movable/source, mob/living/target, damage_dealt) + target.visible_message(span_danger("[source] slams into [target]!"), span_userdanger("[source] tramples you into the ground!")) + target.apply_damage(damage_dealt, BRUTE, wound_bonus = CANT_WOUND) + playsound(get_turf(target), 'sound/effects/meteorimpact.ogg', 100, TRUE) + shake_camera(target, 4, 3) shake_camera(source, 2, 3) /datum/action/cooldown/mob_cooldown/charge/basic_charge @@ -187,18 +193,21 @@ /datum/action/cooldown/mob_cooldown/charge/basic_charge/do_charge_indicator(atom/charger, atom/charge_target) charger.Shake(shake_pixel_shift, shake_pixel_shift, shake_duration) +/datum/action/cooldown/mob_cooldown/charge/basic_charge/can_hit_target(atom/movable/source, atom/target) + if(!isliving(target)) + if(!target.density || target.CanPass(source, get_dir(target, source))) + return FALSE + return TRUE + return ..() + /datum/action/cooldown/mob_cooldown/charge/basic_charge/hit_target(atom/movable/source, atom/target, damage_dealt) var/mob/living/living_source if(isliving(source)) living_source = source if(!isliving(target)) - if(!target.density || target.CanPass(source, get_dir(target, source))) - return source.visible_message(span_danger("[source] smashes into [target]!")) - if(!living_source) - return - living_source.Stun(recoil_duration, ignore_canstun = TRUE) + living_source?.Stun(recoil_duration, ignore_canstun = TRUE) return var/mob/living/living_target = target @@ -208,10 +217,9 @@ living_source.Stun(recoil_duration, ignore_canstun = TRUE) return - living_target.visible_message(span_danger("[source] charges on [living_target]!"), span_userdanger("[source] charges into you!")) + living_target.visible_message(span_danger("[source] charges into [living_target]!"), span_userdanger("[source] charges into you!")) living_target.Knockdown(knockdown_duration) - /datum/status_effect/tired_post_charge id = "tired_post_charge" duration = 1 SECONDS diff --git a/code/datums/actions/mobs/fire_breath.dm b/code/datums/actions/mobs/fire_breath.dm index 45b6538c01836..b3673b2f96cf9 100644 --- a/code/datums/actions/mobs/fire_breath.dm +++ b/code/datums/actions/mobs/fire_breath.dm @@ -37,7 +37,7 @@ var/list/turfs = get_line(owner, target_turf) - get_turf(owner) INVOKE_ASYNC(src, PROC_REF(progressive_fire_line), turfs) -/// Creates fire with a delay on the list of targetted turfs +/// Creates fire with a delay on the list of targeted turfs /datum/action/cooldown/mob_cooldown/fire_breath/proc/progressive_fire_line(list/burn_turfs) if (QDELETED(owner) || owner.stat == DEAD) return diff --git a/code/datums/actions/mobs/personality_commune.dm b/code/datums/actions/mobs/personality_commune.dm new file mode 100644 index 0000000000000..26cf483449204 --- /dev/null +++ b/code/datums/actions/mobs/personality_commune.dm @@ -0,0 +1,56 @@ +// This can probably be changed to use mind linker at some point +/datum/action/personality_commune + name = "Personality Commune" + desc = "Sends thoughts to your alternate consciousness." + background_icon_state = "bg_spell" + button_icon = 'icons/mob/actions/actions_spells.dmi' + button_icon_state = "telepathy" + overlay_icon_state = "bg_spell_border" + + /// Fluff text shown when a message is sent to the pair + var/fluff_text = span_boldnotice("You hear an echoing voice in the back of your head...") + +/datum/action/personality_commune/New(Target) + . = ..() + if(!istype(target, /datum/brain_trauma/severe/split_personality)) + stack_trace("[type] was created on a target that isn't a /datum/brain_trauma/severe/split_personality, this doesn't work.") + qdel(src) + +/datum/action/personality_commune/Grant(mob/grant_to) + if(!istype(grant_to, /mob/living/split_personality)) + return + + return ..() + +/datum/action/personality_commune/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE + + var/datum/brain_trauma/severe/split_personality/trauma = target + var/mob/living/split_personality/non_controller = usr + var/client/non_controller_client = non_controller.client + + var/to_send = tgui_input_text(non_controller, "What would you like to tell your other self?", "Commune") + if(QDELETED(src) || QDELETED(trauma) || !to_send) + return FALSE + + var/mob/living/carbon/human/personality_body = trauma.owner + if(personality_body.client == non_controller_client) // We took control + return FALSE + + var/user_message = span_boldnotice("You concentrate and send thoughts to your other self:") + var/user_message_body = span_notice("[to_send]") + + to_chat(non_controller, "[user_message] [user_message_body]") + + personality_body.balloon_alert(personality_body, "you hear a voice") + to_chat(personality_body, "[fluff_text] [user_message_body]") + + log_directed_talk(non_controller, personality_body, to_send, LOG_SAY, "[name]") + for(var/dead_mob in GLOB.dead_mob_list) + if(!isobserver(dead_mob)) + continue + to_chat(dead_mob, "[FOLLOW_LINK(dead_mob, non_controller)] [span_boldnotice("[non_controller] [name]:")] [span_notice("\"[to_send]\" to")] [span_name("[trauma]")]") + + return TRUE diff --git a/code/datums/ai/_ai_controller.dm b/code/datums/ai/_ai_controller.dm index 04493b44e5d3a..ca5bd67a4f540 100644 --- a/code/datums/ai/_ai_controller.dm +++ b/code/datums/ai/_ai_controller.dm @@ -352,7 +352,11 @@ multiple modular subtrees with behaviors /// Returns true if we have a blackboard key with the provided key and it is not qdeleting /datum/ai_controller/proc/blackboard_key_exists(key) var/datum/key_value = blackboard[key] - return !QDELETED(key_value) + if (isdatum(key_value)) + return !QDELETED(key_value) + if (islist(key_value)) + return length(key_value) > 0 + return !!key_value /** * Used to manage references to datum by AI controllers diff --git a/code/datums/ai/babies/babies_behaviors.dm b/code/datums/ai/babies/babies_behaviors.dm index 553b192a180e4..5941bb818f448 100644 --- a/code/datums/ai/babies/babies_behaviors.dm +++ b/code/datums/ai/babies/babies_behaviors.dm @@ -2,74 +2,77 @@ * Find a compatible, living partner, if we're also alone. */ /datum/ai_behavior/find_partner - action_cooldown = 40 SECONDS - /// Range to look. var/range = 7 - /// Maximum number of children var/max_children = 3 /datum/ai_behavior/find_partner/perform(seconds_per_tick, datum/ai_controller/controller, target_key, partner_types_key, child_types_key) . = ..() - + max_children = controller.blackboard[BB_MAX_CHILDREN] || max_children var/mob/pawn_mob = controller.pawn var/list/partner_types = controller.blackboard[partner_types_key] var/list/child_types = controller.blackboard[child_types_key] + var/mob/living/living_pawn = controller.pawn - var/mob/living/partner var/children = 0 - for(var/mob/other in oview(range, pawn_mob)) + for(var/mob/living/other in oview(range, pawn_mob)) + if(!pawn_mob.faction_check_atom(other)) + finish_action(controller, FALSE) + return + + if(children >= max_children) + finish_action(controller, FALSE) + return + if(other.stat != CONSCIOUS) //Check if it's conscious FIRST. continue - var/is_child = is_type_in_list(other, child_types) - if(is_child) //Check for children SECOND. + + if(is_type_in_list(other, child_types)) //Check for children SECOND. children++ - else if(is_type_in_list(other, partner_types)) - if(other.ckey) - continue - else if(!is_child && other.gender == MALE && !(other.flags_1 & HOLOGRAM_1)) //Better safe than sorry ;_; - partner = other + continue - //shyness check. we're not shy in front of things that share a faction with us. - else if(isliving(other) && !pawn_mob.faction_check_atom(other)) - finish_action(controller, FALSE) - return + if(!is_type_in_list(other, partner_types) || !HAS_TRAIT(other, TRAIT_MOB_BREEDER)) + continue + + if(other.ckey) + continue + + if(other.gender != living_pawn.gender && !(other.flags_1 & HOLOGRAM_1)) //Better safe than sorry ;_; + controller.set_blackboard_key(target_key, other) + finish_action(controller, TRUE) - if(partner && children < max_children) - controller.set_blackboard_key(target_key, partner) + finish_action(controller, FALSE) - finish_action(controller, TRUE) /** * Reproduce. */ /datum/ai_behavior/make_babies - action_cooldown = 40 SECONDS behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH /datum/ai_behavior/make_babies/setup(datum/ai_controller/controller, target_key, child_types_key) + . = ..() var/atom/target = controller.blackboard[target_key] if(!target) return FALSE set_movement_target(controller, target) - return TRUE /datum/ai_behavior/make_babies/perform(seconds_per_tick, datum/ai_controller/controller, target_key, child_types_key) . = ..() var/mob/target = controller.blackboard[target_key] - if(!target || target.stat != CONSCIOUS) + if(QDELETED(target) || target.stat != CONSCIOUS) finish_action(controller, FALSE, target_key) return - - var/child_type = pick_weight(controller.blackboard[child_types_key]) - var/turf/turf_loc = get_turf(controller.pawn.loc) - if(turf_loc) - new child_type(turf_loc) - + var/mob/living/basic/living_pawn = controller.pawn + living_pawn.set_combat_mode(FALSE) + living_pawn.melee_attack(target) finish_action(controller, TRUE, target_key) /datum/ai_behavior/make_babies/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() - controller.clear_blackboard_key(target_key) + if(!succeeded) + return + var/mob/living/living_pawn = controller.pawn + living_pawn.set_combat_mode(initial(living_pawn.combat_mode)) diff --git a/code/datums/ai/babies/babies_subtrees.dm b/code/datums/ai/babies/babies_subtrees.dm index aad92f8422e85..8310cd955733a 100644 --- a/code/datums/ai/babies/babies_subtrees.dm +++ b/code/datums/ai/babies/babies_subtrees.dm @@ -3,11 +3,19 @@ */ /datum/ai_planning_subtree/make_babies var/chance = 5 + operational_datums = list(/datum/component/breed) /datum/ai_planning_subtree/make_babies/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() - if(controller.pawn.gender != FEMALE || !SPT_PROB(chance, seconds_per_tick)) + if(!SPT_PROB(chance, seconds_per_tick)) + return + + if(controller.blackboard_key_exists(BB_BABIES_TARGET)) + controller.queue_behavior(/datum/ai_behavior/make_babies, BB_BABIES_TARGET, BB_BABIES_CHILD_TYPES) + return SUBTREE_RETURN_FINISH_PLANNING + + if(controller.pawn.gender == FEMALE || !controller.blackboard[BB_BREED_READY]) return var/partner_types = controller.blackboard[BB_BABIES_PARTNER_TYPES] @@ -21,7 +29,4 @@ return // Find target - if(controller.blackboard_key_exists(BB_BABIES_TARGET)) - controller.queue_behavior(/datum/ai_behavior/make_babies, BB_BABIES_TARGET, BB_BABIES_CHILD_TYPES) - return SUBTREE_RETURN_FINISH_PLANNING controller.queue_behavior(/datum/ai_behavior/find_partner, BB_BABIES_TARGET, BB_BABIES_PARTNER_TYPES, BB_BABIES_CHILD_TYPES) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm index 91ba7ec489415..21b141feff801 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm @@ -2,10 +2,10 @@ action_cooldown = 0.2 SECONDS // We gotta check unfortunately often because we're in a race condition with nextmove behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION -/datum/ai_behavior/basic_melee_attack/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/basic_melee_attack/setup(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) . = ..() - if(!controller.blackboard_key_exists(targetting_datum_key)) - CRASH("No target datum was supplied in the blackboard for [controller.pawn]") + if(!controller.blackboard[targeting_strategy_key]) + CRASH("No targeting strategy was supplied in the blackboard for [controller.pawn]") //Hiding location is priority var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] @@ -14,7 +14,7 @@ set_movement_target(controller, target) -/datum/ai_behavior/basic_melee_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/basic_melee_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) if (isliving(controller.pawn)) var/mob/living/pawn = controller.pawn if (world.time < pawn.next_move) @@ -22,15 +22,15 @@ . = ..() var/mob/living/basic/basic_mob = controller.pawn - //targetting datum will kill the action if not real anymore + //targeting strategy will kill the action if not real anymore var/atom/target = controller.blackboard[target_key] - var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] + var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) - if(!targetting_datum.can_attack(basic_mob, target)) + if(!targeting_strategy.can_attack(basic_mob, target)) finish_action(controller, FALSE, target_key) return - var/hiding_target = targetting_datum.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something! + var/hiding_target = targeting_strategy.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something! controller.set_blackboard_key(hiding_location_key, hiding_target) @@ -40,7 +40,7 @@ basic_mob.melee_attack(target) -/datum/ai_behavior/basic_melee_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/basic_melee_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targeting_strategy_key, hiding_location_key) . = ..() if(!succeeded) controller.clear_blackboard_key(target_key) @@ -54,30 +54,30 @@ ///do we care about avoiding friendly fire? var/avoid_friendly_fire = FALSE -/datum/ai_behavior/basic_ranged_attack/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/basic_ranged_attack/setup(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) . = ..() var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] if(QDELETED(target)) return FALSE set_movement_target(controller, target) -/datum/ai_behavior/basic_ranged_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/basic_ranged_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) var/mob/living/basic/basic_mob = controller.pawn - //targetting datum will kill the action if not real anymore + //targeting strategy will kill the action if not real anymore var/atom/target = controller.blackboard[target_key] - var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] + var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) - if(!targetting_datum.can_attack(basic_mob, target, chase_range)) + if(!targeting_strategy.can_attack(basic_mob, target, chase_range)) finish_action(controller, FALSE, target_key) return - var/atom/hiding_target = targetting_datum.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something! + var/atom/hiding_target = targeting_strategy.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something! var/atom/final_target = hiding_target ? hiding_target : target if(!can_see(basic_mob, final_target, required_distance)) return - if(avoid_friendly_fire && check_friendly_in_path(basic_mob, target, targetting_datum)) + if(avoid_friendly_fire && check_friendly_in_path(basic_mob, target, targeting_strategy)) adjust_position(basic_mob, target) return ..() @@ -85,17 +85,17 @@ basic_mob.RangedAttack(final_target) return ..() //only start the cooldown when the shot is shot -/datum/ai_behavior/basic_ranged_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/basic_ranged_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targeting_strategy_key, hiding_location_key) . = ..() if(!succeeded) controller.clear_blackboard_key(target_key) -/datum/ai_behavior/basic_ranged_attack/proc/check_friendly_in_path(mob/living/source, atom/target, datum/targetting_datum/targetting_datum) +/datum/ai_behavior/basic_ranged_attack/proc/check_friendly_in_path(mob/living/source, atom/target, datum/targeting_strategy/targeting_strategy) var/list/turfs_list = calculate_trajectory(source, target) for(var/turf/possible_turf as anything in turfs_list) for(var/mob/living/potential_friend in possible_turf) - if(!targetting_datum.can_attack(source, potential_friend)) + if(!targeting_strategy.can_attack(source, potential_friend)) return TRUE return FALSE diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/nearest_targetting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/nearest_targeting.dm similarity index 100% rename from code/datums/ai/basic_mobs/basic_ai_behaviors/nearest_targetting.dm rename to code/datums/ai/basic_mobs/basic_ai_behaviors/nearest_targeting.dm diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm similarity index 82% rename from code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm rename to code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm index 376f62a5855b5..435b9cb1ef3d0 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm @@ -7,16 +7,16 @@ /// Static typecache list of potentially dangerous objs var/static/list/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/vehicle/sealed/mecha)) -/datum/ai_behavior/find_potential_targets/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/find_potential_targets/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) . = ..() var/mob/living/living_mob = controller.pawn - var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] + var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) - if(!targetting_datum) + if(!targeting_strategy) CRASH("No target datum was supplied in the blackboard for [controller.pawn]") var/atom/current_target = controller.blackboard[target_key] - if (targetting_datum.can_attack(living_mob, current_target, vision_range)) + if (targeting_strategy.can_attack(living_mob, current_target, vision_range)) finish_action(controller, succeeded = FALSE) return @@ -37,7 +37,7 @@ var/list/filtered_targets = list() for(var/atom/pot_target in potential_targets) - if(targetting_datum.can_attack(living_mob, pot_target))//Can we attack it? + if(targeting_strategy.can_attack(living_mob, pot_target))//Can we attack it? filtered_targets += pot_target continue @@ -48,7 +48,7 @@ var/atom/target = pick_final_target(controller, filtered_targets) controller.set_blackboard_key(target_key, target) - var/atom/potential_hiding_location = targetting_datum.find_hidden_mobs(living_mob, target) + var/atom/potential_hiding_location = targeting_strategy.find_hidden_mobs(living_mob, target) if(potential_hiding_location) //If they're hiding inside of something, we need to know so we can go for that instead initially. controller.set_blackboard_key(hiding_location_key, potential_hiding_location) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/ventcrawling.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/ventcrawling.dm index f5e4f74a1fecc..e162cc612990a 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/ventcrawling.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/ventcrawling.dm @@ -18,7 +18,7 @@ . = ..() var/obj/machinery/atmospherics/components/unary/vent_pump/entry_vent = controller.blackboard[target_key] || controller.blackboard[BB_ENTRY_VENT_TARGET] var/mob/living/cached_pawn = controller.pawn - if(HAS_TRAIT(cached_pawn, TRAIT_MOVE_VENTCRAWLING) || !controller.blackboard[BB_CURRENTLY_TARGETTING_VENT] || !is_vent_valid(entry_vent)) + if(HAS_TRAIT(cached_pawn, TRAIT_MOVE_VENTCRAWLING) || !controller.blackboard[BB_CURRENTLY_TARGETING_VENT] || !is_vent_valid(entry_vent)) return if(!cached_pawn.can_enter_vent(entry_vent, provide_feedback = FALSE)) // we're an AI we scoff at feedback @@ -30,7 +30,7 @@ finish_action(controller, FALSE, target_key) return - controller.set_blackboard_key(BB_CURRENTLY_TARGETTING_VENT, FALSE) // must be done here because we have a do_after sleep in handle_ventcrawl unfortunately and double dipping could lead to erroneous suicide pill calls. + controller.set_blackboard_key(BB_CURRENTLY_TARGETING_VENT, FALSE) // must be done here because we have a do_after sleep in handle_ventcrawl unfortunately and double dipping could lead to erroneous suicide pill calls. cached_pawn.handle_ventcrawl(entry_vent) if(!HAS_TRAIT(cached_pawn, TRAIT_MOVE_VENTCRAWLING)) //something failed and we ARE NOT IN THE VENT even though the earlier check said we were good to go! odd. finish_action(controller, FALSE, target_key) @@ -134,5 +134,5 @@ controller.clear_blackboard_key(target_key) controller.clear_blackboard_key(BB_ENTRY_VENT_TARGET) controller.clear_blackboard_key(BB_EXIT_VENT_TARGET) - controller.set_blackboard_key(BB_CURRENTLY_TARGETTING_VENT, FALSE) // just in case + controller.set_blackboard_key(BB_CURRENTLY_TARGETING_VENT, FALSE) // just in case diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/wounded_targetting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/wounded_targeting.dm similarity index 100% rename from code/datums/ai/basic_mobs/basic_ai_behaviors/wounded_targetting.dm rename to code/datums/ai/basic_mobs/basic_ai_behaviors/wounded_targeting.dm diff --git a/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm index c3d334165d95c..4116900435460 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm @@ -12,19 +12,19 @@ var/mob/living/pawn = controller.pawn if (LAZYLEN(pawn.do_afters)) return - controller.queue_behavior(melee_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + controller.queue_behavior(melee_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) /// Attack something which is already adjacent to us without moving /datum/ai_behavior/basic_melee_attack/opportunistic action_cooldown = 0.2 SECONDS // We gotta check unfortunately often because we're in a race condition with nextmove behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION -/datum/ai_behavior/basic_melee_attack/opportunistic/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) - if (!controller.blackboard_key_exists(targetting_datum_key)) +/datum/ai_behavior/basic_melee_attack/opportunistic/setup(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) + if (!controller.blackboard_key_exists(targeting_strategy_key)) CRASH("No target datum was supplied in the blackboard for [controller.pawn]") return controller.blackboard_key_exists(target_key) -/datum/ai_behavior/basic_melee_attack/opportunistic/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/basic_melee_attack/opportunistic/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) var/atom/movable/atom_pawn = controller.pawn if(!atom_pawn.CanReach(controller.blackboard[target_key])) finish_action(controller, TRUE, target_key) // Don't clear target diff --git a/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm b/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm index 9f1053f29d3f2..7059bec93fe2f 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm @@ -74,7 +74,7 @@ return FALSE if (basic_mob.see_invisible < object.invisibility) return FALSE - var/list/whitelist = basic_mob.ai_controller.blackboard[BB_OBSTACLE_TARGETTING_WHITELIST] + var/list/whitelist = basic_mob.ai_controller.blackboard[BB_OBSTACLE_TARGETING_WHITELIST] if(whitelist && !is_type_in_typecache(object, whitelist)) return FALSE diff --git a/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm b/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm index 47f4155ac4552..4d5319bca86e7 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/capricious_retaliate.dm @@ -1,19 +1,19 @@ /// Add or remove people to our retaliation shitlist just on an arbitrary whim /datum/ai_planning_subtree/capricious_retaliate /// Blackboard key which tells us how to select valid targets - var/targetting_datum_key = BB_TARGETTING_DATUM + var/targeting_strategy_key = BB_TARGETING_STRATEGY /// Whether we should skip checking faction for our decision var/ignore_faction = TRUE /datum/ai_planning_subtree/capricious_retaliate/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() - controller.queue_behavior(/datum/ai_behavior/capricious_retaliate, targetting_datum_key, ignore_faction) + controller.queue_behavior(/datum/ai_behavior/capricious_retaliate, targeting_strategy_key, ignore_faction) /// Add or remove people to our retaliation shitlist just on an arbitrary whim /datum/ai_behavior/capricious_retaliate action_cooldown = 1 SECONDS -/datum/ai_behavior/capricious_retaliate/perform(seconds_per_tick, datum/ai_controller/controller, targetting_datum_key, ignore_faction) +/datum/ai_behavior/capricious_retaliate/perform(seconds_per_tick, datum/ai_controller/controller, targeting_strategy_key, ignore_faction) . = ..() var/atom/pawn = controller.pawn if (controller.blackboard_key_exists(BB_BASIC_MOB_RETALIATE_LIST)) @@ -35,10 +35,10 @@ var/aggro_range = controller.blackboard[BB_AGGRO_RANGE] || 9 var/list/potential_targets = hearers(aggro_range, get_turf(pawn)) - pawn if (!length(potential_targets)) - failed_targetting(controller, pawn, ignore_faction) + failed_targeting(controller, pawn, ignore_faction) return - var/datum/targetting_datum/target_helper = controller.blackboard[targetting_datum_key] + var/datum/targeting_strategy/target_helper = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) var/mob/living/final_target = null if (ignore_faction) @@ -49,7 +49,7 @@ final_target = test_target if (isnull(final_target)) - failed_targetting(controller, pawn, ignore_faction) + failed_targeting(controller, pawn, ignore_faction) return controller.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, final_target) @@ -57,7 +57,7 @@ finish_action(controller, TRUE, ignore_faction) /// Called if we try but fail to target something -/datum/ai_behavior/capricious_retaliate/proc/failed_targetting(datum/ai_controller/controller, atom/pawn, ignore_faction) +/datum/ai_behavior/capricious_retaliate/proc/failed_targeting(datum/ai_controller/controller, atom/pawn, ignore_faction) finish_action(controller, FALSE, ignore_faction) pawn.visible_message(span_notice("[pawn] grumbles.")) // We're pissed off but with no outlet to vent our frustration upon diff --git a/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm index 4f901745eeea5..4a2f5b476c759 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm @@ -20,7 +20,7 @@ return SUBTREE_RETURN_FINISH_PLANNING //we gotta get out of here. /// Try to escape from your current target, without performing any other actions. -/// Reads from some fleeing-specific targetting keys rather than the current mob target. +/// Reads from some fleeing-specific targeting keys rather than the current mob target. /datum/ai_planning_subtree/flee_target/from_flee_key target_key = BB_BASIC_MOB_FLEE_TARGET hiding_place_key = BB_BASIC_MOB_FLEE_TARGET_HIDING_LOCATION diff --git a/code/datums/ai/basic_mobs/basic_subtrees/opportunistic_ventcrawler.dm b/code/datums/ai/basic_mobs/basic_subtrees/opportunistic_ventcrawler.dm index 63a745305b201..240272d1ef48a 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/opportunistic_ventcrawler.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/opportunistic_ventcrawler.dm @@ -15,6 +15,6 @@ controller.queue_behavior(/datum/ai_behavior/travel_towards, BB_ENTRY_VENT_TARGET) return - controller.set_blackboard_key(BB_CURRENTLY_TARGETTING_VENT, TRUE) + controller.set_blackboard_key(BB_CURRENTLY_TARGETING_VENT, TRUE) controller.queue_behavior(/datum/ai_behavior/crawl_through_vents, BB_ENTRY_VENT_TARGET) return SUBTREE_RETURN_FINISH_PLANNING // we are going into this vent... no distractions diff --git a/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm b/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm index be395f3dfe49d..95a125eea5ce5 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm @@ -14,30 +14,30 @@ . = ..() if(!controller.blackboard_key_exists(target_key)) return - controller.queue_behavior(attack_behavior, target_key, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION, max_range, min_range) + controller.queue_behavior(attack_behavior, target_key, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION, max_range, min_range) /// How often will we try to perform our ranged attack? /datum/ai_behavior/ranged_skirmish action_cooldown = 1 SECONDS -/datum/ai_behavior/ranged_skirmish/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key, max_range, min_range) +/datum/ai_behavior/ranged_skirmish/setup(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key, max_range, min_range) . = ..() var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] return !QDELETED(target) -/datum/ai_behavior/ranged_skirmish/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key, max_range, min_range) +/datum/ai_behavior/ranged_skirmish/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key, max_range, min_range) . = ..() var/atom/target = controller.blackboard[target_key] if (QDELETED(target)) finish_action(controller, succeeded = FALSE) return - var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] - if(!targetting_datum.can_attack(controller.pawn, target)) + var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) + if(!targeting_strategy.can_attack(controller.pawn, target)) finish_action(controller, succeeded = FALSE) return - var/hiding_target = targetting_datum.find_hidden_mobs(controller.pawn, target) + var/hiding_target = targeting_strategy.find_hidden_mobs(controller.pawn, target) controller.set_blackboard_key(hiding_location_key, hiding_target) target = hiding_target || target diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm index 210aaf0aa8b26..5b1f5ffbff9ed 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm @@ -8,7 +8,7 @@ . = ..() if(!controller.blackboard_key_exists(BB_BASIC_MOB_CURRENT_TARGET)) return - controller.queue_behavior(melee_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + controller.queue_behavior(melee_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) if (end_planning) return SUBTREE_RETURN_FINISH_PLANNING //we are going into battle...no distractions. @@ -20,5 +20,5 @@ . = ..() if(!controller.blackboard_key_exists(BB_BASIC_MOB_CURRENT_TARGET)) return - controller.queue_behavior(ranged_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + controller.queue_behavior(ranged_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) return SUBTREE_RETURN_FINISH_PLANNING //we are going into battle...no distractions. diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_nearest_target_to_flee.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_nearest_target_to_flee.dm index 3fe1ada33ba99..6630f7d193d90 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_nearest_target_to_flee.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_nearest_target_to_flee.dm @@ -5,11 +5,11 @@ . = ..() if (controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) return - controller.queue_behavior(/datum/ai_behavior/find_potential_targets/nearest, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + controller.queue_behavior(/datum/ai_behavior/find_potential_targets/nearest, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) /// Find the nearest thing on our list of 'things which have done damage to me' and set it as the flee target /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee - var/targeting_key = BB_TARGETTING_DATUM + var/targeting_key = BB_TARGETING_STRATEGY /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() @@ -18,4 +18,4 @@ controller.queue_behavior(/datum/ai_behavior/target_from_retaliate_list/nearest, BB_BASIC_MOB_RETALIATE_LIST, BB_BASIC_MOB_CURRENT_TARGET, targeting_key, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee/from_flee_key - targeting_key = BB_FLEE_TARGETTING_DATUM + targeting_key = BB_FLEE_TARGETING_STRATEGY diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm index ec4ef1863adc9..1c7d8de9120ba 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm @@ -2,7 +2,7 @@ /datum/ai_planning_subtree/simple_find_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() - controller.queue_behavior(/datum/ai_behavior/find_potential_targets, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + controller.queue_behavior(/datum/ai_behavior/find_potential_targets, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) // Prevents finding a target if a human is nearby /datum/ai_planning_subtree/simple_find_target/not_while_observed diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_wounded_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_wounded_target.dm index 8840c1ea3a76c..7a230014d9ab2 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_wounded_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_wounded_target.dm @@ -3,4 +3,4 @@ /datum/ai_planning_subtree/simple_find_wounded_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() - controller.queue_behavior(/datum/ai_behavior/find_potential_targets/most_wounded, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + controller.queue_behavior(/datum/ai_behavior/find_potential_targets/most_wounded, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm index 701f911d27325..55ec738761317 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm @@ -2,7 +2,7 @@ /datum/ai_planning_subtree/target_retaliate operational_datums = list(/datum/element/ai_retaliate, /datum/component/ai_retaliate_advanced) /// Blackboard key which tells us how to select valid targets - var/targetting_datum_key = BB_TARGETTING_DATUM + var/targeting_strategy_key = BB_TARGETING_STRATEGY /// Blackboard key in which to store selected target var/target_key = BB_BASIC_MOB_CURRENT_TARGET /// Blackboard key in which to store selected target's hiding place @@ -12,16 +12,16 @@ /datum/ai_planning_subtree/target_retaliate/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() - controller.queue_behavior(/datum/ai_behavior/target_from_retaliate_list, BB_BASIC_MOB_RETALIATE_LIST, target_key, targetting_datum_key, hiding_place_key, check_faction) + controller.queue_behavior(/datum/ai_behavior/target_from_retaliate_list, BB_BASIC_MOB_RETALIATE_LIST, target_key, targeting_strategy_key, hiding_place_key, check_faction) /datum/ai_planning_subtree/target_retaliate/check_faction check_faction = TRUE /// Places a mob which you can see and who has recently attacked you into some 'run away from this' AI keys -/// Can use a different targetting datum than you use to select attack targets +/// Can use a different targeting strategy than you use to select attack targets /// Not required if fleeing is the only target behaviour or uses the same target datum /datum/ai_planning_subtree/target_retaliate/to_flee - targetting_datum_key = BB_FLEE_TARGETTING_DATUM + targeting_strategy_key = BB_FLEE_TARGETING_STRATEGY target_key = BB_BASIC_MOB_FLEE_TARGET hiding_place_key = BB_BASIC_MOB_FLEE_TARGET_HIDING_LOCATION @@ -34,11 +34,11 @@ /// How far can we see stuff? var/vision_range = 9 -/datum/ai_behavior/target_from_retaliate_list/perform(seconds_per_tick, datum/ai_controller/controller, shitlist_key, target_key, targetting_datum_key, hiding_location_key, check_faction) +/datum/ai_behavior/target_from_retaliate_list/perform(seconds_per_tick, datum/ai_controller/controller, shitlist_key, target_key, targeting_strategy_key, hiding_location_key, check_faction) . = ..() var/mob/living/living_mob = controller.pawn - var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] - if(!targetting_datum) + var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) + if(!targeting_strategy) CRASH("No target datum was supplied in the blackboard for [controller.pawn]") var/list/shitlist = controller.blackboard[shitlist_key] @@ -47,13 +47,13 @@ if (!check_faction) controller.set_blackboard_key(BB_TEMPORARILY_IGNORE_FACTION, TRUE) - if (!QDELETED(existing_target) && (locate(existing_target) in shitlist) && targetting_datum.can_attack(living_mob, existing_target, vision_range)) + if (!QDELETED(existing_target) && (locate(existing_target) in shitlist) && targeting_strategy.can_attack(living_mob, existing_target, vision_range)) finish_action(controller, succeeded = TRUE, check_faction = check_faction) return var/list/enemies_list = list() for(var/mob/living/potential_target as anything in shitlist) - if(!targetting_datum.can_attack(living_mob, potential_target, vision_range)) + if(!targeting_strategy.can_attack(living_mob, potential_target, vision_range)) continue enemies_list += potential_target @@ -65,7 +65,7 @@ var/atom/new_target = pick_final_target(controller, enemies_list) controller.set_blackboard_key(target_key, new_target) - var/atom/potential_hiding_location = targetting_datum.find_hidden_mobs(living_mob, new_target) + var/atom/potential_hiding_location = targeting_strategy.find_hidden_mobs(living_mob, new_target) if(potential_hiding_location) //If they're hiding inside of something, we need to know so we can go for that instead initially. controller.set_blackboard_key(hiding_location_key, potential_hiding_location) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm b/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm index d9ee3ef09182d..cd809804ba369 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm @@ -1,7 +1,7 @@ /// Attempts to use a mob ability on a target /datum/ai_planning_subtree/targeted_mob_ability /// Blackboard key for the ability - var/ability_key = BB_TARGETTED_ACTION + var/ability_key = BB_TARGETED_ACTION /// Blackboard key for where the target ref is stored var/target_key = BB_BASIC_MOB_CURRENT_TARGET /// Behaviour to perform using ability diff --git a/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm b/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm index fb83b8f8684ad..5ceef67bedb26 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm @@ -1,6 +1,6 @@ /** * Simple behaviours which simply try to use an ability whenever it is available. - * For something which wants a target try `targetted_mob_ability`. + * For something which wants a target try `targeted_mob_ability`. */ /datum/ai_planning_subtree/use_mob_ability /// Blackboard key for the ability diff --git a/code/datums/ai/basic_mobs/generic_controllers.dm b/code/datums/ai/basic_mobs/generic_controllers.dm index 208c1833add84..dae1b944dd321 100644 --- a/code/datums/ai/basic_mobs/generic_controllers.dm +++ b/code/datums/ai/basic_mobs/generic_controllers.dm @@ -1,7 +1,7 @@ /// The most basic AI tree which just finds a guy and then runs at them to click them /datum/ai_controller/basic_controller/simple_hostile blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -14,7 +14,7 @@ /// Find a target, walk at target, attack intervening obstacles /datum/ai_controller/basic_controller/simple_hostile_obstacles blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/datums/ai/basic_mobs/pet_commands/pet_use_targetted_ability.dm b/code/datums/ai/basic_mobs/pet_commands/pet_use_targeted_ability.dm similarity index 100% rename from code/datums/ai/basic_mobs/pet_commands/pet_use_targetted_ability.dm rename to code/datums/ai/basic_mobs/pet_commands/pet_use_targeted_ability.dm diff --git a/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm b/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm similarity index 79% rename from code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm rename to code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm index d8b7e49c23cdd..2505b87a717f9 100644 --- a/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm +++ b/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm @@ -1,18 +1,19 @@ -///Datum for basic mobs to define what they can attack. -/datum/targetting_datum +///Datum for basic mobs to define what they can attack.GET_TARGETING_STRATEGY\((/[^,]*)\), +///Global, just like ai_behaviors +/datum/targeting_strategy ///Returns true or false depending on if the target can be attacked by the mob -/datum/targetting_datum/proc/can_attack(mob/living/living_mob, atom/target, vision_range) +/datum/targeting_strategy/proc/can_attack(mob/living/living_mob, atom/target, vision_range) return ///Returns something the target might be hiding inside of -/datum/targetting_datum/proc/find_hidden_mobs(mob/living/living_mob, atom/target) +/datum/targeting_strategy/proc/find_hidden_mobs(mob/living/living_mob, atom/target) var/atom/target_hiding_location if(istype(target.loc, /obj/structure/closet) || istype(target.loc, /obj/machinery/disposal) || istype(target.loc, /obj/machinery/sleeper)) target_hiding_location = target.loc return target_hiding_location -/datum/targetting_datum/basic +/datum/targeting_strategy/basic /// When we do our basic faction check, do we look for exact faction matches? var/check_factions_exactly = FALSE /// Whether we care for seeing the target or not @@ -22,7 +23,7 @@ /// If this blackboard key is TRUE, makes us only target wounded mobs var/target_wounded_key -/datum/targetting_datum/basic/can_attack(mob/living/living_mob, atom/the_target, vision_range) +/datum/targeting_strategy/basic/can_attack(mob/living/living_mob, atom/the_target, vision_range) var/datum/ai_controller/basic_controller/our_controller = living_mob.ai_controller if(isnull(our_controller)) @@ -82,29 +83,29 @@ return FALSE /// Returns true if the mob and target share factions -/datum/targetting_datum/basic/proc/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) +/datum/targeting_strategy/basic/proc/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) if (controller.blackboard[BB_ALWAYS_IGNORE_FACTION] || controller.blackboard[BB_TEMPORARILY_IGNORE_FACTION]) return FALSE return living_mob.faction_check_atom(the_target, exact_match = check_factions_exactly) /// Subtype more forgiving for items. /// Careful, this can go wrong and keep a mob hyper-focused on an item it can't lose aggro on -/datum/targetting_datum/basic/allow_items +/datum/targeting_strategy/basic/allow_items -/datum/targetting_datum/basic/allow_items/can_attack(mob/living/living_mob, atom/the_target, vision_range) +/datum/targeting_strategy/basic/allow_items/can_attack(mob/living/living_mob, atom/the_target, vision_range) . = ..() if(isitem(the_target)) // trust fall exercise return TRUE /// Subtype which searches for mobs of a size relative to ours -/datum/targetting_datum/basic/of_size +/datum/targeting_strategy/basic/of_size /// If true, we will return mobs which are smaller than us. If false, larger. var/find_smaller = TRUE /// If true, we will return mobs which are the same size as us. var/inclusive = TRUE -/datum/targetting_datum/basic/of_size/can_attack(mob/living/owner, atom/target, vision_range) +/datum/targeting_strategy/basic/of_size/can_attack(mob/living/owner, atom/target, vision_range) if(!isliving(target)) return FALSE . = ..() @@ -119,14 +120,14 @@ return !find_smaller // This is just using the default values but the subtype makes it clearer -/datum/targetting_datum/basic/of_size/ours_or_smaller +/datum/targeting_strategy/basic/of_size/ours_or_smaller -/datum/targetting_datum/basic/of_size/larger +/datum/targeting_strategy/basic/of_size/larger find_smaller = FALSE inclusive = FALSE /// Makes the mob only attack their own faction. Useful mostly if their attacks do something helpful (e.g. healing touch). -/datum/targetting_datum/basic/same_faction +/datum/targeting_strategy/basic/same_faction -/datum/targetting_datum/basic/same_faction/faction_check(mob/living/living_mob, mob/living/the_target) +/datum/targeting_strategy/basic/same_faction/faction_check(mob/living/living_mob, mob/living/the_target) return !..() // inverts logic to ONLY target mobs that share a faction diff --git a/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm b/code/datums/ai/basic_mobs/targeting_strategies/dont_target_friends.dm similarity index 55% rename from code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm rename to code/datums/ai/basic_mobs/targeting_strategies/dont_target_friends.dm index e2081bf308e9c..1b52c4986bb4f 100644 --- a/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm +++ b/code/datums/ai/basic_mobs/targeting_strategies/dont_target_friends.dm @@ -1,12 +1,12 @@ /// Don't target an atom in our friends list (or turfs), anything else is fair game -/datum/targetting_datum/basic/not_friends +/datum/targeting_strategy/basic/not_friends /// Stop regarding someone as a valid target once they pass this stat level, setting it to DEAD means you will happily attack corpses var/attack_until_past_stat = HARD_CRIT /// If we can try to closed turfs or not var/attack_closed_turf = FALSE ///Returns true or false depending on if the target can be attacked by the mob -/datum/targetting_datum/basic/not_friends/can_attack(mob/living/living_mob, atom/target, vision_range) +/datum/targeting_strategy/basic/not_friends/can_attack(mob/living/living_mob, atom/target, vision_range) if(attack_closed_turf && isclosedturf(target)) return TRUE @@ -16,16 +16,16 @@ return ..() ///friends dont care about factions -/datum/targetting_datum/basic/not_friends/faction_check(mob/living/living_mob, mob/living/the_target) +/datum/targeting_strategy/basic/not_friends/faction_check(mob/living/living_mob, mob/living/the_target) return FALSE -/datum/targetting_datum/basic/not_friends/attack_closed_turfs +/datum/targeting_strategy/basic/not_friends/attack_closed_turfs attack_closed_turf = TRUE -/// Subtype that allows us to target items while deftly avoiding attacking our allies. Be careful when it comes to targetting items as an AI could get trapped targetting something it can't destroy. -/datum/targetting_datum/basic/not_friends/allow_items +/// Subtype that allows us to target items while deftly avoiding attacking our allies. Be careful when it comes to targeting items as an AI could get trapped targeting something it can't destroy. +/datum/targeting_strategy/basic/not_friends/allow_items -/datum/targetting_datum/basic/not_friends/allow_items/can_attack(mob/living/living_mob, atom/the_target, vision_range) +/datum/targeting_strategy/basic/not_friends/allow_items/can_attack(mob/living/living_mob, atom/the_target, vision_range) . = ..() if(isitem(the_target)) // trust fall exercise diff --git a/code/datums/ai/basic_mobs/targeting_strategies/with_object.dm b/code/datums/ai/basic_mobs/targeting_strategies/with_object.dm new file mode 100644 index 0000000000000..7cc76d3010c90 --- /dev/null +++ b/code/datums/ai/basic_mobs/targeting_strategies/with_object.dm @@ -0,0 +1,29 @@ +/** + * Find mobs who are holding the bb configurable object type + * + * This is an extension of basic targeting behaviour, that allows you to + * only target the mob if they have a specific item in their hand. + * + */ +/datum/targeting_strategy/basic/holding_object + /// BB key that holds the target typepath to use + var/target_item_key = BB_TARGET_HELD_ITEM + +///Returns true or false depending on if the target can be attacked by the mob +/datum/targeting_strategy/basic/holding_object/can_attack(mob/living/living_mob, atom/target, vision_range) + var/datum/ai_controller/controller = living_mob.ai_controller + var/object_type_path = controller.blackboard[target_item_key] + + if (object_type_path == null) + return FALSE // no op + if(!ismob(target)) + return FALSE // no hands no problems + + // Look at me, type casting like a grown up + var/mob/targetmob = target + // Check if our parent behaviour agrees we can attack this target (we ignore faction by default) + var/can_attack = ..() + if(can_attack && targetmob.is_holding_item_of_type(object_type_path)) + return TRUE // they have the item + // No valid target + return FALSE diff --git a/code/datums/ai/basic_mobs/targetting_datums/with_object.dm b/code/datums/ai/basic_mobs/targetting_datums/with_object.dm deleted file mode 100644 index 91e99bb4a221c..0000000000000 --- a/code/datums/ai/basic_mobs/targetting_datums/with_object.dm +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Find mobs who are holding the configurable object type - * - * This is an extension of basic targeting behaviour, that allows you to - * only target the mob if they have a specific item in their hand. - * - */ -/datum/targetting_datum/basic/holding_object - // We will find mobs who are holding this object in their hands - var/object_type_path = null - -/** - * Create an instance of the holding object targeting datum - * - * * object_type_path Pass an object type path, this will be compared to the items - * in targets hands to filter the target list. - */ -/datum/targetting_datum/basic/holding_object/New(object_type_path) - if (!ispath(object_type_path)) - stack_trace("trying to create an item targeting datum with no valid typepath") - // Leaving object type as null will make this basically a noop - return - src.object_type_path = object_type_path - -///Returns true or false depending on if the target can be attacked by the mob -/datum/targetting_datum/basic/holding_object/can_attack(mob/living/living_mob, atom/target, vision_range) - if (object_type_path == null) - return FALSE // no op - if(!ismob(target)) - return FALSE // no hands no problems - - // Look at me, type casting like a grown up - var/mob/targetmob = target - // Check if our parent behaviour agrees we can attack this target (we ignore faction by default) - var/can_attack = ..() - if(can_attack && targetmob.is_holding_item_of_type(object_type_path)) - return TRUE // they have the item - // No valid target - return FALSE diff --git a/code/datums/ai/dog/dog_behaviors.dm b/code/datums/ai/dog/dog_behaviors.dm index 6c9cb779bb3bd..c7723eab1a182 100644 --- a/code/datums/ai/dog/dog_behaviors.dm +++ b/code/datums/ai/dog/dog_behaviors.dm @@ -7,18 +7,18 @@ behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM required_distance = 3 -/datum/ai_behavior/basic_melee_attack/dog/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/basic_melee_attack/dog/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) controller.behavior_cooldowns[src] = world.time + action_cooldown var/mob/living/living_pawn = controller.pawn if(!(isturf(living_pawn.loc) || HAS_TRAIT(living_pawn, TRAIT_AI_BAGATTACK))) // Void puppies can attack from inside bags - finish_action(controller, FALSE, target_key, targetting_datum_key, hiding_location_key) + finish_action(controller, FALSE, target_key, targeting_strategy_key, hiding_location_key) return // Unfortunately going to repeat this check in parent call but what can you do var/atom/target = controller.blackboard[target_key] - var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] - if (!targetting_datum.can_attack(living_pawn, target)) - finish_action(controller, FALSE, target_key, targetting_datum_key, hiding_location_key) + var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) + if (!targeting_strategy.can_attack(living_pawn, target)) + finish_action(controller, FALSE, target_key, targeting_strategy_key, hiding_location_key) return if (!living_pawn.Adjacent(target)) diff --git a/code/datums/ai/dog/dog_controller.dm b/code/datums/ai/dog/dog_controller.dm index a95e3d57b6b20..a5794ff9b5f46 100644 --- a/code/datums/ai/dog/dog_controller.dm +++ b/code/datums/ai/dog/dog_controller.dm @@ -2,7 +2,7 @@ blackboard = list( BB_DOG_HARASS_HARM = TRUE, BB_VISION_RANGE = AI_DOG_VISION_RANGE, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, ) ai_movement = /datum/ai_movement/basic_avoidance idle_behavior = /datum/idle_behavior/idle_dog @@ -19,9 +19,11 @@ blackboard = list( BB_DOG_HARASS_HARM = TRUE, BB_VISION_RANGE = AI_DOG_VISION_RANGE, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends, - // Find nearby mobs with tongs in hand. - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/holding_object(/obj/item/kitchen/tongs), + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, + // Find nearby mobs ... + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/holding_object, + // With tongs in hand! + BB_TARGET_HELD_ITEM = /obj/item/kitchen/tongs, BB_BABIES_PARTNER_TYPES = list(/mob/living/basic/pet/dog), BB_BABIES_CHILD_TYPES = list(/mob/living/basic/pet/dog/corgi/puppy = 95, /mob/living/basic/pet/dog/corgi/puppy/void = 5), ) @@ -31,7 +33,7 @@ /datum/ai_planning_subtree/make_babies, // Ian WILL prioritise sex over following your instructions /datum/ai_planning_subtree/pet_planning, /datum/ai_planning_subtree/dog_harassment, - // Find targets to run away from (uses the targetting datum from above) + // Find targets to run away from (uses the targeting strategy from above) /datum/ai_planning_subtree/simple_find_target, // Flee from that target /datum/ai_planning_subtree/flee_target, @@ -43,3 +45,20 @@ return return corgi_pawn.access_card.GetAccess() + +/datum/ai_controller/basic_controller/dog/puppy + blackboard = list( + BB_DOG_HARASS_HARM = TRUE, + BB_VISION_RANGE = AI_DOG_VISION_RANGE, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/holding_object, + // With tongs in hand! + BB_TARGET_HELD_ITEM = /obj/item/kitchen/tongs, + ) + planning_subtrees = list( + /datum/ai_planning_subtree/random_speech/dog, + /datum/ai_planning_subtree/pet_planning, + /datum/ai_planning_subtree/dog_harassment, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/flee_target, + ) diff --git a/code/datums/ai/dog/dog_subtrees.dm b/code/datums/ai/dog/dog_subtrees.dm index 66198b61ac305..62f63da54bdd0 100644 --- a/code/datums/ai/dog/dog_subtrees.dm +++ b/code/datums/ai/dog/dog_subtrees.dm @@ -4,27 +4,27 @@ /datum/ai_planning_subtree/dog_harassment/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) if(!SPT_PROB(10, seconds_per_tick)) return - controller.queue_behavior(/datum/ai_behavior/find_hated_dog_target, BB_DOG_HARASS_TARGET, BB_PET_TARGETTING_DATUM) + controller.queue_behavior(/datum/ai_behavior/find_hated_dog_target, BB_DOG_HARASS_TARGET, BB_PET_TARGETING_STRATEGY) var/atom/harass_target = controller.blackboard[BB_DOG_HARASS_TARGET] if (isnull(harass_target)) return - controller.queue_behavior(/datum/ai_behavior/basic_melee_attack/dog, BB_DOG_HARASS_TARGET, BB_PET_TARGETTING_DATUM) + controller.queue_behavior(/datum/ai_behavior/basic_melee_attack/dog, BB_DOG_HARASS_TARGET, BB_PET_TARGETING_STRATEGY) return SUBTREE_RETURN_FINISH_PLANNING /datum/ai_behavior/find_hated_dog_target -/datum/ai_behavior/find_hated_dog_target/setup(datum/ai_controller/controller, target_key, targetting_datum_key) +/datum/ai_behavior/find_hated_dog_target/setup(datum/ai_controller/controller, target_key, targeting_strategy_key) . = ..() var/mob/living/dog = controller.pawn - var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] + var/datum/targeting_strategy/targeting_strategy = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) for(var/mob/living/iter_living in oview(2, dog)) if(iter_living.stat != CONSCIOUS || !HAS_TRAIT(iter_living, TRAIT_HATED_BY_DOGS)) continue if(!isnull(dog.buckled)) dog.audible_message(span_notice("[dog] growls at [iter_living], yet [dog.p_they()] [dog.p_are()] much too comfy to move."), hearing_distance = COMBAT_MESSAGE_RANGE) continue - if(!targetting_datum.can_attack(dog, iter_living)) + if(!targeting_strategy.can_attack(dog, iter_living)) continue dog.audible_message(span_warning("[dog] growls at [iter_living], seemingly annoyed by [iter_living.p_their()] presence."), hearing_distance = COMBAT_MESSAGE_RANGE) diff --git a/code/datums/ai/generic/find_and_set.dm b/code/datums/ai/generic/find_and_set.dm index 8ecc6df7cfbbb..f54ba33e6e3a3 100644 --- a/code/datums/ai/generic/find_and_set.dm +++ b/code/datums/ai/generic/find_and_set.dm @@ -68,12 +68,8 @@ /datum/ai_behavior/find_and_set/in_list /datum/ai_behavior/find_and_set/in_list/search_tactic(datum/ai_controller/controller, locate_paths, search_range) - var/list/found = list() - for(var/locate_path in locate_paths) - var/single_locate = ..(controller, locate_path, search_range) - if(single_locate) - found += single_locate - if(found.len) + var/list/found = typecache_filter_list(oview(search_range, controller.pawn), locate_paths) + if(length(found)) return pick(found) /** diff --git a/code/datums/ai/hunting_behavior/hunting_behaviors.dm b/code/datums/ai/hunting_behavior/hunting_behaviors.dm index 468cfed33fb98..3ea9feb2b3489 100644 --- a/code/datums/ai/hunting_behavior/hunting_behaviors.dm +++ b/code/datums/ai/hunting_behavior/hunting_behaviors.dm @@ -81,6 +81,7 @@ /// Do we reset the target after attacking something, so we can check for status changes. var/always_reset_target = FALSE + /datum/ai_behavior/hunt_target/setup(datum/ai_controller/controller, hunting_target_key, hunting_cooldown_key) . = ..() var/atom/hunt_target = controller.blackboard[hunting_target_key] @@ -123,10 +124,27 @@ controller.clear_blackboard_key(hunting_target_key) /datum/ai_behavior/hunt_target/unarmed_attack_target + ///do we toggle combat mode before interacting with the object? + var/switch_combat_mode = FALSE /datum/ai_behavior/hunt_target/unarmed_attack_target/target_caught(mob/living/hunter, obj/structure/cable/hunted) + if(switch_combat_mode) + hunter.combat_mode = !(hunter.combat_mode) hunter.UnarmedAttack(hunted, TRUE) +/datum/ai_behavior/hunt_target/unarmed_attack_target/finish_action(datum/ai_controller/controller, succeeded, hunting_target_key, hunting_cooldown_key) + . = ..() + if(!switch_combat_mode) + return + var/mob/living/living_pawn = controller.pawn + living_pawn.combat_mode = initial(living_pawn.combat_mode) + +/datum/ai_behavior/hunt_target/unarmed_attack_target/switch_combat_mode + switch_combat_mode = TRUE + +/datum/ai_behavior/hunt_target/unarmed_attack_target/reset_target + always_reset_target = TRUE + /datum/ai_behavior/hunt_target/use_ability_on_target always_reset_target = TRUE ///the ability we will use diff --git a/code/datums/ai/learn_ai.md b/code/datums/ai/learn_ai.md index 9906806cfbd57..e4e8a712cf0bf 100644 --- a/code/datums/ai/learn_ai.md +++ b/code/datums/ai/learn_ai.md @@ -25,7 +25,7 @@ First, let's look at the blackboard. ```dm /datum/ai_controller/basic/cow blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items(), + BB_TARGETING_STRATEGY = new /datum/targeting_strategy/basic/allow_items(), BB_BASIC_MOB_TIP_REACTING = FALSE, BB_BASIC_MOB_TIPPER = null, ) @@ -81,7 +81,7 @@ Okay, so we have blackboard variables, which are considered by subtrees to plan //now we know we have a target but should let a hostile subtree plan attacking humans. let's check if it's actually food if(target in wanted) - controller.queue_behavior(/datum/ai_behavior/basic_melee_attack, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + controller.queue_behavior(/datum/ai_behavior/basic_melee_attack, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) return SUBTREE_RETURN_FINISH_PLANNING //this prevents further subtrees from planning since we want to focus on eating the food ``` @@ -94,7 +94,7 @@ And one of those behaviors, `basic_melee_attack`. As I have been doing so far, I //flag tells the AI it needs to have a movement target to work, and since it doesn't have "AI_BEHAVIOR_MOVE_AND_PERFORM", it won't call perform() every 0.6 seconds until it is in melee range. Smart! behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT -/datum/ai_behavior/basic_melee_attack/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/basic_melee_attack/setup(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) . = ..() //all this is doing in setup is setting the movement target. setup is called once when the behavior is first planned, and returning FALSE can cancel the behavior if something isn't right. @@ -107,20 +107,20 @@ And one of those behaviors, `basic_melee_attack`. As I have been doing so far, I controller.current_movement_target = target ///perform will run every "action_cooldown" deciseconds as long as the conditions are good for it to do so (we set "AI_BEHAVIOR_REQUIRE_MOVEMENT", so it won't perform until in range). -/datum/ai_behavior/basic_melee_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/basic_melee_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) . = ..() var/mob/living/basic/basic_mob = controller.pawn - //targetting datum will kill the action if not real anymore + //targeting strategy will kill the action if not real anymore var/datum/weakref/weak_target = controller.blackboard[target_key] var/atom/target = weak_target?.resolve() - var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] + var/datum/targeting_strategy/targeting_strategy = controller.blackboard[targeting_strategy_key] - if(!targetting_datum.can_attack(basic_mob, target)) + if(!targeting_strategy.can_attack(basic_mob, target)) ///We have a target that is no longer valid to attack. Remember that returning doesn't end the behavior, JUST this single performance. So we call "finish_action" with whether it succeeded in doing what it wanted to do (it didn't, so FALSE) and the blackboard keys passed into this behavior. finish_action(controller, FALSE, target_key) return //don't forget to end the performance too - var/hiding_target = targetting_datum.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something! + var/hiding_target = targeting_strategy.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something! controller.blackboard[hiding_location_key] = hiding_target @@ -131,7 +131,7 @@ And one of those behaviors, `basic_melee_attack`. As I have been doing so far, I basic_mob.melee_attack(target) ///and so the action has ended. we can now clean up the AI's blackboard based on the success of the action, and the keys passed in. -/datum/ai_behavior/basic_melee_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/basic_melee_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targeting_strategy_key, hiding_location_key) . = ..() ///if the behavior failed, the target is no longer valid, so we should lose aggro of them. We remove the target_key (which could be anything, it's whatever key was passed into the behavior by the subtree) from the blackboard. Couldn't do THAT with normal variables! if(!succeeded) diff --git a/code/datums/ai/movement/_ai_movement.dm b/code/datums/ai/movement/_ai_movement.dm index 2b734ca24a920..af29e83f1a4a3 100644 --- a/code/datums/ai/movement/_ai_movement.dm +++ b/code/datums/ai/movement/_ai_movement.dm @@ -24,37 +24,47 @@ if(controller.pathing_attempts >= max_pathing_attempts) controller.CancelActions() -///Should the movement be allowed to happen? As of writing this, MOVELOOP_SKIP_STEP is defined as (1<<0) so be careful on using (return TRUE) or (can_move = TRUE; return can_move) +///Should the movement be allowed to happen? return TRUE if it can, FALSE otherwise /datum/ai_movement/proc/allowed_to_move(datum/move_loop/source) + SHOULD_BE_PURE(TRUE) + var/atom/movable/pawn = source.moving var/datum/ai_controller/controller = source.extra_info - source.delay = controller.movement_delay var/can_move = TRUE - if(controller.ai_traits & STOP_MOVING_WHEN_PULLED && pawn.pulledby) //Need to store more state. Annoying. + if((controller.ai_traits & STOP_MOVING_WHEN_PULLED) && pawn.pulledby) //Need to store more state. Annoying. can_move = FALSE if(!isturf(pawn.loc)) //No moving if not on a turf can_move = FALSE + if(isliving(pawn)) + var/mob/living/pawn_mob = pawn + if(!(pawn_mob.mobility_flags & MOBILITY_MOVE)) + can_move = FALSE + + return can_move + +///Anything to do before moving; any checks if the pawn should be able to move should be placed in allowed_to_move() and called by this proc +/datum/ai_movement/proc/pre_move(datum/move_loop/source) + SIGNAL_HANDLER + SHOULD_NOT_OVERRIDE(TRUE) + + var/datum/ai_controller/controller = source.extra_info + // Check if this controller can actually run, so we don't chase people with corpses if(!controller.able_to_run()) controller.CancelActions() qdel(source) //stop moving return MOVELOOP_SKIP_STEP - //Why doesn't this return TRUE or can_move? - //MOVELOOP_SKIP_STEP is defined as (1<<0) and TRUE are defined as the same "1", returning TRUE would be the equivalent of skipping the move - if(can_move) - return + source.delay = controller.movement_delay + + if(allowed_to_move(source)) + return NONE increment_pathing_failures(controller) return MOVELOOP_SKIP_STEP -///Anything to do before moving; any checks if the pawn should be able to move should be placed in allowed_to_move() and called by this proc -/datum/ai_movement/proc/pre_move(datum/move_loop/source) - SIGNAL_HANDLER - return allowed_to_move(source) - //Anything to do post movement /datum/ai_movement/proc/post_move(datum/move_loop/source, succeeded) SIGNAL_HANDLER diff --git a/code/datums/ai/movement/ai_movement_basic_avoidance.dm b/code/datums/ai/movement/ai_movement_basic_avoidance.dm index ad5b51a0ca372..6b48f1b5e9e1f 100644 --- a/code/datums/ai/movement/ai_movement_basic_avoidance.dm +++ b/code/datums/ai/movement/ai_movement_basic_avoidance.dm @@ -16,10 +16,8 @@ /datum/ai_movement/basic_avoidance/allowed_to_move(datum/move_loop/has_target/dist_bound/source) . = ..() var/turf/target_turf = get_step_towards(source.moving, source.target) - if(!target_turf?.can_cross_safely(source.moving)) - . = MOVELOOP_SKIP_STEP - return . + return FALSE /// Move immediately and don't update our facing /datum/ai_movement/basic_avoidance/backstep diff --git a/code/datums/ai/movement/ai_movement_complete_stop.dm b/code/datums/ai/movement/ai_movement_complete_stop.dm index 7805eeb3f6f65..dcae93f1ba0a5 100644 --- a/code/datums/ai/movement/ai_movement_complete_stop.dm +++ b/code/datums/ai/movement/ai_movement_complete_stop.dm @@ -12,4 +12,4 @@ RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) /datum/ai_movement/complete_stop/allowed_to_move(datum/move_loop/source) - return // no movement allowed + return FALSE diff --git a/code/datums/ai/movement/ai_movement_dumb.dm b/code/datums/ai/movement/ai_movement_dumb.dm index 041f1a967c2ad..06ac4bdd10c4c 100644 --- a/code/datums/ai/movement/ai_movement_dumb.dm +++ b/code/datums/ai/movement/ai_movement_dumb.dm @@ -14,7 +14,5 @@ /datum/ai_movement/dumb/allowed_to_move(datum/move_loop/has_target/source) . = ..() var/turf/target_turf = get_step_towards(source.moving, source.target) - if(!target_turf?.can_cross_safely(source.moving)) - . = MOVELOOP_SKIP_STEP - return . + return FALSE diff --git a/code/datums/ai_laws/ai_laws.dm b/code/datums/ai_laws/ai_laws.dm index c3ea9fcfadfae..9b9f9c6284115 100644 --- a/code/datums/ai_laws/ai_laws.dm +++ b/code/datums/ai_laws/ai_laws.dm @@ -116,7 +116,7 @@ GLOBAL_VAR(round_default_lawset) /// Zeroth law /// A lawset can only have 1 zeroth law, it's the top dog. - /// Nothing removes it unless it's admin forced + /// Removed by things that remove core/inherent laws, but only if protected_zeroth is false. Otherwise, cannot be removed except by admins var/zeroth = null /// Zeroth borg law /// It's just a zeroth law but specially themed for cyborgs diff --git a/code/datums/brain_damage/special.dm b/code/datums/brain_damage/special.dm index ed3e91707b99d..81d354a19e841 100644 --- a/code/datums/brain_damage/special.dm +++ b/code/datums/brain_damage/special.dm @@ -107,6 +107,10 @@ . = ..() QDEL_IN(src, 30 SECONDS) +/obj/effect/client_image_holder/bluespace_stream/generate_image() + . = ..() + apply_wibbly_filters(.) + /obj/effect/client_image_holder/bluespace_stream/Destroy() if(!QDELETED(linked_to)) qdel(linked_to) diff --git a/code/datums/brain_damage/split_personality.dm b/code/datums/brain_damage/split_personality.dm index 92992865e4480..faa05a6bd28ea 100644 --- a/code/datums/brain_damage/split_personality.dm +++ b/code/datums/brain_damage/split_personality.dm @@ -25,11 +25,11 @@ /datum/brain_trauma/severe/split_personality/proc/make_backseats() stranger_backseat = new(owner, src) - var/datum/action/cooldown/spell/personality_commune/stranger_spell = new(src) + var/datum/action/personality_commune/stranger_spell = new(src) stranger_spell.Grant(stranger_backseat) owner_backseat = new(owner, src) - var/datum/action/cooldown/spell/personality_commune/owner_spell = new(src) + var/datum/action/personality_commune/owner_spell = new(src) owner_spell.Grant(owner_backseat) /// Attempts to get a ghost to play the personality diff --git a/code/datums/components/breeding.dm b/code/datums/components/breeding.dm new file mode 100644 index 0000000000000..7c9bcecf7bce5 --- /dev/null +++ b/code/datums/components/breeding.dm @@ -0,0 +1,76 @@ +/* + * A component to allow us to breed + */ +/datum/component/breed + /// additional mobs we can breed with + var/list/can_breed_with + ///path of the baby + var/baby_path + ///time to wait after breeding + var/breed_timer + ///AI key we set when we're ready to breed + var/breed_key = BB_BREED_READY + ///are we ready to breed? + var/ready_to_breed = TRUE + ///callback after we give birth to the child + var/datum/callback/post_birth + +/datum/component/breed/Initialize(list/can_breed_with = list(), breed_timer = 40 SECONDS, baby_path, post_birth) + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + + if(ishuman(parent)) //sin detected + return COMPONENT_INCOMPATIBLE + + if(!ispath(baby_path)) + stack_trace("attempted to add a breeding component with invalid baby path!") + return + + src.can_breed_with = can_breed_with + src.breed_timer = breed_timer + src.baby_path = baby_path + src.post_birth = post_birth + + ADD_TRAIT(parent, TRAIT_SUBTREE_REQUIRED_OPERATIONAL_DATUM, type) + +/datum/component/breed/RegisterWithParent() + RegisterSignal(parent, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(breed_with_partner)) + ADD_TRAIT(parent, TRAIT_MOB_BREEDER, REF(src)) + var/mob/living/parent_mob = parent + parent_mob.ai_controller?.set_blackboard_key(breed_key, TRUE) + +/datum/component/breed/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_HOSTILE_PRE_ATTACKINGTARGET) + REMOVE_TRAIT(parent, TRAIT_MOB_BREEDER, REF(src)) + post_birth = null + + +/datum/component/breed/proc/breed_with_partner(mob/living/source, mob/living/target) + SIGNAL_HANDLER + + if(source.combat_mode) + return + + if(!is_type_in_typecache(target, can_breed_with)) + return + + if(!HAS_TRAIT(target, TRAIT_MOB_BREEDER) || target.gender == source.gender) + return + + if(!ready_to_breed) + source.balloon_alert(source, "not ready!") + return COMPONENT_HOSTILE_NO_ATTACK + + var/turf/delivery_destination = get_turf(source) + var/mob/living/baby = new baby_path(delivery_destination) + new /obj/effect/temp_visual/heart(delivery_destination) + toggle_status(source) + + addtimer(CALLBACK(src, PROC_REF(toggle_status), source), breed_timer) + post_birth?.Invoke(baby, target) + return COMPONENT_HOSTILE_NO_ATTACK + +/datum/component/breed/proc/toggle_status(mob/living/source) + ready_to_breed = !ready_to_breed + source.ai_controller?.set_blackboard_key(BB_BREED_READY, ready_to_breed) + diff --git a/code/datums/components/crafting/ranged_weapon.dm b/code/datums/components/crafting/ranged_weapon.dm index 94a943b42c8fd..a8b64f428d9a5 100644 --- a/code/datums/components/crafting/ranged_weapon.dm +++ b/code/datums/components/crafting/ranged_weapon.dm @@ -206,6 +206,36 @@ time = 5 SECONDS category = CAT_WEAPON_RANGED +/datum/crafting_recipe/rebarxbow + name = "Heated Rebar Crossbow" + result = /obj/item/gun/ballistic/rifle/rebarxbow + reqs = list( + /obj/item/stack/rods = 6, + /obj/item/stack/cable_coil = 12, + /obj/item/inducer = 1, + ) + blacklist = list( + /obj/item/inducer/sci, + ) + tool_behaviors = list(TOOL_WELDER) + time = 5 SECONDS + category = CAT_WEAPON_RANGED + +/datum/crafting_recipe/rebarxbowforced + name = "Forced Rebar Crossbow" + desc = "Get an extra shot in your crossbow... for a chance of shooting yourself when you fire it." + result = /obj/item/gun/ballistic/rifle/rebarxbow/forced + reqs = list( + /obj/item/gun/ballistic/rifle/rebarxbow = 1, + ) + blacklist = list( + /obj/item/gun/ballistic/rifle/rebarxbow/forced, + /obj/item/gun/ballistic/rifle/rebarxbow/syndie, + ) + tool_behaviors = list(TOOL_CROWBAR) + time = 1 SECONDS + category = CAT_WEAPON_RANGED + /datum/crafting_recipe/pipegun_prime name = "Regal Pipegun" always_available = FALSE diff --git a/code/datums/components/crafting/weapon_ammo.dm b/code/datums/components/crafting/weapon_ammo.dm index 437bfaa2e9202..44b8055b3ff94 100644 --- a/code/datums/components/crafting/weapon_ammo.dm +++ b/code/datums/components/crafting/weapon_ammo.dm @@ -12,6 +12,17 @@ time = 0.5 SECONDS category = CAT_WEAPON_AMMO +/datum/crafting_recipe/rebarsyndie + name = "jagged iron rod" + result = /obj/item/ammo_casing/rebar/syndie + reqs = list( + /obj/item/stack/rods = 1, + ) + tool_behaviors = list(TOOL_WIRECUTTER) + time = 0.5 SECONDS + always_available = FALSE + category = CAT_WEAPON_AMMO + /datum/crafting_recipe/pulseslug name = "Pulse Slug Shell" result = /obj/item/ammo_casing/shotgun/pulseslug diff --git a/code/datums/components/damage_chain.dm b/code/datums/components/damage_chain.dm new file mode 100644 index 0000000000000..be61ec68a33cc --- /dev/null +++ b/code/datums/components/damage_chain.dm @@ -0,0 +1,112 @@ +/** + * Draws a line between you and another atom, hurt anyone stood in the line + */ +/datum/component/damage_chain + dupe_mode = COMPONENT_DUPE_ALLOWED + /// How often do we attempt to deal damage? + var/tick_interval + /// Tracks when we can next deal damage + COOLDOWN_DECLARE(tick_cooldown) + /// Damage inflicted per tick + var/damage_per_tick + /// Type of damage to inflict + var/damage_type + /// Optional callback which checks if we can damage the target + var/datum/callback/validate_target + /// Optional callback for additional visuals or text display when dealing damage + var/datum/callback/chain_damage_feedback + /// We will fire the damage feedback callback on every x successful attacks + var/feedback_interval + /// How many successful attacks have we made? + var/successful_attacks = 0 + /// Time between making any attacks at which we just reset the successful attack counter + var/reset_feedback_timer = 0 + /// Our chain + var/datum/beam/chain + +/datum/component/damage_chain/Initialize( + atom/linked_to, + max_distance = 7, + beam_icon = 'icons/effects/beam.dmi', + beam_state = "medbeam", + beam_type = /obj/effect/ebeam, + tick_interval = 0.3 SECONDS, + damage_per_tick = 1.2, + damage_type = BURN, + datum/callback/validate_target = null, + datum/callback/chain_damage_feedback = null, + feedback_interval = 5, +) + . = ..() + if (!isatom(parent)) + return COMPONENT_INCOMPATIBLE + if (!isatom(linked_to)) + CRASH("Attempted to create [type] linking [parent.type] with non-atom [linked_to]!") + + src.tick_interval = tick_interval + src.damage_per_tick = damage_per_tick + src.damage_type = damage_type + src.validate_target = validate_target + src.chain_damage_feedback = chain_damage_feedback + src.feedback_interval = feedback_interval + + var/atom/atom_parent = parent + chain = atom_parent.Beam(linked_to, icon = beam_icon, icon_state = beam_state, beam_type = beam_type, maxdistance = max_distance) + RegisterSignal(chain, COMSIG_QDELETING, PROC_REF(end_beam)) + START_PROCESSING(SSfastprocess, src) + +/datum/component/damage_chain/RegisterWithParent() + RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(end_beam)) // We actually don't really use many signals it's all processing + +/datum/component/damage_chain/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_LIVING_DEATH) + +/datum/component/damage_chain/Destroy(force, silent) + if (!QDELETED(chain)) + UnregisterSignal(chain, COMSIG_QDELETING) + QDEL_NULL(chain) + chain = null + STOP_PROCESSING(SSfastprocess, src) + return ..() + +/// Destroy ourself +/datum/component/damage_chain/proc/end_beam() + SIGNAL_HANDLER + qdel(src) + +/datum/component/damage_chain/process(seconds_per_tick) + var/successful_hit = FALSE + var/list/target_turfs = list() + for(var/obj/effect/ebeam/chainpart in chain.elements) + if (isnull(chainpart) || !chainpart.x || !chainpart.y || !chainpart.z) + continue + var/turf/overlaps = get_turf_pixel(chainpart) + target_turfs |= overlaps + if(overlaps == get_turf(chain.origin) || overlaps == get_turf(chain.target)) + continue + for(var/turf/nearby_turf in circle_range(overlaps, 1)) + target_turfs |= nearby_turf + + for(var/turf/hit_turf as anything in target_turfs) + for(var/mob/living/victim in hit_turf) + if (victim == parent || victim.stat == DEAD) + continue + if (!isnull(validate_target) && !validate_target.Invoke(victim)) + continue + if (successful_attacks == 0) + chain_damage_feedback?.Invoke(victim) + victim.apply_damage(damage_per_tick, damage_type, wound_bonus = CANT_WOUND) + successful_hit = TRUE + + if (isnull(chain_damage_feedback)) + return + if (successful_hit) + successful_attacks++ + reset_feedback_timer = addtimer(CALLBACK(src, PROC_REF(reset_feedback)), 10 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE|TIMER_DELETE_ME) + if (successful_attacks > feedback_interval) + reset_feedback() + +/// Make it so that the next time we hit something we'll invoke the feedback callback +/datum/component/damage_chain/proc/reset_feedback() + successful_attacks = 0 + deltimer(reset_feedback_timer) diff --git a/code/datums/components/direct_explosive_trap.dm b/code/datums/components/direct_explosive_trap.dm new file mode 100644 index 0000000000000..0d204f21a1ee7 --- /dev/null +++ b/code/datums/components/direct_explosive_trap.dm @@ -0,0 +1,85 @@ +/** + * Responds to certain signals and 'explodes' on the person using the item. + * Differs from `interaction_booby_trap` in that this doesn't actually explode, it just directly calls ex_act on one person. + */ +/datum/component/direct_explosive_trap + /// An optional mob to inform about explosions + var/mob/living/saboteur + /// Amount of force to apply + var/explosive_force + /// Colour for examine notification + var/glow_colour + /// Optional additional target checks before we go off + var/datum/callback/explosive_checks + /// Signals which set off the bomb, must pass a mob as the first non-source argument + var/list/triggering_signals + +/datum/component/direct_explosive_trap/Initialize( + mob/living/saboteur, + explosive_force = EXPLODE_HEAVY, + expire_time = 1 MINUTES, + glow_colour = COLOR_RED, + datum/callback/explosive_checks, + list/triggering_signals = list(COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_BUMPED) +) + . = ..() + if (!isatom(parent)) + return COMPONENT_INCOMPATIBLE + src.saboteur = saboteur + src.explosive_force = explosive_force + src.glow_colour = glow_colour + src.explosive_checks = explosive_checks + src.triggering_signals = triggering_signals + + if (expire_time > 0) + addtimer(CALLBACK(src, PROC_REF(bomb_expired)), expire_time, TIMER_DELETE_ME) + +/datum/component/direct_explosive_trap/RegisterWithParent() + if (!(COMSIG_ATOM_EXAMINE in triggering_signals)) // Maybe you're being extra mean with this one + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examined)) + RegisterSignals(parent, triggering_signals, PROC_REF(explode)) + if (!isnull(saboteur)) + RegisterSignal(saboteur, COMSIG_QDELETING, PROC_REF(on_bomber_deleted)) + +/datum/component/direct_explosive_trap/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_ATOM_EXAMINE) + triggering_signals) + if (!isnull(saboteur)) + UnregisterSignal(saboteur, COMSIG_QDELETING) + +/datum/component/direct_explosive_trap/Destroy(force, silent) + if (isnull(saboteur)) + return ..() + UnregisterSignal(saboteur, COMSIG_QDELETING) + saboteur = null + return ..() + +/// Called if we sit too long without going off +/datum/component/direct_explosive_trap/proc/bomb_expired() + if (!isnull(saboteur)) + to_chat(saboteur, span_bolddanger("Failure! Your trap didn't catch anyone this time...")) + qdel(src) + +/// Let people know something is up +/datum/component/direct_explosive_trap/proc/on_examined(datum/source, mob/user, text) + SIGNAL_HANDLER + text += span_holoparasite("It glows with a strange light...") + +/// Blow up +/datum/component/direct_explosive_trap/proc/explode(atom/source, mob/living/victim) + SIGNAL_HANDLER + if (!isliving(victim)) + return + if (!isnull(explosive_checks) && !explosive_checks.Invoke(victim)) + return + to_chat(victim, span_bolddanger("[source] was boobytrapped!")) + if (!isnull(saboteur)) + to_chat(saboteur, span_bolddanger("Success! Your trap on [source] caught [victim.name]!")) + playsound(source, 'sound/effects/explosion2.ogg', 200, TRUE) + new /obj/effect/temp_visual/explosion(get_turf(source)) + EX_ACT(victim, explosive_force) + qdel(src) + +/// Don't hang a reference to the person who placed the bomb +/datum/component/direct_explosive_trap/proc/on_bomber_deleted() + SIGNAL_HANDLER + saboteur = null diff --git a/code/datums/components/drift.dm b/code/datums/components/drift.dm index e974a3465ff1b..6b91a83534fb3 100644 --- a/code/datums/components/drift.dm +++ b/code/datums/components/drift.dm @@ -34,7 +34,7 @@ RegisterSignal(drifting_loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(after_move)) RegisterSignal(drifting_loop, COMSIG_QDELETING, PROC_REF(loop_death)) RegisterSignal(movable_parent, COMSIG_MOVABLE_NEWTONIAN_MOVE, PROC_REF(newtonian_impulse)) - if(drifting_loop.running) + if(drifting_loop.status & MOVELOOP_STATUS_RUNNING) drifting_start(drifting_loop) // There's a good chance it'll autostart, gotta catch that var/visual_delay = movable_parent.inertia_move_delay diff --git a/code/datums/components/energized.dm b/code/datums/components/energized.dm index 41262e23efc6a..f70e661336a11 100644 --- a/code/datums/components/energized.dm +++ b/code/datums/components/energized.dm @@ -1,3 +1,6 @@ +#define NORMAL_TOAST_PROB 3 +#define BROKEN_TOAST_PROB 33 + /datum/component/energized can_transfer = FALSE ///what we give to connect_loc by default, makes slippable mobs moving over us slip @@ -48,24 +51,14 @@ /datum/component/energized/proc/toast(turf/open/floor/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs) SIGNAL_HANDLER - if(!source.broken && !source.burnt) - return - if(!isliving(arrived)) return - if(prob(85)) - if(prob(25)) - do_sparks(1, FALSE, source) - playsound(src, SFX_SPARKS, 40, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - source.audible_message(span_danger("[parent] makes an electric crackle...")) - return - var/mob/living/future_tram_victim = arrived var/datum/transport_controller/linear/tram/tram = transport_ref?.resolve() // Check for stopped states. - if(isnull(tram) || !tram.controller_operational || !inbound || !outbound) + if(isnull(tram) || !tram.controller_operational || !tram.controller_active || !inbound || !outbound) return FALSE var/obj/structure/transport/linear/tram/tram_part = tram.return_closest_platform_to(parent) @@ -76,6 +69,17 @@ if(isnull(source)) return FALSE + var/toast_prob = NORMAL_TOAST_PROB + if(source.broken || source.burnt || HAS_TRAIT(future_tram_victim, TRAIT_CURSED)) + toast_prob = BROKEN_TOAST_PROB + + if(prob(100 - toast_prob)) + if(prob(25)) + do_sparks(1, FALSE, source) + playsound(src, SFX_SPARKS, 40, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + source.audible_message(span_danger("[parent] makes an electric crackle...")) + return FALSE + // Everything will be based on position and travel direction var/plate_pos var/tram_pos @@ -102,7 +106,7 @@ return FALSE if((tram.travel_direction & EAST) && outbound > tram.destination_platform.platform_code) return FALSE - if(approach_distance >= AMBER_THRESHOLD_NORMAL) + if(approach_distance >= AMBER_THRESHOLD_DEGRADED) return FALSE // Finally the interesting part where they ACTUALLY get hit! @@ -112,8 +116,12 @@ action = NOTIFY_ORBIT, header = "Electrifying!", ) + do_sparks(4, FALSE, source) playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) source.audible_message(span_danger("[parent] makes a loud electric crackle!")) to_chat(future_tram_victim, span_userdanger("You hear a loud electric crackle!")) future_tram_victim.electrocute_act(15, src, 1) return TRUE + +#undef NORMAL_TOAST_PROB +#undef BROKEN_TOAST_PROB diff --git a/code/datums/components/gunpoint.dm b/code/datums/components/gunpoint.dm index c248b4f18c04d..bf44f1c4b3c4e 100644 --- a/code/datums/components/gunpoint.dm +++ b/code/datums/components/gunpoint.dm @@ -36,7 +36,16 @@ target = targ weapon = wep - RegisterSignals(targ, list(COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_ITEM_ATTACK, COMSIG_MOVABLE_MOVED, COMSIG_MOB_FIRED_GUN), PROC_REF(trigger_reaction)) + RegisterSignals(targ, list( + COMSIG_MOB_ATTACK_HAND, + COMSIG_MOB_ITEM_ATTACK, + COMSIG_MOVABLE_MOVED, + COMSIG_MOB_FIRED_GUN, + COMSIG_MOVABLE_SET_GRAB_STATE, + COMSIG_LIVING_START_PULL), PROC_REF(trigger_reaction)) + RegisterSignal(targ, COMSIG_ATOM_EXAMINE, PROC_REF(examine_target)) + RegisterSignal(targ, COMSIG_LIVING_PRE_MOB_BUMP, PROC_REF(block_bumps_target)) + RegisterSignals(targ, list(COMSIG_HUMAN_DISARM_HIT, COMSIG_LIVING_GET_PULLED), PROC_REF(cancel)) RegisterSignals(weapon, list(COMSIG_ITEM_DROPPED, COMSIG_ITEM_EQUIPPED), PROC_REF(cancel)) var/distance = min(get_dist(shooter, target), 1) // treat 0 distance as adjacent @@ -77,6 +86,9 @@ RegisterSignal(parent, COMSIG_MOB_ATTACK_HAND, PROC_REF(check_shove)) RegisterSignal(parent, COMSIG_MOB_UPDATE_SIGHT, PROC_REF(check_deescalate)) RegisterSignals(parent, list(COMSIG_LIVING_START_PULL, COMSIG_MOVABLE_BUMP), PROC_REF(check_bump)) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(examine)) + RegisterSignal(parent, COMSIG_LIVING_PRE_MOB_BUMP, PROC_REF(block_bumps_parent)) + RegisterSignal(parent, COMSIG_HUMAN_DISARM_HIT, PROC_REF(cancel)) /datum/component/gunpoint/UnregisterFromParent() UnregisterSignal(parent, COMSIG_MOVABLE_MOVED) @@ -84,6 +96,9 @@ UnregisterSignal(parent, COMSIG_MOB_UPDATE_SIGHT) UnregisterSignal(parent, COMSIG_MOB_ATTACK_HAND) UnregisterSignal(parent, list(COMSIG_LIVING_START_PULL, COMSIG_MOVABLE_BUMP)) + UnregisterSignal(parent, COMSIG_ATOM_EXAMINE) + UnregisterSignal(parent, COMSIG_LIVING_PRE_MOB_BUMP) + UnregisterSignal(parent, COMSIG_HUMAN_DISARM_HIT) ///If the shooter bumps the target, cancel the holdup to avoid cheesing and forcing the charged shot /datum/component/gunpoint/proc/check_bump(atom/B, atom/A) @@ -195,6 +210,30 @@ ) INVOKE_ASYNC(src, PROC_REF(trigger_reaction)) +///Shows if the parent is holding someone at gunpoint +/datum/component/gunpoint/proc/examine(datum/source, mob/user, list/examine_list) + SIGNAL_HANDLER + if(user in viewers(target)) + examine_list += span_boldwarning("[parent] [parent.p_are()] holding [target] at gunpoint with [weapon]!") + +///Shows if the examine target is being held at gunpoint +/datum/component/gunpoint/proc/examine_target(datum/source, mob/user, list/examine_list) + SIGNAL_HANDLER + if(user in viewers(parent)) + examine_list += span_boldwarning("[target] [target.p_are()] being held at gunpoint by [parent]!") + +///Prevents bumping the shooter to break gunpoint since shove does that +/datum/component/gunpoint/proc/block_bumps_parent(mob/bumped, mob/living/bumper) + SIGNAL_HANDLER + to_chat(bumper, span_warning("[bumped] [bumped.p_are()] holding [target] at gunpoint, you cannot push past.")) + return COMPONENT_LIVING_BLOCK_PRE_MOB_BUMP + +///Prevents bumping the target by an ally to cheese and force the charged shot +/datum/component/gunpoint/proc/block_bumps_target(mob/bumped, mob/living/bumper) + SIGNAL_HANDLER + to_chat(bumper, span_warning("[bumped] [bumped.p_are()] being held at gunpoint, it's not wise to push [bumped.p_them()]!")) + return COMPONENT_LIVING_BLOCK_PRE_MOB_BUMP + #undef GUNPOINT_DELAY_STAGE_2 #undef GUNPOINT_DELAY_STAGE_3 #undef GUNPOINT_BASE_WOUND_BONUS diff --git a/code/datums/components/healing_touch.dm b/code/datums/components/healing_touch.dm index a81de7ab04a78..cf6ef88f24d60 100644 --- a/code/datums/components/healing_touch.dm +++ b/code/datums/components/healing_touch.dm @@ -8,10 +8,15 @@ * This intercepts the attack and starts a do_after if the target is in its allowed type list. */ /datum/component/healing_touch + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS /// How much brute damage to heal var/heal_brute /// How much burn damage to heal var/heal_burn + /// How much toxin damage to heal + var/heal_tox + /// How much oxygen damage to heal + var/heal_oxy /// How much stamina damage to heal var/heal_stamina /// Interaction will use this key, and be blocked while this key is in use @@ -26,8 +31,8 @@ var/valid_biotypes /// Which kinds of carbon limbs can we heal, has no effect on non-carbon mobs. Set to null if you don't care about excluding prosthetics. var/required_bodytype - /// How targetting yourself works, expects one of HEALING_TOUCH_ANYONE, HEALING_TOUCH_NOT_SELF, or HEALING_TOUCH_SELF_ONLY - var/self_targetting + /// How targeting yourself works, expects one of HEALING_TOUCH_ANYONE, HEALING_TOUCH_NOT_SELF, or HEALING_TOUCH_SELF_ONLY + var/self_targeting /// Text to print when action starts, replaces %SOURCE% with healer and %TARGET% with healed mob var/action_text /// Text to print when action completes, replaces %SOURCE% with healer and %TARGET% with healed mob @@ -36,10 +41,16 @@ var/show_health /// Color for the healing effect var/heal_color + /// Optional click modifier required + var/required_modifier + /// Callback to run after healing a mob + var/datum/callback/after_healed /datum/component/healing_touch/Initialize( heal_brute = 20, heal_burn = 20, + heal_tox = 0, + heal_oxy = 0, heal_stamina = 0, heal_time = 2 SECONDS, interaction_key = DOAFTER_SOURCE_HEAL_TOUCH, @@ -47,17 +58,21 @@ list/valid_targets_typecache = list(), valid_biotypes = MOB_ORGANIC | MOB_MINERAL, required_bodytype = BODYTYPE_ORGANIC, - self_targetting = HEALING_TOUCH_NOT_SELF, + self_targeting = HEALING_TOUCH_NOT_SELF, action_text = "%SOURCE% begins healing %TARGET%", complete_text = "%SOURCE% finishes healing %TARGET%", show_health = FALSE, heal_color = COLOR_HEALING_CYAN, + required_modifier = null, + datum/callback/after_healed = null, ) if (!isliving(parent)) return COMPONENT_INCOMPATIBLE src.heal_brute = heal_brute src.heal_burn = heal_burn + src.heal_tox = heal_tox + src.heal_oxy = heal_oxy src.heal_stamina = heal_stamina src.heal_time = heal_time src.interaction_key = interaction_key @@ -65,15 +80,25 @@ src.valid_targets_typecache = valid_targets_typecache.Copy() src.valid_biotypes = valid_biotypes src.required_bodytype = required_bodytype - src.self_targetting = self_targetting + src.self_targeting = self_targeting src.action_text = action_text src.complete_text = complete_text src.show_health = show_health src.heal_color = heal_color + src.required_modifier = required_modifier + src.after_healed = after_healed RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(try_healing)) // Players RegisterSignal(parent, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(try_healing)) // NPCs +// Let's populate this list as we actually use it, this thing has too many args +/datum/component/healing_touch/InheritComponent( + datum/component/new_component, + i_am_original, + heal_color, +) + src.heal_color = heal_color + /datum/component/healing_touch/UnregisterFromParent() UnregisterSignal(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) return ..() @@ -83,12 +108,15 @@ return ..() /// Validate our target, and interrupt the attack chain to start healing it if it is allowed -/datum/component/healing_touch/proc/try_healing(mob/living/healer, atom/target) +/datum/component/healing_touch/proc/try_healing(mob/living/healer, atom/target, proximity, modifiers) SIGNAL_HANDLER if (!isliving(target)) return - if (!is_type_in_typecache(target, valid_targets_typecache)) + if (!isnull(required_modifier) && !LAZYACCESS(modifiers, required_modifier)) + return + + if (length(valid_targets_typecache) && !is_type_in_typecache(target, valid_targets_typecache)) return // Fall back to attacking it if (extra_checks && !extra_checks.Invoke(healer, target)) @@ -98,7 +126,7 @@ healer.balloon_alert(healer, "busy!") return COMPONENT_CANCEL_ATTACK_CHAIN - switch (self_targetting) + switch (self_targeting) if (HEALING_TOUCH_NOT_SELF) if (target == healer) healer.balloon_alert(healer, "can't heal yourself!") @@ -131,6 +159,10 @@ return FALSE if (target.getStaminaLoss() > 0 && heal_stamina) return TRUE + if (target.getOxyLoss() > 0 && heal_oxy) + return TRUE + if (target.getToxLoss() > 0 && heal_tox) + return TRUE if (!iscarbon(target)) return (target.getBruteLoss() > 0 && heal_brute) || (target.getFireLoss() > 0 && heal_burn) var/mob/living/carbon/carbon_target = target @@ -154,12 +186,26 @@ if (complete_text) healer.visible_message(span_notice("[format_string(complete_text, healer, target)]")) - target.heal_overall_damage(brute = heal_brute, burn = heal_burn, stamina = heal_stamina, required_bodytype = required_bodytype) + var/healed = target.heal_overall_damage( + brute = heal_brute, + burn = heal_burn, + stamina = heal_stamina, + required_bodytype = required_bodytype, + updating_health = FALSE, + ) + healed += target.adjustOxyLoss(-heal_oxy, updating_health = FALSE, required_biotype = valid_biotypes) + healed += target.adjustToxLoss(-heal_tox, updating_health = FALSE, required_biotype = valid_biotypes) + if (healed <= 0) + return + + target.updatehealth() new /obj/effect/temp_visual/heal(get_turf(target), heal_color) + after_healed?.Invoke(target) - if(show_health && !iscarbon(target)) - var/formatted_string = format_string("%TARGET% now has [target.health]/[target.maxHealth] health.", healer, target) - to_chat(healer, span_danger(formatted_string)) + if(!show_health) + return + var/formatted_string = format_string("%TARGET% now has [health_percentage(target)] health.", healer, target) + to_chat(healer, span_danger(formatted_string)) /// Reformats the passed string with the replacetext keys /datum/component/healing_touch/proc/format_string(string, atom/source, atom/target) diff --git a/code/datums/components/life_link.dm b/code/datums/components/life_link.dm new file mode 100644 index 0000000000000..34cdd0504c6bc --- /dev/null +++ b/code/datums/components/life_link.dm @@ -0,0 +1,169 @@ +/** + * A mob with this component passes all damage (and healing) it takes to another mob, passed as a parameter + * Essentially we use another mob's health bar as our health bar + */ +/datum/component/life_link + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + /// Mob we pass all of our damage to + var/mob/living/host + /// Optional callback invoked when damage gets transferred + var/datum/callback/on_passed_damage + /// Optional callback invoked when the linked mob dies + var/datum/callback/on_linked_death + +/datum/component/life_link/Initialize(mob/living/host, datum/callback/on_passed_damage, datum/callback/on_linked_death) + . = ..() + if (!isliving(parent)) + return COMPONENT_INCOMPATIBLE + if (!istype(host)) + CRASH("Life link created on [parent.type] and attempted to link to invalid type [host?.type].") + register_host(host) + src.on_passed_damage = on_passed_damage + src.on_linked_death = on_linked_death + +/datum/component/life_link/RegisterWithParent() + RegisterSignal(parent, COMSIG_CARBON_LIMB_DAMAGED, PROC_REF(on_limb_damage)) + RegisterSignals(parent, COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES, PROC_REF(on_damage_adjusted)) + RegisterSignal(parent, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(on_health_updated)) + RegisterSignal(parent, COMSIG_MOB_GET_STATUS_TAB_ITEMS, PROC_REF(on_status_tab_updated)) + if (!isnull(host)) + var/mob/living/living_parent = parent + living_parent.updatehealth() + +/datum/component/life_link/UnregisterFromParent() + unregister_host() + UnregisterSignal(parent, list(COMSIG_CARBON_LIMB_DAMAGED, COMSIG_LIVING_HEALTH_UPDATE, COMSIG_MOB_GET_STATUS_TAB_ITEMS) + COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES) + +/datum/component/life_link/InheritComponent(datum/component/new_comp, i_am_original, mob/living/host, datum/callback/on_passed_damage, datum/callback/on_linked_death) + register_host(host) + +/// Set someone up as our new host +/datum/component/life_link/proc/register_host(mob/living/new_host) + unregister_host() + if (isnull(new_host)) + return + host = new_host + RegisterSignal(host, COMSIG_LIVING_DEATH, PROC_REF(on_host_died)) + RegisterSignal(host, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(on_health_updated)) + RegisterSignal(host, COMSIG_LIVING_REVIVE, PROC_REF(on_host_revived)) + RegisterSignal(host, COMSIG_QDELETING, PROC_REF(on_host_deleted)) + var/mob/living/living_parent = parent + living_parent.updatehealth() + +/// Drop someone from being our host +/datum/component/life_link/proc/unregister_host() + if (isnull(host)) + return + UnregisterSignal(host, list(COMSIG_LIVING_DEATH, COMSIG_LIVING_HEALTH_UPDATE, COMSIG_LIVING_REVIVE, COMSIG_QDELETING)) + host = null + +/// Called when your damage goes up or down +/datum/component/life_link/proc/on_damage_adjusted(mob/living/our_mob, type, amount, forced) + SIGNAL_HANDLER + if (forced) + return + amount *= our_mob.get_damage_mod(type) + switch (type) + if(BRUTE) + host.adjustBruteLoss(amount, forced = TRUE) + if(BURN) + host.adjustFireLoss(amount, forced = TRUE) + if(TOX) + host.adjustToxLoss(amount, forced = TRUE) + if(OXY) + host.adjustOxyLoss(amount, forced = TRUE) + if(CLONE) + host.adjustCloneLoss(amount, forced = TRUE) + + on_passed_damage?.Invoke(our_mob, host, amount) + return COMPONENT_IGNORE_CHANGE + +/// Called when someone hurts one of our limbs, bypassing normal damage adjustment +/datum/component/life_link/proc/on_limb_damage(mob/living/our_mob, limb, brute, burn) + SIGNAL_HANDLER + if (brute != 0) + host.adjustBruteLoss(brute, updating_health = FALSE) + if (burn != 0) + host.adjustFireLoss(burn, updating_health = FALSE) + if (brute != 0 || burn != 0) + host.updatehealth() + on_passed_damage?.Invoke(our_mob, host, brute + burn) + return COMPONENT_PREVENT_LIMB_DAMAGE + +/// Called when either the host or parent's health tries to update, update our displayed health +/datum/component/life_link/proc/on_health_updated() + SIGNAL_HANDLER + update_health_hud(parent) + update_med_hud_health(parent) + update_med_hud_status(parent) + +/// Update our parent's health display based on how harmed our host is +/datum/component/life_link/proc/update_health_hud(mob/living/mob_parent) + var/severity = 0 + var/healthpercent = health_percentage(host) + switch(healthpercent) + if(100 to INFINITY) + severity = 0 + if(85 to 100) + severity = 1 + if(70 to 85) + severity = 2 + if(55 to 70) + severity = 3 + if(40 to 55) + severity = 4 + if(25 to 40) + severity = 5 + else + severity = 6 + if(severity > 0) + mob_parent.overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity) + else + mob_parent.clear_fullscreen("brute") + if(mob_parent.hud_used?.healths) + mob_parent.hud_used.healths.maptext = MAPTEXT("
[round(healthpercent, 0.5)]%
") + +/// Update our health on the medical hud +/datum/component/life_link/proc/update_med_hud_health(mob/living/mob_parent) + var/image/holder = mob_parent.hud_list?[HEALTH_HUD] + if(isnull(holder)) + return + holder.icon_state = "hud[RoundHealth(host)]" + var/icon/size_check = icon(mob_parent.icon, mob_parent.icon_state, mob_parent.dir) + holder.pixel_y = size_check.Height() - world.icon_size + +/// Update our vital status on the medical hud +/datum/component/life_link/proc/update_med_hud_status(mob/living/mob_parent) + var/image/holder = mob_parent.hud_list?[STATUS_HUD] + if(isnull(holder)) + return + var/icon/size_check = icon(mob_parent.icon, mob_parent.icon_state, mob_parent.dir) + holder.pixel_y = size_check.Height() - world.icon_size + if(host.stat == DEAD || HAS_TRAIT(host, TRAIT_FAKEDEATH)) + holder.icon_state = "huddead" + else + holder.icon_state = "hudhealthy" + +/// When our status tab updates, draw how much HP our host has in there +/datum/component/life_link/proc/on_status_tab_updated(mob/living/source, list/items) + SIGNAL_HANDLER + var/healthpercent = health_percentage(host) + items += "Host Health: [round(healthpercent, 0.5)]%" + +/// Called when our host dies, we should die too +/datum/component/life_link/proc/on_host_died(mob/living/source, gibbed) + SIGNAL_HANDLER + on_linked_death?.Invoke(parent, host, gibbed) + var/mob/living/living_parent = parent + living_parent.death(gibbed) + +/// Called when our host undies, we should undie too +/datum/component/life_link/proc/on_host_revived(mob/living/source, full_heal_flags) + SIGNAL_HANDLER + var/mob/living/living_parent = parent + living_parent.revive(full_heal_flags) + +/// Called when +/datum/component/life_link/proc/on_host_deleted() + SIGNAL_HANDLER + qdel(src) diff --git a/code/datums/components/lock_on_cursor.dm b/code/datums/components/lock_on_cursor.dm index 0ccac6ee2f923..30140dd95bd70 100644 --- a/code/datums/components/lock_on_cursor.dm +++ b/code/datums/components/lock_on_cursor.dm @@ -8,13 +8,13 @@ */ /datum/component/lock_on_cursor dupe_mode = COMPONENT_DUPE_ALLOWED - /// Appearance to overlay onto whatever we are targetting + /// Appearance to overlay onto whatever we are targeting var/mutable_appearance/lock_appearance /// Current images we are displaying to the client var/list/image/lock_images /// Typecache of things we are allowed to target var/list/target_typecache - /// Cache of weakrefs to ignore targetting formatted as `list(weakref = TRUE)` + /// Cache of weakrefs to ignore targeting formatted as `list(weakref = TRUE)` var/list/immune_weakrefs /// Number of things we can target at once var/lock_amount diff --git a/code/datums/components/omen.dm b/code/datums/components/omen.dm index 8b7a751ef2704..f03f28b8d6aff 100644 --- a/code/datums/components/omen.dm +++ b/code/datums/components/omen.dm @@ -31,6 +31,8 @@ if(!isnull(damage_mod)) src.damage_mod = damage_mod + ADD_TRAIT(parent, TRAIT_CURSED, SMITE_TRAIT) + /** * This is a omen eat omen world! The stronger omen survives. */ @@ -50,6 +52,7 @@ /datum/component/omen/Destroy(force) var/mob/living/person = parent + REMOVE_TRAIT(person, TRAIT_CURSED, SMITE_TRAIT) to_chat(person, span_nicegreen("You feel a horrible omen lifted off your shoulders!")) if(vessel) diff --git a/code/datums/components/orbit_poll.dm b/code/datums/components/orbit_poll.dm index 91b27d4b66797..dda7207ed4546 100644 --- a/code/datums/components/orbit_poll.dm +++ b/code/datums/components/orbit_poll.dm @@ -85,22 +85,47 @@ return for(var/mob/dead/observer/ghost as anything in orbiter_comp.orbiter_list) - if(QDELETED(ghost) || isnull(ghost.client)) + var/client/ghost_client = ghost.client + + if(QDELETED(ghost) || isnull(ghost_client)) continue + if(is_banned_from(ghost.ckey, job_bans)) continue + var/datum/preferences/ghost_prefs = ghost_client.prefs + if(isnull(ghost_prefs)) + candidates += ghost // we'll assume they wanted to be picked despite prefs being null for whatever fucked up reason + continue + + if(!ghost_prefs.read_preference(/datum/preference/toggle/ghost_roles)) + continue + if(!isnull(ghost_client.holder) && !ghost_prefs.read_preference(/datum/preference/toggle/ghost_roles_as_admin)) + continue + candidates += ghost - if(!length(candidates)) + pick_and_offer(candidates) + +/// Takes a list, picks a candidate, and offers the role to them. +/datum/component/orbit_poll/proc/pick_and_offer(list/volunteers) + if(length(volunteers) <= 0) phone_home() return - var/mob/dead/observer/chosen = pick(candidates) + var/mob/dead/observer/chosen = pick(volunteers) + + if(isnull(chosen)) + phone_home() + return - if(chosen) - deadchat_broadcast("[key_name(chosen, include_name = FALSE)] was selected for the role ([title]).", "Ghost Poll: ", parent) + SEND_SOUND(chosen, 'sound/misc/notice2.ogg') + var/response = tgui_alert(chosen, "Do you want to assume the role of [title]?", "Orbit Polling", list("Yes", "No"), 10 SECONDS) + if(response != "Yes") + var/reusable_list = volunteers - chosen + return pick_and_offer(reusable_list) + deadchat_broadcast("[key_name(chosen, include_name = FALSE)] was selected for the role ([title]).", "Ghost Poll: ", parent) phone_home(chosen) /// Make sure to call your parents my dude diff --git a/code/datums/components/pet_commands/fetch.dm b/code/datums/components/pet_commands/fetch.dm index ae33983e1d00d..fa0b3193a4475 100644 --- a/code/datums/components/pet_commands/fetch.dm +++ b/code/datums/components/pet_commands/fetch.dm @@ -3,7 +3,7 @@ * Watch for someone throwing or pointing at something and then go get it and bring it back. * If it's food we might eat it instead. */ -/datum/pet_command/point_targetting/fetch +/datum/pet_command/point_targeting/fetch command_name = "Fetch" command_desc = "Command your pet to retrieve something you throw or point at." radial_icon = 'icons/mob/actions/actions_spells.dmi' @@ -16,22 +16,22 @@ /// If true, this is a poorly trained pet who will eat food you throw instead of bringing it back var/will_eat_targets = TRUE -/datum/pet_command/point_targetting/fetch/New(mob/living/parent) +/datum/pet_command/point_targeting/fetch/New(mob/living/parent) . = ..() if(isnull(parent)) return parent.AddElement(/datum/element/ai_held_item) // We don't remove this on destroy because they might still be holding something -/datum/pet_command/point_targetting/fetch/add_new_friend(mob/living/tamer) +/datum/pet_command/point_targeting/fetch/add_new_friend(mob/living/tamer) . = ..() RegisterSignal(tamer, COMSIG_MOB_THROW, PROC_REF(listened_throw)) -/datum/pet_command/point_targetting/fetch/remove_friend(mob/living/unfriended) +/datum/pet_command/point_targeting/fetch/remove_friend(mob/living/unfriended) . = ..() UnregisterSignal(unfriended, COMSIG_MOB_THROW) /// A friend has thrown something, if we're listening or at least not busy then go get it -/datum/pet_command/point_targetting/fetch/proc/listened_throw(mob/living/carbon/thrower) +/datum/pet_command/point_targeting/fetch/proc/listened_throw(mob/living/carbon/thrower) SIGNAL_HANDLER var/mob/living/parent = weak_parent.resolve() @@ -57,7 +57,7 @@ RegisterSignal(thrown_thing, COMSIG_MOVABLE_THROW_LANDED, PROC_REF(listen_throw_land)) /// A throw we were listening to has finished, see if it's in range for us to try grabbing it -/datum/pet_command/point_targetting/fetch/proc/listen_throw_land(obj/item/thrown_thing, datum/thrownthing/throwing_datum) +/datum/pet_command/point_targeting/fetch/proc/listen_throw_land(obj/item/thrown_thing, datum/thrownthing/throwing_datum) SIGNAL_HANDLER UnregisterSignal(thrown_thing, COMSIG_MOVABLE_THROW_LANDED) @@ -74,7 +74,7 @@ parent.ai_controller.set_blackboard_key(BB_FETCH_DELIVER_TO, throwing_datum.thrower) // Don't try and fetch turfs or anchored objects if someone points at them -/datum/pet_command/point_targetting/fetch/look_for_target(mob/living/pointing_friend, obj/item/pointed_atom) +/datum/pet_command/point_targeting/fetch/look_for_target(mob/living/pointing_friend, obj/item/pointed_atom) if (!istype(pointed_atom)) return FALSE if (pointed_atom.anchored) @@ -87,7 +87,7 @@ parent.ai_controller.set_blackboard_key(BB_FETCH_DELIVER_TO, pointing_friend) // Finally, plan our actions -/datum/pet_command/point_targetting/fetch/execute_action(datum/ai_controller/controller) +/datum/pet_command/point_targeting/fetch/execute_action(datum/ai_controller/controller) controller.queue_behavior(/datum/ai_behavior/forget_failed_fetches) var/atom/target = controller.blackboard[BB_CURRENT_PET_TARGET] diff --git a/code/datums/components/pet_commands/pet_command.dm b/code/datums/components/pet_commands/pet_command.dm index 7899ffce40ae5..7762b9b2aa818 100644 --- a/code/datums/components/pet_commands/pet_command.dm +++ b/code/datums/components/pet_commands/pet_command.dm @@ -109,25 +109,25 @@ CRASH("Pet command execute action not implemented.") /** - * # Point Targetting Pet Command + * # Point Targeting Pet Command * As above but also listens for you pointing at something and marks it as a target */ -/datum/pet_command/point_targetting +/datum/pet_command/point_targeting /// Text describing an action we perform upon receiving a new target var/pointed_reaction - /// Blackboard key for targetting datum, this is likely going to need it - var/targetting_datum_key = BB_PET_TARGETTING_DATUM + /// Blackboard key for targeting strategy, this is likely going to need it + var/targeting_strategy_key = BB_PET_TARGETING_STRATEGY -/datum/pet_command/point_targetting/add_new_friend(mob/living/tamer) +/datum/pet_command/point_targeting/add_new_friend(mob/living/tamer) . = ..() RegisterSignal(tamer, COMSIG_MOB_POINTED, PROC_REF(look_for_target)) -/datum/pet_command/point_targetting/remove_friend(mob/living/unfriended) +/datum/pet_command/point_targeting/remove_friend(mob/living/unfriended) . = ..() UnregisterSignal(unfriended, COMSIG_MOB_POINTED) /// Target the pointed atom for actions -/datum/pet_command/point_targetting/proc/look_for_target(mob/living/friend, atom/pointed_atom) +/datum/pet_command/point_targeting/proc/look_for_target(mob/living/friend, atom/pointed_atom) SIGNAL_HANDLER var/mob/living/parent = weak_parent.resolve() diff --git a/code/datums/components/pet_commands/pet_commands_basic.dm b/code/datums/components/pet_commands/pet_commands_basic.dm index 263f9b17f5b84..c614e623bf869 100644 --- a/code/datums/components/pet_commands/pet_commands_basic.dm +++ b/code/datums/components/pet_commands/pet_commands_basic.dm @@ -102,11 +102,11 @@ * # Pet Command: Use ability * Use an an ability that does not require any targets */ -/datum/pet_command/untargetted_ability - ///untargetted ability we will use +/datum/pet_command/untargeted_ability + ///untargeted ability we will use var/ability_key -/datum/pet_command/untargetted_ability/execute_action(datum/ai_controller/controller) +/datum/pet_command/untargeted_ability/execute_action(datum/ai_controller/controller) var/datum/action/cooldown/ability = controller.blackboard[ability_key] if(!ability?.IsAvailable()) return @@ -118,7 +118,7 @@ * # Pet Command: Attack * Tells a pet to chase and bite the next thing you point at */ -/datum/pet_command/point_targetting/attack +/datum/pet_command/point_targeting/attack command_name = "Attack" command_desc = "Command your pet to attack things that you point out to it." radial_icon = 'icons/effects/effects.dmi' @@ -133,13 +133,13 @@ var/attack_behaviour = /datum/ai_behavior/basic_melee_attack // Refuse to target things we can't target, chiefly other friends -/datum/pet_command/point_targetting/attack/set_command_target(mob/living/parent, atom/target) +/datum/pet_command/point_targeting/attack/set_command_target(mob/living/parent, atom/target) if (!target) return var/mob/living/living_parent = parent if (!living_parent.ai_controller) return - var/datum/targetting_datum/targeter = living_parent.ai_controller.blackboard[targetting_datum_key] + var/datum/targeting_strategy/targeter = GET_TARGETING_STRATEGY(living_parent.ai_controller.blackboard[targeting_strategy_key]) if (!targeter) return if (!targeter.can_attack(living_parent, target)) @@ -147,21 +147,51 @@ return return ..() -/// Display feedback about not targetting something -/datum/pet_command/point_targetting/attack/proc/refuse_target(mob/living/parent, atom/target) +/// Display feedback about not targeting something +/datum/pet_command/point_targeting/attack/proc/refuse_target(mob/living/parent, atom/target) var/mob/living/living_parent = parent living_parent.balloon_alert_to_viewers("[refuse_reaction]") living_parent.visible_message(span_notice("[living_parent] refuses to attack [target].")) -/datum/pet_command/point_targetting/attack/execute_action(datum/ai_controller/controller) - controller.queue_behavior(attack_behaviour, BB_CURRENT_PET_TARGET, targetting_datum_key) +/datum/pet_command/point_targeting/attack/execute_action(datum/ai_controller/controller) + controller.queue_behavior(attack_behaviour, BB_CURRENT_PET_TARGET, targeting_strategy_key) + return SUBTREE_RETURN_FINISH_PLANNING + +/** + * # Breed command. breed with a partner! + */ +/datum/pet_command/point_targeting/breed + command_name = "Breed" + command_desc = "Command your pet to attempt to breed with a partner." + radial_icon = 'icons/mob/simple/animal.dmi' + radial_icon_state = "heart" + speech_commands = list("breed", "consummate") + +/datum/pet_command/point_targeting/breed/set_command_target(mob/living/parent, atom/target) + if(isnull(target) || !isliving(target)) + return + if(!HAS_TRAIT(parent, TRAIT_MOB_BREEDER) || !HAS_TRAIT(target, TRAIT_MOB_BREEDER)) + return + if(isnull(parent.ai_controller)) + return + if(!parent.ai_controller.blackboard[BB_BREED_READY] || isnull(parent.ai_controller.blackboard[BB_BABIES_PARTNER_TYPES])) + return + var/mob/living/living_target = target + if(!living_target.ai_controller?.blackboard[BB_BREED_READY]) + return + return ..() + +/datum/pet_command/point_targeting/breed/execute_action(datum/ai_controller/controller) + if(is_type_in_list(controller.blackboard[BB_CURRENT_PET_TARGET], controller.blackboard[BB_BABIES_PARTNER_TYPES])) + controller.queue_behavior(/datum/ai_behavior/make_babies, BB_CURRENT_PET_TARGET) + controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND) return SUBTREE_RETURN_FINISH_PLANNING /** * # Pet Command: Targetted Ability * Tells a pet to use some kind of ability on the next thing you point at */ -/datum/pet_command/point_targetting/use_ability +/datum/pet_command/point_targeting/use_ability command_name = "Use ability" command_desc = "Command your pet to use one of its special skills on something that you point out to it." radial_icon = 'icons/mob/actions/actions_spells.dmi' @@ -172,7 +202,7 @@ /// Blackboard key where a reference to some kind of mob ability is stored var/pet_ability_key -/datum/pet_command/point_targetting/use_ability/execute_action(datum/ai_controller/controller) +/datum/pet_command/point_targeting/use_ability/execute_action(datum/ai_controller/controller) if (!pet_ability_key) return var/datum/action/cooldown/using_action = controller.blackboard[pet_ability_key] @@ -207,7 +237,7 @@ if(victim.stat > controller.blackboard[BB_TARGET_MINIMUM_STAT]) controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND) return - controller.queue_behavior(protect_behavior, BB_CURRENT_PET_TARGET, BB_PET_TARGETTING_DATUM) + controller.queue_behavior(protect_behavior, BB_CURRENT_PET_TARGET, BB_PET_TARGETING_STRATEGY) return SUBTREE_RETURN_FINISH_PLANNING /datum/pet_command/protect_owner/set_command_active(mob/living/parent, mob/living/victim) diff --git a/code/datums/components/plumbing/_plumbing.dm b/code/datums/components/plumbing/_plumbing.dm index 3de02174273c7..245f8f969a980 100644 --- a/code/datums/components/plumbing/_plumbing.dm +++ b/code/datums/components/plumbing/_plumbing.dm @@ -20,8 +20,6 @@ var/ducting_layer = DUCT_LAYER_DEFAULT ///In-case we don't want the main machine to get the reagents, but perhaps whoever is buckled to it var/recipient_reagents_holder - ///How do we apply the new reagents to the receiver? Generally doesn't matter, but some stuff, like people, does care if its injected or whatevs - var/methods ///What color is our demand connect? var/demand_color = COLOR_RED ///What color is our supply connect? @@ -139,10 +137,8 @@ /datum/component/plumbing/proc/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net) if(!reagents || !target || !target.reagents) return FALSE - if(reagent) - reagents.trans_id_to(target.recipient_reagents_holder, reagent, amount) - else - reagents.trans_to(target.recipient_reagents_holder, amount, methods = methods) + + reagents.trans_to(target.recipient_reagents_holder, amount, target_id = reagent) ///We create our luxurious piping overlays/underlays, to indicate where we do what. only called once if use_overlays = TRUE in Initialize() /datum/component/plumbing/proc/create_overlays(atom/movable/parent_movable, list/overlays) @@ -215,8 +211,11 @@ STOP_PROCESSING(SSplumbing, src) - for(var/duct_dir in ducts) - var/datum/ductnet/duct = ducts[duct_dir] + //remove_plumber() can remove all ducts at once if they all belong to the same pipenet + //for e.g. in case of circular connections + //so we check if we have ducts to remove after each iteration + while(ducts.len) + var/datum/ductnet/duct = ducts[ducts[1]] //for maps index 1 will return the 1st key duct.remove_plumber(src) active = FALSE diff --git a/code/datums/components/plumbing/filter.dm b/code/datums/components/plumbing/filter.dm index 4b8dd8d54a6c2..30e36c057886e 100644 --- a/code/datums/components/plumbing/filter.dm +++ b/code/datums/components/plumbing/filter.dm @@ -31,7 +31,7 @@ direction = get_original_direction(text2num(A)) break if(reagent) - reagents.trans_id_to(target.parent, reagent, amount) + reagents.trans_to(target.parent, amount, target_id = reagent) else for(var/A in reagents.reagent_list) var/datum/reagent/R = A @@ -40,7 +40,7 @@ var/new_amount if(R.volume < amount) new_amount = amount - R.volume - reagents.trans_id_to(target.parent, R.type, amount) + reagents.trans_to(target.parent, amount, target_id = R.type) amount = new_amount if(amount <= 0) break diff --git a/code/datums/components/plumbing/reaction_chamber.dm b/code/datums/components/plumbing/reaction_chamber.dm index 707f7cf6f9c1b..d0aff2f50708c 100644 --- a/code/datums/components/plumbing/reaction_chamber.dm +++ b/code/datums/components/plumbing/reaction_chamber.dm @@ -17,36 +17,23 @@ var/obj/machinery/plumbing/reaction_chamber/chamber = parent if(chamber.emptying) return - var/required_amount = 0 - var/total_present_amount = 0 - var/total_required_amount = 0 //take in reagents - var/datum/reagent/present_reagent var/present_amount var/diff for(var/required_reagent in chamber.required_reagents) - //compute total required amount from all reagents - required_amount = chamber.required_reagents[required_reagent] - total_required_amount += required_amount - //find how much amount is already present if at all and get the reagent reference - present_reagent = null - for(var/datum/reagent/containg_reagent as anything in reagents.reagent_list) - if(required_reagent == containg_reagent.type) - present_reagent = containg_reagent + present_amount = 0 + for(var/datum/reagent/present_reagent as anything in reagents.reagent_list) + if(required_reagent == present_reagent.type) + present_amount = present_reagent.volume break - present_amount = present_reagent ? present_reagent.volume : 0 - //compute how much more is needed and round it. early return only if the request succeded - diff = min(required_amount - present_amount, MACHINE_REAGENT_TRANSFER) - if(diff >= CHEMICAL_VOLUME_ROUNDING && process_request(diff, required_reagent, dir)) + //compute how much more is needed + diff = min(chamber.required_reagents[required_reagent] - present_amount, MACHINE_REAGENT_TRANSFER) + if(diff >= CHEMICAL_QUANTISATION_LEVEL) // the closest we can ask for so values like 0.9999 become 1 + process_request(diff, required_reagent, dir) return - total_present_amount += present_reagent ? present_reagent.volume : 0 - - //do we have close enough - if(total_required_amount - total_present_amount >= CHEMICAL_VOLUME_ROUNDING) //nope - return reagents.flags &= ~NO_REACT reagents.handle_reactions() diff --git a/code/datums/components/ranged_mob_full_auto.dm b/code/datums/components/ranged_mob_full_auto.dm new file mode 100644 index 0000000000000..a33b705d54850 --- /dev/null +++ b/code/datums/components/ranged_mob_full_auto.dm @@ -0,0 +1,203 @@ +#define AUTOFIRE_MOUSEUP 1 +#define AUTOFIRE_MOUSEDOWN 0 + +/// Allows a mob to autofire by holding down the cursor +/datum/component/ranged_mob_full_auto + /// Delay before attempting to fire again, note that this is just when we make attempts and is separate from mob's actual firing cooldown + var/autofire_shot_delay + /// Our client for click tracking + var/client/clicker + /// Are we currently firing? + var/is_firing = FALSE + /// This seems hacky but there can be two MouseDown() without a MouseUp() in between if the user holds click and uses alt+tab, printscreen or similar. + var/awaiting_status = AUTOFIRE_MOUSEDOWN + /// What are we currently shooting at? + var/atom/target + /// Where are we currently shooting at? + var/turf/target_loc + /// When will we next try to shoot? + COOLDOWN_DECLARE(next_shot_cooldown) + +/datum/component/ranged_mob_full_auto/Initialize(autofire_shot_delay = 0.5 SECONDS) + . = ..() + if (!isliving(parent)) + return COMPONENT_INCOMPATIBLE + + src.autofire_shot_delay = autofire_shot_delay + + var/mob/living/living_parent = parent + if (isnull(living_parent.client)) + return + on_gained_client(parent) + +/datum/component/ranged_mob_full_auto/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOB_LOGIN, PROC_REF(on_gained_client)) + RegisterSignal(parent, COMSIG_MOB_LOGOUT, PROC_REF(on_lost_client)) + +/datum/component/ranged_mob_full_auto/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_MOB_LOGIN, COMSIG_MOB_LOGOUT)) + +/datum/component/ranged_mob_full_auto/process(seconds_per_tick) + if (!try_shooting()) + return PROCESS_KILL + +/// Try and take a shot, returns false if we are unable to do so and should stop trying +/datum/component/ranged_mob_full_auto/proc/try_shooting() + if (!is_firing) + return FALSE + if (!COOLDOWN_FINISHED(src, next_shot_cooldown)) + return TRUE // Don't fire but also keep processing + + var/mob/living/living_parent = parent + + if (isnull(target) || get_turf(target) != target_loc) // Target moved or got destroyed since we last aimed. + set_target(target_loc) + target = target_loc // So we keep firing on the emptied tile until we move our mouse and find a new target. + if (get_dist(living_parent, target) <= 0) + set_target(get_step(living_parent, living_parent.dir)) // Shoot in the direction faced if the mouse is on the same tile as we are. + target_loc = target + else if (!in_view_range(living_parent, target)) + stop_firing() + return FALSE // Can't see shit + + living_parent.face_atom(target) + COOLDOWN_START(src, next_shot_cooldown, autofire_shot_delay) + living_parent.RangedAttack(target) + return TRUE + +/// Setter for reference handling +/datum/component/ranged_mob_full_auto/proc/set_target(atom/new_target) + if (!isnull(target)) + UnregisterSignal(target, COMSIG_QDELETING) + target = new_target + if (!isnull(target)) + RegisterSignal(target, COMSIG_QDELETING, PROC_REF(on_target_deleted)) + +/// Don't hang references +/datum/component/ranged_mob_full_auto/proc/on_target_deleted() + SIGNAL_HANDLER + set_target(null) + +/// When we gain a client, start tracking clicks +/datum/component/ranged_mob_full_auto/proc/on_gained_client(mob/living/source) + SIGNAL_HANDLER + clicker = source.client + RegisterSignal(clicker, COMSIG_CLIENT_MOUSEDOWN, PROC_REF(on_mouse_down)) + +/// When we lose our client, stop functioning +/datum/component/ranged_mob_full_auto/proc/on_lost_client(mob/living/source) + SIGNAL_HANDLER + if (!isnull(clicker)) + UnregisterSignal(clicker, list(COMSIG_CLIENT_MOUSEDOWN, COMSIG_CLIENT_MOUSEDRAG, COMSIG_CLIENT_MOUSEUP)) + stop_firing() + clicker = null + +/// On mouse down start shooting! +/datum/component/ranged_mob_full_auto/proc/on_mouse_down(client/source, atom/target, turf/location, control, params) + SIGNAL_HANDLER + if (awaiting_status != AUTOFIRE_MOUSEDOWN) + return // Avoid a double mousedown with no mouseup + var/list/modifiers = params2list(params) + + if (LAZYACCESS(modifiers, SHIFT_CLICK)) + return + if (LAZYACCESS(modifiers, CTRL_CLICK)) + return + if (LAZYACCESS(modifiers, MIDDLE_CLICK)) + return + if (LAZYACCESS(modifiers, RIGHT_CLICK)) + return + if (LAZYACCESS(modifiers, ALT_CLICK)) + return + var/mob/living/living_parent = parent + if (!isturf(living_parent.loc) || living_parent.Adjacent(target)) + return + + if (isnull(location) || istype(target, /atom/movable/screen)) // Clicking on a screen object. + if (target.plane != CLICKCATCHER_PLANE) // The clickcatcher is a special case. We want the click to trigger then, under it. + return // If we click and drag on our worn backpack, for example, we want it to open instead. + set_target(parse_caught_click_modifiers(modifiers, get_turf(source.eye), source)) + params = list2params(modifiers) + if (isnull(target)) + CRASH("Failed to get the turf under clickcatcher") + + awaiting_status = AUTOFIRE_MOUSEUP + source.click_intercept_time = world.time // From this point onwards Click() will no longer be triggered. + if (is_firing) + stop_firing() + + set_target(target) + target_loc = get_turf(target) + INVOKE_ASYNC(src, PROC_REF(start_firing)) + +/// Start tracking mouse movement and processing our shots +/datum/component/ranged_mob_full_auto/proc/start_firing() + if (is_firing) + return + + is_firing = TRUE + if (!try_shooting()) // First one is immediate + stop_firing() + return + + clicker.mouse_override_icon = 'icons/effects/mouse_pointers/weapon_pointer.dmi' + clicker.mouse_pointer_icon = clicker.mouse_override_icon + + START_PROCESSING(SSprojectiles, src) + RegisterSignal(clicker, COMSIG_CLIENT_MOUSEUP, PROC_REF(on_mouse_up)) + RegisterSignal(clicker, COMSIG_CLIENT_MOUSEDRAG, PROC_REF(on_mouse_drag)) + +/// When the mouse moved let's try and shift our aim +/datum/component/ranged_mob_full_auto/proc/on_mouse_drag(client/source, atom/src_object, atom/over_object, turf/src_location, turf/over_location, src_control, over_control, params) + SIGNAL_HANDLER + if (!isnull(over_location)) + set_target(over_object) + target_loc = get_turf(over_object) + return + + //This happens when the mouse is over an inventory or screen object, or on entering deep darkness, for example. + var/list/modifiers = params2list(params) + var/new_target = parse_caught_click_modifiers(modifiers, get_turf(source.eye), source) + params = list2params(modifiers) + + if (!isnull(new_target)) + set_target(new_target) + target_loc = new_target + return + + if (QDELETED(target)) //No new target acquired, and old one was deleted, get us out of here. + stop_firing() + CRASH("on_mouse_drag failed to get the turf under screen object [over_object.type]. Old target was incidentally QDELETED.") + + + set_target(get_turf(target)) //If previous target wasn't a turf, let's turn it into one to avoid locking onto a potentially moving target. + target_loc = target + CRASH("on_mouse_drag failed to get the turf under screen object [over_object.type]") + +/// When the mouse is released we should stop +/datum/component/ranged_mob_full_auto/proc/on_mouse_up() + SIGNAL_HANDLER + if (awaiting_status != AUTOFIRE_MOUSEUP) + return + stop_firing() + return COMPONENT_CLIENT_MOUSEUP_INTERCEPT + +/// Stop watching our mouse and processing shots +/datum/component/ranged_mob_full_auto/proc/stop_firing() + if (!is_firing) + return + + is_firing = FALSE + set_target(null) + target_loc = null + STOP_PROCESSING(SSprojectiles, src) + awaiting_status = AUTOFIRE_MOUSEDOWN + + if (isnull(clicker)) + return + UnregisterSignal(clicker, list(COMSIG_CLIENT_MOUSEDRAG, COMSIG_CLIENT_MOUSEUP)) + clicker.mouse_override_icon = null + clicker.mouse_pointer_icon = null + +#undef AUTOFIRE_MOUSEUP +#undef AUTOFIRE_MOUSEDOWN diff --git a/code/datums/components/reagent_refiller.dm b/code/datums/components/reagent_refiller.dm index 4e2da58c79bc9..ffb451b83ac1a 100644 --- a/code/datums/components/reagent_refiller.dm +++ b/code/datums/components/reagent_refiller.dm @@ -51,15 +51,15 @@ . |= COMPONENT_AFTERATTACK_PROCESSED_ITEM var/obj/item/reagent_containers/container = parent - var/refill = container.reagents.get_master_reagent_id() var/amount = min((container.amount_per_transfer_from_this + container.reagents.total_volume), container.reagents.total_volume) - if (amount == 0) return - if (!is_path_in_list(refill, whitelisted_reagents)) + + var/datum/reagent/refill = container.reagents.get_master_reagent() + if (!is_path_in_list(refill?.type, whitelisted_reagents)) return - addtimer(CALLBACK(src, PROC_REF(add_reagents), container, container.loc, refill, amount), time_to_refill) + addtimer(CALLBACK(src, PROC_REF(add_reagents), container, container.loc, refill.type, amount), time_to_refill) /// Refills the reagent container, and uses cell power if applicable /datum/component/reagent_refiller/proc/add_reagents(obj/item/reagent_containers/target, oldloc, reagent_to_refill, amount) diff --git a/code/datums/components/revenge_ability.dm b/code/datums/components/revenge_ability.dm index f03bc992276fc..8d9faec52e0bc 100644 --- a/code/datums/components/revenge_ability.dm +++ b/code/datums/components/revenge_ability.dm @@ -8,7 +8,7 @@ /// The ability to use when we are attacked var/datum/action/cooldown/ability /// Optional datum for validating targets - var/datum/targetting_datum/targetting + var/datum/targeting_strategy/targeting /// Trigger only if target is at least this far away var/min_range /// Trigger only if target is at least this close @@ -16,12 +16,12 @@ /// Target the ability at ourself instead of at the offender var/target_self -/datum/component/revenge_ability/Initialize(datum/action/cooldown/ability, datum/targetting_datum/targetting, min_range = 0, max_range = INFINITY, target_self = FALSE) +/datum/component/revenge_ability/Initialize(datum/action/cooldown/ability, datum/targeting_strategy/targeting, min_range = 0, max_range = INFINITY, target_self = FALSE) . = ..() if (!isliving(parent)) return COMPONENT_INCOMPATIBLE src.ability = ability - src.targetting = targetting + src.targeting = targeting src.min_range = min_range src.max_range = max_range src.target_self = target_self @@ -45,7 +45,7 @@ var/distance = get_dist(ability_user, attacker) if (distance < min_range || distance > max_range) return - if (targetting && !targetting.can_attack(victim, attacker)) + if (targeting && !targeting.can_attack(victim, attacker)) return INVOKE_ASYNC(ability, TYPE_PROC_REF(/datum/action/cooldown, InterceptClickOn), ability_user, null, (target_self) ? ability_user : attacker) diff --git a/code/datums/components/riding/riding.dm b/code/datums/components/riding/riding.dm index d1a8f827cafe4..c8c969a8c6b5f 100644 --- a/code/datums/components/riding/riding.dm +++ b/code/datums/components/riding/riding.dm @@ -67,8 +67,11 @@ RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(vehicle_moved)) RegisterSignal(parent, COMSIG_MOVABLE_BUMP, PROC_REF(vehicle_bump)) RegisterSignal(parent, COMSIG_BUCKLED_CAN_Z_MOVE, PROC_REF(riding_can_z_move)) + RegisterSignals(parent, GLOB.movement_type_addtrait_signals, PROC_REF(on_movement_type_trait_gain)) + RegisterSignals(parent, GLOB.movement_type_removetrait_signals, PROC_REF(on_movement_type_trait_loss)) if(!can_force_unbuckle) RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(force_unbuckle)) + /** * This proc handles all of the proc calls to things like set_vehicle_dir_layer() that a type of riding datum needs to call on creation * @@ -91,6 +94,10 @@ unequip_buckle_inhands(rider) rider.updating_glide_size = TRUE UnregisterSignal(rider, COMSIG_LIVING_TRY_PULL) + for (var/trait in GLOB.movement_type_trait_to_flag) + if (HAS_TRAIT(parent, trait)) + REMOVE_TRAIT(rider, trait, REF(src)) + REMOVE_TRAIT(rider, TRAIT_NO_FLOATING_ANIM, REF(src)) if(!movable_parent.has_buckled_mobs()) qdel(src) @@ -107,6 +114,11 @@ rider.stop_pulling() RegisterSignal(rider, COMSIG_LIVING_TRY_PULL, PROC_REF(on_rider_try_pull)) + for (var/trait in GLOB.movement_type_trait_to_flag) + if (HAS_TRAIT(parent, trait)) + ADD_TRAIT(rider, trait, REF(src)) + ADD_TRAIT(rider, TRAIT_NO_FLOATING_ANIM, REF(src)) + /// This proc is called when the rider attempts to grab the thing they're riding, preventing them from doing so. /datum/component/riding/proc/on_rider_try_pull(mob/living/rider_pulling, atom/movable/target, force) SIGNAL_HANDLER @@ -297,6 +309,20 @@ SIGNAL_HANDLER return COMPONENT_RIDDEN_ALLOW_Z_MOVE +/// Called when our vehicle gains a movement trait, so we can apply it to the riders +/datum/component/riding/proc/on_movement_type_trait_gain(atom/movable/source, trait) + SIGNAL_HANDLER + var/atom/movable/movable_parent = parent + for (var/mob/rider in movable_parent.buckled_mobs) + ADD_TRAIT(rider, trait, REF(src)) + +/// Called when our vehicle loses a movement trait, so we can remove it from the riders +/datum/component/riding/proc/on_movement_type_trait_loss(atom/movable/source, trait) + SIGNAL_HANDLER + var/atom/movable/movable_parent = parent + for (var/mob/rider in movable_parent.buckled_mobs) + REMOVE_TRAIT(rider, trait, REF(src)) + /datum/component/riding/proc/force_unbuckle(atom/movable/source, mob/living/living_hitter) SIGNAL_HANDLER diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index 900a164831488..75292c01012dd 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -476,7 +476,7 @@ set_vehicle_dir_layer(WEST, ABOVE_MOB_LAYER) /datum/component/riding/creature/guardian/ride_check(mob/living/user, consequences = TRUE) - var/mob/living/simple_animal/hostile/guardian/charger = parent + var/mob/living/basic/guardian/charger = parent if(!istype(charger)) return ..() return charger.summoner == user diff --git a/code/datums/components/shielded.dm b/code/datums/components/shielded.dm index b33f3d986fda3..0265148c8b538 100644 --- a/code/datums/components/shielded.dm +++ b/code/datums/components/shielded.dm @@ -3,6 +3,7 @@ */ /datum/component/shielded + dupe_mode = COMPONENT_DUPE_UNIQUE /// The person currently wearing us var/mob/living/wearer /// How many charges we can have max, and how many we start with @@ -113,7 +114,7 @@ if((slot & ITEM_SLOT_HANDS) && !shield_inhand) lost_wearer(source, user) return - set_wearer(source, user) + set_wearer(user) /// Either we've been dropped or our wearer has been QDEL'd. Either way, they're no longer our problem /datum/component/shielded/proc/lost_wearer(datum/source, mob/user) @@ -125,6 +126,11 @@ wearer = null /datum/component/shielded/proc/set_wearer(mob/user) + if(wearer == user) + return + if(!isnull(wearer)) + CRASH("[type] called set_wearer with [user] but [wearer] was already the wearer!") + wearer = user RegisterSignal(wearer, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays)) RegisterSignal(wearer, COMSIG_QDELETING, PROC_REF(lost_wearer)) diff --git a/code/datums/components/shuttle_cling.dm b/code/datums/components/shuttle_cling.dm index bc6f022ab86e4..9cbff17c0a369 100644 --- a/code/datums/components/shuttle_cling.dm +++ b/code/datums/components/shuttle_cling.dm @@ -90,9 +90,9 @@ return //Do pause/unpause/nothing for the hyperloop - if(should_loop && hyperloop.paused) + if(should_loop && hyperloop.status & MOVELOOP_STATUS_PAUSED) hyperloop.resume_loop() - else if(!should_loop && !hyperloop.paused) + else if(!should_loop && !(hyperloop.status & MOVELOOP_STATUS_PAUSED)) hyperloop.pause_loop() ///Check if we're "holding on" to the shuttle diff --git a/code/datums/components/torn_wall.dm b/code/datums/components/torn_wall.dm index ebe0fe9a0a6e9..566275bdfa6e7 100644 --- a/code/datums/components/torn_wall.dm +++ b/code/datums/components/torn_wall.dm @@ -15,7 +15,7 @@ /datum/component/torn_wall/Initialize() . = ..() - if (!iswallturf(parent) || isindestructiblewall(parent)) + if (!isclosedturf(parent) || isindestructiblewall(parent)) return COMPONENT_INCOMPATIBLE /datum/component/torn_wall/RegisterWithParent() @@ -53,6 +53,12 @@ return var/turf/closed/wall/attached_wall = parent playsound(attached_wall, 'sound/effects/meteorimpact.ogg', 100, vary = TRUE) + + if(ismineralturf(attached_wall)) + var/turf/closed/mineral/mineral_turf = attached_wall + mineral_turf.gets_drilled() + return + attached_wall.dismantle_wall(devastated = TRUE) /// Fix it up on weld diff --git a/code/datums/components/udder.dm b/code/datums/components/udder.dm index c1f0ff0324589..7a2f7b56b7b4c 100644 --- a/code/datums/components/udder.dm +++ b/code/datums/components/udder.dm @@ -13,7 +13,8 @@ /datum/component/udder/Initialize(udder_type = /obj/item/udder, datum/callback/on_milk_callback, datum/callback/on_generate_callback, reagent_produced_typepath = /datum/reagent/consumable/milk) if(!isliving(parent)) //technically is possible to drop this on carbons... but you wouldn't do that to me, would you? return COMPONENT_INCOMPATIBLE - udder = new udder_type(null, parent, on_generate_callback, reagent_produced_typepath) + udder = new udder_type(null) + udder.add_features(parent, on_generate_callback, reagent_produced_typepath) src.on_milk_callback = on_milk_callback /datum/component/udder/RegisterWithParent() @@ -70,14 +71,68 @@ var/mob/living/udder_mob ///optional proc to callback to when the udder generates milk var/datum/callback/on_generate_callback - -/obj/item/udder/Initialize(mapload, udder_mob, on_generate_callback, reagent_produced_typepath = /datum/reagent/consumable/milk) - src.udder_mob = udder_mob - src.on_generate_callback = on_generate_callback + ///do we require some food to generate milk? + var/require_consume_type + ///how long does each food consumption allow us to make milk + var/require_consume_timer = 2 MINUTES + ///hunger key we set to look for food + var/hunger_key = BB_CHECK_HUNGRY + +/obj/item/udder/proc/add_features(parent, callback, reagent = /datum/reagent/consumable/milk) + udder_mob = parent + on_generate_callback = callback create_reagents(size, REAGENT_HOLDER_ALIVE) - src.reagent_produced_typepath = reagent_produced_typepath + reagent_produced_typepath = reagent initial_conditions() + if(isnull(require_consume_type)) + return + RegisterSignal(udder_mob, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(on_mob_consume)) + RegisterSignal(udder_mob, COMSIG_ATOM_ATTACKBY, PROC_REF(on_mob_feed)) + udder_mob.ai_controller?.set_blackboard_key(BB_CHECK_HUNGRY, TRUE) + +/obj/item/udder/proc/on_mob_consume(datum/source, atom/feed) + SIGNAL_HANDLER + + if(!istype(feed, require_consume_type)) + return + INVOKE_ASYNC(src, PROC_REF(handle_consumption), feed) + return COMPONENT_HOSTILE_NO_ATTACK + +/obj/item/udder/proc/on_mob_feed(datum/source, atom/used_item, mob/living/user) + SIGNAL_HANDLER + + if(!istype(used_item, require_consume_type)) + return + INVOKE_ASYNC(src, PROC_REF(handle_consumption), used_item, user) + return COMPONENT_NO_AFTERATTACK + +/obj/item/udder/proc/handle_consumption(atom/movable/food, mob/user) + if(locate(food.type) in src) + if(user) + user.balloon_alert(user, "already full!") + return + playsound(udder_mob.loc,'sound/items/eatfood.ogg', 50, TRUE) + udder_mob.visible_message(span_notice("[udder_mob] gobbles up [food]!"), span_notice("You gobble up [food]!")) + var/atom/movable/final_food = food + if(isstack(food)) //if stack, only consume 1 + var/obj/item/stack/food_stack = food + final_food = food_stack.split_stack(udder_mob, 1) + final_food.forceMove(src) + +/obj/item/udder/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) + if(!istype(arrived, require_consume_type)) + return ..() + + udder_mob.ai_controller?.set_blackboard_key(hunger_key, FALSE) + QDEL_IN(arrived, require_consume_timer) + return ..() + +/obj/item/udder/Exited(atom/movable/gone, direction) . = ..() + if(!istype(gone, require_consume_type)) + return + udder_mob.ai_controller?.set_blackboard_key(hunger_key, TRUE) + /obj/item/udder/Destroy() . = ..() @@ -101,10 +156,13 @@ * Proc called every 2 seconds from SSMobs to add whatever reagent the udder is generating. */ /obj/item/udder/proc/generate() - if(prob(5)) - reagents.add_reagent(reagent_produced_typepath, rand(5, 10), added_purity = 1) - if(on_generate_callback) - on_generate_callback.Invoke(reagents.total_volume, reagents.maximum_volume) + if(!isnull(require_consume_type) && !(locate(require_consume_type) in src)) + return + if(prob(95)) + return + reagents.add_reagent(reagent_produced_typepath, rand(5, 10), added_purity = 1) + if(on_generate_callback) + on_generate_callback.Invoke(reagents.total_volume, reagents.maximum_volume) /** * Proc called from attacking the component parent with the correct item, moves reagents into the glass basically. @@ -125,48 +183,20 @@ /** * # gutlunch udder subtype - * - * Used by gutlunches, and generates healing reagents instead of milk on eating gibs instead of a process. Starts empty! - * Female gutlunches (ahem, guthens if you will) make babies when their udder is full under processing, instead of milk generation */ + /obj/item/udder/gutlunch name = "nutrient sac" - -/obj/item/udder/gutlunch/initial_conditions() - if(!udder_mob) - return - if(udder_mob.gender == FEMALE) - START_PROCESSING(SSobj, src) - RegisterSignal(udder_mob, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(on_mob_attacking)) - -/obj/item/udder/gutlunch/process(seconds_per_tick) - var/mob/living/simple_animal/hostile/asteroid/gutlunch/gutlunch = udder_mob - if(reagents.total_volume != reagents.maximum_volume) - return - if(gutlunch.make_babies()) - reagents.clear_reagents() - //usually this would be a callback but this is a specifically gutlunch feature so fuck it, gutlunch specific proccall - gutlunch.regenerate_icons(reagents.total_volume, reagents.maximum_volume) - -/** - * signal called on parent attacking an atom -*/ -/obj/item/udder/gutlunch/proc/on_mob_attacking(mob/living/simple_animal/hostile/gutlunch, atom/target) - SIGNAL_HANDLER - - if(is_type_in_typecache(target, gutlunch.wanted_objects)) //we eats - generate() - gutlunch.visible_message(span_notice("[udder_mob] slurps up [target].")) - qdel(target) - return COMPONENT_HOSTILE_NO_ATTACK //there is no longer a target to attack + require_consume_type = /obj/item/stack/ore + reagent_produced_typepath = /datum/reagent/medicine/mine_salve /obj/item/udder/gutlunch/generate() - var/made_something = FALSE - if(prob(60)) + . = ..() + if(!.) + return + if(locate(/obj/item/stack/ore/gold) in src) reagents.add_reagent(/datum/reagent/consumable/cream, rand(2, 5), added_purity = 1) - made_something = TRUE - if(prob(45)) + if(locate(/obj/item/stack/ore/bluespace_crystal) in src) reagents.add_reagent(/datum/reagent/medicine/salglu_solution, rand(2,5)) - made_something = TRUE - if(made_something && on_generate_callback) + if(on_generate_callback) on_generate_callback.Invoke(reagents.total_volume, reagents.maximum_volume) diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index fa9f86abbaa3b..79c4909d27702 100644 --- a/code/datums/diseases/advance/symptoms/sensory.dm +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -51,7 +51,7 @@ M.adjust_confusion(-2 SECONDS) if(purge_alcohol) - M.reagents.remove_all_type(/datum/reagent/consumable/ethanol, 3) + M.reagents.remove_reagent(/datum/reagent/consumable/ethanol, 3, include_subtypes = TRUE) M.adjust_drunk_effect(-5) if(A.stage >= 4) diff --git a/code/datums/ductnet.dm b/code/datums/ductnet.dm index e4dd3959c2246..e97add695d9a3 100644 --- a/code/datums/ductnet.dm +++ b/code/datums/ductnet.dm @@ -43,6 +43,7 @@ for(var/dir in P.ducts) if(P.ducts[dir] == src) P.ducts -= dir + if(!ducts.len) //there were no ducts, so it was a direct connection. we destroy ourselves since a ductnet with only one plumber and no ducts is worthless destroy_network() diff --git a/code/datums/elements/chemical_transfer.dm b/code/datums/elements/chemical_transfer.dm index 9802f0cc059af..01296d97adead 100644 --- a/code/datums/elements/chemical_transfer.dm +++ b/code/datums/elements/chemical_transfer.dm @@ -58,7 +58,7 @@ return var/built_attacker_message = replacetext(attacker_message, "%VICTIM", transfer_victim) var/built_victim_message = replacetext(attacker_message, "%ATTACKER", transfer_attacker) - transfer_attacker.reagents?.trans_to(transfer_victim, transfer_attacker.reagents.total_volume, multiplier = 1, preserve_data = 1, no_react = 0, transferred_by = transfer_attacker) + transfer_attacker.reagents?.trans_to(transfer_victim, transfer_attacker.reagents.total_volume, transferred_by = transfer_attacker) to_chat(transfer_attacker, built_attacker_message) to_chat(transfer_victim, built_victim_message) diff --git a/code/datums/elements/cuffsnapping.dm b/code/datums/elements/cuffsnapping.dm index c0dfdcf60913b..df445f4acc971 100644 --- a/code/datums/elements/cuffsnapping.dm +++ b/code/datums/elements/cuffsnapping.dm @@ -7,7 +7,7 @@ * cuffsnapping attacks have a wounding bonus between severe and critical+10 wound thresholds. Without some serious wound protecting * armour this all but guarantees a wound of some sort. The attack is directed specifically at a limb and the limb takes the damage. * - * Requires the cutter_user to be aiming for either leg zone, which will be targetted specifically. They will than have a 3-second long + * Requires the cutter_user to be aiming for either leg zone, which will be targeted specifically. They will than have a 3-second long * do_after before executing the attack. * * cuffsnapping requires the target to either be on the floor, immobilised or buckled to something. And also to have an appropriate leg. diff --git a/code/datums/elements/dextrous.dm b/code/datums/elements/dextrous.dm index 47b6089f19784..681e2a9488d8c 100644 --- a/code/datums/elements/dextrous.dm +++ b/code/datums/elements/dextrous.dm @@ -50,11 +50,10 @@ /// Try picking up items /datum/element/dextrous/proc/on_hand_clicked(mob/living/hand_haver, atom/target, proximity, modifiers) SIGNAL_HANDLER - if(!proximity) - if(isitem(target)) - var/obj/item/obj_item = target - if(!obj_item.atom_storage && !(obj_item.item_flags & IN_STORAGE)) - return NONE + if (!proximity && target.loc != hand_haver) + var/obj/item/obj_item = target + if (istype(obj_item) && !obj_item.atom_storage && !(obj_item.item_flags & IN_STORAGE)) + return NONE if (!isitem(target) && hand_haver.combat_mode) return NONE if (LAZYACCESS(modifiers, RIGHT_CLICK)) diff --git a/code/datums/elements/door_pryer.dm b/code/datums/elements/door_pryer.dm index a17687407e39c..b7f213b3856f6 100644 --- a/code/datums/elements/door_pryer.dm +++ b/code/datums/elements/door_pryer.dm @@ -22,7 +22,7 @@ . = ..() UnregisterSignal(source, COMSIG_LIVING_UNARMED_ATTACK) -/// If we're targetting an airlock, open it +/// If we're targeting an airlock, open it /datum/element/door_pryer/proc/on_attack(mob/living/basic/attacker, atom/target, proximity_flag) SIGNAL_HANDLER if(!proximity_flag || !istype(target, /obj/machinery/door/airlock)) diff --git a/code/datums/elements/footstep.dm b/code/datums/elements/footstep.dm index 3a0a9961843c4..d2f129c09f4fc 100644 --- a/code/datums/elements/footstep.dm +++ b/code/datums/elements/footstep.dm @@ -94,9 +94,9 @@ return . = list(FOOTSTEP_MOB_SHOE = turf.footstep, FOOTSTEP_MOB_BAREFOOT = turf.barefootstep, FOOTSTEP_MOB_HEAVY = turf.heavyfootstep, FOOTSTEP_MOB_CLAW = turf.clawfootstep, STEP_SOUND_PRIORITY = STEP_SOUND_NO_PRIORITY) - SEND_SIGNAL(turf, COMSIG_TURF_PREPARE_STEP_SOUND, .) + var/overriden = SEND_SIGNAL(turf, COMSIG_TURF_PREPARE_STEP_SOUND, .) & FOOTSTEP_OVERRIDEN //The turf has no footstep sound (e.g. open space) and none of the objects on that turf (e.g. catwalks) overrides it - if(isnull(turf.footstep)) + if(!overriden && isnull(turf.footstep)) return null return . diff --git a/code/datums/elements/footstep_override.dm b/code/datums/elements/footstep_override.dm index 4e0c346c5be2e..43d7311328071 100644 --- a/code/datums/elements/footstep_override.dm +++ b/code/datums/elements/footstep_override.dm @@ -78,3 +78,4 @@ steps[FOOTSTEP_MOB_HEAVY] = heavyfootstep steps[FOOTSTEP_MOB_CLAW] = clawfootstep steps[STEP_SOUND_PRIORITY] = priority + return FOOTSTEP_OVERRIDEN diff --git a/code/datums/elements/kneecapping.dm b/code/datums/elements/kneecapping.dm index 340938c430c35..977268e94a10b 100644 --- a/code/datums/elements/kneecapping.dm +++ b/code/datums/elements/kneecapping.dm @@ -7,7 +7,7 @@ * Kneecapping attacks have a wounding bonus between severe and critical+10 wound thresholds. Without some serious wound protecting * armour this all but guarantees a wound of some sort. The attack is directed specifically at a limb and the limb takes the damage. * - * Requires the attacker to be aiming for either leg zone, which will be targetted specifically. They will than have a 3-second long + * Requires the attacker to be aiming for either leg zone, which will be targeted specifically. They will than have a 3-second long * do_after before executing the attack. * * Kneecapping requires the target to either be on the floor, immobilised or buckled to something. And also to have an appropriate leg. diff --git a/code/datums/elements/loomable.dm b/code/datums/elements/loomable.dm index cfd0b4bc83480..76ee071a9a202 100644 --- a/code/datums/elements/loomable.dm +++ b/code/datums/elements/loomable.dm @@ -71,23 +71,33 @@ /// If a do_after of the specified loom_time passes, will create a new one of resulting_atom and either delete the item, or .use the required amount if its a stack /datum/element/loomable/proc/loom_me(obj/item/source, mob/living/user, atom/target) - if(!do_after(user, loom_time, target)) - user.balloon_alert(user, "interrupted!") - return - - ///we need to perform another check in case a stack somehow got diminished in the middle of the do_after - var/successful = TRUE + //this allows us to count the amount of times it has successfully used the stack's required amount + var/spawning_amount = 0 if(isstack(source)) var/obj/item/stack/stack_we_use = source - if(!stack_we_use.use(required_amount)) - successful = FALSE + while(stack_we_use.amount >= required_amount) + if(!do_after(user, loom_time, target)) + break + + if(!stack_we_use.use(required_amount)) + user.balloon_alert(user, "need [required_amount] of [source]!") + break + + spawning_amount++ + else + if(!do_after(user, loom_time, target)) + user.balloon_alert(user, "interrupted!") + return + qdel(source) + spawning_amount++ - //ripbozo - if(!successful) - user.balloon_alert(user, "need [required_amount] of [source]!") + if(spawning_amount == 0) return - var/new_thing = new resulting_atom(target.drop_location()) + var/new_thing + for(var/repeated in 1 to spawning_amount) + new_thing = new resulting_atom(target.drop_location()) + user.balloon_alert_to_viewers("[process_completion_verb] [new_thing]") diff --git a/code/datums/elements/ore_collecting.dm b/code/datums/elements/ore_collecting.dm new file mode 100644 index 0000000000000..30c9ecc7598d8 --- /dev/null +++ b/code/datums/elements/ore_collecting.dm @@ -0,0 +1,26 @@ +/* + * A component to allow us to collect ore + */ +/datum/element/ore_collecting + + +/datum/element/ore_collecting/Attach(datum/target) + . = ..() + + if(!isliving(target)) + return ELEMENT_INCOMPATIBLE + RegisterSignal(target, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(collect_ore)) + +/datum/element/ore_collecting/Detach(datum/target) + . = ..() + UnregisterSignal(target, COMSIG_HOSTILE_PRE_ATTACKINGTARGET) + +/datum/element/ore_collecting/proc/collect_ore(mob/living/source, atom/target) + SIGNAL_HANDLER + + if(!istype(target, /obj/item/stack/ore)) + return + + var/atom/movable/movable_target = target + movable_target.forceMove(source) + return COMPONENT_HOSTILE_NO_ATTACK diff --git a/code/datums/elements/relay_attackers.dm b/code/datums/elements/relay_attackers.dm index 9f134daf71b60..a6c319d7bc9b8 100644 --- a/code/datums/elements/relay_attackers.dm +++ b/code/datums/elements/relay_attackers.dm @@ -33,8 +33,10 @@ )) REMOVE_TRAIT(source, TRAIT_RELAYING_ATTACKER, REF(src)) -/datum/element/relay_attackers/proc/after_attackby(atom/target, obj/item/weapon, mob/attacker) +/datum/element/relay_attackers/proc/after_attackby(atom/target, obj/item/weapon, mob/attacker, proximity_flag, click_parameters) SIGNAL_HANDLER + if(!proximity_flag) // we don't care about someone clicking us with a piece of metal from across the room + return if(weapon.force) relay_attacker(target, attacker, weapon.damtype == STAMINA ? ATTACKER_STAMINA_ATTACK : ATTACKER_DAMAGING_ATTACK) diff --git a/code/datums/elements/wall_tearer.dm b/code/datums/elements/wall_tearer.dm index 75e892dc4cb85..2c9ff5416d59b 100644 --- a/code/datums/elements/wall_tearer.dm +++ b/code/datums/elements/wall_tearer.dm @@ -28,17 +28,15 @@ src.tear_time = tear_time src.reinforced_multiplier = reinforced_multiplier src.do_after_key = do_after_key - RegisterSignal(target, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_attacked_wall)) + RegisterSignals(target, list(COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_LIVING_UNARMED_ATTACK), PROC_REF(on_attacked_wall)) /datum/element/wall_tearer/Detach(datum/source) . = ..() - UnregisterSignal(source, COMSIG_LIVING_UNARMED_ATTACK) + UnregisterSignal(source, list(COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_LIVING_UNARMED_ATTACK)) /// Try to tear up a wall /datum/element/wall_tearer/proc/on_attacked_wall(mob/living/tearer, atom/target, proximity_flag) SIGNAL_HANDLER - if (!proximity_flag) - return NONE if (DOING_INTERACTION_WITH_TARGET(tearer, target) || (!isnull(do_after_key) && DOING_INTERACTION(tearer, do_after_key))) tearer.balloon_alert(tearer, "busy!") return COMPONENT_HOSTILE_NO_ATTACK diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index bdc644ea75179..3c0e2a903c23f 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -14,6 +14,8 @@ var/key = "" /// This will also call the emote. var/key_third_person = "" + /// Needed for more user-friendly emote names, so emotes with keys like "aflap" will show as "flap angry". Defaulted to key. + var/name = "" /// Message displayed when emote is used. var/message = "" /// Message displayed if the user is a mime. @@ -71,6 +73,9 @@ mob_type_blacklist_typecache = typecacheof(mob_type_blacklist_typecache) mob_type_ignore_stat_typecache = typecacheof(mob_type_ignore_stat_typecache) + if(!name) + name = key + /** * Handles the modifications and execution of emotes. * diff --git a/code/datums/greyscale/config_types/greyscale_configs/greyscale_mobs.dm b/code/datums/greyscale/config_types/greyscale_configs/greyscale_mobs.dm index a4c7c372525bf..250eba9a0d51f 100644 --- a/code/datums/greyscale/config_types/greyscale_configs/greyscale_mobs.dm +++ b/code/datums/greyscale/config_types/greyscale_configs/greyscale_mobs.dm @@ -39,3 +39,9 @@ name = "Pony" icon_file = 'icons/mob/simple/animal.dmi' json_config = 'code/datums/greyscale/json_configs/pony.json' + +/datum/greyscale_config/gutlunch + name = "Gutlunch" + icon_file = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' + json_config = 'code/datums/greyscale/json_configs/gutlunch.json' + diff --git a/code/datums/greyscale/json_configs/gutlunch.json b/code/datums/greyscale/json_configs/gutlunch.json new file mode 100644 index 0000000000000..0b93033816344 --- /dev/null +++ b/code/datums/greyscale/json_configs/gutlunch.json @@ -0,0 +1,15 @@ +{ + "gutlunch": [ + { + "type": "icon_state", + "icon_state": "gutlunch", + "blend_mode": "overlay", + "color_ids": [ 1 ] + }, + { + "type": "icon_state", + "icon_state": "gutlunch_face", + "blend_mode": "overlay" + } + ] +} diff --git a/code/datums/id_trim/outfits.dm b/code/datums/id_trim/outfits.dm index 2a06434ecdb86..87f3a5d63a657 100644 --- a/code/datums/id_trim/outfits.dm +++ b/code/datums/id_trim/outfits.dm @@ -65,7 +65,7 @@ /// Trim for cyber police in the Virtual Domain. /datum/id_trim/cyber_police - assignment = "Cyber Police" + assignment = ROLE_CYBER_POLICE trim_state = "trim_deathcommando" department_color = COLOR_BLACK subdepartment_color = COLOR_GREEN diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index 42eed265affbf..fcc432d41f89d 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -116,12 +116,6 @@ log_combat(attacker, defender, "neck chopped") return TRUE -/datum/martial_art/krav_maga/grab_act(mob/living/attacker, mob/living/defender) - if(check_streak(attacker, defender)) - return TRUE - log_combat(attacker, defender, "grabbed (Krav Maga)") - ..() - /datum/martial_art/krav_maga/harm_act(mob/living/attacker, mob/living/defender) if(check_streak(attacker, defender)) return TRUE diff --git a/code/datums/mocking/client.dm b/code/datums/mocking/client.dm index 72a0eddd5da63..418f5cfb8db2f 100644 --- a/code/datums/mocking/client.dm +++ b/code/datums/mocking/client.dm @@ -35,7 +35,9 @@ src.key = "[key]_[mock_client_uid]" ckey = ckey(key) +#ifdef UNIT_TESTS // otherwise this shit can leak into production servers which is drather bad GLOB.directory[ckey] = src +#endif /datum/client_interface/Destroy(force, ...) GLOB.directory -= ckey diff --git a/code/datums/mutations/tongue_spike.dm b/code/datums/mutations/tongue_spike.dm index 5d210c344b516..b33b78d7d1b1e 100644 --- a/code/datums/mutations/tongue_spike.dm +++ b/code/datums/mutations/tongue_spike.dm @@ -173,7 +173,7 @@ return FALSE to_chat(transferred, span_warning("You feel a tiny prick!")) - transferer.reagents.trans_to(transferred, transferer.reagents.total_volume, 1, 1, 0, transferred_by = transferer) + transferer.reagents.trans_to(transferred, transferer.reagents.total_volume, transferred_by = transferer) var/obj/item/hardened_spike/chem/chem_spike = target var/obj/item/bodypart/spike_location = chem_spike.check_embedded() diff --git a/code/datums/proximity_monitor/fields/timestop.dm b/code/datums/proximity_monitor/fields/timestop.dm index 7fad290fc74d2..86ea41aee0138 100644 --- a/code/datums/proximity_monitor/fields/timestop.dm +++ b/code/datums/proximity_monitor/fields/timestop.dm @@ -36,7 +36,7 @@ for(var/mob/living/to_check in GLOB.player_list) if(HAS_TRAIT(to_check, TRAIT_TIME_STOP_IMMUNE)) immune[to_check] = TRUE - for(var/mob/living/simple_animal/hostile/guardian/stand in GLOB.parasites) + for(var/mob/living/basic/guardian/stand in GLOB.parasites) if(stand.summoner && HAS_TRAIT(stand.summoner, TRAIT_TIME_STOP_IMMUNE)) //It would only make sense that a person's stand would also be immune. immune[stand] = TRUE if(start) diff --git a/code/datums/quirks/_quirk_constant_data.dm b/code/datums/quirks/_quirk_constant_data.dm new file mode 100644 index 0000000000000..977c52a6837ae --- /dev/null +++ b/code/datums/quirks/_quirk_constant_data.dm @@ -0,0 +1,72 @@ +GLOBAL_LIST_INIT_TYPED(all_quirk_constant_data, /datum/quirk_constant_data, generate_quirk_constant_data()) + +/// Constructs [GLOB.all_quirk_constant_data] by iterating through a typecache of pregen data, ignoring abstract types, and instantiating the rest. +/proc/generate_quirk_constant_data() + RETURN_TYPE(/list/datum/quirk_constant_data) + + var/list/datum/quirk_constant_data/all_constant_data = list() + + for (var/datum/quirk_constant_data/iterated_path as anything in typecacheof(path = /datum/quirk_constant_data, ignore_root_path = TRUE)) + if (initial(iterated_path.abstract_type) == iterated_path) + continue + + if (!isnull(all_constant_data[initial(iterated_path.associated_typepath)])) + stack_trace("pre-existing pregen data for [initial(iterated_path.associated_typepath)] when [iterated_path] was being considered: [all_constant_data[initial(iterated_path.associated_typepath)]]. \ + this is definitely a bug, and is probably because one of the two pregen data have the wrong quirk typepath defined. [iterated_path] will not be instantiated") + + continue + + var/datum/quirk_constant_data/pregen_data = new iterated_path + all_constant_data[pregen_data.associated_typepath] = pregen_data + + return all_constant_data + +/// A singleton datum representing constant data and procs used by quirks. +/datum/quirk_constant_data + /// Abstract in OOP terms. If this is our type, we will not be instantiated. + var/abstract_type = /datum/quirk_constant_data + + /// The typepath of the quirk we will be associated with in the global list. This is what we represent. + var/datum/quirk/associated_typepath + + /// A lazylist of preference datum typepaths. Any character pref put in here will be rendered in the quirks page under a dropdown. + var/list/datum/preference/customization_options + +/datum/quirk_constant_data/New() + . = ..() + + ASSERT(abstract_type != type && !isnull(associated_typepath), "associated_typepath null - please set it! occured on: [src.type]") + +/// Returns a list of savefile_keys derived from the preference typepaths in [customization_options]. Used in quirks middleware to supply the preferences to render. +/datum/quirk_constant_data/proc/get_customization_data() + RETURN_TYPE(/list) + + var/list/customization_data = list() + + for (var/datum/preference/pref_type as anything in customization_options) + var/datum/preference/pref_instance = GLOB.preference_entries[pref_type] + if (isnull(pref_instance)) + stack_trace("get_customization_data was called before instantiation of [pref_type]!") + continue // just in case its a fluke and its only this one thats not instantiated, we'll check the other pref entries + + customization_data += pref_instance.savefile_key + + return customization_data + +/// Is this quirk customizable? If true, a button will appear within the quirk's description box in the quirks page, and upon clicking it, +/// will open a customization menu for the quirk. +/datum/quirk_constant_data/proc/is_customizable() + return LAZYLEN(customization_options) > 0 + +/datum/quirk_constant_data/Destroy(force, ...) + var/error_message = "[src], a singleton quirk constant data instance, was destroyed! This should not happen!" + if (force) + error_message += " NOTE: This Destroy() was called with force == TRUE. This instance will be deleted and replaced with a new one." + stack_trace(error_message) + + if (!force) + return QDEL_HINT_LETMELIVE + + . = ..() + + GLOB.all_quirk_constant_data[associated_typepath] = new src.type //recover diff --git a/code/datums/quirks/negative_quirks/food_allergy.dm b/code/datums/quirks/negative_quirks/food_allergy.dm index c2f4eae4d0ed2..0b81dece085d1 100644 --- a/code/datums/quirks/negative_quirks/food_allergy.dm +++ b/code/datums/quirks/negative_quirks/food_allergy.dm @@ -25,6 +25,10 @@ GLOBAL_LIST_INIT(possible_food_allergies, list( /// Footype flags that will trigger the allergy var/target_foodtypes = NONE +/datum/quirk_constant_data/food_allergy + associated_typepath = /datum/quirk/item_quirk/food_allergic + customization_options = list(/datum/preference/choiced/food_allergy) + /datum/quirk/item_quirk/food_allergic/add(client/client_source) if(target_foodtypes != NONE) // Already set, don't care return diff --git a/code/datums/quirks/negative_quirks/nearsighted.dm b/code/datums/quirks/negative_quirks/nearsighted.dm index 6a5397b650459..452971a7ad02c 100644 --- a/code/datums/quirks/negative_quirks/nearsighted.dm +++ b/code/datums/quirks/negative_quirks/nearsighted.dm @@ -10,6 +10,10 @@ quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_CHANGES_APPEARANCE mail_goodies = list(/obj/item/clothing/glasses/regular) // extra pair if orginal one gets broken by somebody mean +/datum/quirk_constant_data/nearsighted + associated_typepath = /datum/quirk/item_quirk/nearsighted + customization_options = list(/datum/preference/choiced/glasses) + /datum/quirk/item_quirk/nearsighted/add_unique(client/client_source) var/glasses_name = client_source?.prefs.read_preference(/datum/preference/choiced/glasses) || "Regular" var/obj/item/clothing/glasses/glasses_type diff --git a/code/datums/quirks/negative_quirks/prosthetic_limb.dm b/code/datums/quirks/negative_quirks/prosthetic_limb.dm index e7ea4d75788f1..791837b04d9da 100644 --- a/code/datums/quirks/negative_quirks/prosthetic_limb.dm +++ b/code/datums/quirks/negative_quirks/prosthetic_limb.dm @@ -11,6 +11,10 @@ /// the original limb from before the prosthetic was applied var/obj/item/bodypart/old_limb +/datum/quirk_constant_data/prosthetic_limb + associated_typepath = /datum/quirk/prosthetic_limb + customization_options = list(/datum/preference/choiced/prosthetic) + /datum/quirk/prosthetic_limb/add_unique(client/client_source) var/limb_type = GLOB.limb_choice[client_source?.prefs?.read_preference(/datum/preference/choiced/prosthetic)] if(isnull(limb_type)) //Client gone or they chose a random prosthetic diff --git a/code/datums/quirks/neutral_quirks/phobia.dm b/code/datums/quirks/neutral_quirks/phobia.dm index 224401f0670c5..0375c69b5227c 100644 --- a/code/datums/quirks/neutral_quirks/phobia.dm +++ b/code/datums/quirks/neutral_quirks/phobia.dm @@ -6,6 +6,10 @@ medical_record_text = "Patient has an irrational fear of something." mail_goodies = list(/obj/item/clothing/glasses/blindfold, /obj/item/storage/pill_bottle/psicodine) +/datum/quirk_constant_data/phobia + associated_typepath = /datum/quirk/phobia + customization_options = list(/datum/preference/choiced/phobia) + // Phobia will follow you between transfers /datum/quirk/phobia/add(client/client_source) var/phobia = client_source?.prefs.read_preference(/datum/preference/choiced/phobia) diff --git a/code/datums/quirks/positive_quirks/bilingual.dm b/code/datums/quirks/positive_quirks/bilingual.dm index 324054198b8d6..408a952cfe18a 100644 --- a/code/datums/quirks/positive_quirks/bilingual.dm +++ b/code/datums/quirks/positive_quirks/bilingual.dm @@ -8,6 +8,10 @@ medical_record_text = "Patient speaks multiple languages." mail_goodies = list(/obj/item/taperecorder, /obj/item/clothing/head/frenchberet, /obj/item/clothing/mask/fakemoustache/italian) +/datum/quirk_constant_data/bilingual + associated_typepath = /datum/quirk/bilingual + customization_options = list(/datum/preference/choiced/language) + /datum/quirk/bilingual/add_unique(client/client_source) var/wanted_language = client_source?.prefs.read_preference(/datum/preference/choiced/language) var/datum/language/language_type diff --git a/code/datums/quirks/positive_quirks/tagger.dm b/code/datums/quirks/positive_quirks/tagger.dm index 5aba24d850a45..4b0f48a1ca893 100644 --- a/code/datums/quirks/positive_quirks/tagger.dm +++ b/code/datums/quirks/positive_quirks/tagger.dm @@ -14,6 +14,10 @@ /obj/item/canvas/twentythree_twentythree ) +/datum/quirk_constant_data/tagger + associated_typepath = /datum/quirk/item_quirk/tagger + customization_options = list(/datum/preference/color/paint_color) + /datum/quirk/item_quirk/tagger/add_unique(client/client_source) var/obj/item/toy/crayon/spraycan/can = new can.set_painting_tool_color(client_source?.prefs.read_preference(/datum/preference/color/paint_color)) diff --git a/code/datums/ruins/space.dm b/code/datums/ruins/space.dm index 726b42431a184..05c4940dae9f0 100644 --- a/code/datums/ruins/space.dm +++ b/code/datums/ruins/space.dm @@ -483,3 +483,28 @@ suffix = "infested_frigate.dmm" name = "SYN-C Brutus" description = "This wasn't an outbreak, this was a repelled attack." + +/datum/map_template/ruin/space/garbagetruck1 + id = "garbagetruck1" + suffix = "garbagetruck1.dmm" + name = "Decommissioned Garbage Truck NX1" + description = "An NX-760 interstellar transport barge. At the end of their life cycle, they are often filled with trash and launched into unexplored space to become someone else's problem. This one is full of kitchen waste, and rodents." + +/datum/map_template/ruin/space/garbagetruck2 + id = "garbagetruck2" + suffix = "garbagetruck2.dmm" + name = "Decommissioned Garbage Truck NX2" + description = "An NX-760 interstellar transport barge. At the end of their life cycle, they are often filled with trash and launched into unexplored space to become someone else's problem. This one is full of medical waste, and a syndicate agent." + +/datum/map_template/ruin/space/garbagetruck3 + id = "garbagetruck3" + suffix = "garbagetruck3.dmm" + name = "Decommissioned Garbage Truck NX3" + description = "An NX-760 interstellar transport barge. At the end of their life cycle, they are often filled with trash and launched into unexplored space to become someone else's problem. This one is full of industrial garbage, and a russian drug den." + +/datum/map_template/ruin/space/garbagetruck4 + id = "garbagetruck4" + suffix = "garbagetruck4.dmm" + name = "Decommissioned Garbage Truck NX4" + description = "An NX-760 interstellar transport barge. At the end of their life cycle, they are often filled with trash and launched into unexplored space to become someone else's problem. This one is full of commercial trash, and spiders." + diff --git a/code/datums/sprite_accessories.dm b/code/datums/sprite_accessories.dm index 012211b2421a6..362ebbd5b64ba 100644 --- a/code/datums/sprite_accessories.dm +++ b/code/datums/sprite_accessories.dm @@ -2097,11 +2097,11 @@ name = "Long + Membrane" icon_state = "longmeme" -/datum/sprite_accessory/spines/aqautic +/datum/sprite_accessory/spines/aquatic name = "Aquatic" icon_state = "aqua" -/datum/sprite_accessory/spines_animated/aqautic +/datum/sprite_accessory/spines_animated/aquatic name = "Aquatic" icon_state = "aqua" diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 5101242f42831..fe2c281a3380f 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -557,7 +557,7 @@ owner.AddElement(/datum/element/forced_gravity, 0) owner.AddElement(/datum/element/simple_flying) owner.add_stun_absorption(source = id, priority = 4) - add_traits(list(TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_FREE_HYPERSPACE_MOVEMENT), MAD_WIZARD_TRAIT) + owner.add_traits(list(TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_FREE_HYPERSPACE_MOVEMENT), MAD_WIZARD_TRAIT) owner.playsound_local(get_turf(owner), 'sound/chemistry/ahaha.ogg', vol = 100, vary = TRUE, use_reverb = TRUE) return TRUE @@ -575,7 +575,7 @@ owner.RemoveElement(/datum/element/forced_gravity, 0) owner.RemoveElement(/datum/element/simple_flying) owner.remove_stun_absorption(id) - remove_traits(list(TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_FREE_HYPERSPACE_MOVEMENT), MAD_WIZARD_TRAIT) + owner.remove_traits(list(TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_FREE_HYPERSPACE_MOVEMENT), MAD_WIZARD_TRAIT) /// Gives you a brief period of anti-gravity /datum/status_effect/jump_jet diff --git a/code/datums/status_effects/buffs/stop_drop_roll.dm b/code/datums/status_effects/buffs/stop_drop_roll.dm new file mode 100644 index 0000000000000..43d37654e6177 --- /dev/null +++ b/code/datums/status_effects/buffs/stop_drop_roll.dm @@ -0,0 +1,66 @@ +/datum/status_effect/stop_drop_roll + id = "stop_drop_roll" + alert_type = null + + tick_interval = 0.8 SECONDS + +/datum/status_effect/stop_drop_roll/on_apply() + if(!iscarbon(owner)) + return FALSE + + var/actual_interval = initial(tick_interval) + if(!owner.Knockdown(actual_interval * 2, ignore_canstun = TRUE) || owner.body_position != LYING_DOWN) + to_chat(owner, span_warning("You try to stop, drop, and roll - but you can't get on the ground!")) + return FALSE + + RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(stop_rolling)) + RegisterSignal(owner, COMSIG_LIVING_SET_BODY_POSITION, PROC_REF(body_position_changed)) + ADD_TRAIT(owner, TRAIT_HANDS_BLOCKED, id) // they're kinda busy! + + owner.visible_message( + span_danger("[owner] rolls on the floor, trying to put [owner.p_them()]self out!"), + span_notice("You stop, drop, and roll!"), + ) + // Start with one weaker roll + owner.spin(spintime = actual_interval, speed = actual_interval / 4) + owner.adjust_fire_stacks(-0.25) + return TRUE + +/datum/status_effect/stop_drop_roll/on_remove() + UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_LIVING_SET_BODY_POSITION)) + REMOVE_TRAIT(owner, TRAIT_HANDS_BLOCKED, id) + +/datum/status_effect/stop_drop_roll/tick(seconds_between_ticks) + if(HAS_TRAIT(owner, TRAIT_IMMOBILIZED) || HAS_TRAIT(owner, TRAIT_INCAPACITATED)) + qdel(src) + return + + var/actual_interval = initial(tick_interval) + if(!owner.Knockdown(actual_interval * 1.2, ignore_canstun = TRUE)) + stop_rolling() + return + + owner.spin(spintime = actual_interval, speed = actual_interval / 4) + owner.adjust_fire_stacks(-1) + + if(owner.fire_stacks > 0) + return + + owner.visible_message( + span_danger("[owner] successfully extinguishes [owner.p_them()]self!"), + span_notice("You extinguish yourself."), + ) + qdel(src) + +/datum/status_effect/stop_drop_roll/proc/stop_rolling(datum/source, ...) + SIGNAL_HANDLER + + if(!QDELING(owner)) + to_chat(owner, span_notice("You stop rolling around.")) + qdel(src) + +/datum/status_effect/stop_drop_roll/proc/body_position_changed(datum/source, new_value, old_value) + SIGNAL_HANDLER + + if(new_value != LYING_DOWN) + stop_rolling() diff --git a/code/datums/status_effects/debuffs/fire_stacks.dm b/code/datums/status_effects/debuffs/fire_stacks.dm index 8f52165cdbb12..4a6e7b6b730f6 100644 --- a/code/datums/status_effects/debuffs/fire_stacks.dm +++ b/code/datums/status_effects/debuffs/fire_stacks.dm @@ -201,14 +201,19 @@ var/mob/living/carbon/human/victim = owner var/thermal_protection = victim.get_thermal_protection() - if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT && !no_protection) - return + if(!no_protection) + if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT) + return + if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT) + victim.adjust_bodytemperature(5.5 * seconds_per_tick) + return - if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT && !no_protection) - victim.adjust_bodytemperature(5.5 * seconds_per_tick) - return + var/amount_to_heat = (BODYTEMP_HEATING_MAX + (stacks * 12)) * 0.5 * seconds_per_tick + if(owner.bodytemperature > BODYTEMP_FIRE_TEMP_SOFTCAP) + // Apply dimishing returns upon temp beyond the soft cap + amount_to_heat = amount_to_heat ** (BODYTEMP_FIRE_TEMP_SOFTCAP / owner.bodytemperature) - victim.adjust_bodytemperature((BODYTEMP_HEATING_MAX + (stacks * 12)) * 0.5 * seconds_per_tick) + victim.adjust_bodytemperature(amount_to_heat) victim.add_mood_event("on_fire", /datum/mood_event/on_fire) victim.add_mob_memory(/datum/memory/was_burning) @@ -233,10 +238,10 @@ qdel(moblight) moblight = new moblight_type(owner) - SEND_SIGNAL(owner, COMSIG_LIVING_IGNITED, owner) cache_stacks() update_overlay() update_particles() + SEND_SIGNAL(owner, COMSIG_LIVING_IGNITED, owner) return TRUE /** diff --git a/code/datums/status_effects/gas.dm b/code/datums/status_effects/gas.dm index bcc0a50e70737..f06a289da781d 100644 --- a/code/datums/status_effects/gas.dm +++ b/code/datums/status_effects/gas.dm @@ -33,11 +33,9 @@ /datum/status_effect/freon/proc/do_resist() to_chat(owner, span_notice("You start breaking out of the ice cube...")) - if(do_after(owner, owner, 4 SECONDS)) - if(!QDELETED(src)) - to_chat(owner, span_notice("You break out of the ice cube!")) - owner.remove_status_effect(/datum/status_effect/freon) - + if(do_after(owner, 4 SECONDS, target = owner)) + to_chat(owner, span_notice("You break out of the ice cube!")) + qdel(src) /datum/status_effect/freon/on_remove() if(!owner.stat) diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index 64c78bc7fbb90..416fe03134119 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -149,9 +149,16 @@ /atom/movable/screen/alert/status_effect/holdup name = "Holding Up" - desc = "You're currently pointing a gun at someone." + desc = "You're currently pointing a gun at someone. Click to cancel." icon_state = "aimed" +/atom/movable/screen/alert/status_effect/holdup/Click(location, control, params) + . = ..() + if(!.) + return + var/datum/component/gunpoint/gunpoint = owner.GetComponent(/datum/component/gunpoint) + gunpoint?.cancel() + // this status effect is used to negotiate the high-fiving capabilities of all concerned parties /datum/status_effect/offering id = "offering" diff --git a/code/game/area/areas/ruins/space.dm b/code/game/area/areas/ruins/space.dm index df72a1e0fe44e..6fd9a38196695 100644 --- a/code/game/area/areas/ruins/space.dm +++ b/code/game/area/areas/ruins/space.dm @@ -689,3 +689,13 @@ //SYN-C Brutus, derelict frigate /area/ruin/space/has_grav/infested_frigate name = "SYN-C Brutus" + +//garbage trucks +/area/ruin/space/has_grav/garbagetruck + name = "decommissioned garbage truck" + sound_environment = SOUND_AREA_SMALL_ENCLOSED + ambience_index = AMBIENCE_MAINT +/area/ruin/space/has_grav/garbagetruck/foodwaste +/area/ruin/space/has_grav/garbagetruck/medicalwaste +/area/ruin/space/has_grav/garbagetruck/squat +/area/ruin/space/has_grav/garbagetruck/toystore diff --git a/code/game/area/areas/station/security.dm b/code/game/area/areas/station/security.dm index 918cf30ceb8ca..93629f35628c2 100644 --- a/code/game/area/areas/station/security.dm +++ b/code/game/area/areas/station/security.dm @@ -106,6 +106,10 @@ /area/station/security/execution/education name = "\improper Prisoner Education Chamber" +/area/station/security/mechbay + name = "Security Mechbay" + icon_state = "sec_mechbay" + /* * Security Checkpoints */ @@ -173,9 +177,6 @@ name = "Security Post - Third Floor" icon_state = "checkpoint_3" -/* -* Prison Areas -*/ /area/station/security/prison name = "\improper Prison Wing" diff --git a/code/game/atom/README.md b/code/game/atom/README.md new file mode 100644 index 0000000000000..3ce4f9b0cf951 --- /dev/null +++ b/code/game/atom/README.md @@ -0,0 +1,3 @@ +# Core /atom Systems + +This is a folder of basic systems that apply to all /atom types, split into relevant files. Keep the files named fittingly and don't put anything in `_atom.dm` if you can avoid it. diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm new file mode 100644 index 0000000000000..c5379f40c0576 --- /dev/null +++ b/code/game/atom/_atom.dm @@ -0,0 +1,954 @@ +/** + * The base type for nearly all physical objects in SS13 + + * Lots and lots of functionality lives here, although in general we are striving to move + * as much as possible to the components/elements system + */ +/atom + layer = TURF_LAYER + plane = GAME_PLANE + appearance_flags = TILE_BOUND|LONG_GLIDE + + /// pass_flags that we are. If any of this matches a pass_flag on a moving thing, by default, we let them through. + var/pass_flags_self = NONE + + ///First atom flags var + var/flags_1 = NONE + ///Intearaction flags + var/interaction_flags_atom = NONE + + var/flags_ricochet = NONE + + ///When a projectile tries to ricochet off this atom, the projectile ricochet chance is multiplied by this + var/receive_ricochet_chance_mod = 1 + ///When a projectile ricochets off this atom, it deals the normal damage * this modifier to this atom + var/receive_ricochet_damage_coeff = 0.33 + + ///Reagents holder + var/datum/reagents/reagents = null + + ///all of this atom's HUD (med/sec, etc) images. Associative list of the form: list(hud category = hud image or images for that category). + ///most of the time hud category is associated with a single image, sometimes its associated with a list of images. + ///not every hud in this list is actually used. for ones available for others to see, look at active_hud_list. + var/list/image/hud_list = null + ///all of this atom's HUD images which can actually be seen by players with that hud + var/list/image/active_hud_list = null + ///HUD images that this atom can provide. + var/list/hud_possible + + ///How much this atom resists explosions by, in the end + var/explosive_resistance = 0 + + ///vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays. + var/list/managed_vis_overlays + + /// Lazylist of all images (or atoms, I'm sorry) (hopefully attached to us) to update when we change z levels + /// You will need to manage adding/removing from this yourself, but I'll do the updating for you + var/list/image/update_on_z + + /// Lazylist of all overlays attached to us to update when we change z levels + /// You will need to manage adding/removing from this yourself, but I'll do the updating for you + /// Oh and note, if order of addition is important this WILL break that. so mind yourself + var/list/image/update_overlays_on_z + + ///Cooldown tick timer for buckle messages + var/buckle_message_cooldown = 0 + ///Last fingerprints to touch this atom + var/fingerprintslast + + /// Radiation insulation types + var/rad_insulation = RAD_NO_INSULATION + + /// The icon state intended to be used for the acid component. Used to override the default acid overlay icon state. + var/custom_acid_overlay = null + + var/datum/wires/wires = null + + ///Light systems, both shouldn't be active at the same time. + var/light_system = STATIC_LIGHT + ///Range of the light in tiles. Zero means no light. + var/light_range = 0 + ///Intensity of the light. The stronger, the less shadows you will see on the lit area. + var/light_power = 1 + ///Hexadecimal RGB string representing the colour of the light. White by default. + var/light_color = COLOR_WHITE + /// Angle of light to show in light_dir + /// 360 is a circle, 90 is a cone, etc. + var/light_angle = 360 + /// What angle to project light in + var/light_dir = NORTH + ///Boolean variable for toggleable lights. Has no effect without the proper light_system, light_range and light_power values. + var/light_on = TRUE + /// How many tiles "up" this light is. 1 is typical, should only really change this if it's a floor light + var/light_height = LIGHTING_HEIGHT + ///Bitflags to determine lighting-related atom properties. + var/light_flags = NONE + ///Our light source. Don't fuck with this directly unless you have a good reason! + var/tmp/datum/light_source/light + ///Any light sources that are "inside" of us, for example, if src here was a mob that's carrying a flashlight, that flashlight's light source would be part of this list. + var/tmp/list/light_sources + + /// Last name used to calculate a color for the chatmessage overlays + var/chat_color_name + /// Last color calculated for the the chatmessage overlays + var/chat_color + /// A luminescence-shifted value of the last color calculated for chatmessage overlays + var/chat_color_darkened + + // Use SET_BASE_PIXEL(x, y) to set these in typepath definitions, it'll handle pixel_x and y for you + ///Default pixel x shifting for the atom's icon. + var/base_pixel_x = 0 + ///Default pixel y shifting for the atom's icon. + var/base_pixel_y = 0 + // Use SET_BASE_VISUAL_PIXEL(x, y) to set these in typepath definitions, it'll handle pixel_w and z for you + ///Default pixel w shifting for the atom's icon. + var/base_pixel_w = 0 + ///Default pixel z shifting for the atom's icon. + var/base_pixel_z = 0 + ///Used for changing icon states for different base sprites. + var/base_icon_state + + ///Icon-smoothing behavior. + var/smoothing_flags = NONE + ///What directions this is currently smoothing with. IMPORTANT: This uses the smoothing direction flags as defined in icon_smoothing.dm, instead of the BYOND flags. + var/smoothing_junction = null //This starts as null for us to know when it's first set, but after that it will hold a 8-bit mask ranging from 0 to 255. + ///Smoothing variable + var/top_left_corner + ///Smoothing variable + var/top_right_corner + ///Smoothing variable + var/bottom_left_corner + ///Smoothing variable + var/bottom_right_corner + ///What smoothing groups does this atom belongs to, to match canSmoothWith. If null, nobody can smooth with it. Must be sorted. + var/list/smoothing_groups = null + ///List of smoothing groups this atom can smooth with. If this is null and atom is smooth, it smooths only with itself. Must be sorted. + var/list/canSmoothWith = null + + ///AI controller that controls this atom. type on init, then turned into an instance during runtime + var/datum/ai_controller/ai_controller + + /// forensics datum, contains fingerprints, fibres, blood_dna and hiddenprints on this atom + var/datum/forensics/forensics + + /// How this atom should react to having its astar blocking checked + var/can_astar_pass = CANASTARPASS_DENSITY + +/** + * Top level of the destroy chain for most atoms + * + * Cleans up the following: + * * Removes alternate apperances from huds that see them + * * qdels the reagent holder from atoms if it exists + * * clears the orbiters list + * * clears overlays and priority overlays + * * clears the light object + */ +/atom/Destroy(force) + if(alternate_appearances) + for(var/current_alternate_appearance in alternate_appearances) + var/datum/atom_hud/alternate_appearance/selected_alternate_appearance = alternate_appearances[current_alternate_appearance] + selected_alternate_appearance.remove_atom_from_hud(src) + + if(reagents) + QDEL_NULL(reagents) + + if(forensics) + QDEL_NULL(forensics) + + if(atom_storage) + QDEL_NULL(atom_storage) + + orbiters = null // The component is attached to us normaly and will be deleted elsewhere + + // Checking length(overlays) before cutting has significant speed benefits + if (length(overlays)) + overlays.Cut() + + LAZYNULL(managed_overlays) + if(ai_controller) + QDEL_NULL(ai_controller) + if(light) + QDEL_NULL(light) + if (length(light_sources)) + light_sources.Cut() + + if(smoothing_flags & SMOOTH_QUEUED) + SSicon_smooth.remove_from_queues(src) + + return ..() + +/atom/proc/handle_ricochet(obj/projectile/ricocheting_projectile) + var/turf/p_turf = get_turf(ricocheting_projectile) + var/face_direction = get_dir(src, p_turf) || get_dir(src, ricocheting_projectile) + var/face_angle = dir2angle(face_direction) + var/incidence_s = GET_ANGLE_OF_INCIDENCE(face_angle, (ricocheting_projectile.Angle + 180)) + var/a_incidence_s = abs(incidence_s) + if(a_incidence_s > 90 && a_incidence_s < 270) + return FALSE + if((ricocheting_projectile.armor_flag in list(BULLET, BOMB)) && ricocheting_projectile.ricochet_incidence_leeway) + if((a_incidence_s < 90 && a_incidence_s < 90 - ricocheting_projectile.ricochet_incidence_leeway) || (a_incidence_s > 270 && a_incidence_s -270 > ricocheting_projectile.ricochet_incidence_leeway)) + return FALSE + var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s) + ricocheting_projectile.set_angle(new_angle_s) + return TRUE + +/// Whether the mover object can avoid being blocked by this atom, while arriving from (or leaving through) the border_dir. +/atom/proc/CanPass(atom/movable/mover, border_dir) + SHOULD_CALL_PARENT(TRUE) + SHOULD_BE_PURE(TRUE) + if(SEND_SIGNAL(src, COMSIG_ATOM_TRIED_PASS, mover, border_dir) & COMSIG_COMPONENT_PERMIT_PASSAGE) + return TRUE + if(mover.movement_type & PHASING) + return TRUE + . = CanAllowThrough(mover, border_dir) + // This is cheaper than calling the proc every time since most things dont override CanPassThrough + if(!mover.generic_canpass) + return mover.CanPassThrough(src, REVERSE_DIR(border_dir), .) + +/// Returns true or false to allow the mover to move through src +/atom/proc/CanAllowThrough(atom/movable/mover, border_dir) + SHOULD_CALL_PARENT(TRUE) + //SHOULD_BE_PURE(TRUE) + if(mover.pass_flags & pass_flags_self) + return TRUE + if(mover.throwing && (pass_flags_self & LETPASSTHROW)) + return TRUE + return !density + +/** + * Is this atom currently located on centcom (or riding off into the sunset on a shuttle) + * + * Specifically, is it on the z level and within the centcom areas. + * You can also be in a shuttle during endgame transit. + * + * Used in gamemode to identify mobs who have escaped and for some other areas of the code + * who don't want atoms where they shouldn't be + * + * Returns TRUE if this atom is on centcom or an escape shuttle, or FALSE if not + */ +/atom/proc/onCentCom() + var/turf/current_turf = get_turf(src) + if(!current_turf) + return FALSE + + // This doesn't necessarily check that we're at central command, + // but it checks for any shuttles which have finished are still in hyperspace + // (IE, stuff like the whiteship which fly off into the sunset and "escape") + if(is_reserved_level(current_turf.z)) + return on_escaped_shuttle(ENDGAME_TRANSIT) + + // From here on we only concern ourselves with people actually on the centcom Z + if(!is_centcom_level(current_turf.z)) + return FALSE + + if(istype(current_turf.loc, /area/centcom)) + return TRUE + + // Finally, check if we're on an escaped shuttle + return on_escaped_shuttle() + +/** + * Is the atom in any of the syndicate areas + * + * Either in the syndie base, or any of their shuttles + * + * Also used in gamemode code for win conditions + * + * Returns TRUE if this atom is on the syndicate recon base, any of its shuttles, or an escape shuttle, or FALSE if not + */ +/atom/proc/onSyndieBase() + var/turf/current_turf = get_turf(src) + if(!current_turf) + return FALSE + + // Syndicate base is loaded in a reserved level. If not reserved, we don't care. + if(!is_reserved_level(current_turf.z)) + return FALSE + + var/static/list/syndie_typecache = typecacheof(list( + /area/centcom/syndicate_mothership, // syndicate base itself + /area/shuttle/assault_pod, // steel rain + /area/shuttle/syndicate, // infiltrator + )) + + if(is_type_in_typecache(current_turf.loc, syndie_typecache)) + return TRUE + + // Finally, check if we're on an escaped shuttle + return on_escaped_shuttle() + +/** + * Checks that we're on a shuttle that's escaped + * + * * check_for_launch_status - What launch status do we check for? Generally the two you want to check for are ENDGAME_LAUNCHED or ENDGAME_TRANSIT + * + * Returns TRUE if this atom is on a shuttle which is escaping or has escaped, or FALSE otherwise + */ +/atom/proc/on_escaped_shuttle(check_for_launch_status = ENDGAME_LAUNCHED) + var/turf/current_turf = get_turf(src) + if(!current_turf) + return FALSE + + for(var/obj/docking_port/mobile/mobile_docking_port as anything in SSshuttle.mobile_docking_ports) + if(mobile_docking_port.launch_status != check_for_launch_status) + continue + for(var/area/shuttle/shuttle_area as anything in mobile_docking_port.shuttle_areas) + if(current_turf in shuttle_area.get_contained_turfs()) + return TRUE + + return FALSE + +/** + * Is the atom in an away mission + * + * Must be in the away mission z-level to return TRUE + * + * Also used in gamemode code for win conditions + */ +/atom/proc/onAwayMission() + var/turf/current_turf = get_turf(src) + if(!current_turf) + return FALSE + + if(is_away_level(current_turf.z)) + return TRUE + + return FALSE + +/** + * Ensure a list of atoms/reagents exists inside this atom + * + * Goes throught he list of passed in parts, if they're reagents, adds them to our reagent holder + * creating the reagent holder if it exists. + * + * If the part is a moveable atom and the previous location of the item was a mob/living, + * it calls the inventory handler transferItemToLoc for that mob/living and transfers the part + * to this atom + * + * Otherwise it simply forceMoves the atom into this atom + */ +/atom/proc/CheckParts(list/parts_list, datum/crafting_recipe/current_recipe) + SEND_SIGNAL(src, COMSIG_ATOM_CHECKPARTS, parts_list, current_recipe) + if(!parts_list) + return + for(var/part in parts_list) + if(istype(part, /datum/reagent)) + if(!reagents) + reagents = new() + reagents.reagent_list.Add(part) + reagents.conditional_update() + else if(ismovable(part)) + var/atom/movable/object = part + if(isliving(object.loc)) + var/mob/living/living = object.loc + living.transferItemToLoc(object, src) + else + object.forceMove(src) + SEND_SIGNAL(object, COMSIG_ATOM_USED_IN_CRAFT, src) + parts_list.Cut() + +///Take air from the passed in gas mixture datum +/atom/proc/assume_air(datum/gas_mixture/giver) + return null + +///Remove air from this atom +/atom/proc/remove_air(amount) + return null + +///Return the current air environment in this atom +/atom/proc/return_air() + if(loc) + return loc.return_air() + else + return null + +///Return the air if we can analyze it +/atom/proc/return_analyzable_air() + return null + +///Check if this atoms eye is still alive (probably) +/atom/proc/check_eye(mob/user) + SIGNAL_HANDLER + return + +/atom/proc/Bumped(atom/movable/bumped_atom) + set waitfor = FALSE + SEND_SIGNAL(src, COMSIG_ATOM_BUMPED, bumped_atom) + +/// Convenience proc to see if a container is open for chemistry handling +/atom/proc/is_open_container() + return is_refillable() && is_drainable() + +/// Is this atom injectable into other atoms +/atom/proc/is_injectable(mob/user, allowmobs = TRUE) + return reagents && (reagents.flags & (INJECTABLE | REFILLABLE)) + +/// Can we draw from this atom with an injectable atom +/atom/proc/is_drawable(mob/user, allowmobs = TRUE) + return reagents && (reagents.flags & (DRAWABLE | DRAINABLE)) + +/// Can this atoms reagents be refilled +/atom/proc/is_refillable() + return reagents && (reagents.flags & REFILLABLE) + +/// Is this atom drainable of reagents +/atom/proc/is_drainable() + return reagents && (reagents.flags & DRAINABLE) + +/** Handles exposing this atom to a list of reagents. + * + * Sends COMSIG_ATOM_EXPOSE_REAGENTS + * Calls expose_atom() for every reagent in the reagent list. + * + * Arguments: + * - [reagents][/list]: The list of reagents the atom is being exposed to. + * - [source][/datum/reagents]: The reagent holder the reagents are being sourced from. + * - methods: How the atom is being exposed to the reagents. Bitflags. + * - volume_modifier: Volume multiplier. + * - show_message: Whether to display anything to mobs when they are exposed. + */ +/atom/proc/expose_reagents(list/reagents, datum/reagents/source, methods=TOUCH, volume_modifier=1, show_message=TRUE) + . = SEND_SIGNAL(src, COMSIG_ATOM_EXPOSE_REAGENTS, reagents, source, methods, volume_modifier, show_message) + if(. & COMPONENT_NO_EXPOSE_REAGENTS) + return + + SEND_SIGNAL(source, COMSIG_REAGENTS_EXPOSE_ATOM, src, reagents, methods, volume_modifier, show_message) + for(var/datum/reagent/current_reagent as anything in reagents) + . |= current_reagent.expose_atom(src, reagents[current_reagent]) + SEND_SIGNAL(src, COMSIG_ATOM_AFTER_EXPOSE_REAGENTS, reagents, source, methods, volume_modifier, show_message) + +/// Are you allowed to drop this atom +/atom/proc/AllowDrop() + return FALSE + +///Is this atom within 1 tile of another atom +/atom/proc/HasProximity(atom/movable/proximity_check_mob as mob|obj) + return + +/// Sets the wire datum of an atom +/atom/proc/set_wires(datum/wires/new_wires) + wires = new_wires + +///Return true if we're inside the passed in atom +/atom/proc/in_contents_of(container)//can take class or object instance as argument + if(ispath(container)) + if(istype(src.loc, container)) + return TRUE + else if(src in container) + return TRUE + return FALSE + +/** + * Checks the atom's loc and calls update_held_items on it if it is a mob. + * + * This should only be used in situations when you are unable to use /datum/element/update_icon_updates_onmob for whatever reason. + * Check code/datums/elements/update_icon_updates_onmob.dm before using this. Adding that to the atom and calling update_appearance will work for most cases. + * + * Arguments: + * * mob/target - The mob to update the icons of. Optional argument, use if the atom's loc is not the mob you want to update. + */ +/atom/proc/update_inhand_icon(mob/target = loc) + SHOULD_CALL_PARENT(TRUE) + if(!istype(target)) + return + + target.update_held_items() + + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_INHAND_ICON, target) + +/** + * An atom we are buckled or is contained within us has tried to move + * + * Default behaviour is to send a warning that the user can't move while buckled as long + * as the [buckle_message_cooldown][/atom/var/buckle_message_cooldown] has expired (50 ticks) + */ +/atom/proc/relaymove(mob/living/user, direction) + if(SEND_SIGNAL(src, COMSIG_ATOM_RELAYMOVE, user, direction) & COMSIG_BLOCK_RELAYMOVE) + return + if(buckle_message_cooldown <= world.time) + buckle_message_cooldown = world.time + 25 + balloon_alert(user, "can't move while buckled!") + return + +/** + * A special case of relaymove() in which the person relaying the move may be "driving" this atom + * + * This is a special case for vehicles and ridden animals where the relayed movement may be handled + * by the riding component attached to this atom. Returns TRUE as long as there's nothing blocking + * the movement, or FALSE if the signal gets a reply that specifically blocks the movement + */ +/atom/proc/relaydrive(mob/living/user, direction) + return !(SEND_SIGNAL(src, COMSIG_RIDDEN_DRIVER_MOVE, user, direction) & COMPONENT_DRIVER_BLOCK_MOVE) + +///returns the mob's dna info as a list, to be inserted in an object's blood_DNA list +/mob/living/proc/get_blood_dna_list() + if(get_blood_id() != /datum/reagent/blood) + return + return list("ANIMAL DNA" = "Y-") + +///Get the mobs dna list +/mob/living/carbon/get_blood_dna_list() + if(get_blood_id() != /datum/reagent/blood) + return + var/list/blood_dna = list() + if(dna) + blood_dna[dna.unique_enzymes] = dna.blood_type + else + blood_dna["UNKNOWN DNA"] = "X*" + return blood_dna + +/mob/living/carbon/alien/get_blood_dna_list() + return list("UNKNOWN DNA" = "X*") + +/mob/living/silicon/get_blood_dna_list() + return + +///to add a mob's dna info into an object's blood_dna list. +/atom/proc/transfer_mob_blood_dna(mob/living/injected_mob) + // Returns 0 if we have that blood already + var/new_blood_dna = injected_mob.get_blood_dna_list() + if(!new_blood_dna) + return FALSE + var/old_length = GET_ATOM_BLOOD_DNA_LENGTH(src) + add_blood_DNA(new_blood_dna) + if(GET_ATOM_BLOOD_DNA_LENGTH(src) == old_length) + return FALSE + return TRUE + +///to add blood from a mob onto something, and transfer their dna info +/atom/proc/add_mob_blood(mob/living/injected_mob) + var/list/blood_dna = injected_mob.get_blood_dna_list() + if(!blood_dna) + return FALSE + return add_blood_DNA(blood_dna) + +///Is this atom in space +/atom/proc/isinspace() + if(isspaceturf(get_turf(src))) + return TRUE + else + return FALSE + +/** + * If someone's trying to dump items onto our atom, where should they be dumped to? + * + * Return a loc to place objects, or null to stop dumping. + */ +/atom/proc/get_dumping_location() + return null + +/** + * the vision impairment to give to the mob whose perspective is set to that atom + * + * (e.g. an unfocused camera giving you an impaired vision when looking through it) + */ +/atom/proc/get_remote_view_fullscreens(mob/user) + return + +/** + * the sight changes to give to the mob whose perspective is set to that atom + * + * (e.g. A mob with nightvision loses its nightvision while looking through a normal camera) + */ +/atom/proc/update_remote_sight(mob/living/user) + return + + +/** + * Hook for running code when a dir change occurs + * + * Not recommended to use, listen for the [COMSIG_ATOM_DIR_CHANGE] signal instead (sent by this proc) + */ +/atom/proc/setDir(newdir) + SHOULD_CALL_PARENT(TRUE) + if (SEND_SIGNAL(src, COMSIG_ATOM_PRE_DIR_CHANGE, dir, newdir) & COMPONENT_ATOM_BLOCK_DIR_CHANGE) + newdir = dir + return + SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir) + dir = newdir + SEND_SIGNAL(src, COMSIG_ATOM_POST_DIR_CHANGE, dir, newdir) + if(smoothing_flags & SMOOTH_BORDER_OBJECT) + QUEUE_SMOOTH_NEIGHBORS(src) + +/** + * Wash this atom + * + * This will clean it off any temporary stuff like blood. Override this in your item to add custom cleaning behavior. + * Returns true if any washing was necessary and thus performed + * Arguments: + * * clean_types: any of the CLEAN_ constants + */ +/atom/proc/wash(clean_types) + SHOULD_CALL_PARENT(TRUE) + if(SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, clean_types) & COMPONENT_CLEANED) + return TRUE + + // Basically "if has washable coloration" + if(length(atom_colours) >= WASHABLE_COLOUR_PRIORITY && atom_colours[WASHABLE_COLOUR_PRIORITY]) + remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + return TRUE + return FALSE + +///Where atoms should drop if taken from this atom +/atom/proc/drop_location() + var/atom/location = loc + if(!location) + return null + return location.AllowDrop() ? location : location.drop_location() + +/** + * An atom has entered this atom's contents + * + * Default behaviour is to send the [COMSIG_ATOM_ENTERED] + */ +/atom/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) + SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, arrived, old_loc, old_locs) + SEND_SIGNAL(arrived, COMSIG_ATOM_ENTERING, src, old_loc, old_locs) + +/** + * An atom is attempting to exit this atom's contents + * + * Default behaviour is to send the [COMSIG_ATOM_EXIT] + */ +/atom/Exit(atom/movable/leaving, direction) + // Don't call `..()` here, otherwise `Uncross()` gets called. + // See the doc comment on `Uncross()` to learn why this is bad. + + if(SEND_SIGNAL(src, COMSIG_ATOM_EXIT, leaving, direction) & COMPONENT_ATOM_BLOCK_EXIT) + return FALSE + + return TRUE + +/** + * An atom has exited this atom's contents + * + * Default behaviour is to send the [COMSIG_ATOM_EXITED] + */ +/atom/Exited(atom/movable/gone, direction) + SEND_SIGNAL(src, COMSIG_ATOM_EXITED, gone, direction) + +///Return atom temperature +/atom/proc/return_temperature() + return + +/atom/proc/process_recipes(mob/living/user, obj/item/processed_object, list/processing_recipes) + //Only one recipe? use the first + if(processing_recipes.len == 1) + StartProcessingAtom(user, processed_object, processing_recipes[1]) + return + //Otherwise, select one with a radial + ShowProcessingGui(user, processed_object, processing_recipes) + +///Creates the radial and processes the selected option +/atom/proc/ShowProcessingGui(mob/living/user, obj/item/processed_object, list/possible_options) + var/list/choices_to_options = list() //Dict of object name | dict of object processing settings + var/list/choices = list() + + for(var/list/current_option as anything in possible_options) + var/atom/current_option_type = current_option[TOOL_PROCESSING_RESULT] + choices_to_options[initial(current_option_type.name)] = current_option + var/image/option_image = image(icon = initial(current_option_type.icon), icon_state = initial(current_option_type.icon_state)) + choices += list("[initial(current_option_type.name)]" = option_image) + + var/pick = show_radial_menu(user, src, choices, radius = 36, require_near = TRUE) + if(!pick) + return + + StartProcessingAtom(user, processed_object, choices_to_options[pick]) + + +/atom/proc/StartProcessingAtom(mob/living/user, obj/item/process_item, list/chosen_option) + var/processing_time = chosen_option[TOOL_PROCESSING_TIME] + to_chat(user, span_notice("You start working on [src].")) + if(process_item.use_tool(src, user, processing_time, volume=50)) + var/atom/atom_to_create = chosen_option[TOOL_PROCESSING_RESULT] + var/list/atom/created_atoms = list() + var/amount_to_create = chosen_option[TOOL_PROCESSING_AMOUNT] + for(var/i = 1 to amount_to_create) + var/atom/created_atom = new atom_to_create(drop_location()) + if(custom_materials) + created_atom.set_custom_materials(custom_materials, 1 / amount_to_create) + created_atom.pixel_x = pixel_x + created_atom.pixel_y = pixel_y + if(i > 1) + created_atom.pixel_x += rand(-8,8) + created_atom.pixel_y += rand(-8,8) + created_atom.OnCreatedFromProcessing(user, process_item, chosen_option, src) + created_atoms.Add(created_atom) + to_chat(user, span_notice("You manage to create [amount_to_create] [initial(atom_to_create.gender) == PLURAL ? "[initial(atom_to_create.name)]" : "[initial(atom_to_create.name)][plural_s(initial(atom_to_create.name))]"] from [src].")) + SEND_SIGNAL(src, COMSIG_ATOM_PROCESSED, user, process_item, created_atoms) + UsedforProcessing(user, process_item, chosen_option) + return + +/atom/proc/UsedforProcessing(mob/living/user, obj/item/used_item, list/chosen_option) + qdel(src) + return + +/atom/proc/OnCreatedFromProcessing(mob/living/user, obj/item/work_tool, list/chosen_option, atom/original_atom) + SHOULD_CALL_PARENT(TRUE) + + SEND_SIGNAL(src, COMSIG_ATOM_CREATEDBY_PROCESSING, original_atom, chosen_option) + if(user.mind) + ADD_TRAIT(src, TRAIT_FOOD_CHEF_MADE, REF(user.mind)) + +///Connect this atom to a shuttle +/atom/proc/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock) + return + +/atom/proc/intercept_zImpact(list/falling_movables, levels = 1) + SHOULD_CALL_PARENT(TRUE) + . |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, falling_movables, levels) + +///Setter for the `density` variable to append behavior related to its changing. +/atom/proc/set_density(new_value) + SHOULD_CALL_PARENT(TRUE) + if(density == new_value) + return + . = density + density = new_value + + +///Setter for the `base_pixel_x` variable to append behavior related to its changing. +/atom/proc/set_base_pixel_x(new_value) + if(base_pixel_x == new_value) + return + . = base_pixel_x + base_pixel_x = new_value + + pixel_x = pixel_x + base_pixel_x - . + + +///Setter for the `base_pixel_y` variable to append behavior related to its changing. +/atom/proc/set_base_pixel_y(new_value) + if(base_pixel_y == new_value) + return + . = base_pixel_y + base_pixel_y = new_value + + pixel_y = pixel_y + base_pixel_y - . + +// Not a valid operation, turfs and movables handle block differently +/atom/proc/set_explosion_block(explosion_block) + return + +/** + * Returns true if this atom has gravity for the passed in turf + * + * Sends signals [COMSIG_ATOM_HAS_GRAVITY] and [COMSIG_TURF_HAS_GRAVITY], both can force gravity with + * the forced gravity var. + * + * micro-optimized to hell because this proc is very hot, being called several times per movement every movement. + * + * HEY JACKASS, LISTEN + * IF YOU ADD SOMETHING TO THIS PROC, MAKE SURE /mob/living ACCOUNTS FOR IT + * Living mobs treat gravity in an event based manner. We've decomposed this proc into different checks + * for them to use. If you add more to it, make sure you do that, or things will behave strangely + * + * Gravity situations: + * * No gravity if you're not in a turf + * * No gravity if this atom is in is a space turf + * * Gravity if the area it's in always has gravity + * * Gravity if there's a gravity generator on the z level + * * Gravity if the Z level has an SSMappingTrait for ZTRAIT_GRAVITY + * * otherwise no gravity + */ +/atom/proc/has_gravity(turf/gravity_turf) + if(!isturf(gravity_turf)) + gravity_turf = get_turf(src) + + if(!gravity_turf)//no gravity in nullspace + return FALSE + + var/list/forced_gravity = list() + SEND_SIGNAL(src, COMSIG_ATOM_HAS_GRAVITY, gravity_turf, forced_gravity) + SEND_SIGNAL(gravity_turf, COMSIG_TURF_HAS_GRAVITY, src, forced_gravity) + if(length(forced_gravity)) + var/positive_grav = max(forced_gravity) + var/negative_grav = min(min(forced_gravity), 0) //negative grav needs to be below or equal to 0 + + //our gravity is sum of the most massive positive and negative numbers returned by the signal + //so that adding two forced_gravity elements with an effect size of 1 each doesnt add to 2 gravity + //but negative force gravity effects can cancel out positive ones + + return (positive_grav + negative_grav) + + var/area/turf_area = gravity_turf.loc + + return !gravity_turf.force_no_gravity && (SSmapping.gravity_by_z_level[gravity_turf.z] || turf_area.has_gravity) + +/** + * Used to set something as 'open' if it's being used as a supplypod + * + * Override this if you want an atom to be usable as a supplypod. + */ +/atom/proc/setOpened() + return + +/** + * Used to set something as 'closed' if it's being used as a supplypod + * + * Override this if you want an atom to be usable as a supplypod. + */ +/atom/proc/setClosed() + return + +/** + * Used to attempt to charge an object with a payment component. + * + * Use this if an atom needs to attempt to charge another atom. + */ +/atom/proc/attempt_charge(atom/sender, atom/target, extra_fees = 0) + return SEND_SIGNAL(sender, COMSIG_OBJ_ATTEMPT_CHARGE, target, extra_fees) + +///Passes Stat Browser Panel clicks to the game and calls client click on an atom +/atom/Topic(href, list/href_list) + . = ..() + if(!usr?.client) + return + var/client/usr_client = usr.client + var/list/paramslist = list() + + if(href_list["statpanel_item_click"]) + switch(href_list["statpanel_item_click"]) + if("left") + paramslist[LEFT_CLICK] = "1" + if("right") + paramslist[RIGHT_CLICK] = "1" + if("middle") + paramslist[MIDDLE_CLICK] = "1" + else + return + + if(href_list["statpanel_item_shiftclick"]) + paramslist[SHIFT_CLICK] = "1" + if(href_list["statpanel_item_ctrlclick"]) + paramslist[CTRL_CLICK] = "1" + if(href_list["statpanel_item_altclick"]) + paramslist[ALT_CLICK] = "1" + + var/mouseparams = list2params(paramslist) + usr_client.Click(src, loc, null, mouseparams) + return TRUE + +/atom/MouseEntered(location, control, params) + SSmouse_entered.hovers[usr.client] = src + +/// Fired whenever this atom is the most recent to be hovered over in the tick. +/// Preferred over MouseEntered if you do not need information such as the position of the mouse. +/// Especially because this is deferred over a tick, do not trust that `client` is not null. +/atom/proc/on_mouse_enter(client/client) + SHOULD_NOT_SLEEP(TRUE) + + var/mob/user = client?.mob + if (isnull(user)) + return + + // Screentips + var/datum/hud/active_hud = user.hud_used + if(!active_hud) + return + + var/screentips_enabled = active_hud.screentips_enabled + if(screentips_enabled == SCREENTIP_PREFERENCE_DISABLED || flags_1 & NO_SCREENTIPS_1) + active_hud.screentip_text.maptext = "" + return + + active_hud.screentip_text.maptext_y = 10 // 10px lines us up with the action buttons top left corner + var/lmb_rmb_line = "" + var/ctrl_lmb_ctrl_rmb_line = "" + var/alt_lmb_alt_rmb_line = "" + var/shift_lmb_ctrl_shift_lmb_line = "" + var/extra_lines = 0 + var/extra_context = "" + + if (isliving(user) || isovermind(user) || isaicamera(user)) + var/obj/item/held_item = user.get_active_held_item() + + if (flags_1 & HAS_CONTEXTUAL_SCREENTIPS_1 || held_item?.item_flags & ITEM_HAS_CONTEXTUAL_SCREENTIPS) + var/list/context = list() + + var/contextual_screentip_returns = \ + SEND_SIGNAL(src, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, context, held_item, user) \ + | (held_item && SEND_SIGNAL(held_item, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET, context, src, user)) + + if (contextual_screentip_returns & CONTEXTUAL_SCREENTIP_SET) + var/screentip_images = active_hud.screentip_images + // LMB and RMB on one line... + var/lmb_text = build_context(context, SCREENTIP_CONTEXT_LMB, screentip_images) + var/rmb_text = build_context(context, SCREENTIP_CONTEXT_RMB, screentip_images) + + if (lmb_text != "") + lmb_rmb_line = lmb_text + if (rmb_text != "") + lmb_rmb_line += " | [rmb_text]" + else if (rmb_text != "") + lmb_rmb_line = rmb_text + + // Ctrl-LMB, Ctrl-RMB on one line... + if (lmb_rmb_line != "") + lmb_rmb_line += "
" + extra_lines++ + if (SCREENTIP_CONTEXT_CTRL_LMB in context) + ctrl_lmb_ctrl_rmb_line += build_context(context, SCREENTIP_CONTEXT_CTRL_LMB, screentip_images) + + if (SCREENTIP_CONTEXT_CTRL_RMB in context) + if (ctrl_lmb_ctrl_rmb_line != "") + ctrl_lmb_ctrl_rmb_line += " | " + ctrl_lmb_ctrl_rmb_line += build_context(context, SCREENTIP_CONTEXT_CTRL_RMB, screentip_images) + + // Alt-LMB, Alt-RMB on one line... + if (ctrl_lmb_ctrl_rmb_line != "") + ctrl_lmb_ctrl_rmb_line += "
" + extra_lines++ + if (SCREENTIP_CONTEXT_ALT_LMB in context) + alt_lmb_alt_rmb_line += build_context(context, SCREENTIP_CONTEXT_ALT_LMB, screentip_images) + if (SCREENTIP_CONTEXT_ALT_RMB in context) + if (alt_lmb_alt_rmb_line != "") + alt_lmb_alt_rmb_line += " | " + alt_lmb_alt_rmb_line += build_context(context, SCREENTIP_CONTEXT_ALT_RMB, screentip_images) + + // Shift-LMB, Ctrl-Shift-LMB on one line... + if (alt_lmb_alt_rmb_line != "") + alt_lmb_alt_rmb_line += "
" + extra_lines++ + if (SCREENTIP_CONTEXT_SHIFT_LMB in context) + shift_lmb_ctrl_shift_lmb_line += build_context(context, SCREENTIP_CONTEXT_SHIFT_LMB, screentip_images) + if (SCREENTIP_CONTEXT_CTRL_SHIFT_LMB in context) + if (shift_lmb_ctrl_shift_lmb_line != "") + shift_lmb_ctrl_shift_lmb_line += " | " + shift_lmb_ctrl_shift_lmb_line += build_context(context, SCREENTIP_CONTEXT_CTRL_SHIFT_LMB, screentip_images) + + if (shift_lmb_ctrl_shift_lmb_line != "") + extra_lines++ + + if(extra_lines) + extra_context = "
[lmb_rmb_line][ctrl_lmb_ctrl_rmb_line][alt_lmb_alt_rmb_line][shift_lmb_ctrl_shift_lmb_line]" + //first extra line pushes atom name line up 11px, subsequent lines push it up 9px, this offsets that and keeps the first line in the same place + active_hud.screentip_text.maptext_y = -1 + (extra_lines - 1) * -9 + + if (screentips_enabled == SCREENTIP_PREFERENCE_CONTEXT_ONLY && extra_context == "") + active_hud.screentip_text.maptext = "" + else + //We inline a MAPTEXT() here, because there's no good way to statically add to a string like this + active_hud.screentip_text.maptext = "[name][extra_context]" + +/** + * This proc is used for telling whether something can pass by this atom in a given direction, for use by the pathfinding system. + * + * Trying to generate one long path across the station will call this proc on every single object on every single tile that we're seeing if we can move through, likely + * multiple times per tile since we're likely checking if we can access said tile from multiple directions, so keep these as lightweight as possible. + * + * For turfs this will only be used if pathing_pass_method is TURF_PATHING_PASS_PROC + * + * Arguments: + * * to_dir - What direction we're trying to move in, relevant for things like directional windows that only block movement in certain directions + * * pass_info - Datum that stores info about the thing that's trying to pass us + * + * IMPORTANT NOTE: /turf/proc/LinkBlockedWithAccess assumes that overrides of CanAStarPass will always return true if density is FALSE + * If this is NOT you, ensure you edit your can_astar_pass variable. Check __DEFINES/path.dm + **/ +/atom/proc/CanAStarPass(to_dir, datum/can_pass_info/pass_info) + if(pass_info.pass_flags & pass_flags_self) + return TRUE + . = !density diff --git a/code/game/alternate_appearance.dm b/code/game/atom/alternate_appearance.dm similarity index 99% rename from code/game/alternate_appearance.dm rename to code/game/atom/alternate_appearance.dm index 9f3da121b1217..86732dd9ed452 100644 --- a/code/game/alternate_appearance.dm +++ b/code/game/atom/alternate_appearance.dm @@ -1,5 +1,8 @@ GLOBAL_LIST_EMPTY(active_alternate_appearances) +/atom + var/list/alternate_appearances + /atom/proc/remove_alt_appearance(key) if(alternate_appearances) for(var/K in alternate_appearances) diff --git a/code/game/atom/atom_act.dm b/code/game/atom/atom_act.dm new file mode 100644 index 0000000000000..4c4ec04d66766 --- /dev/null +++ b/code/game/atom/atom_act.dm @@ -0,0 +1,226 @@ +/* + * +++++++++++++++++++++++++++++++++++++++++ ABOUT THIS FILE +++++++++++++++++++++++++++++++++++++++++++++ + * Not everything here necessarily has the name pattern of [x]_act() + * This is a file for various atom procs that simply get called when something is happening to that atom. + * If you're adding something here, you likely want a signal and SHOULD_CALL_PARENT(TRUE) + * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + */ + +/** + * Respond to fire being used on our atom + * + * Default behaviour is to send [COMSIG_ATOM_FIRE_ACT] and return + */ +/atom/proc/fire_act(exposed_temperature, exposed_volume) + SEND_SIGNAL(src, COMSIG_ATOM_FIRE_ACT, exposed_temperature, exposed_volume) + return FALSE + +/** + * Sends [COMSIG_ATOM_EXTINGUISH] signal, which properly removes burning component if it is present. + * + * Default behaviour is to send [COMSIG_ATOM_ACID_ACT] and return + */ +/atom/proc/extinguish() + SHOULD_CALL_PARENT(TRUE) + return SEND_SIGNAL(src, COMSIG_ATOM_EXTINGUISH) + +/** + * React to being hit by an explosion + * + * Should be called through the [EX_ACT] wrapper macro. + * The wrapper takes care of the [COMSIG_ATOM_EX_ACT] signal. + * as well as calling [/atom/proc/contents_explosion]. + * + * Returns TRUE by default, and behavior should be implemented on children procs on a per-atom basis. Should only return FALSE if we resist the explosion for any reason. + * We assume that the default is TRUE because all atoms should be considered destructible in some manner unless they explicitly opt out (in our current framework). + * However, the return value itself doesn't have any external consumers, it's only so children procs can listen to the value from their parent procs (due to the nature of the [EX_ACT] macro). + * Thus, the return value only matters on overrides of this proc, and the only thing that truly matters is the code that is executed (applying damage, calling damage procs, etc.) + * + */ +/atom/proc/ex_act(severity, target) + set waitfor = FALSE + return TRUE + +/// Handle what happens when your contents are exploded by a bomb +/atom/proc/contents_explosion(severity, target) + return //For handling the effects of explosions on contents that would not normally be effected + +/** + * React to a hit by a blob objecd + * + * default behaviour is to send the [COMSIG_ATOM_BLOB_ACT] signal + */ +/atom/proc/blob_act(obj/structure/blob/attacking_blob) + var/blob_act_result = SEND_SIGNAL(src, COMSIG_ATOM_BLOB_ACT, attacking_blob) + if (blob_act_result & COMPONENT_CANCEL_BLOB_ACT) + return FALSE + return TRUE + +/** + * React to an EMP of the given severity + * + * Default behaviour is to send the [COMSIG_ATOM_PRE_EMP_ACT] and [COMSIG_ATOM_EMP_ACT] signal + * + * If the pre-signal does not return protection, and there are attached wires then we call + * [emp_pulse][/datum/wires/proc/emp_pulse] on the wires + * + * We then return the protection value + */ +/atom/proc/emp_act(severity) + var/protection = SEND_SIGNAL(src, COMSIG_ATOM_PRE_EMP_ACT, severity) + if(!(protection & EMP_PROTECT_WIRES) && istype(wires)) + wires.emp_pulse() + + SEND_SIGNAL(src, COMSIG_ATOM_EMP_ACT, severity, protection) + return protection // Pass the protection value collected here upwards + +/** + * React to a hit by a projectile object + * + * @params + * * hitting_projectile - projectile + * * def_zone - zone hit + * * piercing_hit - is this hit piercing or normal? + */ +/atom/proc/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit = FALSE) + SHOULD_CALL_PARENT(TRUE) + + var/sigreturn = SEND_SIGNAL(src, COMSIG_ATOM_PRE_BULLET_ACT, hitting_projectile, def_zone) + if(sigreturn & COMPONENT_BULLET_PIERCED) + return BULLET_ACT_FORCE_PIERCE + if(sigreturn & COMPONENT_BULLET_BLOCKED) + return BULLET_ACT_BLOCK + if(sigreturn & COMPONENT_BULLET_ACTED) + return BULLET_ACT_HIT + + SEND_SIGNAL(src, COMSIG_ATOM_BULLET_ACT, hitting_projectile, def_zone) + if(QDELETED(hitting_projectile)) // Signal deleted it? + return BULLET_ACT_BLOCK + + return hitting_projectile.on_hit( + target = src, + // This armor check only matters for the visuals and messages in on_hit(), it's not actually used to reduce damage since + // only living mobs use armor to reduce damage, but on_hit() is going to need the value no matter what is shot. + blocked = check_projectile_armor(def_zone, hitting_projectile), + pierce_hit = piercing_hit, + ) + +/** + * React to being hit by a thrown object + * + * Default behaviour is to call [hitby_react][/atom/proc/hitby_react] on ourselves after 2 seconds if we are dense + * and under normal gravity. + * + * Im not sure why this the case, maybe to prevent lots of hitby's if the thrown object is + * deleted shortly after hitting something (during explosions or other massive events that + * throw lots of items around - singularity being a notable example) + */ +/atom/proc/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) + SEND_SIGNAL(src, COMSIG_ATOM_HITBY, hitting_atom, skipcatch, hitpush, blocked, throwingdatum) + if(density && !has_gravity(hitting_atom)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...). + addtimer(CALLBACK(src, PROC_REF(hitby_react), hitting_atom), 2) + +/** + * We have have actually hit the passed in atom + * + * Default behaviour is to move back from the item that hit us + */ +/atom/proc/hitby_react(atom/movable/harmed_atom) + if(harmed_atom && isturf(harmed_atom.loc)) + step(harmed_atom, REVERSE_DIR(harmed_atom.dir)) + +///Handle the atom being slipped over +/atom/proc/handle_slip(mob/living/carbon/slipped_carbon, knockdown_amount, obj/slipping_object, lube, paralyze, force_drop) + return + +///Used for making a sound when a mob involuntarily falls into the ground. +/atom/proc/handle_fall(mob/faller) + return + +///Respond to the singularity eating this atom +/atom/proc/singularity_act() + return + +/** + * Respond to the singularity pulling on us + * + * Default behaviour is to send [COMSIG_ATOM_SING_PULL] and return + */ +/atom/proc/singularity_pull(obj/singularity/singularity, current_size) + SEND_SIGNAL(src, COMSIG_ATOM_SING_PULL, singularity, current_size) + +/** + * Respond to acid being used on our atom + * + * Default behaviour is to send [COMSIG_ATOM_ACID_ACT] and return + */ +/atom/proc/acid_act(acidpwr, acid_volume) + SEND_SIGNAL(src, COMSIG_ATOM_ACID_ACT, acidpwr, acid_volume) + return FALSE + +/** + * Respond to an emag being used on our atom + * + * Args: + * * mob/user: The mob that used the emag. Nullable. + * * obj/item/card/emag/emag_card: The emag that was used. Nullable. + * + * Returns: + * TRUE if the emag had any effect, falsey otherwise. + */ +/atom/proc/emag_act(mob/user, obj/item/card/emag/emag_card) + return (SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT, user, emag_card)) + +/** + * Respond to narsie eating our atom + * + * Default behaviour is to send [COMSIG_ATOM_NARSIE_ACT] and return + */ +/atom/proc/narsie_act() + SEND_SIGNAL(src, COMSIG_ATOM_NARSIE_ACT) + +/** + * Respond to an electric bolt action on our item + * + * Default behaviour is to return, we define here to allow for cleaner code later on + */ +/atom/proc/zap_act(power, zap_flags) + return + +/** + * Called when the atom log's in or out + * + * Default behaviour is to call on_log on the location this atom is in + */ +/atom/proc/on_log(login) + if(loc) + loc.on_log(login) + +/** + * Causes effects when the atom gets hit by a rust effect from heretics + * + * Override this if you want custom behaviour in whatever gets hit by the rust + */ +/atom/proc/rust_heretic_act() + return + +///Called when something resists while this atom is its loc +/atom/proc/container_resist_act(mob/living/user) + return + +/** + * Respond to an RCD acting on our item + * + * Default behaviour is to send [COMSIG_ATOM_RCD_ACT] and return FALSE + */ +/atom/proc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, list/rcd_data) + SEND_SIGNAL(src, COMSIG_ATOM_RCD_ACT, user, the_rcd, rcd_data["[RCD_DESIGN_MODE]"]) + return FALSE + +///Return the values you get when an RCD eats you? +/atom/proc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + return FALSE + +///This atom has been hit by a hulkified mob in hulk mode (user) +/atom/proc/attack_hulk(mob/living/carbon/human/user) + SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user) diff --git a/code/game/atom/atom_appearance.dm b/code/game/atom/atom_appearance.dm new file mode 100644 index 0000000000000..d3e0a64d69cbb --- /dev/null +++ b/code/game/atom/atom_appearance.dm @@ -0,0 +1,112 @@ +/atom + ///overlays managed by [update_overlays][/atom/proc/update_overlays] to prevent removing overlays that weren't added by the same proc. Single items are stored on their own, not in a list. + var/list/managed_overlays + +/** + * Updates the appearence of the icon + * + * Mostly delegates to update_name, update_desc, and update_icon + * + * Arguments: + * - updates: A set of bitflags dictating what should be updated. Defaults to [ALL] + */ +/atom/proc/update_appearance(updates=ALL) + SHOULD_NOT_SLEEP(TRUE) + SHOULD_CALL_PARENT(TRUE) + + . = NONE + updates &= ~SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_APPEARANCE, updates) + if(updates & UPDATE_NAME) + . |= update_name(updates) + if(updates & UPDATE_DESC) + . |= update_desc(updates) + if(updates & UPDATE_ICON) + . |= update_icon(updates) + +/// Updates the name of the atom +/atom/proc/update_name(updates=ALL) + SHOULD_CALL_PARENT(TRUE) + return SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_NAME, updates) + +/// Updates the description of the atom +/atom/proc/update_desc(updates=ALL) + SHOULD_CALL_PARENT(TRUE) + return SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_DESC, updates) + +/// Updates the icon of the atom +/atom/proc/update_icon(updates=ALL) + SHOULD_CALL_PARENT(TRUE) + + . = NONE + updates &= ~SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON, updates) + if(updates & UPDATE_ICON_STATE) + update_icon_state() + . |= UPDATE_ICON_STATE + + if(updates & UPDATE_OVERLAYS) + if(LAZYLEN(managed_vis_overlays)) + SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) + + var/list/new_overlays = update_overlays(updates) + var/nulls = 0 + for(var/i in 1 to length(new_overlays)) + var/atom/maybe_not_an_atom = new_overlays[i] + if(isnull(maybe_not_an_atom)) + nulls++ + continue + if(istext(maybe_not_an_atom) || isicon(maybe_not_an_atom)) + continue + new_overlays[i] = maybe_not_an_atom.appearance + if(nulls) + for(var/i in 1 to nulls) + new_overlays -= null + + var/identical = FALSE + var/new_length = length(new_overlays) + if(!managed_overlays && !new_length) + identical = TRUE + else if(!islist(managed_overlays)) + if(new_length == 1 && managed_overlays == new_overlays[1]) + identical = TRUE + else if(length(managed_overlays) == new_length) + identical = TRUE + for(var/i in 1 to length(managed_overlays)) + if(managed_overlays[i] != new_overlays[i]) + identical = FALSE + break + + if(!identical) + var/full_control = FALSE + if(managed_overlays) + full_control = length(overlays) == (islist(managed_overlays) ? length(managed_overlays) : 1) + if(full_control) + overlays = null + else + cut_overlay(managed_overlays) + + switch(length(new_overlays)) + if(0) + if(full_control) + POST_OVERLAY_CHANGE(src) + managed_overlays = null + if(1) + add_overlay(new_overlays) + managed_overlays = new_overlays[1] + else + add_overlay(new_overlays) + managed_overlays = new_overlays + + . |= UPDATE_OVERLAYS + + . |= SEND_SIGNAL(src, COMSIG_ATOM_UPDATED_ICON, updates, .) + +/// Updates the icon state of the atom +/atom/proc/update_icon_state() + SHOULD_CALL_PARENT(TRUE) + return SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON_STATE) + +/// Updates the overlays of the atom +/atom/proc/update_overlays() + SHOULD_CALL_PARENT(TRUE) + . = list() + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_OVERLAYS, .) diff --git a/code/game/atom/atom_color.dm b/code/game/atom/atom_color.dm new file mode 100644 index 0000000000000..e5b52460aa04d --- /dev/null +++ b/code/game/atom/atom_color.dm @@ -0,0 +1,71 @@ +/* + Atom Colour Priority System + A System that gives finer control over which atom colour to colour the atom with. + The "highest priority" one is always displayed as opposed to the default of + "whichever was set last is displayed" +*/ + +/atom + /** + * used to store the different colors on an atom + * + * its inherent color, the colored paint applied on it, special color effect etc... + */ + var/list/atom_colours + +///Adds an instance of colour_type to the atom's atom_colours list +/atom/proc/add_atom_colour(coloration, colour_priority) + if(!atom_colours || !atom_colours.len) + atom_colours = list() + atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently. + if(!coloration) + return + if(colour_priority > atom_colours.len) + return + atom_colours[colour_priority] = coloration + update_atom_colour() + + +///Removes an instance of colour_type from the atom's atom_colours list +/atom/proc/remove_atom_colour(colour_priority, coloration) + if(!atom_colours) + return + if(colour_priority > atom_colours.len) + return + if(coloration && atom_colours[colour_priority] != coloration) + return //if we don't have the expected color (for a specific priority) to remove, do nothing + atom_colours[colour_priority] = null + update_atom_colour() + +/** + * Checks if this atom has the passed color + * Can optionally be supplied with a range of priorities, IE only checking "washable" or above + */ +/atom/proc/is_atom_colour(looking_for_color, min_priority_index = 1, max_priority_index = COLOUR_PRIORITY_AMOUNT) + // make sure uppertext hex strings don't mess with lowertext hex strings + looking_for_color = lowertext(looking_for_color) + + if(!LAZYLEN(atom_colours)) + // no atom colors list has been set up, just check the color var + return lowertext(color) == looking_for_color + + for(var/i in min_priority_index to max_priority_index) + if(lowertext(atom_colours[i]) == looking_for_color) + return TRUE + + return FALSE + +///Resets the atom's color to null, and then sets it to the highest priority colour available +/atom/proc/update_atom_colour() + color = null + if(!atom_colours) + return + for(var/checked_color in atom_colours) + if(islist(checked_color)) + var/list/color_list = checked_color + if(color_list.len) + color = color_list + return + else if(checked_color) + color = checked_color + return diff --git a/code/game/atom_defense.dm b/code/game/atom/atom_defense.dm similarity index 86% rename from code/game/atom_defense.dm rename to code/game/atom/atom_defense.dm index df7ad78b81cc4..0541915a38c93 100644 --- a/code/game/atom_defense.dm +++ b/code/game/atom/atom_defense.dm @@ -1,3 +1,17 @@ +/atom + ///any atom that uses integrity and can be damaged must set this to true, otherwise the integrity procs will throw an error + var/uses_integrity = FALSE + + VAR_PROTECTED/datum/armor/armor_type = /datum/armor/none + VAR_PRIVATE/datum/armor/armor + + VAR_PRIVATE/atom_integrity //defaults to max_integrity + var/max_integrity = 500 + var/integrity_failure = 0 //0 if we have no special broken behavior, otherwise is a percentage of at what point the atom breaks. 0.5 being 50% + ///Damage under this value will be completely ignored + var/damage_deflection = 0 + + var/resistance_flags = NONE // INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ON_FIRE | UNACIDABLE | ACID_PROOF /// The essential proc to call when an atom must receive damage of any kind. /atom/proc/take_damage(damage_amount, damage_type = BRUTE, damage_flag = "", sound_effect = TRUE, attack_dir, armour_penetration = 0) @@ -19,14 +33,18 @@ . = damage_amount + var/previous_atom_integrity = atom_integrity + update_integrity(atom_integrity - damage_amount) + var/integrity_failure_amount = integrity_failure * max_integrity + //BREAKING FIRST - if(integrity_failure && atom_integrity <= integrity_failure * max_integrity) + if(integrity_failure && previous_atom_integrity > integrity_failure_amount && atom_integrity <= integrity_failure_amount) atom_break(damage_flag) //DESTROYING SECOND - if(atom_integrity <= 0) + if(atom_integrity <= 0 && previous_atom_integrity > 0) atom_destruction(damage_flag) /// Proc for recovering atom_integrity. Returns the amount repaired by diff --git a/code/game/atom/atom_examine.dm b/code/game/atom/atom_examine.dm new file mode 100644 index 0000000000000..e7664b81efc13 --- /dev/null +++ b/code/game/atom/atom_examine.dm @@ -0,0 +1,102 @@ +/atom + ///If non-null, overrides a/an/some in all cases + var/article + +/** + * Called when a mob examines (shift click or verb) this atom + * + * Default behaviour is to get the name and icon of the object and it's reagents where + * the [TRANSPARENT] flag is set on the reagents holder + * + * Produces a signal [COMSIG_ATOM_EXAMINE] + */ +/atom/proc/examine(mob/user) + var/examine_string = get_examine_string(user, thats = TRUE) + if(examine_string) + . = list("[examine_string].") + else + . = list() + + . += get_name_chaser(user) + if(desc) + . += desc + + if(custom_materials) + var/list/materials_list = list() + for(var/custom_material in custom_materials) + var/datum/material/current_material = GET_MATERIAL_REF(custom_material) + materials_list += "[current_material.name]" + . += "It is made out of [english_list(materials_list)]." + + if(reagents) + var/user_sees_reagents = user.can_see_reagents() + var/reagent_sigreturn = SEND_SIGNAL(src, COMSIG_ATOM_REAGENT_EXAMINE, user, ., user_sees_reagents) + if(!(reagent_sigreturn & STOP_GENERIC_REAGENT_EXAMINE)) + if(reagents.flags & TRANSPARENT) + if(reagents.total_volume) + . += "It contains [reagents.total_volume] units of various reagents[user_sees_reagents ? ":" : "."]" + if(user_sees_reagents) //Show each individual reagent for detailed examination + for(var/datum/reagent/current_reagent as anything in reagents.reagent_list) + . += "• [round(current_reagent.volume, CHEMICAL_VOLUME_ROUNDING)] units of [current_reagent.name]" + if(reagents.is_reacting) + . += span_warning("It is currently reacting!") + . += span_notice("The solution's pH is [round(reagents.ph, 0.01)] and has a temperature of [reagents.chem_temp]K.") + + else + . += "It contains:
Nothing." + else if(reagents.flags & AMOUNT_VISIBLE) + if(reagents.total_volume) + . += span_notice("It has [reagents.total_volume] unit\s left.") + else + . += span_danger("It's empty.") + + SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE, user, .) + +/** + * Called when a mob examines (shift click or verb) this atom twice (or more) within EXAMINE_MORE_WINDOW (default 1 second) + * + * This is where you can put extra information on something that may be superfluous or not important in critical gameplay + * moments, while allowing people to manually double-examine to take a closer look + * + * Produces a signal [COMSIG_ATOM_EXAMINE_MORE] + */ +/atom/proc/examine_more(mob/user) + SHOULD_CALL_PARENT(TRUE) + RETURN_TYPE(/list) + + . = list() + SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE_MORE, user, .) + SEND_SIGNAL(user, COMSIG_MOB_EXAMINING_MORE, src, .) + +/** + * Get the name of this object for examine + * + * You can override what is returned from this proc by registering to listen for the + * [COMSIG_ATOM_GET_EXAMINE_NAME] signal + */ +/atom/proc/get_examine_name(mob/user) + . = "\a [src]" + var/list/override = list(gender == PLURAL ? "some" : "a", " ", "[name]") + if(article) + . = "[article] [src]" + override[EXAMINE_POSITION_ARTICLE] = article + if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED) + . = override.Join("") + +///Generate the full examine string of this atom (including icon for goonchat) +/atom/proc/get_examine_string(mob/user, thats = FALSE) + return "[icon2html(src, user)] [thats? "That's ":""][get_examine_name(user)]" + +/** + * Returns an extended list of examine strings for any contained ID cards. + * + * Arguments: + * * user - The user who is doing the examining. + */ +/atom/proc/get_id_examine_strings(mob/user) + . = list() + return + +///Used to insert text after the name but before the description in examine() +/atom/proc/get_name_chaser(mob/user, list/name_chaser = list()) + return name_chaser diff --git a/code/game/atom/atom_greyscale.dm b/code/game/atom/atom_greyscale.dm new file mode 100644 index 0000000000000..51d24b8528bb8 --- /dev/null +++ b/code/game/atom/atom_greyscale.dm @@ -0,0 +1,30 @@ +/atom + ///The config type to use for greyscaled sprites. Both this and greyscale_colors must be assigned to work. + var/greyscale_config + ///A string of hex format colors to be used by greyscale sprites, ex: "#0054aa#badcff" + var/greyscale_colors + +/// Handles updates to greyscale value updates. +/// The colors argument can be either a list or the full color string. +/// Child procs should call parent last so the update happens after all changes. +/atom/proc/set_greyscale(list/colors, new_config) + SHOULD_CALL_PARENT(TRUE) + if(istype(colors)) + colors = colors.Join("") + if(!isnull(colors) && greyscale_colors != colors) // If you want to disable greyscale stuff then give a blank string + greyscale_colors = colors + + if(!isnull(new_config) && greyscale_config != new_config) + greyscale_config = new_config + + update_greyscale() + +/// Checks if this atom uses the GAGS system and if so updates the icon +/atom/proc/update_greyscale() + SHOULD_CALL_PARENT(TRUE) + if(greyscale_colors && greyscale_config) + icon = SSgreyscale.GetColoredIconByType(greyscale_config, greyscale_colors) + if(!smoothing_flags) // This is a bitfield but we're just checking that some sort of smoothing is happening + return + update_atom_colour() + QUEUE_SMOOTH(src) diff --git a/code/game/atom/atom_invisibility.dm b/code/game/atom/atom_invisibility.dm new file mode 100644 index 0000000000000..53fbe895817cf --- /dev/null +++ b/code/game/atom/atom_invisibility.dm @@ -0,0 +1,72 @@ +// Index defines +#define INVISIBILITY_VALUE 1 +#define INVISIBILITY_PRIORITY 2 + +/atom + VAR_PRIVATE/list/invisibility_sources + VAR_PRIVATE/current_invisibility_priority = -INFINITY + +/atom/proc/RecalculateInvisibility() + PRIVATE_PROC(TRUE) + + if(!invisibility_sources) + current_invisibility_priority = -INFINITY + invisibility = initial(invisibility) + return + + var/highest_priority + var/list/highest_priority_invisibility_data + for(var/entry in invisibility_sources) + var/list/priority_data + if(islist(entry)) + priority_data = entry + else + priority_data = invisibility_sources[entry] + + var/priority = priority_data[INVISIBILITY_PRIORITY] + if(highest_priority > priority) // In the case of equal priorities, we use the last thing in the list so that more recent changes apply first + continue + + highest_priority = priority + highest_priority_invisibility_data = priority_data + + current_invisibility_priority = highest_priority + invisibility = highest_priority_invisibility_data[INVISIBILITY_VALUE] + +/** + * Sets invisibility according to priority. + * If you want to be able to undo the value you set back to what it would be otherwise, + * you should provide an id here and remove it using RemoveInvisibility(id) + */ +/atom/proc/SetInvisibility(desired_value, id, priority=0) + if(!invisibility_sources) + invisibility_sources = list() + + if(id) + invisibility_sources[id] = list(desired_value, priority) + else + invisibility_sources += list(list(desired_value, priority)) + + if(current_invisibility_priority > priority) + return + + RecalculateInvisibility() + +/// Removes the specified invisibility source from the tracker +/atom/proc/RemoveInvisibility(id) + if(!invisibility_sources) + return + + var/list/priority_data = invisibility_sources[id] + invisibility_sources -= id + + if(length(invisibility_sources) == 0) + invisibility_sources = null + + if(current_invisibility_priority > priority_data[INVISIBILITY_PRIORITY]) + return + + RecalculateInvisibility() + +#undef INVISIBILITY_VALUE +#undef INVISIBILITY_PRIORITY diff --git a/code/game/atom/atom_materials.dm b/code/game/atom/atom_materials.dm new file mode 100644 index 0000000000000..ae9a5b3a18e37 --- /dev/null +++ b/code/game/atom/atom_materials.dm @@ -0,0 +1,128 @@ +/atom + ///The custom materials this atom is made of, used by a lot of things like furniture, walls, and floors (if I finish the functionality, that is.) + ///The list referenced by this var can be shared by multiple objects and should not be directly modified. Instead, use [set_custom_materials][/atom/proc/set_custom_materials]. + var/list/datum/material/custom_materials + ///Bitfield for how the atom handles materials. + var/material_flags = NONE + ///Modifier that raises/lowers the effect of the amount of a material, prevents small and easy to get items from being death machines. + var/material_modifier = 1 + +/// Sets the custom materials for an item. +/atom/proc/set_custom_materials(list/materials, multiplier = 1) + if(custom_materials && material_flags & MATERIAL_EFFECTS) //Only runs if custom materials existed at first and affected src. + for(var/current_material in custom_materials) + var/datum/material/custom_material = GET_MATERIAL_REF(current_material) + custom_material.on_removed(src, custom_materials[current_material] * material_modifier, material_flags) //Remove the current materials + + if(!length(materials)) + custom_materials = null + return + + if(material_flags & MATERIAL_EFFECTS) + for(var/current_material in materials) + var/datum/material/custom_material = GET_MATERIAL_REF(current_material) + custom_material.on_applied(src, materials[current_material] * multiplier * material_modifier, material_flags) + + custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials, multiplier) + +/** + * Returns the material composition of the atom. + * + * Used when recycling items, specifically to turn alloys back into their component mats. + * + * Exists because I'd need to add a way to un-alloy alloys or otherwise deal + * with people converting the entire stations material supply into alloys. + * + * Arguments: + * - flags: A set of flags determining how exactly the materials are broken down. + */ +/atom/proc/get_material_composition(breakdown_flags=NONE) + . = list() + if(!(breakdown_flags & BREAKDOWN_INCLUDE_ALCHEMY) && HAS_TRAIT(src, TRAIT_MAT_TRANSMUTED)) + return + + var/list/cached_materials = custom_materials + for(var/mat in cached_materials) + var/datum/material/material = GET_MATERIAL_REF(mat) + var/list/material_comp = material.return_composition(cached_materials[mat], breakdown_flags) + for(var/comp_mat in material_comp) + .[comp_mat] += material_comp[comp_mat] + +/** + * Fetches a list of all of the materials this object has of the desired type. Returns null if there is no valid materials of the type + * + * Arguments: + * - [required_material][/datum/material]: The type of material we are checking for + * - mat_amount: The minimum required amount of material + */ +/atom/proc/has_material_type(datum/material/required_material, mat_amount = 0) + var/list/cached_materials = custom_materials + if(!length(cached_materials)) + return null + + var/materials_of_type + for(var/current_material in cached_materials) + if(cached_materials[current_material] < mat_amount) + continue + var/datum/material/material = GET_MATERIAL_REF(current_material) + if(!istype(material, required_material)) + continue + LAZYSET(materials_of_type, material, cached_materials[current_material]) + + return materials_of_type + +/** + * Fetches a list of all of the materials this object has with the desired material category. + * + * Arguments: + * - category: The category to check for + * - any_flags: Any bitflags that must be present for the category + * - all_flags: All bitflags that must be present for the category + * - no_flags: Any bitflags that must not be present for the category + * - mat_amount: The minimum amount of materials that must be present + */ +/atom/proc/has_material_category(category, any_flags=0, all_flags=0, no_flags=0, mat_amount=0) + var/list/cached_materials = custom_materials + if(!length(cached_materials)) + return null + + var/materials_of_category + for(var/current_material in cached_materials) + if(cached_materials[current_material] < mat_amount) + continue + var/datum/material/material = GET_MATERIAL_REF(current_material) + var/category_flags = material?.categories[category] + if(isnull(category_flags)) + continue + if(any_flags && !(category_flags & any_flags)) + continue + if(all_flags && (all_flags != (category_flags & all_flags))) + continue + if(no_flags && (category_flags & no_flags)) + continue + LAZYSET(materials_of_category, material, cached_materials[current_material]) + return materials_of_category + +/** + * Gets the most common material in the object. + */ +/atom/proc/get_master_material() + var/list/cached_materials = custom_materials + if(!length(cached_materials)) + return null + + var/most_common_material = null + var/max_amount = 0 + for(var/material in cached_materials) + if(cached_materials[material] > max_amount) + most_common_material = material + max_amount = cached_materials[material] + + if(most_common_material) + return GET_MATERIAL_REF(most_common_material) + +/** + * Gets the total amount of materials in this atom. + */ +/atom/proc/get_custom_material_amount() + return isnull(custom_materials) ? 0 : counterlist_sum(custom_materials) diff --git a/code/game/atom/atom_merger.dm b/code/game/atom/atom_merger.dm new file mode 100644 index 0000000000000..1787d51675baf --- /dev/null +++ b/code/game/atom/atom_merger.dm @@ -0,0 +1,14 @@ +/atom + ///Holds merger groups currently active on the atom. Do not access directly, use GetMergeGroup() instead. + var/list/datum/merger/mergers + +/// Gets a merger datum representing the connected blob of objects in the allowed_types argument +/atom/proc/GetMergeGroup(id, list/allowed_types) + RETURN_TYPE(/datum/merger) + var/datum/merger/candidate + if(mergers) + candidate = mergers[id] + if(!candidate) + new /datum/merger(id, allowed_types, src) + candidate = mergers[id] + return candidate diff --git a/code/game/atom/atom_orbit.dm b/code/game/atom/atom_orbit.dm new file mode 100644 index 0000000000000..8eecddd952d48 --- /dev/null +++ b/code/game/atom/atom_orbit.dm @@ -0,0 +1,33 @@ +/atom + ///Reference to atom being orbited + var/atom/orbit_target + ///The orbiter component, if there's anything orbiting this atom + var/datum/component/orbiter/orbiters + +/** + * Recursive getter method to return a list of all ghosts orbitting this atom + * + * This will work fine without manually passing arguments. + * * processed - The list of atoms we've already convered + * * source - Is this the atom for who we're counting up all the orbiters? + * * ignored_stealthed_admins - If TRUE, don't count admins who are stealthmoded and orbiting this + */ +/atom/proc/get_all_orbiters(list/processed, source = TRUE, ignore_stealthed_admins = TRUE) + var/list/output = list() + if(!processed) + processed = list() + else if(src in processed) + return output + + if(!source) + output += src + + processed += src + for(var/atom/atom_orbiter as anything in orbiters?.orbiter_list) + output += atom_orbiter.get_all_orbiters(processed, source = FALSE) + return output + +/mob/get_all_orbiters(list/processed, source = TRUE, ignore_stealthed_admins = TRUE) + if(!source && ignore_stealthed_admins && client?.holder?.fakekey) + return list() + return ..() diff --git a/code/game/atom/atom_storage.dm b/code/game/atom/atom_storage.dm new file mode 100644 index 0000000000000..6273c28fc2e87 --- /dev/null +++ b/code/game/atom/atom_storage.dm @@ -0,0 +1,41 @@ +/atom + /// the datum handler for our contents - see create_storage() for creation method + var/datum/storage/atom_storage + +/// A quick and easy way to create a storage datum for an atom +/atom/proc/create_storage( + max_slots, + max_specific_storage, + max_total_storage, + numerical_stacking = FALSE, + allow_quick_gather = FALSE, + allow_quick_empty = FALSE, + collection_mode = COLLECT_ONE, + attack_hand_interact = TRUE, + list/canhold, + list/canthold, + storage_type = /datum/storage, +) + + if(atom_storage) + QDEL_NULL(atom_storage) + + atom_storage = new storage_type(src, max_slots, max_specific_storage, max_total_storage, numerical_stacking, allow_quick_gather, collection_mode, attack_hand_interact) + + if(canhold || canthold) + atom_storage.set_holdable(canhold, canthold) + + return atom_storage + +/// A quick and easy way to /clone/ a storage datum for an atom (does not copy over contents, only the datum details) +/atom/proc/clone_storage(datum/storage/cloning) + if(atom_storage) + QDEL_NULL(atom_storage) + + atom_storage = new cloning.type(src, cloning.max_slots, cloning.max_specific_storage, cloning.max_total_storage, cloning.numerical_stacking, cloning.allow_quick_gather, cloning.collection_mode, cloning.attack_hand_interact) + + if(cloning.can_hold || cloning.cant_hold) + if(!atom_storage.can_hold && !atom_storage.cant_hold) //In the event that the can/can't hold lists are already in place (such as from storage objects added on initialize). + atom_storage.set_holdable(cloning.can_hold, cloning.cant_hold) + + return atom_storage diff --git a/code/game/atom/atom_tool_acts.dm b/code/game/atom/atom_tool_acts.dm new file mode 100644 index 0000000000000..f6ce7eb96c7d2 --- /dev/null +++ b/code/game/atom/atom_tool_acts.dm @@ -0,0 +1,120 @@ +/** + *Tool behavior procedure. Redirects to tool-specific procs by default. + * + * You can override it to catch all tool interactions, for use in complex deconstruction procs. + * + * Must return parent proc ..() in the end if overridden + */ +/atom/proc/tool_act(mob/living/user, obj/item/tool, tool_type, is_right_clicking) + var/act_result + var/signal_result + + var/is_left_clicking = !is_right_clicking + + if(is_left_clicking) // Left click first for sensibility + var/list/processing_recipes = list() //List of recipes that can be mutated by sending the signal + signal_result = SEND_SIGNAL(src, COMSIG_ATOM_TOOL_ACT(tool_type), user, tool, processing_recipes) + if(signal_result & COMPONENT_BLOCK_TOOL_ATTACK) // The COMSIG_ATOM_TOOL_ACT signal is blocking the act + return TOOL_ACT_SIGNAL_BLOCKING + if(processing_recipes.len) + process_recipes(user, tool, processing_recipes) + if(QDELETED(tool)) + return TRUE + else + signal_result = SEND_SIGNAL(src, COMSIG_ATOM_SECONDARY_TOOL_ACT(tool_type), user, tool) + if(signal_result & COMPONENT_BLOCK_TOOL_ATTACK) // The COMSIG_ATOM_TOOL_ACT signal is blocking the act + return TOOL_ACT_SIGNAL_BLOCKING + + switch(tool_type) + if(TOOL_CROWBAR) + act_result = is_left_clicking ? crowbar_act(user, tool) : crowbar_act_secondary(user, tool) + if(TOOL_MULTITOOL) + act_result = is_left_clicking ? multitool_act(user, tool) : multitool_act_secondary(user, tool) + if(TOOL_SCREWDRIVER) + act_result = is_left_clicking ? screwdriver_act(user, tool) : screwdriver_act_secondary(user, tool) + if(TOOL_WRENCH) + act_result = is_left_clicking ? wrench_act(user, tool) : wrench_act_secondary(user, tool) + if(TOOL_WIRECUTTER) + act_result = is_left_clicking ? wirecutter_act(user, tool) : wirecutter_act_secondary(user, tool) + if(TOOL_WELDER) + act_result = is_left_clicking ? welder_act(user, tool) : welder_act_secondary(user, tool) + if(TOOL_ANALYZER) + act_result = is_left_clicking ? analyzer_act(user, tool) : analyzer_act_secondary(user, tool) + if(!act_result) + return + + // A tooltype_act has completed successfully + if(is_left_clicking) + log_tool("[key_name(user)] used [tool] on [src] at [AREACOORD(src)]") + SEND_SIGNAL(tool, COMSIG_TOOL_ATOM_ACTED_PRIMARY(tool_type), src) + else + log_tool("[key_name(user)] used [tool] on [src] (right click) at [AREACOORD(src)]") + SEND_SIGNAL(tool, COMSIG_TOOL_ATOM_ACTED_SECONDARY(tool_type), src) + return TOOL_ACT_TOOLTYPE_SUCCESS + +//! Tool-specific behavior procs. +/// + +/// Called on an object when a tool with crowbar capabilities is used to left click an object +/atom/proc/crowbar_act(mob/living/user, obj/item/tool) + return + +/// Called on an object when a tool with crowbar capabilities is used to right click an object +/atom/proc/crowbar_act_secondary(mob/living/user, obj/item/tool) + return + +/// Called on an object when a tool with multitool capabilities is used to left click an object +/atom/proc/multitool_act(mob/living/user, obj/item/tool) + return + +/// Called on an object when a tool with multitool capabilities is used to right click an object +/atom/proc/multitool_act_secondary(mob/living/user, obj/item/tool) + return + +///Check if an item supports a data buffer (is a multitool) +/atom/proc/multitool_check_buffer(user, obj/item/multitool, silent = FALSE) + if(!istype(multitool, /obj/item/multitool)) + if(user && !silent) + to_chat(user, span_warning("[multitool] has no data buffer!")) + return FALSE + return TRUE + +/// Called on an object when a tool with screwdriver capabilities is used to left click an object +/atom/proc/screwdriver_act(mob/living/user, obj/item/tool) + return + +/// Called on an object when a tool with screwdriver capabilities is used to right click an object +/atom/proc/screwdriver_act_secondary(mob/living/user, obj/item/tool) + return + +/// Called on an object when a tool with wrench capabilities is used to left click an object +/atom/proc/wrench_act(mob/living/user, obj/item/tool) + return + +/// Called on an object when a tool with wrench capabilities is used to right click an object +/atom/proc/wrench_act_secondary(mob/living/user, obj/item/tool) + return + +/// Called on an object when a tool with wirecutter capabilities is used to left click an object +/atom/proc/wirecutter_act(mob/living/user, obj/item/tool) + return + +/// Called on an object when a tool with wirecutter capabilities is used to right click an object +/atom/proc/wirecutter_act_secondary(mob/living/user, obj/item/tool) + return + +/// Called on an object when a tool with welder capabilities is used to left click an object +/atom/proc/welder_act(mob/living/user, obj/item/tool) + return + +/// Called on an object when a tool with welder capabilities is used to right click an object +/atom/proc/welder_act_secondary(mob/living/user, obj/item/tool) + return + +/// Called on an object when a tool with analyzer capabilities is used to left click an object +/atom/proc/analyzer_act(mob/living/user, obj/item/tool) + return + +/// Called on an object when a tool with analyzer capabilities is used to right click an object +/atom/proc/analyzer_act_secondary(mob/living/user, obj/item/tool) + return diff --git a/code/game/atom/atom_vv.dm b/code/game/atom/atom_vv.dm new file mode 100644 index 0000000000000..8393ecabcfd51 --- /dev/null +++ b/code/game/atom/atom_vv.dm @@ -0,0 +1,271 @@ +/** + * Return the markup to for the dropdown list for the VV panel for this atom + * + * Override in subtypes to add custom VV handling in the VV panel + */ +/atom/vv_get_dropdown() + . = ..() + VV_DROPDOWN_OPTION("", "---------") + if(!ismovable(src)) + var/turf/curturf = get_turf(src) + if(curturf) + . += "" + VV_DROPDOWN_OPTION(VV_HK_MODIFY_TRANSFORM, "Modify Transform") + VV_DROPDOWN_OPTION(VV_HK_SPIN_ANIMATION, "SpinAnimation") + VV_DROPDOWN_OPTION(VV_HK_STOP_ALL_ANIMATIONS, "Stop All Animations") + VV_DROPDOWN_OPTION(VV_HK_SHOW_HIDDENPRINTS, "Show Hiddenprint log") + VV_DROPDOWN_OPTION(VV_HK_ADD_REAGENT, "Add Reagent") + VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EMP, "EMP Pulse") + VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EXPLOSION, "Explosion") + VV_DROPDOWN_OPTION(VV_HK_EDIT_FILTERS, "Edit Filters") + VV_DROPDOWN_OPTION(VV_HK_EDIT_COLOR_MATRIX, "Edit Color as Matrix") + VV_DROPDOWN_OPTION(VV_HK_TEST_MATRIXES, "Test Matrices") + VV_DROPDOWN_OPTION(VV_HK_ADD_AI, "Add AI controller") + VV_DROPDOWN_OPTION(VV_HK_ARMOR_MOD, "Modify Armor") + if(greyscale_colors) + VV_DROPDOWN_OPTION(VV_HK_MODIFY_GREYSCALE, "Modify greyscale colors") + +/atom/vv_do_topic(list/href_list) + . = ..() + if(href_list[VV_HK_ADD_REAGENT] && check_rights(R_VAREDIT)) + if(!reagents) + var/amount = input(usr, "Specify the reagent size of [src]", "Set Reagent Size", 50) as num|null + if(amount) + create_reagents(amount) + + if(reagents) + var/chosen_id + switch(tgui_alert(usr, "Choose a method.", "Add Reagents", list("Search", "Choose from a list", "I'm feeling lucky"))) + if("Search") + var/valid_id + while(!valid_id) + chosen_id = input(usr, "Enter the ID of the reagent you want to add.", "Search reagents") as null|text + if(isnull(chosen_id)) //Get me out of here! + break + if (!ispath(text2path(chosen_id))) + chosen_id = pick_closest_path(chosen_id, make_types_fancy(subtypesof(/datum/reagent))) + if (ispath(chosen_id)) + valid_id = TRUE + else + valid_id = TRUE + if(!valid_id) + to_chat(usr, span_warning("A reagent with that ID doesn't exist!")) + if("Choose from a list") + chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in sort_list(subtypesof(/datum/reagent), GLOBAL_PROC_REF(cmp_typepaths_asc)) + if("I'm feeling lucky") + chosen_id = pick(subtypesof(/datum/reagent)) + if(chosen_id) + var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", reagents.maximum_volume) as num|null + if(amount) + reagents.add_reagent(chosen_id, amount) + log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to [src]") + message_admins(span_notice("[key_name(usr)] has added [amount] units of [chosen_id] to [src]")) + + if(href_list[VV_HK_TRIGGER_EXPLOSION] && check_rights(R_FUN)) + usr.client.cmd_admin_explosion(src) + + if(href_list[VV_HK_TRIGGER_EMP] && check_rights(R_FUN)) + usr.client.cmd_admin_emp(src) + + if(href_list[VV_HK_SHOW_HIDDENPRINTS] && check_rights(R_ADMIN)) + usr.client.cmd_show_hiddenprints(src) + + if(href_list[VV_HK_ARMOR_MOD]) + var/list/pickerlist = list() + var/list/armorlist = get_armor().get_rating_list() + + for (var/i in armorlist) + pickerlist += list(list("value" = armorlist[i], "name" = i)) + + var/list/result = presentpicker(usr, "Modify armor", "Modify armor: [src]", Button1="Save", Button2 = "Cancel", Timeout=FALSE, inputtype = "text", values = pickerlist) + var/list/armor_all = ARMOR_LIST_ALL() + + if (islist(result)) + if (result["button"] != 2) // If the user pressed the cancel button + // text2num conveniently returns a null on invalid values + var/list/converted = list() + for(var/armor_key in armor_all) + converted[armor_key] = text2num(result["values"][armor_key]) + set_armor(get_armor().generate_new_with_specific(converted)) + var/message = "[key_name(usr)] modified the armor on [src] ([type]) to: " + for(var/armor_key in armor_all) + message += "[armor_key]=[get_armor_rating(armor_key)]," + message = copytext(message, 1, -1) + log_admin(span_notice(message)) + message_admins(span_notice(message)) + + if(href_list[VV_HK_ADD_AI]) + if(!check_rights(R_VAREDIT)) + return + var/result = input(usr, "Choose the AI controller to apply to this atom WARNING: Not all AI works on all atoms.", "AI controller") as null|anything in subtypesof(/datum/ai_controller) + if(!result) + return + ai_controller = new result(src) + + if(href_list[VV_HK_MODIFY_TRANSFORM] && check_rights(R_VAREDIT)) + var/result = input(usr, "Choose the transformation to apply","Transform Mod") as null|anything in list("Scale","Translate","Rotate","Shear") + var/matrix/M = transform + if(!result) + return + switch(result) + if("Scale") + var/x = input(usr, "Choose x mod","Transform Mod") as null|num + var/y = input(usr, "Choose y mod","Transform Mod") as null|num + if(isnull(x) || isnull(y)) + return + transform = M.Scale(x,y) + if("Translate") + var/x = input(usr, "Choose x mod (negative = left, positive = right)","Transform Mod") as null|num + var/y = input(usr, "Choose y mod (negative = down, positive = up)","Transform Mod") as null|num + if(isnull(x) || isnull(y)) + return + transform = M.Translate(x,y) + if("Shear") + var/x = input(usr, "Choose x mod","Transform Mod") as null|num + var/y = input(usr, "Choose y mod","Transform Mod") as null|num + if(isnull(x) || isnull(y)) + return + transform = M.Shear(x,y) + if("Rotate") + var/angle = input(usr, "Choose angle to rotate","Transform Mod") as null|num + if(isnull(angle)) + return + transform = M.Turn(angle) + + SEND_SIGNAL(src, COMSIG_ATOM_VV_MODIFY_TRANSFORM) + + if(href_list[VV_HK_SPIN_ANIMATION] && check_rights(R_VAREDIT)) + var/num_spins = input(usr, "Do you want infinite spins?", "Spin Animation") in list("Yes", "No") + if(num_spins == "No") + num_spins = input(usr, "How many spins?", "Spin Animation") as null|num + else + num_spins = -1 + if(!num_spins) + return + var/spin_speed = input(usr, "How fast?", "Spin Animation") as null|num + if(!spin_speed) + return + var/direction = input(usr, "Which direction?", "Spin Animation") in list("Clockwise", "Counter-clockwise") + switch(direction) + if("Clockwise") + direction = 1 + if("Counter-clockwise") + direction = 0 + else + return + SpinAnimation(spin_speed, num_spins, direction) + + if(href_list[VV_HK_STOP_ALL_ANIMATIONS] && check_rights(R_VAREDIT)) + var/result = input(usr, "Are you sure?", "Stop Animating") in list("Yes", "No") + if(result == "Yes") + animate(src, transform = null, flags = ANIMATION_END_NOW) // Literally just fucking stop animating entirely because admin said so + return + + if(href_list[VV_HK_AUTO_RENAME] && check_rights(R_VAREDIT)) + var/newname = input(usr, "What do you want to rename this to?", "Automatic Rename") as null|text + // Check the new name against the chat filter. If it triggers the IC chat filter, give an option to confirm. + if(newname && !(is_ic_filtered(newname) || is_soft_ic_filtered(newname) && tgui_alert(usr, "Your selected name contains words restricted by IC chat filters. Confirm this new name?", "IC Chat Filter Conflict", list("Confirm", "Cancel")) != "Confirm")) + vv_auto_rename(newname) + + if(href_list[VV_HK_EDIT_FILTERS] && check_rights(R_VAREDIT)) + usr.client?.open_filter_editor(src) + + if(href_list[VV_HK_EDIT_COLOR_MATRIX] && check_rights(R_VAREDIT)) + usr.client?.open_color_matrix_editor(src) + + if(href_list[VV_HK_TEST_MATRIXES] && check_rights(R_VAREDIT)) + usr.client?.open_matrix_tester(src) + +/atom/vv_get_header() + . = ..() + var/refid = REF(src) + . += "[VV_HREF_TARGETREF(refid, VV_HK_AUTO_RENAME, "[src]")]" + . += "
<< [dir2text(dir) || dir] >>" + +/** + * call back when a var is edited on this atom + * + * Can be used to implement special handling of vars + * + * At the atom level, if you edit a var named "color" it will add the atom colour with + * admin level priority to the atom colours list + * + * Also, if GLOB.Debug2 is FALSE, it sets the [ADMIN_SPAWNED_1] flag on [flags_1][/atom/var/flags_1], which signifies + * the object has been admin edited + */ +/atom/vv_edit_var(var_name, var_value) + var/old_light_flags = light_flags + // Disable frozen lights for now, so we can actually modify it + light_flags &= ~LIGHT_FROZEN + switch(var_name) + if(NAMEOF(src, light_range)) + if(light_system == STATIC_LIGHT) + set_light(l_range = var_value) + else + set_light_range(var_value) + . = TRUE + if(NAMEOF(src, light_power)) + if(light_system == STATIC_LIGHT) + set_light(l_power = var_value) + else + set_light_power(var_value) + . = TRUE + if(NAMEOF(src, light_color)) + if(light_system == STATIC_LIGHT) + set_light(l_color = var_value) + else + set_light_color(var_value) + . = TRUE + if(NAMEOF(src, light_angle)) + if(light_system == STATIC_LIGHT) + set_light(l_angle = var_value) + . = TRUE + if(NAMEOF(src, light_dir)) + if(light_system == STATIC_LIGHT) + set_light(l_dir = var_value) + . = TRUE + if(NAMEOF(src, light_height)) + if(light_system == STATIC_LIGHT) + set_light(l_height = var_value) + . = TRUE + if(NAMEOF(src, light_on)) + if(light_system == STATIC_LIGHT) + set_light(l_on = var_value) + else + set_light_on(var_value) + . = TRUE + if(NAMEOF(src, light_flags)) + set_light_flags(var_value) + // I'm sorry + old_light_flags = var_value + . = TRUE + if(NAMEOF(src, smoothing_junction)) + set_smoothed_icon_state(var_value) + . = TRUE + if(NAMEOF(src, opacity)) + set_opacity(var_value) + . = TRUE + if(NAMEOF(src, base_pixel_x)) + set_base_pixel_x(var_value) + . = TRUE + if(NAMEOF(src, base_pixel_y)) + set_base_pixel_y(var_value) + . = TRUE + + light_flags = old_light_flags + if(!isnull(.)) + datum_flags |= DF_VAR_EDITED + return + + if(!GLOB.Debug2) + flags_1 |= ADMIN_SPAWNED_1 + + . = ..() + + switch(var_name) + if(NAMEOF(src, color)) + add_atom_colour(color, ADMIN_COLOUR_PRIORITY) + update_appearance() + +/atom/proc/vv_auto_rename(newname) + name = newname diff --git a/code/game/atoms_initializing_EXPENSIVE.dm b/code/game/atom/atoms_initializing_EXPENSIVE.dm similarity index 76% rename from code/game/atoms_initializing_EXPENSIVE.dm rename to code/game/atom/atoms_initializing_EXPENSIVE.dm index 1ecc6390edc34..2a3a442e04d71 100644 --- a/code/game/atoms_initializing_EXPENSIVE.dm +++ b/code/game/atom/atoms_initializing_EXPENSIVE.dm @@ -52,6 +52,27 @@ return qdeleted || QDELING(A) +/** + * Called when an atom is created in byond (built in engine proc) + * + * Not a lot happens here in SS13 code, as we offload most of the work to the + * [Intialization][/atom/proc/Initialize] proc, mostly we run the preloader + * if the preloader is being used and then call [InitAtom][/datum/controller/subsystem/atoms/proc/InitAtom] of which the ultimate + * result is that the Intialize proc is called. + * + */ +/atom/New(loc, ...) + //atom creation method that preloads variables at creation + if(GLOB.use_preloader && src.type == GLOB._preloader_path)//in case the instanciated atom is creating other atoms in New() + world.preloader_load(src) + + var/do_initialize = SSatoms.initialized + if(do_initialize != INITIALIZATION_INSSATOMS) + args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD + if(SSatoms.InitAtom(src, FALSE, args)) + //we were deleted + return + /** * The primary method that objects are setup in SS13 with * @@ -126,3 +147,17 @@ ai_controller = new ai_controller(src) return INITIALIZE_HINT_NORMAL + +/** + * Late Intialization, for code that should run after all atoms have run Intialization + * + * To have your LateIntialize proc be called, your atoms [Initalization][/atom/proc/Initialize] + * proc must return the hint + * [INITIALIZE_HINT_LATELOAD] otherwise it will never be called. + * + * useful for doing things like finding other machines on GLOB.machines because you can guarantee + * that all atoms will actually exist in the "WORLD" at this time and that all their Intialization + * code has been run + */ +/atom/proc/LateInitialize() + set waitfor = FALSE diff --git a/code/game/atoms.dm b/code/game/atoms.dm deleted file mode 100644 index 339aef1feab90..0000000000000 --- a/code/game/atoms.dm +++ /dev/null @@ -1,2290 +0,0 @@ -/** - * The base type for nearly all physical objects in SS13 - - * Lots and lots of functionality lives here, although in general we are striving to move - * as much as possible to the components/elements system - */ -/atom - layer = TURF_LAYER - plane = GAME_PLANE - appearance_flags = TILE_BOUND|LONG_GLIDE - - /// pass_flags that we are. If any of this matches a pass_flag on a moving thing, by default, we let them through. - var/pass_flags_self = NONE - - ///If non-null, overrides a/an/some in all cases - var/article - - ///First atom flags var - var/flags_1 = NONE - ///Intearaction flags - var/interaction_flags_atom = NONE - - var/flags_ricochet = NONE - - ///When a projectile tries to ricochet off this atom, the projectile ricochet chance is multiplied by this - var/receive_ricochet_chance_mod = 1 - ///When a projectile ricochets off this atom, it deals the normal damage * this modifier to this atom - var/receive_ricochet_damage_coeff = 0.33 - - ///Reagents holder - var/datum/reagents/reagents = null - - ///all of this atom's HUD (med/sec, etc) images. Associative list of the form: list(hud category = hud image or images for that category). - ///most of the time hud category is associated with a single image, sometimes its associated with a list of images. - ///not every hud in this list is actually used. for ones available for others to see, look at active_hud_list. - var/list/image/hud_list = null - ///all of this atom's HUD images which can actually be seen by players with that hud - var/list/image/active_hud_list = null - ///HUD images that this atom can provide. - var/list/hud_possible - - ///How much this atom resists explosions by, in the end - var/explosive_resistance = 0 - - /** - * used to store the different colors on an atom - * - * its inherent color, the colored paint applied on it, special color effect etc... - */ - var/list/atom_colours - - - /// a very temporary list of overlays to remove - var/list/remove_overlays - /// a very temporary list of overlays to add - var/list/add_overlays - - ///vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays. - var/list/managed_vis_overlays - ///overlays managed by [update_overlays][/atom/proc/update_overlays] to prevent removing overlays that weren't added by the same proc. Single items are stored on their own, not in a list. - var/list/managed_overlays - - /// Lazylist of all images (or atoms, I'm sorry) (hopefully attached to us) to update when we change z levels - /// You will need to manage adding/removing from this yourself, but I'll do the updating for you - var/list/image/update_on_z - - /// Lazylist of all overlays attached to us to update when we change z levels - /// You will need to manage adding/removing from this yourself, but I'll do the updating for you - /// Oh and note, if order of addition is important this WILL break that. so mind yourself - var/list/image/update_overlays_on_z - - ///Cooldown tick timer for buckle messages - var/buckle_message_cooldown = 0 - ///Last fingerprints to touch this atom - var/fingerprintslast - - //List of datums orbiting this atom - var/datum/component/orbiter/orbiters - - /// Radiation insulation types - var/rad_insulation = RAD_NO_INSULATION - - /// The icon state intended to be used for the acid component. Used to override the default acid overlay icon state. - var/custom_acid_overlay = null - - ///The custom materials this atom is made of, used by a lot of things like furniture, walls, and floors (if I finish the functionality, that is.) - ///The list referenced by this var can be shared by multiple objects and should not be directly modified. Instead, use [set_custom_materials][/atom/proc/set_custom_materials]. - var/list/datum/material/custom_materials - ///Bitfield for how the atom handles materials. - var/material_flags = NONE - ///Modifier that raises/lowers the effect of the amount of a material, prevents small and easy to get items from being death machines. - var/material_modifier = 1 - - var/datum/wires/wires = null - - var/list/alternate_appearances - - ///Light systems, both shouldn't be active at the same time. - var/light_system = STATIC_LIGHT - ///Range of the light in tiles. Zero means no light. - var/light_range = 0 - ///Intensity of the light. The stronger, the less shadows you will see on the lit area. - var/light_power = 1 - ///Hexadecimal RGB string representing the colour of the light. White by default. - var/light_color = COLOR_WHITE - /// Angle of light to show in light_dir - /// 360 is a circle, 90 is a cone, etc. - var/light_angle = 360 - /// What angle to project light in - var/light_dir = NORTH - ///Boolean variable for toggleable lights. Has no effect without the proper light_system, light_range and light_power values. - var/light_on = TRUE - /// How many tiles "up" this light is. 1 is typical, should only really change this if it's a floor light - var/light_height = LIGHTING_HEIGHT - ///Bitflags to determine lighting-related atom properties. - var/light_flags = NONE - ///Our light source. Don't fuck with this directly unless you have a good reason! - var/tmp/datum/light_source/light - ///Any light sources that are "inside" of us, for example, if src here was a mob that's carrying a flashlight, that flashlight's light source would be part of this list. - var/tmp/list/light_sources - - /// Last name used to calculate a color for the chatmessage overlays - var/chat_color_name - /// Last color calculated for the the chatmessage overlays - var/chat_color - /// A luminescence-shifted value of the last color calculated for chatmessage overlays - var/chat_color_darkened - - // Use SET_BASE_PIXEL(x, y) to set these in typepath definitions, it'll handle pixel_x and y for you - ///Default pixel x shifting for the atom's icon. - var/base_pixel_x = 0 - ///Default pixel y shifting for the atom's icon. - var/base_pixel_y = 0 - // Use SET_BASE_VISUAL_PIXEL(x, y) to set these in typepath definitions, it'll handle pixel_w and z for you - ///Default pixel w shifting for the atom's icon. - var/base_pixel_w = 0 - ///Default pixel z shifting for the atom's icon. - var/base_pixel_z = 0 - ///Used for changing icon states for different base sprites. - var/base_icon_state - - ///The config type to use for greyscaled sprites. Both this and greyscale_colors must be assigned to work. - var/greyscale_config - ///A string of hex format colors to be used by greyscale sprites, ex: "#0054aa#badcff" - var/greyscale_colors - - ///Holds merger groups currently active on the atom. Do not access directly, use GetMergeGroup() instead. - var/list/datum/merger/mergers - - ///Icon-smoothing behavior. - var/smoothing_flags = NONE - ///What directions this is currently smoothing with. IMPORTANT: This uses the smoothing direction flags as defined in icon_smoothing.dm, instead of the BYOND flags. - var/smoothing_junction = null //This starts as null for us to know when it's first set, but after that it will hold a 8-bit mask ranging from 0 to 255. - ///Smoothing variable - var/top_left_corner - ///Smoothing variable - var/top_right_corner - ///Smoothing variable - var/bottom_left_corner - ///Smoothing variable - var/bottom_right_corner - ///What smoothing groups does this atom belongs to, to match canSmoothWith. If null, nobody can smooth with it. Must be sorted. - var/list/smoothing_groups = null - ///List of smoothing groups this atom can smooth with. If this is null and atom is smooth, it smooths only with itself. Must be sorted. - var/list/canSmoothWith = null - ///Reference to atom being orbited - var/atom/orbit_target - ///AI controller that controls this atom. type on init, then turned into an instance during runtime - var/datum/ai_controller/ai_controller - - ///any atom that uses integrity and can be damaged must set this to true, otherwise the integrity procs will throw an error - var/uses_integrity = FALSE - - VAR_PROTECTED/datum/armor/armor_type = /datum/armor/none - VAR_PRIVATE/datum/armor/armor - - VAR_PRIVATE/atom_integrity //defaults to max_integrity - var/max_integrity = 500 - var/integrity_failure = 0 //0 if we have no special broken behavior, otherwise is a percentage of at what point the atom breaks. 0.5 being 50% - ///Damage under this value will be completely ignored - var/damage_deflection = 0 - - var/resistance_flags = NONE // INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ON_FIRE | UNACIDABLE | ACID_PROOF - /// forensics datum, contains fingerprints, fibres, blood_dna and hiddenprints on this atom - var/datum/forensics/forensics - - /// the datum handler for our contents - see create_storage() for creation method - var/datum/storage/atom_storage - /// How this atom should react to having its astar blocking checked - var/can_astar_pass = CANASTARPASS_DENSITY - - VAR_PRIVATE/list/invisibility_sources - VAR_PRIVATE/current_invisibility_priority = -INFINITY - -/** - * Called when an atom is created in byond (built in engine proc) - * - * Not a lot happens here in SS13 code, as we offload most of the work to the - * [Intialization][/atom/proc/Initialize] proc, mostly we run the preloader - * if the preloader is being used and then call [InitAtom][/datum/controller/subsystem/atoms/proc/InitAtom] of which the ultimate - * result is that the Intialize proc is called. - * - */ -/atom/New(loc, ...) - //atom creation method that preloads variables at creation - if(GLOB.use_preloader && src.type == GLOB._preloader_path)//in case the instanciated atom is creating other atoms in New() - world.preloader_load(src) - - var/do_initialize = SSatoms.initialized - if(do_initialize != INITIALIZATION_INSSATOMS) - args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD - if(SSatoms.InitAtom(src, FALSE, args)) - //we were deleted - return - -/** - * Late Intialization, for code that should run after all atoms have run Intialization - * - * To have your LateIntialize proc be called, your atoms [Initalization][/atom/proc/Initialize] - * proc must return the hint - * [INITIALIZE_HINT_LATELOAD] otherwise it will never be called. - * - * useful for doing things like finding other machines on GLOB.machines because you can guarantee - * that all atoms will actually exist in the "WORLD" at this time and that all their Intialization - * code has been run - */ -/atom/proc/LateInitialize() - set waitfor = FALSE - -/** - * Top level of the destroy chain for most atoms - * - * Cleans up the following: - * * Removes alternate apperances from huds that see them - * * qdels the reagent holder from atoms if it exists - * * clears the orbiters list - * * clears overlays and priority overlays - * * clears the light object - */ -/atom/Destroy(force) - if(alternate_appearances) - for(var/current_alternate_appearance in alternate_appearances) - var/datum/atom_hud/alternate_appearance/selected_alternate_appearance = alternate_appearances[current_alternate_appearance] - selected_alternate_appearance.remove_atom_from_hud(src) - - if(reagents) - QDEL_NULL(reagents) - - if(forensics) - QDEL_NULL(forensics) - - if(atom_storage) - QDEL_NULL(atom_storage) - - orbiters = null // The component is attached to us normaly and will be deleted elsewhere - - // Checking length(overlays) before cutting has significant speed benefits - if (length(overlays)) - overlays.Cut() - - LAZYNULL(managed_overlays) - if(ai_controller) - QDEL_NULL(ai_controller) - if(light) - QDEL_NULL(light) - if (length(light_sources)) - light_sources.Cut() - - if(smoothing_flags & SMOOTH_QUEUED) - SSicon_smooth.remove_from_queues(src) - - return ..() - -/// A quick and easy way to create a storage datum for an atom -/atom/proc/create_storage( - max_slots, - max_specific_storage, - max_total_storage, - numerical_stacking = FALSE, - allow_quick_gather = FALSE, - allow_quick_empty = FALSE, - collection_mode = COLLECT_ONE, - attack_hand_interact = TRUE, - list/canhold, - list/canthold, - storage_type = /datum/storage, -) - - if(atom_storage) - QDEL_NULL(atom_storage) - - atom_storage = new storage_type(src, max_slots, max_specific_storage, max_total_storage, numerical_stacking, allow_quick_gather, collection_mode, attack_hand_interact) - - if(canhold || canthold) - atom_storage.set_holdable(canhold, canthold) - - return atom_storage - -/// A quick and easy way to /clone/ a storage datum for an atom (does not copy over contents, only the datum details) -/atom/proc/clone_storage(datum/storage/cloning) - if(atom_storage) - QDEL_NULL(atom_storage) - - atom_storage = new cloning.type(src, cloning.max_slots, cloning.max_specific_storage, cloning.max_total_storage, cloning.numerical_stacking, cloning.allow_quick_gather, cloning.collection_mode, cloning.attack_hand_interact) - - if(cloning.can_hold || cloning.cant_hold) - if(!atom_storage.can_hold && !atom_storage.cant_hold) //In the event that the can/can't hold lists are already in place (such as from storage objects added on initialize). - atom_storage.set_holdable(cloning.can_hold, cloning.cant_hold) - - return atom_storage - -/atom/proc/handle_ricochet(obj/projectile/ricocheting_projectile) - var/turf/p_turf = get_turf(ricocheting_projectile) - var/face_direction = get_dir(src, p_turf) || get_dir(src, ricocheting_projectile) - var/face_angle = dir2angle(face_direction) - var/incidence_s = GET_ANGLE_OF_INCIDENCE(face_angle, (ricocheting_projectile.Angle + 180)) - var/a_incidence_s = abs(incidence_s) - if(a_incidence_s > 90 && a_incidence_s < 270) - return FALSE - if((ricocheting_projectile.armor_flag in list(BULLET, BOMB)) && ricocheting_projectile.ricochet_incidence_leeway) - if((a_incidence_s < 90 && a_incidence_s < 90 - ricocheting_projectile.ricochet_incidence_leeway) || (a_incidence_s > 270 && a_incidence_s -270 > ricocheting_projectile.ricochet_incidence_leeway)) - return FALSE - var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s) - ricocheting_projectile.set_angle(new_angle_s) - return TRUE - -/// Whether the mover object can avoid being blocked by this atom, while arriving from (or leaving through) the border_dir. -/atom/proc/CanPass(atom/movable/mover, border_dir) - SHOULD_CALL_PARENT(TRUE) - SHOULD_BE_PURE(TRUE) - if(SEND_SIGNAL(src, COMSIG_ATOM_TRIED_PASS, mover, border_dir) & COMSIG_COMPONENT_PERMIT_PASSAGE) - return TRUE - if(mover.movement_type & PHASING) - return TRUE - . = CanAllowThrough(mover, border_dir) - // This is cheaper than calling the proc every time since most things dont override CanPassThrough - if(!mover.generic_canpass) - return mover.CanPassThrough(src, REVERSE_DIR(border_dir), .) - -/// Returns true or false to allow the mover to move through src -/atom/proc/CanAllowThrough(atom/movable/mover, border_dir) - SHOULD_CALL_PARENT(TRUE) - //SHOULD_BE_PURE(TRUE) - if(mover.pass_flags & pass_flags_self) - return TRUE - if(mover.throwing && (pass_flags_self & LETPASSTHROW)) - return TRUE - return !density - -/** - * Is this atom currently located on centcom (or riding off into the sunset on a shuttle) - * - * Specifically, is it on the z level and within the centcom areas. - * You can also be in a shuttle during endgame transit. - * - * Used in gamemode to identify mobs who have escaped and for some other areas of the code - * who don't want atoms where they shouldn't be - * - * Returns TRUE if this atom is on centcom or an escape shuttle, or FALSE if not - */ -/atom/proc/onCentCom() - var/turf/current_turf = get_turf(src) - if(!current_turf) - return FALSE - - // This doesn't necessarily check that we're at central command, - // but it checks for any shuttles which have finished are still in hyperspace - // (IE, stuff like the whiteship which fly off into the sunset and "escape") - if(is_reserved_level(current_turf.z)) - return on_escaped_shuttle(ENDGAME_TRANSIT) - - // From here on we only concern ourselves with people actually on the centcom Z - if(!is_centcom_level(current_turf.z)) - return FALSE - - if(istype(current_turf.loc, /area/centcom)) - return TRUE - - // Finally, check if we're on an escaped shuttle - return on_escaped_shuttle() - -/** - * Is the atom in any of the syndicate areas - * - * Either in the syndie base, or any of their shuttles - * - * Also used in gamemode code for win conditions - * - * Returns TRUE if this atom is on the syndicate recon base, any of its shuttles, or an escape shuttle, or FALSE if not - */ -/atom/proc/onSyndieBase() - var/turf/current_turf = get_turf(src) - if(!current_turf) - return FALSE - - // Syndicate base is loaded in a reserved level. If not reserved, we don't care. - if(!is_reserved_level(current_turf.z)) - return FALSE - - var/static/list/syndie_typecache = typecacheof(list( - /area/centcom/syndicate_mothership, // syndicate base itself - /area/shuttle/assault_pod, // steel rain - /area/shuttle/syndicate, // infiltrator - )) - - if(is_type_in_typecache(current_turf.loc, syndie_typecache)) - return TRUE - - // Finally, check if we're on an escaped shuttle - return on_escaped_shuttle() - -/** - * Checks that we're on a shuttle that's escaped - * - * * check_for_launch_status - What launch status do we check for? Generally the two you want to check for are ENDGAME_LAUNCHED or ENDGAME_TRANSIT - * - * Returns TRUE if this atom is on a shuttle which is escaping or has escaped, or FALSE otherwise - */ -/atom/proc/on_escaped_shuttle(check_for_launch_status = ENDGAME_LAUNCHED) - var/turf/current_turf = get_turf(src) - if(!current_turf) - return FALSE - - for(var/obj/docking_port/mobile/mobile_docking_port as anything in SSshuttle.mobile_docking_ports) - if(mobile_docking_port.launch_status != check_for_launch_status) - continue - for(var/area/shuttle/shuttle_area as anything in mobile_docking_port.shuttle_areas) - if(current_turf in shuttle_area.get_contained_turfs()) - return TRUE - - return FALSE - -/** - * Is the atom in an away mission - * - * Must be in the away mission z-level to return TRUE - * - * Also used in gamemode code for win conditions - */ -/atom/proc/onAwayMission() - var/turf/current_turf = get_turf(src) - if(!current_turf) - return FALSE - - if(is_away_level(current_turf.z)) - return TRUE - - return FALSE - - - -///This atom has been hit by a hulkified mob in hulk mode (user) -/atom/proc/attack_hulk(mob/living/carbon/human/user) - SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user) - -/** - * Ensure a list of atoms/reagents exists inside this atom - * - * Goes throught he list of passed in parts, if they're reagents, adds them to our reagent holder - * creating the reagent holder if it exists. - * - * If the part is a moveable atom and the previous location of the item was a mob/living, - * it calls the inventory handler transferItemToLoc for that mob/living and transfers the part - * to this atom - * - * Otherwise it simply forceMoves the atom into this atom - */ -/atom/proc/CheckParts(list/parts_list, datum/crafting_recipe/current_recipe) - SEND_SIGNAL(src, COMSIG_ATOM_CHECKPARTS, parts_list, current_recipe) - if(!parts_list) - return - for(var/part in parts_list) - if(istype(part, /datum/reagent)) - if(!reagents) - reagents = new() - reagents.reagent_list.Add(part) - reagents.conditional_update() - else if(ismovable(part)) - var/atom/movable/object = part - if(isliving(object.loc)) - var/mob/living/living = object.loc - living.transferItemToLoc(object, src) - else - object.forceMove(src) - SEND_SIGNAL(object, COMSIG_ATOM_USED_IN_CRAFT, src) - parts_list.Cut() - -///Take air from the passed in gas mixture datum -/atom/proc/assume_air(datum/gas_mixture/giver) - return null - -///Remove air from this atom -/atom/proc/remove_air(amount) - return null - -///Return the current air environment in this atom -/atom/proc/return_air() - if(loc) - return loc.return_air() - else - return null - -///Return the air if we can analyze it -/atom/proc/return_analyzable_air() - return null - -///Check if this atoms eye is still alive (probably) -/atom/proc/check_eye(mob/user) - SIGNAL_HANDLER - return - -/atom/proc/Bumped(atom/movable/bumped_atom) - set waitfor = FALSE - SEND_SIGNAL(src, COMSIG_ATOM_BUMPED, bumped_atom) - -/// Convenience proc to see if a container is open for chemistry handling -/atom/proc/is_open_container() - return is_refillable() && is_drainable() - -/// Is this atom injectable into other atoms -/atom/proc/is_injectable(mob/user, allowmobs = TRUE) - return reagents && (reagents.flags & (INJECTABLE | REFILLABLE)) - -/// Can we draw from this atom with an injectable atom -/atom/proc/is_drawable(mob/user, allowmobs = TRUE) - return reagents && (reagents.flags & (DRAWABLE | DRAINABLE)) - -/// Can this atoms reagents be refilled -/atom/proc/is_refillable() - return reagents && (reagents.flags & REFILLABLE) - -/// Is this atom drainable of reagents -/atom/proc/is_drainable() - return reagents && (reagents.flags & DRAINABLE) - -/** Handles exposing this atom to a list of reagents. - * - * Sends COMSIG_ATOM_EXPOSE_REAGENTS - * Calls expose_atom() for every reagent in the reagent list. - * - * Arguments: - * - [reagents][/list]: The list of reagents the atom is being exposed to. - * - [source][/datum/reagents]: The reagent holder the reagents are being sourced from. - * - methods: How the atom is being exposed to the reagents. Bitflags. - * - volume_modifier: Volume multiplier. - * - show_message: Whether to display anything to mobs when they are exposed. - */ -/atom/proc/expose_reagents(list/reagents, datum/reagents/source, methods=TOUCH, volume_modifier=1, show_message=TRUE) - . = SEND_SIGNAL(src, COMSIG_ATOM_EXPOSE_REAGENTS, reagents, source, methods, volume_modifier, show_message) - if(. & COMPONENT_NO_EXPOSE_REAGENTS) - return - - SEND_SIGNAL(source, COMSIG_REAGENTS_EXPOSE_ATOM, src, reagents, methods, volume_modifier, show_message) - for(var/datum/reagent/current_reagent as anything in reagents) - . |= current_reagent.expose_atom(src, reagents[current_reagent]) - SEND_SIGNAL(src, COMSIG_ATOM_AFTER_EXPOSE_REAGENTS, reagents, source, methods, volume_modifier, show_message) - -/// Are you allowed to drop this atom -/atom/proc/AllowDrop() - return FALSE - -///Is this atom within 1 tile of another atom -/atom/proc/HasProximity(atom/movable/proximity_check_mob as mob|obj) - return - -/// Sets the wire datum of an atom -/atom/proc/set_wires(datum/wires/new_wires) - wires = new_wires - -/** - * React to an EMP of the given severity - * - * Default behaviour is to send the [COMSIG_ATOM_PRE_EMP_ACT] and [COMSIG_ATOM_EMP_ACT] signal - * - * If the pre-signal does not return protection, and there are attached wires then we call - * [emp_pulse][/datum/wires/proc/emp_pulse] on the wires - * - * We then return the protection value - */ -/atom/proc/emp_act(severity) - var/protection = SEND_SIGNAL(src, COMSIG_ATOM_PRE_EMP_ACT, severity) - if(!(protection & EMP_PROTECT_WIRES) && istype(wires)) - wires.emp_pulse() - - SEND_SIGNAL(src, COMSIG_ATOM_EMP_ACT, severity, protection) - return protection // Pass the protection value collected here upwards - -/** - * React to a hit by a projectile object - * - * @params - * * hitting_projectile - projectile - * * def_zone - zone hit - * * piercing_hit - is this hit piercing or normal? - */ -/atom/proc/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit = FALSE) - SHOULD_CALL_PARENT(TRUE) - - var/sigreturn = SEND_SIGNAL(src, COMSIG_ATOM_PRE_BULLET_ACT, hitting_projectile, def_zone) - if(sigreturn & COMPONENT_BULLET_PIERCED) - return BULLET_ACT_FORCE_PIERCE - if(sigreturn & COMPONENT_BULLET_BLOCKED) - return BULLET_ACT_BLOCK - if(sigreturn & COMPONENT_BULLET_ACTED) - return BULLET_ACT_HIT - - SEND_SIGNAL(src, COMSIG_ATOM_BULLET_ACT, hitting_projectile, def_zone) - if(QDELETED(hitting_projectile)) // Signal deleted it? - return BULLET_ACT_BLOCK - - return hitting_projectile.on_hit( - target = src, - // This armor check only matters for the visuals and messages in on_hit(), it's not actually used to reduce damage since - // only living mobs use armor to reduce damage, but on_hit() is going to need the value no matter what is shot. - blocked = check_projectile_armor(def_zone, hitting_projectile), - pierce_hit = piercing_hit, - ) - -///Return true if we're inside the passed in atom -/atom/proc/in_contents_of(container)//can take class or object instance as argument - if(ispath(container)) - if(istype(src.loc, container)) - return TRUE - else if(src in container) - return TRUE - return FALSE - -/** - * Get the name of this object for examine - * - * You can override what is returned from this proc by registering to listen for the - * [COMSIG_ATOM_GET_EXAMINE_NAME] signal - */ -/atom/proc/get_examine_name(mob/user) - . = "\a [src]" - var/list/override = list(gender == PLURAL ? "some" : "a", " ", "[name]") - if(article) - . = "[article] [src]" - override[EXAMINE_POSITION_ARTICLE] = article - if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED) - . = override.Join("") - -///Generate the full examine string of this atom (including icon for goonchat) -/atom/proc/get_examine_string(mob/user, thats = FALSE) - return "[icon2html(src, user)] [thats? "That's ":""][get_examine_name(user)]" - -/** - * Returns an extended list of examine strings for any contained ID cards. - * - * Arguments: - * * user - The user who is doing the examining. - */ -/atom/proc/get_id_examine_strings(mob/user) - . = list() - return - -///Used to insert text after the name but before the description in examine() -/atom/proc/get_name_chaser(mob/user, list/name_chaser = list()) - return name_chaser - -/** - * Called when a mob examines (shift click or verb) this atom - * - * Default behaviour is to get the name and icon of the object and it's reagents where - * the [TRANSPARENT] flag is set on the reagents holder - * - * Produces a signal [COMSIG_ATOM_EXAMINE] - */ -/atom/proc/examine(mob/user) - var/examine_string = get_examine_string(user, thats = TRUE) - if(examine_string) - . = list("[examine_string].") - else - . = list() - - . += get_name_chaser(user) - if(desc) - . += desc - - if(custom_materials) - var/list/materials_list = list() - for(var/custom_material in custom_materials) - var/datum/material/current_material = GET_MATERIAL_REF(custom_material) - materials_list += "[current_material.name]" - . += "It is made out of [english_list(materials_list)]." - - if(reagents) - var/user_sees_reagents = user.can_see_reagents() - var/reagent_sigreturn = SEND_SIGNAL(src, COMSIG_ATOM_REAGENT_EXAMINE, user, ., user_sees_reagents) - if(!(reagent_sigreturn & STOP_GENERIC_REAGENT_EXAMINE)) - if(reagents.flags & TRANSPARENT) - if(reagents.total_volume) - . += "It contains [reagents.total_volume] units of various reagents[user_sees_reagents ? ":" : "."]" - if(user_sees_reagents) //Show each individual reagent for detailed examination - for(var/datum/reagent/current_reagent as anything in reagents.reagent_list) - . += "• [round(current_reagent.volume, CHEMICAL_VOLUME_ROUNDING)] units of [current_reagent.name]" - if(reagents.is_reacting) - . += span_warning("It is currently reacting!") - . += span_notice("The solution's pH is [round(reagents.ph, 0.01)] and has a temperature of [reagents.chem_temp]K.") - - else - . += "It contains:
Nothing." - else if(reagents.flags & AMOUNT_VISIBLE) - if(reagents.total_volume) - . += span_notice("It has [reagents.total_volume] unit\s left.") - else - . += span_danger("It's empty.") - - SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE, user, .) - -/** - * Called when a mob examines (shift click or verb) this atom twice (or more) within EXAMINE_MORE_WINDOW (default 1 second) - * - * This is where you can put extra information on something that may be superfluous or not important in critical gameplay - * moments, while allowing people to manually double-examine to take a closer look - * - * Produces a signal [COMSIG_ATOM_EXAMINE_MORE] - */ -/atom/proc/examine_more(mob/user) - SHOULD_CALL_PARENT(TRUE) - RETURN_TYPE(/list) - - . = list() - SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE_MORE, user, .) - SEND_SIGNAL(user, COMSIG_MOB_EXAMINING_MORE, src, .) - -/** - * Updates the appearence of the icon - * - * Mostly delegates to update_name, update_desc, and update_icon - * - * Arguments: - * - updates: A set of bitflags dictating what should be updated. Defaults to [ALL] - */ -/atom/proc/update_appearance(updates=ALL) - SHOULD_NOT_SLEEP(TRUE) - SHOULD_CALL_PARENT(TRUE) - - . = NONE - updates &= ~SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_APPEARANCE, updates) - if(updates & UPDATE_NAME) - . |= update_name(updates) - if(updates & UPDATE_DESC) - . |= update_desc(updates) - if(updates & UPDATE_ICON) - . |= update_icon(updates) - -/// Updates the name of the atom -/atom/proc/update_name(updates=ALL) - SHOULD_CALL_PARENT(TRUE) - return SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_NAME, updates) - -/// Updates the description of the atom -/atom/proc/update_desc(updates=ALL) - SHOULD_CALL_PARENT(TRUE) - return SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_DESC, updates) - -/// Updates the icon of the atom -/atom/proc/update_icon(updates=ALL) - SHOULD_CALL_PARENT(TRUE) - - . = NONE - updates &= ~SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON, updates) - if(updates & UPDATE_ICON_STATE) - update_icon_state() - . |= UPDATE_ICON_STATE - - if(updates & UPDATE_OVERLAYS) - if(LAZYLEN(managed_vis_overlays)) - SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) - - var/list/new_overlays = update_overlays(updates) - var/nulls = 0 - for(var/i in 1 to length(new_overlays)) - var/atom/maybe_not_an_atom = new_overlays[i] - if(isnull(maybe_not_an_atom)) - nulls++ - continue - if(istext(maybe_not_an_atom) || isicon(maybe_not_an_atom)) - continue - new_overlays[i] = maybe_not_an_atom.appearance - if(nulls) - for(var/i in 1 to nulls) - new_overlays -= null - - var/identical = FALSE - var/new_length = length(new_overlays) - if(!managed_overlays && !new_length) - identical = TRUE - else if(!islist(managed_overlays)) - if(new_length == 1 && managed_overlays == new_overlays[1]) - identical = TRUE - else if(length(managed_overlays) == new_length) - identical = TRUE - for(var/i in 1 to length(managed_overlays)) - if(managed_overlays[i] != new_overlays[i]) - identical = FALSE - break - - if(!identical) - var/full_control = FALSE - if(managed_overlays) - full_control = length(overlays) == (islist(managed_overlays) ? length(managed_overlays) : 1) - if(full_control) - overlays = null - else - cut_overlay(managed_overlays) - - switch(length(new_overlays)) - if(0) - if(full_control) - POST_OVERLAY_CHANGE(src) - managed_overlays = null - if(1) - add_overlay(new_overlays) - managed_overlays = new_overlays[1] - else - add_overlay(new_overlays) - managed_overlays = new_overlays - - . |= UPDATE_OVERLAYS - - . |= SEND_SIGNAL(src, COMSIG_ATOM_UPDATED_ICON, updates, .) - -/// Updates the icon state of the atom -/atom/proc/update_icon_state() - SHOULD_CALL_PARENT(TRUE) - return SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON_STATE) - -/// Updates the overlays of the atom -/atom/proc/update_overlays() - SHOULD_CALL_PARENT(TRUE) - . = list() - SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_OVERLAYS, .) - -/** - * Checks the atom's loc and calls update_held_items on it if it is a mob. - * - * This should only be used in situations when you are unable to use /datum/element/update_icon_updates_onmob for whatever reason. - * Check code/datums/elements/update_icon_updates_onmob.dm before using this. Adding that to the atom and calling update_appearance will work for most cases. - * - * Arguments: - * * mob/target - The mob to update the icons of. Optional argument, use if the atom's loc is not the mob you want to update. - */ -/atom/proc/update_inhand_icon(mob/target = loc) - SHOULD_CALL_PARENT(TRUE) - if(!istype(target)) - return - - target.update_held_items() - - SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_INHAND_ICON, target) - -/// Handles updates to greyscale value updates. -/// The colors argument can be either a list or the full color string. -/// Child procs should call parent last so the update happens after all changes. -/atom/proc/set_greyscale(list/colors, new_config) - SHOULD_CALL_PARENT(TRUE) - if(istype(colors)) - colors = colors.Join("") - if(!isnull(colors) && greyscale_colors != colors) // If you want to disable greyscale stuff then give a blank string - greyscale_colors = colors - - if(!isnull(new_config) && greyscale_config != new_config) - greyscale_config = new_config - - update_greyscale() - -/// Checks if this atom uses the GAGS system and if so updates the icon -/atom/proc/update_greyscale() - SHOULD_CALL_PARENT(TRUE) - if(greyscale_colors && greyscale_config) - icon = SSgreyscale.GetColoredIconByType(greyscale_config, greyscale_colors) - if(!smoothing_flags) // This is a bitfield but we're just checking that some sort of smoothing is happening - return - update_atom_colour() - QUEUE_SMOOTH(src) - -/** - * An atom we are buckled or is contained within us has tried to move - * - * Default behaviour is to send a warning that the user can't move while buckled as long - * as the [buckle_message_cooldown][/atom/var/buckle_message_cooldown] has expired (50 ticks) - */ -/atom/proc/relaymove(mob/living/user, direction) - if(SEND_SIGNAL(src, COMSIG_ATOM_RELAYMOVE, user, direction) & COMSIG_BLOCK_RELAYMOVE) - return - if(buckle_message_cooldown <= world.time) - buckle_message_cooldown = world.time + 25 - balloon_alert(user, "can't move while buckled!") - return - -/** - * A special case of relaymove() in which the person relaying the move may be "driving" this atom - * - * This is a special case for vehicles and ridden animals where the relayed movement may be handled - * by the riding component attached to this atom. Returns TRUE as long as there's nothing blocking - * the movement, or FALSE if the signal gets a reply that specifically blocks the movement - */ -/atom/proc/relaydrive(mob/living/user, direction) - return !(SEND_SIGNAL(src, COMSIG_RIDDEN_DRIVER_MOVE, user, direction) & COMPONENT_DRIVER_BLOCK_MOVE) - -/// Handle what happens when your contents are exploded by a bomb -/atom/proc/contents_explosion(severity, target) - return //For handling the effects of explosions on contents that would not normally be effected - -/** - * React to being hit by an explosion - * - * Should be called through the [EX_ACT] wrapper macro. - * The wrapper takes care of the [COMSIG_ATOM_EX_ACT] signal. - * as well as calling [/atom/proc/contents_explosion]. - * - * Returns TRUE by default, and behavior should be implemented on children procs on a per-atom basis. Should only return FALSE if we resist the explosion for any reason. - * We assume that the default is TRUE because all atoms should be considered destructible in some manner unless they explicitly opt out (in our current framework). - * However, the return value itself doesn't have any external consumers, it's only so children procs can listen to the value from their parent procs (due to the nature of the [EX_ACT] macro). - * Thus, the return value only matters on overrides of this proc, and the only thing that truly matters is the code that is executed (applying damage, calling damage procs, etc.) - * - */ -/atom/proc/ex_act(severity, target) - set waitfor = FALSE - return TRUE - -/** - * React to a hit by a blob objecd - * - * default behaviour is to send the [COMSIG_ATOM_BLOB_ACT] signal - */ -/atom/proc/blob_act(obj/structure/blob/attacking_blob) - var/blob_act_result = SEND_SIGNAL(src, COMSIG_ATOM_BLOB_ACT, attacking_blob) - if (blob_act_result & COMPONENT_CANCEL_BLOB_ACT) - return FALSE - return TRUE - -/** - * Respond to fire being used on our atom - * - * Default behaviour is to send [COMSIG_ATOM_FIRE_ACT] and return - */ -/atom/proc/fire_act(exposed_temperature, exposed_volume) - SEND_SIGNAL(src, COMSIG_ATOM_FIRE_ACT, exposed_temperature, exposed_volume) - return FALSE - -/** - * Sends [COMSIG_ATOM_EXTINGUISH] signal, which properly removes burning component if it is present. - * - * Default behaviour is to send [COMSIG_ATOM_ACID_ACT] and return - */ -/atom/proc/extinguish() - SHOULD_CALL_PARENT(TRUE) - return SEND_SIGNAL(src, COMSIG_ATOM_EXTINGUISH) - -/** - * React to being hit by a thrown object - * - * Default behaviour is to call [hitby_react][/atom/proc/hitby_react] on ourselves after 2 seconds if we are dense - * and under normal gravity. - * - * Im not sure why this the case, maybe to prevent lots of hitby's if the thrown object is - * deleted shortly after hitting something (during explosions or other massive events that - * throw lots of items around - singularity being a notable example) - */ -/atom/proc/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) - SEND_SIGNAL(src, COMSIG_ATOM_HITBY, hitting_atom, skipcatch, hitpush, blocked, throwingdatum) - if(density && !has_gravity(hitting_atom)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...). - addtimer(CALLBACK(src, PROC_REF(hitby_react), hitting_atom), 2) - -/** - * We have have actually hit the passed in atom - * - * Default behaviour is to move back from the item that hit us - */ -/atom/proc/hitby_react(atom/movable/harmed_atom) - if(harmed_atom && isturf(harmed_atom.loc)) - step(harmed_atom, REVERSE_DIR(harmed_atom.dir)) - -///Handle the atom being slipped over -/atom/proc/handle_slip(mob/living/carbon/slipped_carbon, knockdown_amount, obj/slipping_object, lube, paralyze, force_drop) - return - -///returns the mob's dna info as a list, to be inserted in an object's blood_DNA list -/mob/living/proc/get_blood_dna_list() - if(get_blood_id() != /datum/reagent/blood) - return - return list("ANIMAL DNA" = "Y-") - -///Get the mobs dna list -/mob/living/carbon/get_blood_dna_list() - if(get_blood_id() != /datum/reagent/blood) - return - var/list/blood_dna = list() - if(dna) - blood_dna[dna.unique_enzymes] = dna.blood_type - else - blood_dna["UNKNOWN DNA"] = "X*" - return blood_dna - -/mob/living/carbon/alien/get_blood_dna_list() - return list("UNKNOWN DNA" = "X*") - -/mob/living/silicon/get_blood_dna_list() - return - -///to add a mob's dna info into an object's blood_dna list. -/atom/proc/transfer_mob_blood_dna(mob/living/injected_mob) - // Returns 0 if we have that blood already - var/new_blood_dna = injected_mob.get_blood_dna_list() - if(!new_blood_dna) - return FALSE - var/old_length = GET_ATOM_BLOOD_DNA_LENGTH(src) - add_blood_DNA(new_blood_dna) - if(GET_ATOM_BLOOD_DNA_LENGTH(src) == old_length) - return FALSE - return TRUE - -///to add blood from a mob onto something, and transfer their dna info -/atom/proc/add_mob_blood(mob/living/injected_mob) - var/list/blood_dna = injected_mob.get_blood_dna_list() - if(!blood_dna) - return FALSE - return add_blood_DNA(blood_dna) - -///Is this atom in space -/atom/proc/isinspace() - if(isspaceturf(get_turf(src))) - return TRUE - else - return FALSE - -///Used for making a sound when a mob involuntarily falls into the ground. -/atom/proc/handle_fall(mob/faller) - return - -///Respond to the singularity eating this atom -/atom/proc/singularity_act() - return - -/** - * Respond to the singularity pulling on us - * - * Default behaviour is to send [COMSIG_ATOM_SING_PULL] and return - */ -/atom/proc/singularity_pull(obj/singularity/singularity, current_size) - SEND_SIGNAL(src, COMSIG_ATOM_SING_PULL, singularity, current_size) - - -/** - * Respond to acid being used on our atom - * - * Default behaviour is to send [COMSIG_ATOM_ACID_ACT] and return - */ -/atom/proc/acid_act(acidpwr, acid_volume) - SEND_SIGNAL(src, COMSIG_ATOM_ACID_ACT, acidpwr, acid_volume) - return FALSE - -/** - * Respond to an emag being used on our atom - * - * Args: - * * mob/user: The mob that used the emag. Nullable. - * * obj/item/card/emag/emag_card: The emag that was used. Nullable. - * - * Returns: - * TRUE if the emag had any effect, falsey otherwise. - */ -/atom/proc/emag_act(mob/user, obj/item/card/emag/emag_card) - return (SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT, user, emag_card)) - -/** - * Respond to narsie eating our atom - * - * Default behaviour is to send [COMSIG_ATOM_NARSIE_ACT] and return - */ -/atom/proc/narsie_act() - SEND_SIGNAL(src, COMSIG_ATOM_NARSIE_ACT) - - -///Return the values you get when an RCD eats you? -/atom/proc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - return FALSE - - -/** - * Respond to an RCD acting on our item - * - * Default behaviour is to send [COMSIG_ATOM_RCD_ACT] and return FALSE - */ -/atom/proc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, list/rcd_data) - SEND_SIGNAL(src, COMSIG_ATOM_RCD_ACT, user, the_rcd, rcd_data["[RCD_DESIGN_MODE]"]) - return FALSE - -/** - * Respond to an electric bolt action on our item - * - * Default behaviour is to return, we define here to allow for cleaner code later on - */ -/atom/proc/zap_act(power, zap_flags) - return - -/** - * If someone's trying to dump items onto our atom, where should they be dumped to? - * - * Return a loc to place objects, or null to stop dumping. - */ -/atom/proc/get_dumping_location() - return null - -/** - * the vision impairment to give to the mob whose perspective is set to that atom - * - * (e.g. an unfocused camera giving you an impaired vision when looking through it) - */ -/atom/proc/get_remote_view_fullscreens(mob/user) - return - -/** - * the sight changes to give to the mob whose perspective is set to that atom - * - * (e.g. A mob with nightvision loses its nightvision while looking through a normal camera) - */ -/atom/proc/update_remote_sight(mob/living/user) - return - - -/** - * Hook for running code when a dir change occurs - * - * Not recommended to use, listen for the [COMSIG_ATOM_DIR_CHANGE] signal instead (sent by this proc) - */ -/atom/proc/setDir(newdir) - SHOULD_CALL_PARENT(TRUE) - if (SEND_SIGNAL(src, COMSIG_ATOM_PRE_DIR_CHANGE, dir, newdir) & COMPONENT_ATOM_BLOCK_DIR_CHANGE) - newdir = dir - return - SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir) - dir = newdir - SEND_SIGNAL(src, COMSIG_ATOM_POST_DIR_CHANGE, dir, newdir) - if(smoothing_flags & SMOOTH_BORDER_OBJECT) - QUEUE_SMOOTH_NEIGHBORS(src) - -/** - * Called when the atom log's in or out - * - * Default behaviour is to call on_log on the location this atom is in - */ -/atom/proc/on_log(login) - if(loc) - loc.on_log(login) - - -/* - Atom Colour Priority System - A System that gives finer control over which atom colour to colour the atom with. - The "highest priority" one is always displayed as opposed to the default of - "whichever was set last is displayed" -*/ - - -///Adds an instance of colour_type to the atom's atom_colours list -/atom/proc/add_atom_colour(coloration, colour_priority) - if(!atom_colours || !atom_colours.len) - atom_colours = list() - atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently. - if(!coloration) - return - if(colour_priority > atom_colours.len) - return - atom_colours[colour_priority] = coloration - update_atom_colour() - - -///Removes an instance of colour_type from the atom's atom_colours list -/atom/proc/remove_atom_colour(colour_priority, coloration) - if(!atom_colours) - return - if(colour_priority > atom_colours.len) - return - if(coloration && atom_colours[colour_priority] != coloration) - return //if we don't have the expected color (for a specific priority) to remove, do nothing - atom_colours[colour_priority] = null - update_atom_colour() - -/** - * Checks if this atom has the passed color - * Can optionally be supplied with a range of priorities, IE only checking "washable" or above - */ -/atom/proc/is_atom_colour(looking_for_color, min_priority_index = 1, max_priority_index = COLOUR_PRIORITY_AMOUNT) - // make sure uppertext hex strings don't mess with lowertext hex strings - looking_for_color = lowertext(looking_for_color) - - if(!LAZYLEN(atom_colours)) - // no atom colors list has been set up, just check the color var - return lowertext(color) == looking_for_color - - for(var/i in min_priority_index to max_priority_index) - if(lowertext(atom_colours[i]) == looking_for_color) - return TRUE - - return FALSE - -///Resets the atom's color to null, and then sets it to the highest priority colour available -/atom/proc/update_atom_colour() - color = null - if(!atom_colours) - return - for(var/checked_color in atom_colours) - if(islist(checked_color)) - var/list/color_list = checked_color - if(color_list.len) - color = color_list - return - else if(checked_color) - color = checked_color - return - - -/** - * Wash this atom - * - * This will clean it off any temporary stuff like blood. Override this in your item to add custom cleaning behavior. - * Returns true if any washing was necessary and thus performed - * Arguments: - * * clean_types: any of the CLEAN_ constants - */ -/atom/proc/wash(clean_types) - SHOULD_CALL_PARENT(TRUE) - if(SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, clean_types) & COMPONENT_CLEANED) - return TRUE - - // Basically "if has washable coloration" - if(length(atom_colours) >= WASHABLE_COLOUR_PRIORITY && atom_colours[WASHABLE_COLOUR_PRIORITY]) - remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - return TRUE - return FALSE - -/** - * call back when a var is edited on this atom - * - * Can be used to implement special handling of vars - * - * At the atom level, if you edit a var named "color" it will add the atom colour with - * admin level priority to the atom colours list - * - * Also, if GLOB.Debug2 is FALSE, it sets the [ADMIN_SPAWNED_1] flag on [flags_1][/atom/var/flags_1], which signifies - * the object has been admin edited - */ -/atom/vv_edit_var(var_name, var_value) - var/old_light_flags = light_flags - // Disable frozen lights for now, so we can actually modify it - light_flags &= ~LIGHT_FROZEN - switch(var_name) - if(NAMEOF(src, light_range)) - if(light_system == STATIC_LIGHT) - set_light(l_range = var_value) - else - set_light_range(var_value) - . = TRUE - if(NAMEOF(src, light_power)) - if(light_system == STATIC_LIGHT) - set_light(l_power = var_value) - else - set_light_power(var_value) - . = TRUE - if(NAMEOF(src, light_color)) - if(light_system == STATIC_LIGHT) - set_light(l_color = var_value) - else - set_light_color(var_value) - . = TRUE - if(NAMEOF(src, light_angle)) - if(light_system == STATIC_LIGHT) - set_light(l_angle = var_value) - . = TRUE - if(NAMEOF(src, light_dir)) - if(light_system == STATIC_LIGHT) - set_light(l_dir = var_value) - . = TRUE - if(NAMEOF(src, light_height)) - if(light_system == STATIC_LIGHT) - set_light(l_height = var_value) - . = TRUE - if(NAMEOF(src, light_on)) - if(light_system == STATIC_LIGHT) - set_light(l_on = var_value) - else - set_light_on(var_value) - . = TRUE - if(NAMEOF(src, light_flags)) - set_light_flags(var_value) - // I'm sorry - old_light_flags = var_value - . = TRUE - if(NAMEOF(src, smoothing_junction)) - set_smoothed_icon_state(var_value) - . = TRUE - if(NAMEOF(src, opacity)) - set_opacity(var_value) - . = TRUE - if(NAMEOF(src, base_pixel_x)) - set_base_pixel_x(var_value) - . = TRUE - if(NAMEOF(src, base_pixel_y)) - set_base_pixel_y(var_value) - . = TRUE - - light_flags = old_light_flags - if(!isnull(.)) - datum_flags |= DF_VAR_EDITED - return - - if(!GLOB.Debug2) - flags_1 |= ADMIN_SPAWNED_1 - - . = ..() - - switch(var_name) - if(NAMEOF(src, color)) - add_atom_colour(color, ADMIN_COLOUR_PRIORITY) - update_appearance() - - -/** - * Return the markup to for the dropdown list for the VV panel for this atom - * - * Override in subtypes to add custom VV handling in the VV panel - */ -/atom/vv_get_dropdown() - . = ..() - VV_DROPDOWN_OPTION("", "---------") - if(!ismovable(src)) - var/turf/curturf = get_turf(src) - if(curturf) - . += "" - VV_DROPDOWN_OPTION(VV_HK_MODIFY_TRANSFORM, "Modify Transform") - VV_DROPDOWN_OPTION(VV_HK_SPIN_ANIMATION, "SpinAnimation") - VV_DROPDOWN_OPTION(VV_HK_STOP_ALL_ANIMATIONS, "Stop All Animations") - VV_DROPDOWN_OPTION(VV_HK_SHOW_HIDDENPRINTS, "Show Hiddenprint log") - VV_DROPDOWN_OPTION(VV_HK_ADD_REAGENT, "Add Reagent") - VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EMP, "EMP Pulse") - VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EXPLOSION, "Explosion") - VV_DROPDOWN_OPTION(VV_HK_EDIT_FILTERS, "Edit Filters") - VV_DROPDOWN_OPTION(VV_HK_EDIT_COLOR_MATRIX, "Edit Color as Matrix") - VV_DROPDOWN_OPTION(VV_HK_TEST_MATRIXES, "Test Matrices") - VV_DROPDOWN_OPTION(VV_HK_ADD_AI, "Add AI controller") - VV_DROPDOWN_OPTION(VV_HK_ARMOR_MOD, "Modify Armor") - if(greyscale_colors) - VV_DROPDOWN_OPTION(VV_HK_MODIFY_GREYSCALE, "Modify greyscale colors") - -/atom/vv_do_topic(list/href_list) - . = ..() - if(href_list[VV_HK_ADD_REAGENT] && check_rights(R_VAREDIT)) - if(!reagents) - var/amount = input(usr, "Specify the reagent size of [src]", "Set Reagent Size", 50) as num|null - if(amount) - create_reagents(amount) - - if(reagents) - var/chosen_id - switch(tgui_alert(usr, "Choose a method.", "Add Reagents", list("Search", "Choose from a list", "I'm feeling lucky"))) - if("Search") - var/valid_id - while(!valid_id) - chosen_id = input(usr, "Enter the ID of the reagent you want to add.", "Search reagents") as null|text - if(isnull(chosen_id)) //Get me out of here! - break - if (!ispath(text2path(chosen_id))) - chosen_id = pick_closest_path(chosen_id, make_types_fancy(subtypesof(/datum/reagent))) - if (ispath(chosen_id)) - valid_id = TRUE - else - valid_id = TRUE - if(!valid_id) - to_chat(usr, span_warning("A reagent with that ID doesn't exist!")) - if("Choose from a list") - chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in sort_list(subtypesof(/datum/reagent), GLOBAL_PROC_REF(cmp_typepaths_asc)) - if("I'm feeling lucky") - chosen_id = pick(subtypesof(/datum/reagent)) - if(chosen_id) - var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", reagents.maximum_volume) as num|null - if(amount) - reagents.add_reagent(chosen_id, amount) - log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to [src]") - message_admins(span_notice("[key_name(usr)] has added [amount] units of [chosen_id] to [src]")) - - if(href_list[VV_HK_TRIGGER_EXPLOSION] && check_rights(R_FUN)) - usr.client.cmd_admin_explosion(src) - - if(href_list[VV_HK_TRIGGER_EMP] && check_rights(R_FUN)) - usr.client.cmd_admin_emp(src) - - if(href_list[VV_HK_SHOW_HIDDENPRINTS] && check_rights(R_ADMIN)) - usr.client.cmd_show_hiddenprints(src) - - if(href_list[VV_HK_ARMOR_MOD]) - var/list/pickerlist = list() - var/list/armorlist = get_armor().get_rating_list() - - for (var/i in armorlist) - pickerlist += list(list("value" = armorlist[i], "name" = i)) - - var/list/result = presentpicker(usr, "Modify armor", "Modify armor: [src]", Button1="Save", Button2 = "Cancel", Timeout=FALSE, inputtype = "text", values = pickerlist) - var/list/armor_all = ARMOR_LIST_ALL() - - if (islist(result)) - if (result["button"] != 2) // If the user pressed the cancel button - // text2num conveniently returns a null on invalid values - var/list/converted = list() - for(var/armor_key in armor_all) - converted[armor_key] = text2num(result["values"][armor_key]) - set_armor(get_armor().generate_new_with_specific(converted)) - var/message = "[key_name(usr)] modified the armor on [src] ([type]) to: " - for(var/armor_key in armor_all) - message += "[armor_key]=[get_armor_rating(armor_key)]," - message = copytext(message, 1, -1) - log_admin(span_notice(message)) - message_admins(span_notice(message)) - - if(href_list[VV_HK_ADD_AI]) - if(!check_rights(R_VAREDIT)) - return - var/result = input(usr, "Choose the AI controller to apply to this atom WARNING: Not all AI works on all atoms.", "AI controller") as null|anything in subtypesof(/datum/ai_controller) - if(!result) - return - ai_controller = new result(src) - - if(href_list[VV_HK_MODIFY_TRANSFORM] && check_rights(R_VAREDIT)) - var/result = input(usr, "Choose the transformation to apply","Transform Mod") as null|anything in list("Scale","Translate","Rotate","Shear") - var/matrix/M = transform - if(!result) - return - switch(result) - if("Scale") - var/x = input(usr, "Choose x mod","Transform Mod") as null|num - var/y = input(usr, "Choose y mod","Transform Mod") as null|num - if(isnull(x) || isnull(y)) - return - transform = M.Scale(x,y) - if("Translate") - var/x = input(usr, "Choose x mod (negative = left, positive = right)","Transform Mod") as null|num - var/y = input(usr, "Choose y mod (negative = down, positive = up)","Transform Mod") as null|num - if(isnull(x) || isnull(y)) - return - transform = M.Translate(x,y) - if("Shear") - var/x = input(usr, "Choose x mod","Transform Mod") as null|num - var/y = input(usr, "Choose y mod","Transform Mod") as null|num - if(isnull(x) || isnull(y)) - return - transform = M.Shear(x,y) - if("Rotate") - var/angle = input(usr, "Choose angle to rotate","Transform Mod") as null|num - if(isnull(angle)) - return - transform = M.Turn(angle) - - SEND_SIGNAL(src, COMSIG_ATOM_VV_MODIFY_TRANSFORM) - - if(href_list[VV_HK_SPIN_ANIMATION] && check_rights(R_VAREDIT)) - var/num_spins = input(usr, "Do you want infinite spins?", "Spin Animation") in list("Yes", "No") - if(num_spins == "No") - num_spins = input(usr, "How many spins?", "Spin Animation") as null|num - else - num_spins = -1 - if(!num_spins) - return - var/spin_speed = input(usr, "How fast?", "Spin Animation") as null|num - if(!spin_speed) - return - var/direction = input(usr, "Which direction?", "Spin Animation") in list("Clockwise", "Counter-clockwise") - switch(direction) - if("Clockwise") - direction = 1 - if("Counter-clockwise") - direction = 0 - else - return - SpinAnimation(spin_speed, num_spins, direction) - - if(href_list[VV_HK_STOP_ALL_ANIMATIONS] && check_rights(R_VAREDIT)) - var/result = input(usr, "Are you sure?", "Stop Animating") in list("Yes", "No") - if(result == "Yes") - animate(src, transform = null, flags = ANIMATION_END_NOW) // Literally just fucking stop animating entirely because admin said so - return - - if(href_list[VV_HK_AUTO_RENAME] && check_rights(R_VAREDIT)) - var/newname = input(usr, "What do you want to rename this to?", "Automatic Rename") as null|text - // Check the new name against the chat filter. If it triggers the IC chat filter, give an option to confirm. - if(newname && !(is_ic_filtered(newname) || is_soft_ic_filtered(newname) && tgui_alert(usr, "Your selected name contains words restricted by IC chat filters. Confirm this new name?", "IC Chat Filter Conflict", list("Confirm", "Cancel")) != "Confirm")) - vv_auto_rename(newname) - - if(href_list[VV_HK_EDIT_FILTERS] && check_rights(R_VAREDIT)) - usr.client?.open_filter_editor(src) - - if(href_list[VV_HK_EDIT_COLOR_MATRIX] && check_rights(R_VAREDIT)) - usr.client?.open_color_matrix_editor(src) - - if(href_list[VV_HK_TEST_MATRIXES] && check_rights(R_VAREDIT)) - usr.client?.open_matrix_tester(src) - -/atom/vv_get_header() - . = ..() - var/refid = REF(src) - . += "[VV_HREF_TARGETREF(refid, VV_HK_AUTO_RENAME, "[src]")]" - . += "
<< [dir2text(dir) || dir] >>" - -///Where atoms should drop if taken from this atom -/atom/proc/drop_location() - var/atom/location = loc - if(!location) - return null - return location.AllowDrop() ? location : location.drop_location() - -/atom/proc/vv_auto_rename(newname) - name = newname - -/** - * An atom has entered this atom's contents - * - * Default behaviour is to send the [COMSIG_ATOM_ENTERED] - */ -/atom/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) - SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, arrived, old_loc, old_locs) - SEND_SIGNAL(arrived, COMSIG_ATOM_ENTERING, src, old_loc, old_locs) - -/** - * An atom is attempting to exit this atom's contents - * - * Default behaviour is to send the [COMSIG_ATOM_EXIT] - */ -/atom/Exit(atom/movable/leaving, direction) - // Don't call `..()` here, otherwise `Uncross()` gets called. - // See the doc comment on `Uncross()` to learn why this is bad. - - if(SEND_SIGNAL(src, COMSIG_ATOM_EXIT, leaving, direction) & COMPONENT_ATOM_BLOCK_EXIT) - return FALSE - - return TRUE - -/** - * An atom has exited this atom's contents - * - * Default behaviour is to send the [COMSIG_ATOM_EXITED] - */ -/atom/Exited(atom/movable/gone, direction) - SEND_SIGNAL(src, COMSIG_ATOM_EXITED, gone, direction) - -///Return atom temperature -/atom/proc/return_temperature() - return - -/** - *Tool behavior procedure. Redirects to tool-specific procs by default. - * - * You can override it to catch all tool interactions, for use in complex deconstruction procs. - * - * Must return parent proc ..() in the end if overridden - */ -/atom/proc/tool_act(mob/living/user, obj/item/tool, tool_type, is_right_clicking) - var/act_result - var/signal_result - - var/is_left_clicking = !is_right_clicking - - if(is_left_clicking) // Left click first for sensibility - var/list/processing_recipes = list() //List of recipes that can be mutated by sending the signal - signal_result = SEND_SIGNAL(src, COMSIG_ATOM_TOOL_ACT(tool_type), user, tool, processing_recipes) - if(signal_result & COMPONENT_BLOCK_TOOL_ATTACK) // The COMSIG_ATOM_TOOL_ACT signal is blocking the act - return TOOL_ACT_SIGNAL_BLOCKING - if(processing_recipes.len) - process_recipes(user, tool, processing_recipes) - if(QDELETED(tool)) - return TRUE - else - signal_result = SEND_SIGNAL(src, COMSIG_ATOM_SECONDARY_TOOL_ACT(tool_type), user, tool) - if(signal_result & COMPONENT_BLOCK_TOOL_ATTACK) // The COMSIG_ATOM_TOOL_ACT signal is blocking the act - return TOOL_ACT_SIGNAL_BLOCKING - - switch(tool_type) - if(TOOL_CROWBAR) - act_result = is_left_clicking ? crowbar_act(user, tool) : crowbar_act_secondary(user, tool) - if(TOOL_MULTITOOL) - act_result = is_left_clicking ? multitool_act(user, tool) : multitool_act_secondary(user, tool) - if(TOOL_SCREWDRIVER) - act_result = is_left_clicking ? screwdriver_act(user, tool) : screwdriver_act_secondary(user, tool) - if(TOOL_WRENCH) - act_result = is_left_clicking ? wrench_act(user, tool) : wrench_act_secondary(user, tool) - if(TOOL_WIRECUTTER) - act_result = is_left_clicking ? wirecutter_act(user, tool) : wirecutter_act_secondary(user, tool) - if(TOOL_WELDER) - act_result = is_left_clicking ? welder_act(user, tool) : welder_act_secondary(user, tool) - if(TOOL_ANALYZER) - act_result = is_left_clicking ? analyzer_act(user, tool) : analyzer_act_secondary(user, tool) - if(!act_result) - return - - // A tooltype_act has completed successfully - if(is_left_clicking) - log_tool("[key_name(user)] used [tool] on [src] at [AREACOORD(src)]") - SEND_SIGNAL(tool, COMSIG_TOOL_ATOM_ACTED_PRIMARY(tool_type), src) - else - log_tool("[key_name(user)] used [tool] on [src] (right click) at [AREACOORD(src)]") - SEND_SIGNAL(tool, COMSIG_TOOL_ATOM_ACTED_SECONDARY(tool_type), src) - return TOOL_ACT_TOOLTYPE_SUCCESS - - -/atom/proc/process_recipes(mob/living/user, obj/item/processed_object, list/processing_recipes) - //Only one recipe? use the first - if(processing_recipes.len == 1) - StartProcessingAtom(user, processed_object, processing_recipes[1]) - return - //Otherwise, select one with a radial - ShowProcessingGui(user, processed_object, processing_recipes) - -///Creates the radial and processes the selected option -/atom/proc/ShowProcessingGui(mob/living/user, obj/item/processed_object, list/possible_options) - var/list/choices_to_options = list() //Dict of object name | dict of object processing settings - var/list/choices = list() - - for(var/list/current_option as anything in possible_options) - var/atom/current_option_type = current_option[TOOL_PROCESSING_RESULT] - choices_to_options[initial(current_option_type.name)] = current_option - var/image/option_image = image(icon = initial(current_option_type.icon), icon_state = initial(current_option_type.icon_state)) - choices += list("[initial(current_option_type.name)]" = option_image) - - var/pick = show_radial_menu(user, src, choices, radius = 36, require_near = TRUE) - if(!pick) - return - - StartProcessingAtom(user, processed_object, choices_to_options[pick]) - - -/atom/proc/StartProcessingAtom(mob/living/user, obj/item/process_item, list/chosen_option) - var/processing_time = chosen_option[TOOL_PROCESSING_TIME] - to_chat(user, span_notice("You start working on [src].")) - if(process_item.use_tool(src, user, processing_time, volume=50)) - var/atom/atom_to_create = chosen_option[TOOL_PROCESSING_RESULT] - var/list/atom/created_atoms = list() - var/amount_to_create = chosen_option[TOOL_PROCESSING_AMOUNT] - for(var/i = 1 to amount_to_create) - var/atom/created_atom = new atom_to_create(drop_location()) - if(custom_materials) - created_atom.set_custom_materials(custom_materials, 1 / amount_to_create) - created_atom.pixel_x = pixel_x - created_atom.pixel_y = pixel_y - if(i > 1) - created_atom.pixel_x += rand(-8,8) - created_atom.pixel_y += rand(-8,8) - created_atom.OnCreatedFromProcessing(user, process_item, chosen_option, src) - created_atoms.Add(created_atom) - to_chat(user, span_notice("You manage to create [amount_to_create] [initial(atom_to_create.gender) == PLURAL ? "[initial(atom_to_create.name)]" : "[initial(atom_to_create.name)][plural_s(initial(atom_to_create.name))]"] from [src].")) - SEND_SIGNAL(src, COMSIG_ATOM_PROCESSED, user, process_item, created_atoms) - UsedforProcessing(user, process_item, chosen_option) - return - -/atom/proc/UsedforProcessing(mob/living/user, obj/item/used_item, list/chosen_option) - qdel(src) - return - -/atom/proc/OnCreatedFromProcessing(mob/living/user, obj/item/work_tool, list/chosen_option, atom/original_atom) - SHOULD_CALL_PARENT(TRUE) - - SEND_SIGNAL(src, COMSIG_ATOM_CREATEDBY_PROCESSING, original_atom, chosen_option) - if(user.mind) - ADD_TRAIT(src, TRAIT_FOOD_CHEF_MADE, REF(user.mind)) - -//! Tool-specific behavior procs. -/// - -/// Called on an object when a tool with crowbar capabilities is used to left click an object -/atom/proc/crowbar_act(mob/living/user, obj/item/tool) - return - -/// Called on an object when a tool with crowbar capabilities is used to right click an object -/atom/proc/crowbar_act_secondary(mob/living/user, obj/item/tool) - return - -/// Called on an object when a tool with multitool capabilities is used to left click an object -/atom/proc/multitool_act(mob/living/user, obj/item/tool) - return - -/// Called on an object when a tool with multitool capabilities is used to right click an object -/atom/proc/multitool_act_secondary(mob/living/user, obj/item/tool) - return - -///Check if an item supports a data buffer (is a multitool) -/atom/proc/multitool_check_buffer(user, obj/item/multitool, silent = FALSE) - if(!istype(multitool, /obj/item/multitool)) - if(user && !silent) - to_chat(user, span_warning("[multitool] has no data buffer!")) - return FALSE - return TRUE - -/// Called on an object when a tool with screwdriver capabilities is used to left click an object -/atom/proc/screwdriver_act(mob/living/user, obj/item/tool) - return - -/// Called on an object when a tool with screwdriver capabilities is used to right click an object -/atom/proc/screwdriver_act_secondary(mob/living/user, obj/item/tool) - return - -/// Called on an object when a tool with wrench capabilities is used to left click an object -/atom/proc/wrench_act(mob/living/user, obj/item/tool) - return - -/// Called on an object when a tool with wrench capabilities is used to right click an object -/atom/proc/wrench_act_secondary(mob/living/user, obj/item/tool) - return - -/// Called on an object when a tool with wirecutter capabilities is used to left click an object -/atom/proc/wirecutter_act(mob/living/user, obj/item/tool) - return - -/// Called on an object when a tool with wirecutter capabilities is used to right click an object -/atom/proc/wirecutter_act_secondary(mob/living/user, obj/item/tool) - return - -/// Called on an object when a tool with welder capabilities is used to left click an object -/atom/proc/welder_act(mob/living/user, obj/item/tool) - return - -/// Called on an object when a tool with welder capabilities is used to right click an object -/atom/proc/welder_act_secondary(mob/living/user, obj/item/tool) - return - -/// Called on an object when a tool with analyzer capabilities is used to left click an object -/atom/proc/analyzer_act(mob/living/user, obj/item/tool) - return - -/// Called on an object when a tool with analyzer capabilities is used to right click an object -/atom/proc/analyzer_act_secondary(mob/living/user, obj/item/tool) - return - -///Connect this atom to a shuttle -/atom/proc/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock) - return - -/atom/proc/intercept_zImpact(list/falling_movables, levels = 1) - SHOULD_CALL_PARENT(TRUE) - . |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, falling_movables, levels) - -/// Sets the custom materials for an item. -/atom/proc/set_custom_materials(list/materials, multiplier = 1) - if(custom_materials && material_flags & MATERIAL_EFFECTS) //Only runs if custom materials existed at first and affected src. - for(var/current_material in custom_materials) - var/datum/material/custom_material = GET_MATERIAL_REF(current_material) - custom_material.on_removed(src, custom_materials[current_material] * material_modifier, material_flags) //Remove the current materials - - if(!length(materials)) - custom_materials = null - return - - if(material_flags & MATERIAL_EFFECTS) - for(var/current_material in materials) - var/datum/material/custom_material = GET_MATERIAL_REF(current_material) - custom_material.on_applied(src, materials[current_material] * multiplier * material_modifier, material_flags) - - custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials, multiplier) - -/** - * Returns the material composition of the atom. - * - * Used when recycling items, specifically to turn alloys back into their component mats. - * - * Exists because I'd need to add a way to un-alloy alloys or otherwise deal - * with people converting the entire stations material supply into alloys. - * - * Arguments: - * - flags: A set of flags determining how exactly the materials are broken down. - */ -/atom/proc/get_material_composition(breakdown_flags=NONE) - . = list() - if(!(breakdown_flags & BREAKDOWN_INCLUDE_ALCHEMY) && HAS_TRAIT(src, TRAIT_MAT_TRANSMUTED)) - return - - var/list/cached_materials = custom_materials - for(var/mat in cached_materials) - var/datum/material/material = GET_MATERIAL_REF(mat) - var/list/material_comp = material.return_composition(cached_materials[mat], breakdown_flags) - for(var/comp_mat in material_comp) - .[comp_mat] += material_comp[comp_mat] - -/** - * Fetches a list of all of the materials this object has of the desired type. Returns null if there is no valid materials of the type - * - * Arguments: - * - [required_material][/datum/material]: The type of material we are checking for - * - mat_amount: The minimum required amount of material - */ -/atom/proc/has_material_type(datum/material/required_material, mat_amount = 0) - var/list/cached_materials = custom_materials - if(!length(cached_materials)) - return null - - var/materials_of_type - for(var/current_material in cached_materials) - if(cached_materials[current_material] < mat_amount) - continue - var/datum/material/material = GET_MATERIAL_REF(current_material) - if(!istype(material, required_material)) - continue - LAZYSET(materials_of_type, material, cached_materials[current_material]) - - return materials_of_type - -/** - * Fetches a list of all of the materials this object has with the desired material category. - * - * Arguments: - * - category: The category to check for - * - any_flags: Any bitflags that must be present for the category - * - all_flags: All bitflags that must be present for the category - * - no_flags: Any bitflags that must not be present for the category - * - mat_amount: The minimum amount of materials that must be present - */ -/atom/proc/has_material_category(category, any_flags=0, all_flags=0, no_flags=0, mat_amount=0) - var/list/cached_materials = custom_materials - if(!length(cached_materials)) - return null - - var/materials_of_category - for(var/current_material in cached_materials) - if(cached_materials[current_material] < mat_amount) - continue - var/datum/material/material = GET_MATERIAL_REF(current_material) - var/category_flags = material?.categories[category] - if(isnull(category_flags)) - continue - if(any_flags && !(category_flags & any_flags)) - continue - if(all_flags && (all_flags != (category_flags & all_flags))) - continue - if(no_flags && (category_flags & no_flags)) - continue - LAZYSET(materials_of_category, material, cached_materials[current_material]) - return materials_of_category - -/** - * Gets the most common material in the object. - */ -/atom/proc/get_master_material() - var/list/cached_materials = custom_materials - if(!length(cached_materials)) - return null - - var/most_common_material = null - var/max_amount = 0 - for(var/material in cached_materials) - if(cached_materials[material] > max_amount) - most_common_material = material - max_amount = cached_materials[material] - - if(most_common_material) - return GET_MATERIAL_REF(most_common_material) - -/** - * Gets the total amount of materials in this atom. - */ -/atom/proc/get_custom_material_amount() - return isnull(custom_materials) ? 0 : counterlist_sum(custom_materials) - - -///Setter for the `density` variable to append behavior related to its changing. -/atom/proc/set_density(new_value) - SHOULD_CALL_PARENT(TRUE) - if(density == new_value) - return - . = density - density = new_value - - -///Setter for the `base_pixel_x` variable to append behavior related to its changing. -/atom/proc/set_base_pixel_x(new_value) - if(base_pixel_x == new_value) - return - . = base_pixel_x - base_pixel_x = new_value - - pixel_x = pixel_x + base_pixel_x - . - - -///Setter for the `base_pixel_y` variable to append behavior related to its changing. -/atom/proc/set_base_pixel_y(new_value) - if(base_pixel_y == new_value) - return - . = base_pixel_y - base_pixel_y = new_value - - pixel_y = pixel_y + base_pixel_y - . - -// Not a valid operation, turfs and movables handle block differently -/atom/proc/set_explosion_block(explosion_block) - return - -/** - * Returns true if this atom has gravity for the passed in turf - * - * Sends signals [COMSIG_ATOM_HAS_GRAVITY] and [COMSIG_TURF_HAS_GRAVITY], both can force gravity with - * the forced gravity var. - * - * micro-optimized to hell because this proc is very hot, being called several times per movement every movement. - * - * HEY JACKASS, LISTEN - * IF YOU ADD SOMETHING TO THIS PROC, MAKE SURE /mob/living ACCOUNTS FOR IT - * Living mobs treat gravity in an event based manner. We've decomposed this proc into different checks - * for them to use. If you add more to it, make sure you do that, or things will behave strangely - * - * Gravity situations: - * * No gravity if you're not in a turf - * * No gravity if this atom is in is a space turf - * * Gravity if the area it's in always has gravity - * * Gravity if there's a gravity generator on the z level - * * Gravity if the Z level has an SSMappingTrait for ZTRAIT_GRAVITY - * * otherwise no gravity - */ -/atom/proc/has_gravity(turf/gravity_turf) - if(!isturf(gravity_turf)) - gravity_turf = get_turf(src) - - if(!gravity_turf)//no gravity in nullspace - return FALSE - - var/list/forced_gravity = list() - SEND_SIGNAL(src, COMSIG_ATOM_HAS_GRAVITY, gravity_turf, forced_gravity) - SEND_SIGNAL(gravity_turf, COMSIG_TURF_HAS_GRAVITY, src, forced_gravity) - if(length(forced_gravity)) - var/positive_grav = max(forced_gravity) - var/negative_grav = min(min(forced_gravity), 0) //negative grav needs to be below or equal to 0 - - //our gravity is sum of the most massive positive and negative numbers returned by the signal - //so that adding two forced_gravity elements with an effect size of 1 each doesnt add to 2 gravity - //but negative force gravity effects can cancel out positive ones - - return (positive_grav + negative_grav) - - var/area/turf_area = gravity_turf.loc - - return !gravity_turf.force_no_gravity && (SSmapping.gravity_by_z_level[gravity_turf.z] || turf_area.has_gravity) - -/** - * Causes effects when the atom gets hit by a rust effect from heretics - * - * Override this if you want custom behaviour in whatever gets hit by the rust - */ -/atom/proc/rust_heretic_act() - return - -/** - * Used to set something as 'open' if it's being used as a supplypod - * - * Override this if you want an atom to be usable as a supplypod. - */ -/atom/proc/setOpened() - return - -/** - * Used to set something as 'closed' if it's being used as a supplypod - * - * Override this if you want an atom to be usable as a supplypod. - */ -/atom/proc/setClosed() - return - - -///Called when something resists while this atom is its loc -/atom/proc/container_resist_act(mob/living/user) - -/** - * Used to attempt to charge an object with a payment component. - * - * Use this if an atom needs to attempt to charge another atom. - */ -/atom/proc/attempt_charge(atom/sender, atom/target, extra_fees = 0) - return SEND_SIGNAL(sender, COMSIG_OBJ_ATTEMPT_CHARGE, target, extra_fees) - -///Passes Stat Browser Panel clicks to the game and calls client click on an atom -/atom/Topic(href, list/href_list) - . = ..() - if(!usr?.client) - return - var/client/usr_client = usr.client - var/list/paramslist = list() - - if(href_list["statpanel_item_click"]) - switch(href_list["statpanel_item_click"]) - if("left") - paramslist[LEFT_CLICK] = "1" - if("right") - paramslist[RIGHT_CLICK] = "1" - if("middle") - paramslist[MIDDLE_CLICK] = "1" - else - return - - if(href_list["statpanel_item_shiftclick"]) - paramslist[SHIFT_CLICK] = "1" - if(href_list["statpanel_item_ctrlclick"]) - paramslist[CTRL_CLICK] = "1" - if(href_list["statpanel_item_altclick"]) - paramslist[ALT_CLICK] = "1" - - var/mouseparams = list2params(paramslist) - usr_client.Click(src, loc, null, mouseparams) - return TRUE - -/** - * Recursive getter method to return a list of all ghosts orbitting this atom - * - * This will work fine without manually passing arguments. - * * processed - The list of atoms we've already convered - * * source - Is this the atom for who we're counting up all the orbiters? - * * ignored_stealthed_admins - If TRUE, don't count admins who are stealthmoded and orbiting this - */ -/atom/proc/get_all_orbiters(list/processed, source = TRUE, ignore_stealthed_admins = TRUE) - var/list/output = list() - if(!processed) - processed = list() - else if(src in processed) - return output - - if(!source) - output += src - - processed += src - for(var/atom/atom_orbiter as anything in orbiters?.orbiter_list) - output += atom_orbiter.get_all_orbiters(processed, source = FALSE) - return output - -/mob/get_all_orbiters(list/processed, source = TRUE, ignore_stealthed_admins = TRUE) - if(!source && ignore_stealthed_admins && client?.holder?.fakekey) - return list() - return ..() - -/atom/MouseEntered(location, control, params) - SSmouse_entered.hovers[usr.client] = src - -/// Fired whenever this atom is the most recent to be hovered over in the tick. -/// Preferred over MouseEntered if you do not need information such as the position of the mouse. -/// Especially because this is deferred over a tick, do not trust that `client` is not null. -/atom/proc/on_mouse_enter(client/client) - SHOULD_NOT_SLEEP(TRUE) - - var/mob/user = client?.mob - if (isnull(user)) - return - - // Screentips - var/datum/hud/active_hud = user.hud_used - if(!active_hud) - return - - var/screentips_enabled = active_hud.screentips_enabled - if(screentips_enabled == SCREENTIP_PREFERENCE_DISABLED || flags_1 & NO_SCREENTIPS_1) - active_hud.screentip_text.maptext = "" - return - - active_hud.screentip_text.maptext_y = 10 // 10px lines us up with the action buttons top left corner - var/lmb_rmb_line = "" - var/ctrl_lmb_ctrl_rmb_line = "" - var/alt_lmb_alt_rmb_line = "" - var/shift_lmb_ctrl_shift_lmb_line = "" - var/extra_lines = 0 - var/extra_context = "" - - if (isliving(user) || isovermind(user) || isaicamera(user)) - var/obj/item/held_item = user.get_active_held_item() - - if (flags_1 & HAS_CONTEXTUAL_SCREENTIPS_1 || held_item?.item_flags & ITEM_HAS_CONTEXTUAL_SCREENTIPS) - var/list/context = list() - - var/contextual_screentip_returns = \ - SEND_SIGNAL(src, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, context, held_item, user) \ - | (held_item && SEND_SIGNAL(held_item, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET, context, src, user)) - - if (contextual_screentip_returns & CONTEXTUAL_SCREENTIP_SET) - var/screentip_images = active_hud.screentip_images - // LMB and RMB on one line... - var/lmb_text = build_context(context, SCREENTIP_CONTEXT_LMB, screentip_images) - var/rmb_text = build_context(context, SCREENTIP_CONTEXT_RMB, screentip_images) - - if (lmb_text != "") - lmb_rmb_line = lmb_text - if (rmb_text != "") - lmb_rmb_line += " | [rmb_text]" - else if (rmb_text != "") - lmb_rmb_line = rmb_text - - // Ctrl-LMB, Ctrl-RMB on one line... - if (lmb_rmb_line != "") - lmb_rmb_line += "
" - extra_lines++ - if (SCREENTIP_CONTEXT_CTRL_LMB in context) - ctrl_lmb_ctrl_rmb_line += build_context(context, SCREENTIP_CONTEXT_CTRL_LMB, screentip_images) - - if (SCREENTIP_CONTEXT_CTRL_RMB in context) - if (ctrl_lmb_ctrl_rmb_line != "") - ctrl_lmb_ctrl_rmb_line += " | " - ctrl_lmb_ctrl_rmb_line += build_context(context, SCREENTIP_CONTEXT_CTRL_RMB, screentip_images) - - // Alt-LMB, Alt-RMB on one line... - if (ctrl_lmb_ctrl_rmb_line != "") - ctrl_lmb_ctrl_rmb_line += "
" - extra_lines++ - if (SCREENTIP_CONTEXT_ALT_LMB in context) - alt_lmb_alt_rmb_line += build_context(context, SCREENTIP_CONTEXT_ALT_LMB, screentip_images) - if (SCREENTIP_CONTEXT_ALT_RMB in context) - if (alt_lmb_alt_rmb_line != "") - alt_lmb_alt_rmb_line += " | " - alt_lmb_alt_rmb_line += build_context(context, SCREENTIP_CONTEXT_ALT_RMB, screentip_images) - - // Shift-LMB, Ctrl-Shift-LMB on one line... - if (alt_lmb_alt_rmb_line != "") - alt_lmb_alt_rmb_line += "
" - extra_lines++ - if (SCREENTIP_CONTEXT_SHIFT_LMB in context) - shift_lmb_ctrl_shift_lmb_line += build_context(context, SCREENTIP_CONTEXT_SHIFT_LMB, screentip_images) - if (SCREENTIP_CONTEXT_CTRL_SHIFT_LMB in context) - if (shift_lmb_ctrl_shift_lmb_line != "") - shift_lmb_ctrl_shift_lmb_line += " | " - shift_lmb_ctrl_shift_lmb_line += build_context(context, SCREENTIP_CONTEXT_CTRL_SHIFT_LMB, screentip_images) - - if (shift_lmb_ctrl_shift_lmb_line != "") - extra_lines++ - - if(extra_lines) - extra_context = "
[lmb_rmb_line][ctrl_lmb_ctrl_rmb_line][alt_lmb_alt_rmb_line][shift_lmb_ctrl_shift_lmb_line]" - //first extra line pushes atom name line up 11px, subsequent lines push it up 9px, this offsets that and keeps the first line in the same place - active_hud.screentip_text.maptext_y = -1 + (extra_lines - 1) * -9 - - if (screentips_enabled == SCREENTIP_PREFERENCE_CONTEXT_ONLY && extra_context == "") - active_hud.screentip_text.maptext = "" - else - //We inline a MAPTEXT() here, because there's no good way to statically add to a string like this - active_hud.screentip_text.maptext = "[name][extra_context]" - -/// Gets a merger datum representing the connected blob of objects in the allowed_types argument -/atom/proc/GetMergeGroup(id, list/allowed_types) - RETURN_TYPE(/datum/merger) - var/datum/merger/candidate - if(mergers) - candidate = mergers[id] - if(!candidate) - new /datum/merger(id, allowed_types, src) - candidate = mergers[id] - return candidate - -/** - * This proc is used for telling whether something can pass by this atom in a given direction, for use by the pathfinding system. - * - * Trying to generate one long path across the station will call this proc on every single object on every single tile that we're seeing if we can move through, likely - * multiple times per tile since we're likely checking if we can access said tile from multiple directions, so keep these as lightweight as possible. - * - * For turfs this will only be used if pathing_pass_method is TURF_PATHING_PASS_PROC - * - * Arguments: - * * to_dir - What direction we're trying to move in, relevant for things like directional windows that only block movement in certain directions - * * pass_info - Datum that stores info about the thing that's trying to pass us - * - * IMPORTANT NOTE: /turf/proc/LinkBlockedWithAccess assumes that overrides of CanAStarPass will always return true if density is FALSE - * If this is NOT you, ensure you edit your can_astar_pass variable. Check __DEFINES/path.dm - **/ -/atom/proc/CanAStarPass(to_dir, datum/can_pass_info/pass_info) - if(pass_info.pass_flags & pass_flags_self) - return TRUE - . = !density - -/// Makes this atom look like a "hologram" -/// So transparent, blue, with a scanline and an emissive glow -/// This is acomplished using a combination of filters and render steps/overlays -/// The degree of the opacity is optional, based off the opacity arg (0 -> 1) -/atom/proc/makeHologram(opacity = 0.5) - // First, we'll make things blue (roughly) and sorta transparent - add_filter("HOLO: Color and Transparent", 1, color_matrix_filter(rgb(125,180,225, opacity * 255))) - // Now we're gonna do a scanline effect - // Gonna take this atom and give it a render target, then use it as a source for a filter - // (We use an atom because it seems as if setting render_target on an MA is just invalid. I hate this engine) - var/atom/movable/scanline = new(null) - scanline.icon = 'icons/effects/effects.dmi' - scanline.icon_state = "scanline" - scanline.appearance_flags |= RESET_TRANSFORM - // * so it doesn't render - var/static/uid_scan = 0 - scanline.render_target = "*HoloScanline [uid_scan]" - uid_scan++ - // Now we add it as a filter, and overlay the appearance so the render source is always around - add_filter("HOLO: Scanline", 2, alpha_mask_filter(render_source = scanline.render_target)) - add_overlay(scanline) - qdel(scanline) - // Annd let's make the sucker emissive, so it glows in the dark - if(!render_target) - var/static/uid = 0 - render_target = "HOLOGRAM [uid]" - uid++ - // I'm using static here to reduce the overhead, it does mean we need to do plane stuff manually tho - var/static/atom/movable/render_step/emissive/glow = new(null) - glow.render_source = render_target - SET_PLANE_EXPLICIT(glow, initial(glow.plane), src) - // We're creating a render step that copies ourselves, and draws it to the emissive plane - // Then we overlay it, and release "ownership" back to this proc, since we get to keep the appearance it generates - // We can't just use an MA from the start cause render_source setting starts going fuckey REALLY quick - var/mutable_appearance/glow_appearance = new(glow) - add_overlay(glow_appearance) - LAZYADD(update_overlays_on_z, glow_appearance) - -/** - * Proc called when you want the atom to spin around the center of its icon (or where it would be if its transform var is translated) - * By default, it makes the atom spin forever and ever at a speed of 60 rpm. - * - * Arguments: - * * speed: how much it takes for the atom to complete one 360° rotation - * * loops: how many times do we want the atom to rotate - * * clockwise: whether the atom ought to spin clockwise or counter-clockwise - * * segments: in how many animate calls the rotation is split. Probably unnecessary, but you shouldn't set it lower than 3 anyway. - * * parallel: whether the animation calls have the ANIMATION_PARALLEL flag, necessary for it to run alongside concurrent animations. - */ -/atom/proc/SpinAnimation(speed = 1 SECONDS, loops = -1, clockwise = TRUE, segments = 3, parallel = TRUE) - if(!segments) - return - var/segment = 360/segments - if(!clockwise) - segment = -segment - SEND_SIGNAL(src, COMSIG_ATOM_SPIN_ANIMATION, speed, loops, segments, segment) - do_spin_animation(speed, loops, segments, segment, parallel) - -#define INVISIBILITY_VALUE 1 -#define INVISIBILITY_PRIORITY 2 - -/atom/proc/RecalculateInvisibility() - PRIVATE_PROC(TRUE) - - if(!invisibility_sources) - current_invisibility_priority = -INFINITY - invisibility = initial(invisibility) - return - - var/highest_priority - var/list/highest_priority_invisibility_data - for(var/entry in invisibility_sources) - var/list/priority_data - if(islist(entry)) - priority_data = entry - else - priority_data = invisibility_sources[entry] - - var/priority = priority_data[INVISIBILITY_PRIORITY] - if(highest_priority > priority) // In the case of equal priorities, we use the last thing in the list so that more recent changes apply first - continue - - highest_priority = priority - highest_priority_invisibility_data = priority_data - - current_invisibility_priority = highest_priority - invisibility = highest_priority_invisibility_data[INVISIBILITY_VALUE] - -/** - * Sets invisibility according to priority. - * If you want to be able to undo the value you set back to what it would be otherwise, - * you should provide an id here and remove it using RemoveInvisibility(id) - */ -/atom/proc/SetInvisibility(desired_value, id, priority=0) - if(!invisibility_sources) - invisibility_sources = list() - - if(id) - invisibility_sources[id] = list(desired_value, priority) - else - invisibility_sources += list(list(desired_value, priority)) - - if(current_invisibility_priority > priority) - return - - RecalculateInvisibility() - -/// Removes the specified invisibility source from the tracker -/atom/proc/RemoveInvisibility(id) - if(!invisibility_sources) - return - - var/list/priority_data = invisibility_sources[id] - invisibility_sources -= id - - if(length(invisibility_sources) == 0) - invisibility_sources = null - - if(current_invisibility_priority > priority_data[INVISIBILITY_PRIORITY]) - return - - RecalculateInvisibility() - -#undef INVISIBILITY_VALUE -#undef INVISIBILITY_PRIORITY diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index c9680744fcbff..90cafd9180ac1 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -7,6 +7,7 @@ base_icon_state = "pdapainter" density = TRUE max_integrity = 200 + integrity_failure = 0.5 /// Current ID card inserted into the machine. var/obj/item/card/id/stored_id_card = null /// Current PDA inserted into the machine. @@ -160,9 +161,6 @@ eject_id_card(user) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/machinery/pdapainter/deconstruct(disassembled = TRUE) - atom_break() - /** * Insert a PDA into the machine. * diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 73cb940512650..4e195bfd913cd 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -131,7 +131,7 @@ var/subsystem_type = /datum/controller/subsystem/machines var/obj/item/circuitboard/circuit // Circuit to be created and inserted when the machinery is created - var/interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN|INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_OPEN_SILICON|INTERACT_MACHINE_SET_MACHINE + var/interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN|INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_OPEN_SILICON var/fair_market_price = 69 var/market_verb = "Customer" var/payment_department = ACCOUNT_ENG @@ -512,19 +512,24 @@ return TRUE ///Get a valid powered area to reference for power use, mainly for wall-mounted machinery that isn't always mapped directly in a powered location. -/obj/machinery/proc/get_room_area(area/machine_room) +/obj/machinery/proc/get_room_area() var/area/machine_area = get_area(src) - if(!machine_area.always_unpowered) ///check our loc first to see if its a powered area - machine_room = machine_area - return machine_room - var/turf/mounted_wall = get_step(src,dir) - if (mounted_wall && istype(mounted_wall, /turf/closed)) + if(isnull(machine_area)) + return null // ?? + + // check our own loc first to see if its a powered area + if(!machine_area.always_unpowered) + return machine_area + + // loc area wasn't good, checking adjacent wall for a good area to use + var/turf/mounted_wall = get_step(src, dir) + if(isclosedturf(mounted_wall)) var/area/wall_area = get_area(mounted_wall) - if(!wall_area.always_unpowered) //loc area wasn't good, checking adjacent wall for a good area to use - machine_room = wall_area - return machine_room - machine_room = machine_area ///couldn't find a proper powered area on loc or adjacent wall, defaulting back to loc and blaming mappers - return machine_room + if(!wall_area.always_unpowered) + return wall_area + + // couldn't find a proper powered area on loc or adjacent wall, defaulting back to loc and blaming mappers + return machine_area ///makes this machine draw power from its area according to which use_power mode it is set to /obj/machinery/proc/update_current_power_usage() diff --git a/code/game/machinery/barsigns.dm b/code/game/machinery/barsigns.dm index 5ac2d4932911e..64b104b40074e 100644 --- a/code/game/machinery/barsigns.dm +++ b/code/game/machinery/barsigns.dm @@ -37,7 +37,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/barsign, 32) update_appearance() /obj/machinery/barsign/update_icon_state() - if(!(machine_stat & (NOPOWER|BROKEN)) && chosen_sign && chosen_sign.icon_state) + if(!(machine_stat & BROKEN) && (!(machine_stat & NOPOWER) || machine_stat & EMPED) && chosen_sign && chosen_sign.icon_state) icon_state = chosen_sign.icon_state else icon_state = "empty" @@ -60,7 +60,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/barsign, 32) /obj/machinery/barsign/update_overlays() . = ..() - if(machine_stat & (NOPOWER|BROKEN)) + if(((machine_stat & NOPOWER) && !(machine_stat & EMPED)) || (machine_stat & BROKEN)) return if(chosen_sign && chosen_sign.light_mask) @@ -292,6 +292,12 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/barsign, 32) desc = "Honk." neon_color = "#FF998A" +/datum/barsign/le_cafe_silencieux + name = "Le Café Silencieux" + icon_state = "le_cafe_silencieux" + desc = "..." + neon_color = "#ffffff" + /datum/barsign/thenest name = "The Nest" icon_state = "thenest" @@ -394,6 +400,30 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/barsign, 32) desc = "Mothroaches politely greet you into the bar, or are they greeting eachother?" neon_color = "#649e8a" +/datum/barsign/rock_bottom + name = "Rock Bottom" + icon_state = "rock-bottom" + desc = "When it feels like you're stuck in a pit, might as well have a drink." + neon_color = "#aa2811" + +/datum/barsign/orangejuice + name = "Oranges' Juicery" + icon_state = "orangejuice" + desc = "For those who wish to be optimally tactful to the non-alcoholic population." + neon_color = COLOR_ORANGE + +/datum/barsign/tearoom + name = "Little Treats Tea Room" + icon_state = "little_treats" + desc = "A delightfully relaxing tearoom for all the fancy lads in the cosmos." + neon_color = COLOR_LIGHT_ORANGE + +/datum/barsign/assembly_line + name = "The Assembly Line" + icon_state = "the-assembly-line" + desc = "Where every drink is masterfully crafted with industrial efficiency!" + neon_color = "#ffffff" + // Hidden signs list below this point /datum/barsign/hiddensigns diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm index 1b10a7f2264f0..33e5ce2623438 100644 --- a/code/game/machinery/computer/_computer.dm +++ b/code/game/machinery/computer/_computer.dm @@ -6,7 +6,7 @@ max_integrity = 200 integrity_failure = 0.5 armor_type = /datum/armor/machinery_computer - interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_SET_MACHINE|INTERACT_MACHINE_REQUIRES_LITERACY + interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_REQUIRES_LITERACY /// How bright we are when turned on. var/brightness_on = 1 /// Icon_state of the keyboard overlay. diff --git a/code/game/machinery/computer/arcade/arcade.dm b/code/game/machinery/computer/arcade/arcade.dm index 58a7280e8643e..9ff935a91653f 100644 --- a/code/game/machinery/computer/arcade/arcade.dm +++ b/code/game/machinery/computer/arcade/arcade.dm @@ -77,7 +77,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( icon_keyboard = null icon_screen = "invaders" light_color = LIGHT_COLOR_GREEN - interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_SET_MACHINE // we don't need to be literate to play video games fam + interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON var/list/prize_override /obj/machinery/computer/arcade/proc/Reset() @@ -157,6 +157,8 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( icon_state = "arcade" circuit = /obj/item/circuitboard/computer/arcade/battle + interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_SET_MACHINE // we don't need to be literate to play video games fam + var/enemy_name = "Space Villain" ///Enemy health/attack points var/enemy_hp = 100 diff --git a/code/game/machinery/computer/arena.dm b/code/game/machinery/computer/arena.dm index 39b39af197b61..1ba000fa5da5a 100644 --- a/code/game/machinery/computer/arena.dm +++ b/code/game/machinery/computer/arena.dm @@ -21,6 +21,9 @@ /// Controller for admin event arenas /obj/machinery/computer/arena name = "arena controller" + + interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_SET_MACHINE|INTERACT_MACHINE_REQUIRES_LITERACY + /// Arena ID var/arena_id = ARENA_DEFAULT_ID /// Enables/disables spawning diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 6bc5c6f60d2fc..a1a1fe0ada2a9 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -19,7 +19,7 @@ /// All the plane masters that need to be applied. var/atom/movable/screen/background/cam_background - interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_SET_MACHINE|INTERACT_MACHINE_REQUIRES_SIGHT + interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_REQUIRES_SIGHT /obj/machinery/computer/security/Initialize(mapload) . = ..() diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 870f64dd57584..4750feb3b9b9d 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -24,7 +24,7 @@ ///Should we supress any view changes? var/should_supress_view_changes = TRUE - interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_SET_MACHINE | INTERACT_MACHINE_REQUIRES_SIGHT + interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_REQUIRES_SIGHT /obj/machinery/computer/camera_advanced/Initialize(mapload) . = ..() @@ -76,12 +76,10 @@ /obj/machinery/computer/camera_advanced/remove_eye_control(mob/living/user) if(!user) return - for(var/V in actions) - var/datum/action/A = V - A.Remove(user) - for(var/V in eyeobj.visibleCameraChunks) - var/datum/camerachunk/C = V - C.remove(eyeobj) + for(var/datum/action/actions_removed as anything in actions) + actions_removed.Remove(user) + for(var/datum/camerachunk/camerachunks_gone as anything in eyeobj.visibleCameraChunks) + camerachunks_gone.remove(eyeobj) if(user.client) user.reset_perspective(null) if(eyeobj.visible_icon && user.client) @@ -91,12 +89,12 @@ eyeobj.eye_user = null user.remote_control = null current_user = null - user.unset_machine() + unset_machine(user) playsound(src, 'sound/machines/terminal_off.ogg', 25, FALSE) /obj/machinery/computer/camera_advanced/check_eye(mob/user) if(!can_use(user) || (issilicon(user) && !user.has_unlimited_silicon_privilege)) - user.unset_machine() + unset_machine(user) /obj/machinery/computer/camera_advanced/Destroy() if(eyeobj) @@ -105,7 +103,7 @@ current_user = null return ..() -/obj/machinery/computer/camera_advanced/on_unset_machine(mob/M) +/obj/machinery/computer/camera_advanced/proc/unset_machine(mob/M) if(M == current_user) remove_eye_control(M) @@ -155,7 +153,7 @@ give_eye_control(L) eyeobj.setLoc(camera_location) else - user.unset_machine() + unset_machine(user) else give_eye_control(L) eyeobj.setLoc(eyeobj.loc) diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index 47a202ae2421a..72bdb8a7a5cd3 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -400,7 +400,6 @@ . = TRUE add_fingerprint(usr) - usr.set_machine(src) switch(action) // Connect this DNA Console to a nearby DNA Scanner diff --git a/code/game/machinery/computer/orders/order_computer/mining_order.dm b/code/game/machinery/computer/orders/order_computer/mining_order.dm index 214065a243a39..7e7eabcc1bfd5 100644 --- a/code/game/machinery/computer/orders/order_computer/mining_order.dm +++ b/code/game/machinery/computer/orders/order_computer/mining_order.dm @@ -41,7 +41,7 @@ cost = get_total_cost(), \ contains = things_to_order, ) - var/datum/supply_order/new_order = new( + var/datum/supply_order/disposable/new_order = new( pack = mining_pack, orderer = purchaser, orderer_rank = "Mining Vendor", diff --git a/code/game/machinery/computer/prisoner/_prisoner.dm b/code/game/machinery/computer/prisoner/_prisoner.dm index 05bb4042c8be4..970b5f4f9be26 100644 --- a/code/game/machinery/computer/prisoner/_prisoner.dm +++ b/code/game/machinery/computer/prisoner/_prisoner.dm @@ -1,4 +1,5 @@ /obj/machinery/computer/prisoner + interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_SET_MACHINE|INTERACT_MACHINE_REQUIRES_LITERACY var/obj/item/card/id/advanced/prisoner/contained_id /obj/machinery/computer/prisoner/Destroy() diff --git a/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm b/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm index 97b80b91969c3..cbe6e1c31c7de 100644 --- a/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm @@ -60,7 +60,7 @@ var/obj/item/bodypart/head/head = human_receiver.get_bodypart(BODY_ZONE_HEAD) head.unarmed_damage_low = 10 head.unarmed_damage_high = 15 - head.unarmed_stun_threshold = 15 + head.unarmed_effectiveness = 15 /obj/item/organ/internal/tongue/carp/on_remove(mob/living/carbon/tongue_owner) . = ..() @@ -74,7 +74,7 @@ var/obj/item/bodypart/head/head = human_receiver.get_bodypart(BODY_ZONE_HEAD) head.unarmed_damage_low = initial(head.unarmed_damage_low) head.unarmed_damage_high = initial(head.unarmed_damage_high) - head.unarmed_stun_threshold = initial(head.unarmed_stun_threshold) + head.unarmed_effectiveness = initial(head.unarmed_effectiveness) /obj/item/organ/internal/tongue/carp/on_life(seconds_per_tick, times_fired) . = ..() diff --git a/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm index 257831472d601..47d65a9492f04 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm @@ -69,10 +69,7 @@ name = odd_organ_name() icon_state = FLY_INFUSED_ORGAN_ICON AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/fly) - -/obj/item/organ/internal/heart/fly/update_icon_state() - SHOULD_CALL_PARENT(FALSE) - return //don't set icon thank you + AddElement(/datum/element/update_icon_blocker) /obj/item/organ/internal/lungs/fly desc = FLY_INFUSED_ORGAN_DESC diff --git a/code/game/machinery/embedded_controller/access_controller.dm b/code/game/machinery/embedded_controller/access_controller.dm index 7a92b1bbfaa3a..75ddb36063307 100644 --- a/code/game/machinery/embedded_controller/access_controller.dm +++ b/code/game/machinery/embedded_controller/access_controller.dm @@ -106,6 +106,7 @@ base_icon_state = "access_control" name = "access console" desc = "A small console that can cycle opening between two airlocks." + interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN|INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_OPEN_SILICON|INTERACT_MACHINE_SET_MACHINE var/obj/machinery/door/airlock/interiorAirlock var/obj/machinery/door/airlock/exteriorAirlock var/idInterior diff --git a/code/game/machinery/newscaster/newscaster_machine.dm b/code/game/machinery/newscaster/newscaster_machine.dm index 1ae08c066f043..fc908a98840bc 100644 --- a/code/game/machinery/newscaster/newscaster_machine.dm +++ b/code/game/machinery/newscaster/newscaster_machine.dm @@ -12,7 +12,7 @@ armor_type = /datum/armor/machinery_newscaster max_integrity = 200 integrity_failure = 0.25 - interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_SET_MACHINE|INTERACT_MACHINE_REQUIRES_LITERACY + interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_REQUIRES_LITERACY ///Reference to the currently logged in user. var/datum/bank_account/current_user ///Name of the logged in user. diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index 0ce5e8b3d63ac..d0be7d6af94fd 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -3,6 +3,7 @@ desc = "An energy shield used to contain hull breaches." icon = 'icons/effects/effects.dmi' icon_state = "shield-old" + integrity_failure = 0.5 density = TRUE move_resist = INFINITY opacity = FALSE @@ -183,11 +184,6 @@ if(deployed_shields.len && SPT_PROB(2.5, seconds_per_tick)) qdel(pick(deployed_shields)) - -/obj/machinery/shieldgen/deconstruct(disassembled = TRUE) - atom_break() - locked = pick(0,1) - /obj/machinery/shieldgen/interact(mob/user) . = ..() if(.) diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 15c740a31e4bd..87be631edaf09 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -143,7 +143,7 @@ /obj/machinery/suit_storage_unit/interdyne mask_type = /obj/item/clothing/mask/gas/syndicate - storage_type = /obj/item/tank/jetpack/oxygen/harness + storage_type = /obj/item/tank/internals/oxygen mod_type = /obj/item/mod/control/pre_equipped/interdyne /obj/machinery/suit_storage_unit/void_old @@ -380,6 +380,7 @@ choices, custom_check = CALLBACK(src, PROC_REF(check_interactable), user), require_near = !issilicon(user), + autopick_single_option = FALSE ) if (!choice) diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index 9ff9ee7f76b31..956e2bd758868 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -481,7 +481,7 @@ var/datum/reagents/reactants = new(time_release) reactants.my_atom = src for(var/obj/item/reagent_containers/RC in beakers) - RC.reagents.trans_to(reactants, RC.reagents.total_volume*fraction, 1, 1, 1) + RC.reagents.trans_to(reactants, RC.reagents.total_volume * fraction, no_react = TRUE) chem_splash(get_turf(src), reagents, spread_range, list(reactants), temp_boost) // Detonate it again in one second, until it's out of juice. diff --git a/code/game/machinery/telecomms/machines/receiver.dm b/code/game/machinery/telecomms/machines/receiver.dm index 0c4b6d2a02dbc..def8384b1394c 100644 --- a/code/game/machinery/telecomms/machines/receiver.dm +++ b/code/game/machinery/telecomms/machines/receiver.dm @@ -20,9 +20,15 @@ if(!is_freq_listening(signal)) return - // send the signal to the hub if possible, or a bus otherwise - if(!relay_information(signal, /obj/machinery/telecomms/hub)) - relay_information(signal, /obj/machinery/telecomms/bus) + // Make a copy of the signal so that other recievers can still recieve this signal + var/datum/signal/subspace/signal_copy = signal.copy() + + // Signal has been recieved, so remove receiving levels. This list will be used later on to determine broadcasting levels. + signal_copy.levels = list() + + // Send the signal to a hub if possible, or a bus otherwise. + if(!relay_information(signal_copy, /obj/machinery/telecomms/hub)) + relay_information(signal_copy, /obj/machinery/telecomms/bus) use_power(idle_power_usage) diff --git a/code/game/objects/effects/anomalies/anomalies_bluespace.dm b/code/game/objects/effects/anomalies/anomalies_bluespace.dm index 1bd343302fa2c..fa88e7d268d61 100644 --- a/code/game/objects/effects/anomalies/anomalies_bluespace.dm +++ b/code/game/objects/effects/anomalies/anomalies_bluespace.dm @@ -10,6 +10,10 @@ ///Distance we can teleport someone passively var/teleport_distance = 4 +/obj/effect/anomaly/bluespace/Initialize(mapload, new_lifespan, drops_core) + . = ..() + apply_wibbly_filters(src) + /obj/effect/anomaly/bluespace/anomalyEffect() ..() for(var/mob/living/M in range(teleport_range,src)) @@ -98,4 +102,3 @@ var/mob/living/living = bumpee living.apply_status_effect(/datum/status_effect/teleport_madness) - diff --git a/code/game/objects/effects/anomalies/anomalies_flux.dm b/code/game/objects/effects/anomalies/anomalies_flux.dm index 35b8bc388d720..91f09095d6f6f 100644 --- a/code/game/objects/effects/anomalies/anomalies_flux.dm +++ b/code/game/objects/effects/anomalies/anomalies_flux.dm @@ -14,6 +14,7 @@ COMSIG_ATOM_ENTERED = PROC_REF(on_entered), ) AddElement(/datum/element/connect_loc, loc_connections) + apply_wibbly_filters(src) /obj/effect/anomaly/flux/anomalyEffect() ..() diff --git a/code/game/objects/effects/anomalies/anomalies_gravity.dm b/code/game/objects/effects/anomalies/anomalies_gravity.dm index efd49ef502f63..fa7c4f48a36f3 100644 --- a/code/game/objects/effects/anomalies/anomalies_gravity.dm +++ b/code/game/objects/effects/anomalies/anomalies_gravity.dm @@ -23,6 +23,7 @@ COMSIG_ATOM_ENTERED = PROC_REF(on_entered), ) AddElement(/datum/element/connect_loc, loc_connections) + apply_wibbly_filters(src) warp = new(src) vis_contents += warp diff --git a/code/game/objects/effects/anomalies/anomalies_hallucination.dm b/code/game/objects/effects/anomalies/anomalies_hallucination.dm index 83648601017d4..a6696070df1c7 100644 --- a/code/game/objects/effects/anomalies/anomalies_hallucination.dm +++ b/code/game/objects/effects/anomalies/anomalies_hallucination.dm @@ -15,6 +15,10 @@ span_warning("You are going insane!"), ) +/obj/effect/anomaly/hallucination/Initialize(mapload, new_lifespan, drops_core) + . = ..() + apply_wibbly_filters(src) + /obj/effect/anomaly/hallucination/anomalyEffect(seconds_per_tick) . = ..() ticks += seconds_per_tick diff --git a/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm b/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm index f97f3482e8362..b290c23ac3f4d 100644 --- a/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm +++ b/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm @@ -7,6 +7,10 @@ var/releasedelay = 10 aSignal = /obj/item/assembly/signaler/anomaly/pyro +/obj/effect/anomaly/pyro/Initialize(mapload, new_lifespan, drops_core) + . = ..() + apply_wibbly_filters(src) + /obj/effect/anomaly/pyro/anomalyEffect(seconds_per_tick) ..() ticks += seconds_per_tick diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index 591036b30d9d4..091b470067320 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -43,6 +43,8 @@ var/force_teleport = FALSE /// Does this portal create spark effect when teleporting? var/sparkless = FALSE + /// If FALSE, the wibble filter will not be applied to this portal (only a visual effect). + var/wibbles = TRUE /obj/effect/portal/anom name = "wormhole" @@ -53,6 +55,7 @@ mech_sized = TRUE teleport_channel = TELEPORT_CHANNEL_WORMHOLE light_on = FALSE + wibbles = FALSE /obj/effect/portal/Move(newloc) for(var/T in newloc) @@ -100,6 +103,8 @@ hardlinked = automatic_link if(isturf(hard_target_override)) hard_target = hard_target_override + if(wibbles) + apply_wibbly_filters(src) /obj/effect/portal/singularity_pull() return diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index 68a25f411b96c..393b9fdb7080f 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -287,6 +287,10 @@ icon_state = "bluestream_fade" duration = 9 +/obj/effect/temp_visual/bluespace_fissure/Initialize(mapload) + . = ..() + apply_wibbly_filters(src) + /obj/effect/temp_visual/gib_animation icon = 'icons/mob/simple/mob.dmi' duration = 15 diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 5abdfe436cc30..a93d2b4b56d29 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -421,7 +421,7 @@ ///Separator between the items on the list var/sep = "" ///Nodes that can be boosted - var/list/boostable_nodes = techweb_item_boost_check(src) + var/list/boostable_nodes = techweb_item_unlock_check(src) if (boostable_nodes) for(var/id in boostable_nodes) var/datum/techweb_node/node = SSresearch.techweb_node_by_id(id) @@ -596,9 +596,6 @@ R.activate_module(src) R.hud_used.update_robot_modules_display() -/obj/item/proc/GetDeconstructableContents() - return get_all_contents() - src - // afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency /obj/item/proc/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) @@ -1193,7 +1190,7 @@ return src /** - * tryEmbed() is for when you want to try embedding something without dealing with the damage + hit messages of calling hitby() on the item while targetting the target. + * tryEmbed() is for when you want to try embedding something without dealing with the damage + hit messages of calling hitby() on the item while targeting the target. * * Really, this is used mostly with projectiles with shrapnel payloads, from [/datum/element/embed/proc/checkEmbedProjectile], and called on said shrapnel. Mostly acts as an intermediate between different embed elements. * diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 2e4de954f37f2..5f7e9a8f1c449 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -649,10 +649,8 @@ return FALSE var/list/user_memories = user.mind.memories var/datum/memory/key/account/user_key = user_memories[/datum/memory/key/account] - var/user_account = 11111 - if(!isnull(user_key)) - user_account = user_key.remembered_id - var/new_bank_id = tgui_input_number(user, "Enter the account ID to associate with this card.", "Link Bank Account", user_account, 999999, 111111) + var/default_account = (istype(user_key) && user_key.remembered_id) || 11111 + var/new_bank_id = tgui_input_number(user, "Enter the account ID to associate with this card.", "Link Bank Account", default_account, 999999, 111111) if(!new_bank_id || QDELETED(user) || QDELETED(src) || issilicon(user) || !alt_click_can_use_id(user) || loc != user) return FALSE if(registered_account?.account_id == new_bank_id) diff --git a/code/game/objects/items/circuitboards/circuitboard.dm b/code/game/objects/items/circuitboards/circuitboard.dm index 1e12576f68626..c32de5b336ddb 100644 --- a/code/game/objects/items/circuitboards/circuitboard.dm +++ b/code/game/objects/items/circuitboards/circuitboard.dm @@ -108,7 +108,7 @@ micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells. . = ..() if(!LAZYLEN(req_components)) . += span_info("It requires no components.") - return . + return var/list/nice_list = list() for(var/component_path in req_components) @@ -118,27 +118,33 @@ micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells. var/component_name var/component_amount = req_components[component_path] + //e.g. "glass sheet" vs. "glass" if(ispath(component_path, /obj/item/stack)) var/obj/item/stack/stack_path = component_path - if(initial(stack_path.singular_name)) - component_name = initial(stack_path.singular_name) //e.g. "glass sheet" vs. "glass" - else if(ispath(component_path, /obj/item/stock_parts) && !specific_parts) - var/obj/item/stock_parts/stock_part = component_path - component_name = initial(stock_part.base_name) || initial(stock_part.name) - else if(ispath(component_path, /obj/item/stock_parts)) - var/obj/item/stock_parts/stock_part = component_path - component_name = initial(stock_part.name) - else if(ispath(component_path, /datum/stock_part)) - var/datum/stock_part/stock_part = component_path - var/obj/item/stock_parts/physical_object_type = initial(stock_part.physical_object_type) - component_name = initial(physical_object_type.base_name) || initial(physical_object_type.name) + component_name = initial(stack_path.singular_name) + + //stock parts in datum or obj form + else if(ispath(component_path, /obj/item/stock_parts) || ispath(component_path, /datum/stock_part)) + var/obj/item/stock_parts/stock_part + if(ispath(component_path, /obj/item/stock_parts)) + stock_part = component_path + else + var/datum/stock_part/datum_part = component_path + stock_part = initial(datum_part.physical_object_type) + + if(!specific_parts) + component_name = initial(stock_part.base_name) + if(!component_name) + component_name = initial(stock_part.name) + + //beakers, any non conventional part else if(ispath(component_path, /atom)) var/atom/stock_part = component_path component_name = initial(stock_part.name) + //append decoded name to final result if (isnull(component_name)) stack_trace("[component_path] was an invalid component") - nice_list += list("[component_amount] [component_name]\s") . += span_info("It requires [english_list(nice_list)].") diff --git a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm index 08f2f111783c7..c052a9c18e181 100644 --- a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm @@ -255,7 +255,8 @@ build_path = /obj/machinery/ntnet_relay req_components = list( /obj/item/stack/cable_coil = 2, - /datum/stock_part/filter = 1) + /datum/stock_part/filter = 1, + ) /obj/item/circuitboard/machine/pacman name = "PACMAN-type Generator" @@ -550,7 +551,7 @@ /obj/item/circuitboard/machine/smartfridge/apply_default_parts(obj/machinery/smartfridge/smartfridge) build_path = smartfridge.base_build_path - if(!fridges_name_paths.Find(build_path, fridges_name_paths)) + if(!fridges_name_paths.Find(build_path)) name = "[initial(smartfridge.name)]" //if it's a unique type, give it a unique name. is_special_type = TRUE return ..() @@ -960,7 +961,8 @@ req_components = list( /datum/stock_part/scanning_module = 1, /datum/stock_part/servo = 1, - /datum/stock_part/micro_laser = 1) + /datum/stock_part/micro_laser = 1, + ) /obj/item/circuitboard/machine/experimentor name = "E.X.P.E.R.I-MENTOR" diff --git a/code/game/objects/items/crab17.dm b/code/game/objects/items/crab17.dm index a20fcce5db86c..1e43197c47ef2 100644 --- a/code/game/objects/items/crab17.dm +++ b/code/game/objects/items/crab17.dm @@ -197,7 +197,7 @@ if(!(B?.being_dumped)) accounts_to_rob -= B continue - var/amount = B.account_balance * percentage_lost + var/amount = round(B.account_balance * percentage_lost) // We don't want fractions of a credit stolen. That's just agony for everyone. var/datum/bank_account/account = bogdanoff?.get_bank_account() if (account) // get_bank_account() may return FALSE account.transfer_money(B, amount, "?VIVA¿: !LA CRABBE¡") diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 7f7f733ad863a..af470ead50bdb 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -367,7 +367,8 @@ .["has_cap"] = has_cap .["is_capped"] = is_capped .["can_change_colour"] = can_change_colour - .["current_colour"] = paint_color + .["selected_color"] = GLOB.pipe_color_name[paint_color] || paint_color + .["paint_colors"] = GLOB.pipe_paint_colors /obj/item/toy/crayon/ui_act(action, list/params) . = ..() @@ -390,8 +391,14 @@ text_buffer = "" else paint_mode = PAINT_NORMAL - if("select_colour") + if("custom_color") . = can_change_colour && pick_painting_tool_color(usr, paint_color) + if("color") + if(!can_change_colour) + return + paint_color = GLOB.pipe_paint_colors[params["paint_color"]] + set_painting_tool_color(paint_color) + . = TRUE if("enter_text") var/txt = tgui_input_text(usr, "Choose what to write", "Scribbles", text_buffer) if(isnull(txt)) @@ -841,7 +848,6 @@ user.visible_message(span_notice("[user] coats [target] with spray paint!"), span_notice("You coat [target] with spray paint.")) return - if(isobj(target) && !(target.flags_1 & UNPAINTABLE_1)) var/color_is_dark = FALSE if(actually_paints) @@ -851,7 +857,26 @@ to_chat(user, span_warning("A color that dark on an object like this? Surely not...")) return FALSE - target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY) + if(istype(target, /obj/item/pipe)) + if(GLOB.pipe_color_name.Find(paint_color)) + var/obj/item/pipe/target_pipe = target + target_pipe.pipe_color = paint_color + target.add_atom_colour(paint_color, FIXED_COLOUR_PRIORITY) + balloon_alert(user, "painted in [GLOB.pipe_color_name[paint_color]] color") + else + balloon_alert(user, "invalid pipe color!") + return FALSE + else if(istype(target, /obj/machinery/atmospherics)) + if(GLOB.pipe_color_name.Find(paint_color)) + var/obj/machinery/atmospherics/target_pipe = target + target_pipe.paint(paint_color) + balloon_alert(user, "painted in [GLOB.pipe_color_name[paint_color]] color") + else + balloon_alert(user, "invalid pipe color!") + return FALSE + else + target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY) + if(isitem(target) && isliving(target.loc)) var/obj/item/target_item = target var/mob/living/holder = target.loc @@ -859,6 +884,7 @@ holder.update_held_items() else holder.update_clothing(target_item.slot_flags) + if(!(SEND_SIGNAL(target, COMSIG_OBJ_PAINTED, user, src, color_is_dark) & DONT_USE_SPRAYCAN_CHARGES)) use_charges(user, 2, requires_full = FALSE) reagents.trans_to(target, ., volume_multiplier, transferred_by = user, methods = VAPOR) diff --git a/code/game/objects/items/devices/pipe_painter.dm b/code/game/objects/items/devices/pipe_painter.dm index 63ae58a0ae388..3a3b9055725a7 100644 --- a/code/game/objects/items/devices/pipe_painter.dm +++ b/code/game/objects/items/devices/pipe_painter.dm @@ -9,19 +9,24 @@ custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, /datum/material/glass = SHEET_MATERIAL_AMOUNT) -/obj/item/pipe_painter/afterattack(atom/A, mob/user, proximity_flag) +/obj/item/pipe_painter/afterattack(atom/target, mob/user, proximity_flag) . = ..() //Make sure we only paint adjacent items if(!proximity_flag) return - if(!istype(A, /obj/machinery/atmospherics/pipe)) - return - - var/obj/machinery/atmospherics/pipe/P = A - if(P.paint(GLOB.pipe_paint_colors[paint_color])) + if(istype(target, /obj/machinery/atmospherics)) + var/obj/machinery/atmospherics/target_pipe = target + target_pipe.paint(GLOB.pipe_paint_colors[paint_color]) + playsound(src, 'sound/machines/click.ogg', 50, TRUE) + balloon_alert(user, "painted in [paint_color] color") + else if(istype(target, /obj/item/pipe)) + var/obj/item/pipe/target_pipe = target + var/color = GLOB.pipe_paint_colors[paint_color] + target_pipe.pipe_color = color + target.add_atom_colour(color, FIXED_COLOUR_PRIORITY) playsound(src, 'sound/machines/click.ogg', 50, TRUE) - user.visible_message(span_notice("[user] paints \the [P] [paint_color]."),span_notice("You paint \the [P] [paint_color].")) + balloon_alert(user, "painted in [paint_color] color") /obj/item/pipe_painter/attack_self(mob/user) paint_color = tgui_input_list(user, "Which colour do you want to use?", "Pipe painter", GLOB.pipe_paint_colors) diff --git a/code/game/objects/items/devices/portable_chem_mixer.dm b/code/game/objects/items/devices/portable_chem_mixer.dm index 18458f75697ad..7d8aa808df968 100644 --- a/code/game/objects/items/devices/portable_chem_mixer.dm +++ b/code/game/objects/items/devices/portable_chem_mixer.dm @@ -4,19 +4,18 @@ icon = 'icons/obj/medical/chemical.dmi' icon_state = "portablechemicalmixer_open" worn_icon_state = "portable_chem_mixer" + equip_sound = 'sound/items/equip/toolbelt_equip.ogg' w_class = WEIGHT_CLASS_HUGE slot_flags = ITEM_SLOT_BELT - equip_sound = 'sound/items/equip/toolbelt_equip.ogg' custom_price = PAYCHECK_CREW * 10 custom_premium_price = PAYCHECK_CREW * 14 - var/obj/item/reagent_containers/beaker = null ///Creating an empty slot for a beaker that can be added to dispense into - var/amount = 30 ///The amount of reagent that is to be dispensed currently - - var/list/dispensable_reagents = list() ///List in which all currently dispensable reagents go - - ///If the UI has the pH meter shown - var/show_ph = TRUE + ///Creating an empty slot for a beaker that can be added to dispense into + var/obj/item/reagent_containers/beaker = null + ///The amount of reagent that is to be dispensed currently + var/amount = 30 + ///List in which all currently dispensable reagents go + var/list/dispensable_reagents = list() /obj/item/storage/portable_chem_mixer/Initialize(mapload) . = ..() @@ -29,45 +28,56 @@ /obj/item/reagent_containers/cup/glass/waterbottle, /obj/item/reagent_containers/condiment, )) + register_context() /obj/item/storage/portable_chem_mixer/Destroy() QDEL_NULL(beaker) return ..() -/obj/item/storage/portable_chem_mixer/ex_act(severity, target) - if(severity > EXPLODE_LIGHT) - return ..() +/obj/item/storage/portable_chem_mixer/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() - return FALSE + context[SCREENTIP_CONTEXT_CTRL_LMB] = "[atom_storage.locked ? "Un" : ""]Lock storage" + if(atom_storage.locked && !QDELETED(beaker)) + context[SCREENTIP_CONTEXT_ALT_LMB] = "Eject beaker" -/obj/item/storage/portable_chem_mixer/attackby(obj/item/I, mob/user, params) - if (is_reagent_container(I) && !(I.item_flags & ABSTRACT) && I.is_open_container() && atom_storage.locked) - var/obj/item/reagent_containers/B = I - . = TRUE //no afterattack - if(!user.transferItemToLoc(B, src)) - return - replace_beaker(user, B) - update_appearance() - ui_interact(user) - return - return ..() + if(!isnull(held_item)) + if (!atom_storage.locked || \ + (held_item.item_flags & ABSTRACT) || \ + !is_reagent_container(held_item) || \ + !held_item.is_open_container() \ + ) + return CONTEXTUAL_SCREENTIP_SET + context[SCREENTIP_CONTEXT_LMB] = "Insert beaker" -/** - * Updates the contents of the portable chemical mixer - * - * A list of dispensable reagents is created by iterating through each source beaker in the portable chemical beaker and reading its contents - */ -/obj/item/storage/portable_chem_mixer/proc/update_contents() - dispensable_reagents.Cut() + return CONTEXTUAL_SCREENTIP_SET + +/obj/item/storage/portable_chem_mixer/examine(mob/user) + . = ..() + if(!atom_storage.locked) + . += span_notice("Use [EXAMINE_HINT("ctrl click")] to lock in order to use its interface.") + else + . += span_notice("Its storage is locked, use [EXAMINE_HINT("ctrl click")] to unlock it.") + if(QDELETED(beaker)) + . += span_notice("A beaker can be inserted to dispense reagents after it is locked.") + else + . += span_notice("A beaker of [beaker.reagents.maximum_volume] units capacity is inserted.") + . += span_notice("It can be ejected with [EXAMINE_HINT("alt click")].") - for (var/obj/item/reagent_containers/B in contents) - var/key = B.reagents.get_master_reagent_id() - if (!(key in dispensable_reagents)) - dispensable_reagents[key] = list() - dispensable_reagents[key]["reagents"] = list() - dispensable_reagents[key]["reagents"] += B.reagents +/obj/item/storage/portable_chem_mixer/ex_act(severity, target) + return severity > EXPLODE_LIGHT ? ..() : FALSE + +/obj/item/storage/portable_chem_mixer/attackby(obj/item/weapon, mob/user, params) + if (!atom_storage.locked || \ + (weapon.item_flags & ABSTRACT) || \ + !is_reagent_container(weapon) || \ + !weapon.is_open_container() \ + ) + return ..() - return + replace_beaker(user, weapon) + update_appearance() + return TRUE /obj/item/storage/portable_chem_mixer/update_icon_state() if(!atom_storage.locked) @@ -79,28 +89,52 @@ icon_state = "portablechemicalmixer_empty" return ..() - /obj/item/storage/portable_chem_mixer/AltClick(mob/living/user) if(!atom_storage.locked) + balloon_alert(user, "lock first to use alt eject!") return ..() if(!can_interact(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return + replace_beaker(user) update_appearance() /obj/item/storage/portable_chem_mixer/CtrlClick(mob/living/user) - if(atom_storage.locked) + if(atom_storage.locked == STORAGE_FULLY_LOCKED) atom_storage.locked = STORAGE_NOT_LOCKED + replace_beaker(user) + SStgui.close_all_uis() else atom_storage.locked = STORAGE_FULLY_LOCKED - if (!atom_storage.locked) - update_contents() - if (atom_storage.locked) atom_storage.hide_contents(usr) - replace_beaker(user) + update_appearance() - playsound(src, 'sound/items/screwdriver2.ogg', 50) - return + +/obj/item/storage/portable_chem_mixer/Exited(atom/movable/gone, direction) + . = ..() + if(gone == beaker) + beaker = null + else + update_contents() + +/// Reload dispensable reagents from new contents +/obj/item/storage/portable_chem_mixer/proc/update_contents() + dispensable_reagents.Cut() + for (var/obj/item/reagent_containers/container in contents) + var/datum/reagent/key = container.reagents.get_master_reagent() + if(isnull(key)) //no reagent inside container + continue + + var/key_type = key.type + if (!(key_type in dispensable_reagents)) + dispensable_reagents[key_type] = list() + dispensable_reagents[key_type]["reagents"] = list() + dispensable_reagents[key_type]["reagents"] += container.reagents + +/obj/item/storage/portable_chem_mixer/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) + . = ..() + if(!atom_storage.locked) + update_contents() /** * Replaces the beaker of the portable chemical mixer with another beaker, or simply adds the new beaker if none is in currently @@ -111,34 +145,12 @@ * * obj/item/reagent_containers/new_beaker - The new beaker that the user wants to put into the device */ /obj/item/storage/portable_chem_mixer/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker) - if(!user) - return FALSE if(beaker) user.put_in_hands(beaker) - beaker = null if(new_beaker) - beaker = new_beaker - return TRUE - -/obj/item/storage/portable_chem_mixer/attack_hand(mob/user, list/modifiers) - if (loc != user) - return ..() - else - if (!atom_storage.locked) - return ..() - if(atom_storage?.locked) - ui_interact(user) - return - -/obj/item/storage/portable_chem_mixer/attack_self(mob/user) - if(loc == user) - if (atom_storage.locked) - ui_interact(user) - return - else - to_chat(user, span_notice("It looks like this device can be worn as a belt for increased accessibility. A label indicates that the 'CTRL'-button on the device may be used to close it after it has been filled with bottles and beakers of chemicals.")) + if(!user.transferItemToLoc(new_beaker, src)) return - return + beaker = new_beaker /obj/item/storage/portable_chem_mixer/MouseDrop(obj/over_object) . = ..() @@ -149,30 +161,29 @@ M.putItemFromInventoryInHandIfPossible(src, H.held_index) /obj/item/storage/portable_chem_mixer/ui_interact(mob/user, datum/tgui/ui) + if(loc != user) + balloon_alert(user, "hold it in your hand!") + return + if(!atom_storage.locked) + balloon_alert(user, "lock it first!") + return + ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "PortableChemMixer", name) - - var/is_hallucinating = FALSE - if(isliving(user)) - var/mob/living/living_user = user - is_hallucinating = !!living_user.has_status_effect(/datum/status_effect/hallucination) - - if(is_hallucinating) - // to not ruin the immersion by constantly changing the fake chemicals - ui.set_autoupdate(FALSE) - ui.open() + var/is_hallucinating = FALSE + if(isliving(user)) + var/mob/living/living_user = user + is_hallucinating = !!living_user.has_status_effect(/datum/status_effect/hallucination) + ui.set_autoupdate(!is_hallucinating) // to not ruin the immersion by constantly changing the fake chemicals + /obj/item/storage/portable_chem_mixer/ui_data(mob/user) - var/list/data = list() - data["amount"] = amount - data["isBeakerLoaded"] = beaker ? 1 : 0 - data["beakerCurrentVolume"] = beaker ? beaker.reagents.total_volume : null - data["beakerMaxVolume"] = beaker ? beaker.volume : null - data["beakerTransferAmounts"] = beaker ? list(1,5,10,30,50,100) : null - data["showpH"] = show_ph - var/chemicals[0] + . = list() + .["amount"] = amount + + var/list/chemicals = list() var/is_hallucinating = FALSE if(isliving(user)) var/mob/living/living_user = user @@ -190,46 +201,54 @@ total_ph = rs.ph if(is_hallucinating && prob(5)) chemname = "[pick_list_replacements("hallucination.json", "chemicals")]" - chemicals.Add(list(list("title" = chemname, "id" = ckey(temp.name), "volume" = total_volume, "pH" = total_ph))) - data["chemicals"] = chemicals - var/beakerContents[0] - if(beaker) - for(var/datum/reagent/R in beaker.reagents.reagent_list) - beakerContents.Add(list(list("name" = R.name, "id" = ckey(R.name), "volume" = R.volume, "pH" = R.ph))) // list in a list because Byond merges the first list... - data["beakerCurrentpH"] = round(beaker.reagents.ph, 0.01) - data["beakerContents"] = beakerContents - - return data - -/obj/item/storage/portable_chem_mixer/ui_act(action, params) + chemicals += list(list("title" = chemname, "id" = temp.name, "volume" = total_volume, "pH" = total_ph)) + .["chemicals"] = chemicals + + var/list/beaker_data = null + if(!QDELETED(beaker)) + beaker_data = list() + beaker_data["maxVolume"] = beaker.volume + beaker_data["transferAmounts"] = beaker.possible_transfer_amounts + beaker_data["pH"] = round(beaker.reagents.ph, 0.01) + beaker_data["currentVolume"] = round(beaker.reagents.total_volume, 0.01) + var/list/beakerContents = list() + if(length(beaker?.reagents.reagent_list)) + for(var/datum/reagent/reagent in beaker.reagents.reagent_list) + beakerContents += list(list("name" = reagent.name, "volume" = round(reagent.volume, 0.01))) // list in a list because Byond merges the first list... + beaker_data["contents"] = beakerContents + .["beaker"] = beaker_data + +/obj/item/storage/portable_chem_mixer/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) return + switch(action) if("amount") - var/target = text2num(params["target"]) - amount = target - . = TRUE + amount = text2num(params["target"]) + return TRUE + if("dispense") - var/reagent_name = params["reagent"] - var/datum/reagent/reagent = GLOB.name2reagent[reagent_name] - var/entry = dispensable_reagents[reagent] - if(beaker && beaker.loc == src) - var/datum/reagents/R = beaker.reagents - var/actual = min(amount, 1000, R.maximum_volume - R.total_volume) - // todo: add check if we have enough reagent left - for (var/datum/reagents/source in entry["reagents"]) + var/datum/reagent/reagent = GLOB.name2reagent[params["reagent"]] + if(isnull(reagent)) + return + + if(!QDELETED(beaker)) + var/datum/reagents/container = beaker.reagents + var/actual = min(amount, 1000, container.maximum_volume - container.total_volume) + for (var/datum/reagents/source in dispensable_reagents[reagent]["reagents"]) var/to_transfer = min(source.total_volume, actual) - source.trans_to(beaker, to_transfer) + source.trans_to(beaker, to_transfer, transferred_by = ui.user) actual -= to_transfer if (actual <= 0) break - . = TRUE + return TRUE + if("remove") - var/amount = text2num(params["amount"]) - beaker.reagents.remove_all(amount) - . = TRUE + beaker.reagents.remove_all(text2num(params["amount"])) + return TRUE + if("eject") - replace_beaker(usr) + replace_beaker(ui.user) update_appearance() - . = TRUE + return TRUE diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 7455f9567cb5d..ae96f60fea0be 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -351,7 +351,6 @@ GLOBAL_LIST_INIT(channel_tokens, list( make_syndie() /obj/item/radio/headset/screwdriver_act(mob/living/user, obj/item/tool) - user.set_machine(src) if(keyslot || keyslot2) for(var/ch_name in channels) SSradio.remove_object(src, GLOB.radiochannels[ch_name]) @@ -373,8 +372,6 @@ GLOBAL_LIST_INIT(channel_tokens, list( return TRUE /obj/item/radio/headset/attackby(obj/item/W, mob/user, params) - user.set_machine(src) - if(istype(W, /obj/item/encryptionkey)) if(keyslot && keyslot2) to_chat(user, span_warning("The headset can't hold another key!")) diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index e397cc4fbb82e..3aa6ed15f5b4e 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -314,19 +314,9 @@ if(advanced && humantarget.has_dna()) render_list += "Genetic Stability: [humantarget.dna.stability]%.\n" - // Species and body temperature + // Hulk and body temperature var/datum/species/targetspecies = humantarget.dna.species - var/mutant = humantarget.dna.check_mutation(/datum/mutation/human/hulk) \ - || targetspecies.mutantlungs != initial(targetspecies.mutantlungs) \ - || targetspecies.mutantbrain != initial(targetspecies.mutantbrain) \ - || targetspecies.mutantheart != initial(targetspecies.mutantheart) \ - || targetspecies.mutanteyes != initial(targetspecies.mutanteyes) \ - || targetspecies.mutantears != initial(targetspecies.mutantears) \ - || targetspecies.mutanttongue != initial(targetspecies.mutanttongue) \ - || targetspecies.mutantliver != initial(targetspecies.mutantliver) \ - || targetspecies.mutantstomach != initial(targetspecies.mutantstomach) \ - || targetspecies.mutantappendix != initial(targetspecies.mutantappendix) \ - || istype(humantarget.get_organ_slot(ORGAN_SLOT_EXTERNAL_WINGS), /obj/item/organ/external/wings/functional) + var/mutant = humantarget.dna.check_mutation(/datum/mutation/human/hulk) render_list += "Species: [targetspecies.name][mutant ? "-derived mutant" : ""]\n" var/core_temperature_message = "Core temperature: [round(humantarget.coretemperature-T0C, 0.1)] °C ([round(humantarget.coretemperature*1.8-459.67,0.1)] °F)" diff --git a/code/game/objects/items/food/misc.dm b/code/game/objects/items/food/misc.dm index 25be1aabfeaec..840d431bfa55e 100644 --- a/code/game/objects/items/food/misc.dm +++ b/code/game/objects/items/food/misc.dm @@ -432,6 +432,18 @@ . = ..() AddComponent(/datum/component/customizable_reagent_holder, /obj/item/food/sushi/empty, CUSTOM_INGREDIENT_ICON_FILL, max_ingredients = 6) +/obj/item/food/seaweedsheet/saltcane + name = "dried saltcane sheathe" + desc = "A dried sheet of saltcane sheathe can used for making sushi. Use an ingredient on it to start making custom sushi!" + icon_state = "seaweedsheet" + food_reagents = list( + /datum/reagent/consumable/nutriment = 1, + /datum/reagent/consumable/nutriment/vitamin = 1, + ) + tastes = list("seaweed" = 1) + foodtypes = VEGETABLES + w_class = WEIGHT_CLASS_SMALL + /obj/item/food/granola_bar name = "granola bar" desc = "A dried mixture of oats, nuts, fruits, and chocolate condensed into a chewy bar. Makes a great snack while space-hiking." diff --git a/code/game/objects/items/granters/crafting/rebarxbowsyndie.dm b/code/game/objects/items/granters/crafting/rebarxbowsyndie.dm new file mode 100644 index 0000000000000..fd38d4f4ccb20 --- /dev/null +++ b/code/game/objects/items/granters/crafting/rebarxbowsyndie.dm @@ -0,0 +1,13 @@ +/obj/item/book/granter/crafting_recipe/dusting/rebarxbowsyndie_ammo + name = "SYNDICATE REBAR CROSSBOW OWNERS MANUAL" + desc = "This book will self destruct upon being read a second time." + crafting_recipe_types = list( + /datum/crafting_recipe/rebarsyndie + ) + uses = 1 + remarks = list( + "AIM FOR THE LEGS TO CRIPPLE YOUR FOES", + "USE A ROD AND WIRECUTTERS TO MAKE BETTER AMMO", + "BE AWARE OF THE SCOPE'S BLIND SPOTS", + "READ THIS BOOK AGAIN TO DUST IT.", + ) diff --git a/code/game/objects/items/granters/martial_arts/sleeping_carp.dm b/code/game/objects/items/granters/martial_arts/sleeping_carp.dm index ab3e343b28d6c..3c66ce8affa15 100644 --- a/code/game/objects/items/granters/martial_arts/sleeping_carp.dm +++ b/code/game/objects/items/granters/martial_arts/sleeping_carp.dm @@ -4,7 +4,7 @@ martial_name = "sleeping carp" desc = "A scroll filled with strange markings. It seems to be drawings of some sort of martial art." greet = "You have learned the ancient martial art of the Sleeping Carp! Your hand-to-hand combat has become much more effective, and you are now able to deflect any projectiles \ - directed toward you while in Throw Mode. Your body has also hardened itself, granting extra protection against lasting wounds that would otherwise mount during extended combat. \ + directed toward you while in Combat Mode. Your body has also hardened itself, granting extra protection against lasting wounds that would otherwise mount during extended combat. \ However, you are also unable to use any ranged weaponry. You can learn more about your newfound art by using the Recall Teachings verb in the Sleeping Carp tab." icon = 'icons/obj/scrolls.dmi' icon_state = "sleepingcarp" diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm index 49304446c0ba6..f8ac3748de9e5 100644 --- a/code/game/objects/items/grenades/chem_grenade.dm +++ b/code/game/objects/items/grenades/chem_grenade.dm @@ -313,11 +313,11 @@ var/container_ratio = available_extract_volume / beaker_total_volume var/datum/reagents/tmp_holder = new/datum/reagents(beaker_total_volume) for(var/obj/item/container as anything in other_containers) - container.reagents.trans_to(tmp_holder, container.reagents.total_volume * container_ratio, 1, preserve_data = TRUE, no_react = TRUE) + container.reagents.trans_to(tmp_holder, container.reagents.total_volume * container_ratio, no_react = TRUE) for(var/obj/item/slime_extract/extract as anything in extracts) var/available_volume = extract.reagents.maximum_volume - extract.reagents.total_volume - tmp_holder.trans_to(extract, beaker_total_volume * (available_volume / available_extract_volume), 1, preserve_data = TRUE, no_react = TRUE) + tmp_holder.trans_to(extract, beaker_total_volume * (available_volume / available_extract_volume), no_react = TRUE) extract.reagents.handle_reactions() // Reaction handling in the transfer proc is reciprocal and we don't want to blow up the tmp holder early. if(QDELETED(extract)) @@ -390,7 +390,12 @@ var/datum/reagents/reactants = new(unit_spread) reactants.my_atom = src for(var/obj/item/reagent_containers/reagent_container in beakers) - reagent_container.reagents.trans_to(reactants, reagent_container.reagents.total_volume*fraction, threatscale, 1, 1) + reagent_container.reagents.trans_to( + reactants, + reagent_container.reagents.total_volume * fraction, + threatscale, + no_react = TRUE + ) chem_splash(get_turf(src), reagents, affected_area, list(reactants), ignition_temp, threatscale) var/turf/detonated_turf = get_turf(src) diff --git a/code/game/objects/items/maintenance_loot.dm b/code/game/objects/items/maintenance_loot.dm index bfdc53ea916ed..538e4cac93d43 100644 --- a/code/game/objects/items/maintenance_loot.dm +++ b/code/game/objects/items/maintenance_loot.dm @@ -11,8 +11,8 @@ lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' //wow, lore - desc = "A hefty lead pipe.\nLead in an uncommon sight in this sector after being phased out due to employee health concerns. \ - \nThose of a more cynical disposition assume that the NT lead ban is a scheme to prevent divertion to Syndicate ammunition factories." + desc = "A hefty lead pipe.\nLead is an uncommon sight in this sector after being phased out due to employee health concerns. \ + \nThose of a more cynical disposition have claimed that the NT lead ban is a scheme to prevent diversion to Syndicate ammunition factories." force = 15 throwforce = 12 throw_range = 4 @@ -25,12 +25,12 @@ //Add lead material to this once implemented. /obj/item/stock_parts/cell/lead name = "lead-acid battery" - desc = "A type of primitive battery. It is quite large feels unexpectedly heavy." + desc = "A primitive battery. It is quite large and feels unexpectedly heavy." icon = 'icons/obj/maintenance_loot.dmi' icon_state = "lead_battery" throwforce = 10 maxcharge = 20000 //decent max charge - chargerate = 1400 //charging is about 30% less efficient compared lithium batteries. + chargerate = 1400 //charging is about 30% less efficient than lithium batteries. charge_light_type = null connector_type = "leadacid" rating = 2 //Kind of a mid-tier battery diff --git a/code/game/objects/items/manuals.dm b/code/game/objects/items/manuals.dm index ffbeea5975cfd..e89391f788727 100644 --- a/code/game/objects/items/manuals.dm +++ b/code/game/objects/items/manuals.dm @@ -232,228 +232,3 @@ Good luck! "} - -// Wiki books that are linked to the configured wiki link. - -// A book that links to the wiki -/obj/item/book/manual/wiki - var/page_link = "" - window_size = "970x710" - -/obj/item/book/manual/wiki/attack_self() - if(!book_data.content) - initialize_wikibook() - return ..() - -/obj/item/book/manual/wiki/proc/initialize_wikibook() - var/wikiurl = CONFIG_GET(string/wikiurl) - if(wikiurl) - var/wikiinfo = {" - - - - - - - - -

You start skimming through the manual...

- - - - - - "} - book_data.set_content(wikiinfo, trusted = TRUE) - -/obj/item/book/manual/wiki/chemistry - name = "Chemistry Textbook" - icon_state ="chemistrybook" - starting_author = "Nanotrasen" - starting_title = "Chemistry Textbook" - page_link = "Guide_to_chemistry" - -/obj/item/book/manual/wiki/engineering_construction - name = "Station Repairs and Construction" - icon_state ="bookEngineering" - starting_author = "Engineering Encyclopedia" - starting_title = "Station Repairs and Construction" - page_link = "Guide_to_construction" - -/obj/item/book/manual/wiki/engineering_guide - name = "Engineering Textbook" - icon_state ="bookEngineering2" - starting_author = "Engineering Encyclopedia" - starting_title = "Engineering Textbook" - page_link = "Guide_to_engineering" - -/obj/item/book/manual/wiki/security_space_law - name = "Space Law" - desc = "A set of Nanotrasen guidelines for keeping law and order on their space stations." - icon_state = "bookSpaceLaw" - starting_author = "Nanotrasen" - starting_title = "Space Law" - page_link = "Space_Law" - -/obj/item/book/manual/wiki/security_space_law/suicide_act(mob/living/user) - user.visible_message(span_suicide("[user] pretends to read \the [src] intently... then promptly dies of laughter!")) - return OXYLOSS - -/obj/item/book/manual/wiki/infections - name = "Infections - Making your own pandemic!" - icon_state = "bookInfections" - starting_author = "Infections Encyclopedia" - starting_title = "Infections - Making your own pandemic!" - page_link = "Infections" - -/obj/item/book/manual/wiki/telescience - name = "Teleportation Science - Bluespace for dummies!" - icon_state = "book7" - starting_author = "University of Bluespace" - starting_title = "Teleportation Science - Bluespace for dummies!" - page_link = "Guide_to_telescience" - -/obj/item/book/manual/wiki/engineering_hacking - name = "Hacking" - icon_state ="bookHacking" - starting_author = "Engineering Encyclopedia" - starting_title = "Hacking" - page_link = "Hacking" - -/obj/item/book/manual/wiki/detective - name = "The Film Noir: Proper Procedures for Investigations" - icon_state ="bookDetective" - starting_author = "Nanotrasen" - starting_title = "The Film Noir: Proper Procedures for Investigations" - page_link = "Detective" - -/obj/item/book/manual/wiki/barman_recipes - name = "Barman Recipes: Mixing Drinks and Changing Lives" - icon_state = "barbook" - starting_author = "Sir John Rose" - starting_title = "Barman Recipes: Mixing Drinks and Changing Lives" - page_link = "Guide_to_drinks" - -/obj/item/book/manual/wiki/robotics_cyborgs - name = "Robotics for Dummies" - icon_state = "borgbook" - starting_author = "XISC" - starting_title = "Robotics for Dummies" - page_link = "Guide_to_robotics" - -/obj/item/book/manual/wiki/research_and_development - name = "Research and Development 101" - icon_state = "rdbook" - starting_author = "Dr. L. Ight" - starting_title = "Research and Development 101" - page_link = "Guide_to_Research_and_Development" - -/obj/item/book/manual/wiki/experimentor - name = "Mentoring your Experiments" - icon_state = "rdbook" - starting_author = "Dr. H.P. Kritz" - starting_title = "Mentoring your Experiments" - page_link = "Experimentor" - -/obj/item/book/manual/wiki/cooking_to_serve_man - name = "To Serve Man" - desc = "It's a cookbook!" - icon_state ="cooked_book" - starting_author = "the Kanamitan Empire" - starting_title = "To Serve Man" - page_link = "Guide_to_food" - -/obj/item/book/manual/wiki/tcomms - name = "Subspace Telecommunications And You" - icon_state = "book3" - starting_author = "Engineering Encyclopedia" - starting_title = "Subspace Telecommunications And You" - page_link = "Guide_to_Telecommunications" - -/obj/item/book/manual/wiki/atmospherics - name = "Lexica Atmosia" - icon_state = "book5" - starting_author = "the City-state of Atmosia" - starting_title = "Lexica Atmosia" - page_link = "Guide_to_Atmospherics" - -/obj/item/book/manual/wiki/medicine - name = "Medical Space Compendium, Volume 638" - icon_state = "book8" - starting_author = "Medical Journal" - starting_title = "Medical Space Compendium, Volume 638" - page_link = "Guide_to_medicine" - -/obj/item/book/manual/wiki/surgery - name = "Brain Surgery for Dummies" - icon_state = "book4" - starting_author = "Dr. F. Fran" - starting_title = "Brain Surgery for Dummies" - page_link = "Surgery" - -/obj/item/book/manual/wiki/grenades - name = "DIY Chemical Grenades" - icon_state = "book2" - starting_author = "W. Powell" - starting_title = "DIY Chemical Grenades" - page_link = "Grenade" - -/obj/item/book/manual/wiki/ordnance - name = "Ordnance for Dummies or: How I Learned to Stop Worrying and Love the Maxcap" - icon_state = "book6" - starting_author = "Cuban Pete" - starting_title = "Ordnance for Dummies or: How I Learned to Stop Worrying and Love the Maxcap" - page_link = "Guide_to_toxins" - -/obj/item/book/manual/wiki/ordnance/suicide_act(mob/living/user) - var/mob/living/carbon/human/H = user - user.visible_message(span_suicide("[user] starts dancing to the Rhumba Beat! It looks like [user.p_theyre()] trying to commit suicide!")) - playsound(loc, 'sound/effects/spray.ogg', 10, TRUE, -3) - if (!QDELETED(H)) - H.emote("spin") - sleep(2 SECONDS) - for(var/obj/item/W in H) - H.dropItemToGround(W) - if(prob(50)) - step(W, pick(GLOB.alldirs)) - ADD_TRAIT(H, TRAIT_DISFIGURED, TRAIT_GENERIC) - for(var/obj/item/bodypart/part as anything in H.bodyparts) - part.adjustBleedStacks(5) - H.gib_animation() - sleep(0.3 SECONDS) - H.adjustBruteLoss(1000) //to make the body super-bloody - // if we use gib() then the body gets deleted - H.spawn_gibs() - H.spill_organs(DROP_ALL_REMAINS) - H.spread_bodyparts(DROP_BRAIN) - return BRUTELOSS - -/obj/item/book/manual/wiki/plumbing - name = "Chemical Factories Without Narcotics" - icon_state ="plumbingbook" - starting_author = "Nanotrasen" - starting_title = "Chemical Factories Without Narcotics" - page_link = "Guide_to_plumbing" - -/obj/item/book/manual/wiki/cytology - name = "Unethically Grown Organics" - icon_state ="cytologybook" - starting_author = "Kryson" - starting_title = "Unethically Grown Organics" - page_link = "Guide_to_cytology" - -/obj/item/book/manual/wiki/tgc - name = "Tactical Game Cards - Player's Handbook" - icon_state = "tgcbook" - starting_author = "Nanotrasen Edu-tainment Division" - starting_title = "Tactical Game Cards - Player's Handbook" - page_link = "Tactical_Game_Cards" diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/melee/baton.dm index 6777d7934ff88..bca28a32ce54b 100644 --- a/code/game/objects/items/melee/baton.dm +++ b/code/game/objects/items/melee/baton.dm @@ -42,22 +42,22 @@ /// Boolean on whether people with chunky fingers can use this baton. var/chunky_finger_usable = FALSE - /// The context to show when the baton is active and targetting a living thing + /// The context to show when the baton is active and targeting a living thing var/context_living_target_active = "Stun" - /// The context to show when the baton is active and targetting a living thing in combat mode + /// The context to show when the baton is active and targeting a living thing in combat mode var/context_living_target_active_combat_mode = "Stun" - /// The context to show when the baton is inactive and targetting a living thing + /// The context to show when the baton is inactive and targeting a living thing var/context_living_target_inactive = "Prod" - /// The context to show when the baton is inactive and targetting a living thing in combat mode + /// The context to show when the baton is inactive and targeting a living thing in combat mode var/context_living_target_inactive_combat_mode = "Attack" - /// The RMB context to show when the baton is active and targetting a living thing + /// The RMB context to show when the baton is active and targeting a living thing var/context_living_rmb_active = "Attack" - /// The RMB context to show when the baton is inactive and targetting a living thing + /// The RMB context to show when the baton is inactive and targeting a living thing var/context_living_rmb_inactive = "Attack" /obj/item/melee/baton/Initialize(mapload) diff --git a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm index 26b5a4439ea20..d34cb7227632a 100644 --- a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm +++ b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm @@ -364,7 +364,6 @@ /datum/status_effect/golem/titanium/proc/buff_arm(obj/item/bodypart/arm/arm) arm.unarmed_damage_low += damage_increase arm.unarmed_damage_high += damage_increase - arm.unarmed_stun_threshold += damage_increase // We don't want to make knockdown more likely RegisterSignal(arm, COMSIG_QDELETING, PROC_REF(on_arm_destroyed)) LAZYADD(modified_arms, arm) @@ -383,7 +382,6 @@ return arm.unarmed_damage_low -= damage_increase arm.unarmed_damage_high -= damage_increase - arm.unarmed_stun_threshold -= damage_increase UnregisterSignal(arm, COMSIG_QDELETING) /// Remove references to deleted arms diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index fb4f72d68d162..2caf25321d0ea 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -12,8 +12,8 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \ new/datum/stack_recipe("catwalk floor tile", /obj/item/stack/tile/catwalk_tile, 1, 4, 20, category = CAT_TILES), \ new/datum/stack_recipe("stairs frame", /obj/structure/stairs_frame, 10, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), \ new/datum/stack_recipe("white cane", /obj/item/cane/white, 3, time = 1 SECONDS, one_per_turf = FALSE, category = CAT_TOOLS), \ + new/datum/stack_recipe("sharpened iron rod", /obj/item/ammo_casing/rebar, 1, time = 0.2 SECONDS, one_per_turf = FALSE, category = CAT_WEAPON_AMMO), \ )) - /obj/item/stack/rods name = "iron rod" desc = "Some rods. Can be used for building or something." diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 9ec054ea2008e..641ba6cc77399 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -303,6 +303,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ new/datum/stack_recipe("wooden barricade", /obj/structure/barricade/wooden, 5, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), \ new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_DOORS), \ new/datum/stack_recipe("wooden stairs frame", /obj/structure/stairs_frame/wood, 10, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), \ + new/datum/stack_recipe("wooden fence", /obj/structure/railing/wooden_fence, 2, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), \ new/datum/stack_recipe("coffin", /obj/structure/closet/crate/coffin, 5, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ new/datum/stack_recipe("book case", /obj/structure/bookcase, 4, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ new/datum/stack_recipe("drying rack", /obj/machinery/smartfridge/drying_rack, 10, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_TOOLS), \ diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index ac4a4ec93baae..1644a7da981b9 100644 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -75,7 +75,7 @@ /obj/item/wirecutters, /obj/item/wrench, /obj/item/spess_knife, - /obj/item/melee/sickly_blade/knock, + /obj/item/melee/sickly_blade/lock, )) /obj/item/storage/belt/utility/chief @@ -698,19 +698,23 @@ /obj/item/storage/belt/bandolier name = "bandolier" - desc = "A bandolier for holding rifle and shotgun ammunition." + desc = "A bandolier for holding rifle shotgun, and bigger revolver caliber ammunition." icon_state = "bandolier" inhand_icon_state = "bandolier" worn_icon_state = "bandolier" /obj/item/storage/belt/bandolier/Initialize(mapload) . = ..() - atom_storage.max_slots = 18 - atom_storage.max_total_storage = 18 + atom_storage.max_slots = 24 + atom_storage.max_total_storage = 24 + atom_storage.numerical_stacking = TRUE + atom_storage.allow_quick_gather = TRUE + atom_storage.allow_quick_empty = TRUE atom_storage.numerical_stacking = TRUE atom_storage.set_holdable(list( /obj/item/ammo_casing/strilka310, /obj/item/ammo_casing/shotgun, + /obj/item/ammo_casing/a357, )) /obj/item/storage/belt/fannypack diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index a5263780a9bf7..817565b70cddc 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -340,6 +340,14 @@ icon_state = "syndiebox" illustration = "writing_syndie" +/obj/item/storage/box/syndie_kit/rebarxbowsyndie + name = "Boxed Rebar Crossbow" + desc = "Now features instruction manual for making ammo." + +/obj/item/storage/box/syndie_kit/rebarxbowsyndie/PopulateContents() + new /obj/item/book/granter/crafting_recipe/dusting/rebarxbowsyndie_ammo(src) + new /obj/item/gun/ballistic/rifle/rebarxbow/syndie(src) + /obj/item/storage/box/syndie_kit/origami_bundle name = "origami kit" desc = "A box full of a number of rather masterfully engineered paper planes and a manual on \"The Art of Origami\"." diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm index 04eb28e236ec2..558c287e1e509 100644 --- a/code/game/objects/items/tanks/watertank.dm +++ b/code/game/objects/items/tanks/watertank.dm @@ -467,7 +467,7 @@ var/inj_am = injection_amount * seconds_per_tick var/used_amount = inj_am / usage_ratio - reagents.trans_to(user, used_amount, multiplier=usage_ratio, methods = INJECT) + reagents.trans_to(user, used_amount, usage_ratio, methods = INJECT) update_appearance() user.update_worn_back() //for overlays update diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm index 11470620c49f5..485ff0863a880 100644 --- a/code/game/objects/items/tools/crowbar.dm +++ b/code/game/objects/items/tools/crowbar.dm @@ -70,6 +70,24 @@ desc = "It's a bulky crowbar. It almost seems deliberately designed to not be able to fit inside of a backpack." w_class = WEIGHT_CLASS_BULKY +/obj/item/crowbar/hammer + name = "claw hammer" + desc = "It's a heavy hammer with a pry bar on the back of its head. Nails aren't common in space, but this tool can still be used as a weapon or a crowbar." + force = 11 + w_class = WEIGHT_CLASS_NORMAL + icon = 'icons/obj/weapons/hammer.dmi' + icon_state = "clawhammer" + lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi' + inhand_icon_state = "clawhammer" + belt_icon_state = "clawhammer" + throwforce = 10 + throw_range = 5 + throw_speed = 3 + toolspeed = 2 + custom_materials = list(/datum/material/wood=SMALL_MATERIAL_AMOUNT*0.5, /datum/material/iron=SMALL_MATERIAL_AMOUNT*0.7) + wound_bonus = 35 + /obj/item/crowbar/large/heavy //from space ruin name = "heavy crowbar" desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big. It feels oddly heavy.." diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 8c949b36a79e4..b2cba11907ac4 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -113,6 +113,21 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 throw_range = 5 armour_penetration = 35 +/obj/item/claymore/carrot + name = "carrot sword" + desc = "A full-sized carrot sword. Definitely \not\ good for the eyes, not anymore." + icon_state = "carrot_sword" + inhand_icon_state = "carrot_sword" + worn_icon_state = "carrot_sword" + flags_1 = NONE + force = 19 + throwforce = 7 + throw_speed = 3 + throw_range = 7 + armour_penetration = 5 + block_chance = 10 + resistance_flags = NONE + /obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim." flags_1 = CONDUCT_1 diff --git a/code/game/objects/items/wiki_manuals.dm b/code/game/objects/items/wiki_manuals.dm new file mode 100644 index 0000000000000..7209d76cc5735 --- /dev/null +++ b/code/game/objects/items/wiki_manuals.dm @@ -0,0 +1,228 @@ +// Wiki books that are linked to the configured wiki link. + +/// The size of the window that the wiki books open in. +#define BOOK_WINDOW_BROWSE_SIZE "970x710" +/// This macro will resolve to code that will open up the associated wiki page in the window. +#define WIKI_PAGE_IFRAME(wikiurl, link_identifier) {" + + + + + + + +

You start skimming through the manual...

+ + + + "} + +// A book that links to the wiki +/obj/item/book/manual/wiki + starting_content = "Nanotrasen presently does not have any resources on this topic. If you would like to know more, contact your local Central Command representative." // safety + /// The ending URL of the page that we link to. + var/page_link = "" + +/obj/item/book/manual/wiki/display_content(mob/living/user) + var/wiki_url = CONFIG_GET(string/wikiurl) + if(!wiki_url) + user.balloon_alert(user, "this book is empty!") + return + + credit_book_to_reader(user) + DIRECT_OUTPUT(user, browse(WIKI_PAGE_IFRAME(wiki_url, page_link), "window=manual;size=[BOOK_WINDOW_BROWSE_SIZE]")) // if you change this GUARANTEE that it works. + +/obj/item/book/manual/wiki/chemistry + name = "Chemistry Textbook" + icon_state ="chemistrybook" + starting_author = "Nanotrasen" + starting_title = "Chemistry Textbook" + page_link = "Guide_to_chemistry" + +/obj/item/book/manual/wiki/engineering_construction + name = "Station Repairs and Construction" + icon_state ="bookEngineering" + starting_author = "Engineering Encyclopedia" + starting_title = "Station Repairs and Construction" + page_link = "Guide_to_construction" + +/obj/item/book/manual/wiki/engineering_guide + name = "Engineering Textbook" + icon_state ="bookEngineering2" + starting_author = "Engineering Encyclopedia" + starting_title = "Engineering Textbook" + page_link = "Guide_to_engineering" + +/obj/item/book/manual/wiki/security_space_law + name = "Space Law" + desc = "A set of Nanotrasen guidelines for keeping law and order on their space stations." + icon_state = "bookSpaceLaw" + starting_author = "Nanotrasen" + starting_title = "Space Law" + page_link = "Space_Law" + +/obj/item/book/manual/wiki/security_space_law/suicide_act(mob/living/user) + user.visible_message(span_suicide("[user] pretends to read \the [src] intently... then promptly dies of laughter!")) + return OXYLOSS + +/obj/item/book/manual/wiki/infections + name = "Infections - Making your own pandemic!" + icon_state = "bookInfections" + starting_author = "Infections Encyclopedia" + starting_title = "Infections - Making your own pandemic!" + page_link = "Infections" + +/obj/item/book/manual/wiki/telescience + name = "Teleportation Science - Bluespace for dummies!" + icon_state = "book7" + starting_author = "University of Bluespace" + starting_title = "Teleportation Science - Bluespace for dummies!" + page_link = "Guide_to_telescience" + +/obj/item/book/manual/wiki/engineering_hacking + name = "Hacking" + icon_state ="bookHacking" + starting_author = "Engineering Encyclopedia" + starting_title = "Hacking" + page_link = "Hacking" + +/obj/item/book/manual/wiki/detective + name = "The Film Noir: Proper Procedures for Investigations" + icon_state ="bookDetective" + starting_author = "Nanotrasen" + starting_title = "The Film Noir: Proper Procedures for Investigations" + page_link = "Detective" + +/obj/item/book/manual/wiki/barman_recipes + name = "Barman Recipes: Mixing Drinks and Changing Lives" + icon_state = "barbook" + starting_author = "Sir John Rose" + starting_title = "Barman Recipes: Mixing Drinks and Changing Lives" + page_link = "Guide_to_drinks" + +/obj/item/book/manual/wiki/robotics_cyborgs + name = "Robotics for Dummies" + icon_state = "borgbook" + starting_author = "XISC" + starting_title = "Robotics for Dummies" + page_link = "Guide_to_robotics" + +/obj/item/book/manual/wiki/research_and_development + name = "Research and Development 101" + icon_state = "rdbook" + starting_author = "Dr. L. Ight" + starting_title = "Research and Development 101" + page_link = "Guide_to_Research_and_Development" + +/obj/item/book/manual/wiki/experimentor + name = "Mentoring your Experiments" + icon_state = "rdbook" + starting_author = "Dr. H.P. Kritz" + starting_title = "Mentoring your Experiments" + page_link = "Experimentor" + +/obj/item/book/manual/wiki/cooking_to_serve_man + name = "To Serve Man" + desc = "It's a cookbook!" + icon_state ="cooked_book" + starting_author = "the Kanamitan Empire" + starting_title = "To Serve Man" + page_link = "Guide_to_food" + +/obj/item/book/manual/wiki/tcomms + name = "Subspace Telecommunications And You" + icon_state = "book3" + starting_author = "Engineering Encyclopedia" + starting_title = "Subspace Telecommunications And You" + page_link = "Guide_to_Telecommunications" + +/obj/item/book/manual/wiki/atmospherics + name = "Lexica Atmosia" + icon_state = "book5" + starting_author = "the City-state of Atmosia" + starting_title = "Lexica Atmosia" + page_link = "Guide_to_Atmospherics" + +/obj/item/book/manual/wiki/medicine + name = "Medical Space Compendium, Volume 638" + icon_state = "book8" + starting_author = "Medical Journal" + starting_title = "Medical Space Compendium, Volume 638" + page_link = "Guide_to_medicine" + +/obj/item/book/manual/wiki/surgery + name = "Brain Surgery for Dummies" + icon_state = "book4" + starting_author = "Dr. F. Fran" + starting_title = "Brain Surgery for Dummies" + page_link = "Surgery" + +/obj/item/book/manual/wiki/grenades + name = "DIY Chemical Grenades" + icon_state = "book2" + starting_author = "W. Powell" + starting_title = "DIY Chemical Grenades" + page_link = "Grenade" + +/obj/item/book/manual/wiki/ordnance + name = "Ordnance for Dummies or: How I Learned to Stop Worrying and Love the Maxcap" + icon_state = "book6" + starting_author = "Cuban Pete" + starting_title = "Ordnance for Dummies or: How I Learned to Stop Worrying and Love the Maxcap" + page_link = "Guide_to_toxins" + +/obj/item/book/manual/wiki/ordnance/suicide_act(mob/living/user) + var/mob/living/carbon/human/H = user + user.visible_message(span_suicide("[user] starts dancing to the Rhumba Beat! It looks like [user.p_theyre()] trying to commit suicide!")) + playsound(loc, 'sound/effects/spray.ogg', 10, TRUE, -3) + if (!QDELETED(H)) + H.emote("spin") + sleep(2 SECONDS) + for(var/obj/item/W in H) + H.dropItemToGround(W) + if(prob(50)) + step(W, pick(GLOB.alldirs)) + ADD_TRAIT(H, TRAIT_DISFIGURED, TRAIT_GENERIC) + for(var/obj/item/bodypart/part as anything in H.bodyparts) + part.adjustBleedStacks(5) + H.gib_animation() + sleep(0.3 SECONDS) + H.adjustBruteLoss(1000) //to make the body super-bloody + // if we use gib() then the body gets deleted + H.spawn_gibs() + H.spill_organs(DROP_ALL_REMAINS) + H.spread_bodyparts(DROP_BRAIN) + return BRUTELOSS + +/obj/item/book/manual/wiki/plumbing + name = "Chemical Factories Without Narcotics" + icon_state ="plumbingbook" + starting_author = "Nanotrasen" + starting_title = "Chemical Factories Without Narcotics" + page_link = "Guide_to_plumbing" + +/obj/item/book/manual/wiki/cytology + name = "Unethically Grown Organics" + icon_state ="cytologybook" + starting_author = "Kryson" + starting_title = "Unethically Grown Organics" + page_link = "Guide_to_cytology" + +/obj/item/book/manual/wiki/tgc + name = "Tactical Game Cards - Player's Handbook" + icon_state = "tgcbook" + starting_author = "Nanotrasen Edu-tainment Division" + starting_title = "Tactical Game Cards - Player's Handbook" + page_link = "Tactical_Game_Cards" + +#undef BOOK_WINDOW_BROWSE_SIZE +#undef WIKI_PAGE_IFRAME diff --git a/code/game/objects/items/singularityhammer.dm b/code/game/objects/items/wizard_weapons.dm similarity index 98% rename from code/game/objects/items/singularityhammer.dm rename to code/game/objects/items/wizard_weapons.dm index 50a97c215d850..b16f5be5bfd48 100644 --- a/code/game/objects/items/singularityhammer.dm +++ b/code/game/objects/items/wizard_weapons.dm @@ -77,12 +77,12 @@ return . /obj/item/mjollnir - name = "Mjolnir" + name = "Mjollnir" desc = "A weapon worthy of a god, able to strike with the force of a lightning bolt. It crackles with barely contained energy." icon = 'icons/obj/weapons/hammer.dmi' icon_state = "mjollnir0" base_icon_state = "mjollnir" - worn_icon_state = "mjolnir" + worn_icon_state = "mjollnir" lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi' flags_1 = CONDUCT_1 diff --git a/code/game/objects/structures/cannons/cannon.dm b/code/game/objects/structures/cannons/cannon.dm index 12fa04dbe0b94..dea2864fabe61 100644 --- a/code/game/objects/structures/cannons/cannon.dm +++ b/code/game/objects/structures/cannons/cannon.dm @@ -101,11 +101,11 @@ to_chat(user, span_warning("[powder_keg] doesn't have at least 15u of gunpowder to fill [src]!")) return if(has_enough_gunpowder) - powder_keg.reagents.trans_id_to(src, /datum/reagent/gunpowder, amount = charge_size) + powder_keg.reagents.trans_to(src, charge_size, target_id = /datum/reagent/gunpowder) balloon_alert(user, "[src] loaded with gunpowder") return if(has_enough_alt_fuel) - powder_keg.reagents.trans_id_to(src, /datum/reagent/fuel, amount = charge_size) + powder_keg.reagents.trans_to(src, charge_size, target_id = /datum/reagent/fuel) balloon_alert(user, "[src] loaded with welding fuel") return ..() diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index d517ebb11969d..724b7951b7606 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -37,12 +37,18 @@ if(isnull(crate_paint_jobs)) crate_paint_jobs = list( "Internals" = list("icon_state" = "o2crate"), - "Medical" = list("icon_state" = "medicalcrate"), + "Medical" = list("icon_state" = "medical"), + "Medical Plus" = list("icon_state" = "medicalcrate"), "Radiation" = list("icon_state" = "radiation"), "Hydrophonics" = list("icon_state" = "hydrocrate"), "Science" = list("icon_state" = "scicrate"), + "Robotics" = list("icon_state" = "robo"), "Solar" = list("icon_state" = "engi_e_crate"), - "Engineering" = list("icon_state" = "engi_crate") + "Engineering" = list("icon_state" = "engi_crate"), + "Atmospherics" = list("icon_state" = "atmos"), + "Cargo" = list("icon_state" = "cargo"), + "Mining" = list("icon_state" = "mining"), + "Command" = list("icon_state" = "centcom") ) if(paint_jobs) paint_jobs = crate_paint_jobs @@ -203,6 +209,10 @@ icon_state = "medicalcrate" base_icon_state = "medicalcrate" +/obj/structure/closet/crate/medical/department + icon_state = "medical" + base_icon_state = "medical" + /obj/structure/closet/crate/freezer desc = "A freezer." name = "freezer" @@ -259,6 +269,11 @@ new /obj/item/bodypart/leg/right/robot/surplus(src) new /obj/item/bodypart/leg/right/robot/surplus(src) +/obj/structure/closet/crate/freezer/food + name = "food icebox" + icon_state = "food" + base_icon_state = "food" + /obj/structure/closet/crate/radiation desc = "A crate with a radiation sign on it." name = "radiation crate" @@ -271,6 +286,21 @@ icon_state = "hydrocrate" base_icon_state = "hydrocrate" +/obj/structure/closet/crate/centcom + name = "centcom crate" + icon_state = "centcom" + base_icon_state = "centcom" + +/obj/structure/closet/crate/cargo + name = "cargo crate" + icon_state = "cargo" + base_icon_state = "cargo" + +/obj/structure/closet/crate/cargo/mining + name = "mining crate" + icon_state = "mining" + base_icon_state = "mining" + /obj/structure/closet/crate/engineering name = "engineering crate" icon_state = "engi_crate" @@ -280,6 +310,11 @@ icon_state = "engi_e_crate" base_icon_state = "engi_e_crate" +/obj/structure/closet/crate/engineering/atmos + name = "atmospherics crate" + icon_state = "atmos" + base_icon_state = "atmos" + /obj/structure/closet/crate/rcd desc = "A crate for the storage of an RCD." name = "\improper RCD crate" @@ -298,10 +333,15 @@ icon_state = "scicrate" base_icon_state = "scicrate" +/obj/structure/closet/crate/science/robo + name = "robotics crate" + icon_state = "robo" + base_icon_state = "robo" + /obj/structure/closet/crate/mod name = "MOD crate" - icon_state = "scicrate" - base_icon_state = "scicrate" + icon_state = "robo" + base_icon_state = "robo" /obj/structure/closet/crate/mod/PopulateContents() ..() @@ -325,6 +365,8 @@ /obj/structure/closet/crate/goldcrate name = "gold crate" + icon_state = "gold" + base_icon_state = "gold" /obj/structure/closet/crate/goldcrate/PopulateContents() ..() @@ -338,6 +380,8 @@ /obj/structure/closet/crate/silvercrate name = "silver crate" + icon_state = "silver" + base_icon_state = "silver" /obj/structure/closet/crate/silvercrate/PopulateContents() ..() diff --git a/code/game/objects/structures/crates_lockers/crates/secure.dm b/code/game/objects/structures/crates_lockers/crates/secure.dm index 595481b707c27..81f7b97a3c159 100644 --- a/code/game/objects/structures/crates_lockers/crates/secure.dm +++ b/code/game/objects/structures/crates_lockers/crates/secure.dm @@ -63,8 +63,8 @@ base_icon_state = "hydrosecurecrate" /obj/structure/closet/crate/secure/freezer //for consistency with other "freezer" closets/crates - desc = "An insulated crate with a lock on it, used to secure perishables." - name = "secure kitchen crate" + desc = "An icebox with a lock on it, used to secure perishables." + name = "secure kitchen icebox" icon_state = "kitchen_secure_crate" base_icon_state = "kitchen_secure_crate" paint_jobs = null @@ -79,18 +79,49 @@ . = ..() new /obj/effect/spawner/random/food_or_drink/pizzaparty(src) +/obj/structure/closet/crate/secure/centcom + name = "secure centcom crate" + icon_state = "centcom_secure" + base_icon_state = "centcom_secure" + +/obj/structure/closet/crate/secure/cargo + name = "secure cargo crate" + icon_state = "cargo_secure" + base_icon_state = "cargo_secure" + +/obj/structure/closet/crate/secure/cargo/mining + name = "secure mining crate" + icon_state = "mining_secure" + base_icon_state = "mining_secure" + +/obj/structure/closet/crate/secure/radiation + name = "secure radioation crate" + icon_state = "radiation_secure" + base_icon_state = "radiation_secure" + /obj/structure/closet/crate/secure/engineering desc = "A crate with a lock on it, painted in the scheme of the station's engineers." name = "secure engineering crate" icon_state = "engi_secure_crate" base_icon_state = "engi_secure_crate" +/obj/structure/closet/crate/secure/engineering/atmos + name = "secure atmospherics crate" + desc = "A crate with a lock on it, painted in the scheme of the station's atmospherics engineers." + icon_state = "atmos_secure" + base_icon_state = "atmos_secure" + /obj/structure/closet/crate/secure/science name = "secure science crate" desc = "A crate with a lock on it, painted in the scheme of the station's scientists." icon_state = "scisecurecrate" base_icon_state = "scisecurecrate" +/obj/structure/closet/crate/secure/science/robo + name = "robotics science crate" + icon_state = "robo_secure" + base_icon_state = "robo_secure" + /obj/structure/closet/crate/secure/owned name = "private crate" desc = "A crate cover designed to only open for who purchased its contents." diff --git a/code/game/objects/structures/crates_lockers/crates/syndicrate.dm b/code/game/objects/structures/crates_lockers/crates/syndicrate.dm index ff7cf8df03ba4..8403f82213511 100644 --- a/code/game/objects/structures/crates_lockers/crates/syndicrate.dm +++ b/code/game/objects/structures/crates_lockers/crates/syndicrate.dm @@ -1,4 +1,4 @@ -/obj/structure/closet/crate/syndicrate +/obj/structure/closet/crate/secure/syndicrate name = "surplus syndicrate" desc = "A conspicuous crate with the Syndicate logo on it. You don't know how to open it." icon_state = "syndicrate" @@ -20,7 +20,7 @@ laser = 50 energy = 100 -/obj/structure/closet/crate/syndicrate/before_open(mob/living/user, force) +/obj/structure/closet/crate/secure/syndicrate/before_open(mob/living/user, force) . = ..() if(!.) return FALSE @@ -31,7 +31,7 @@ return TRUE -/obj/structure/closet/crate/syndicrate/take_damage(damage_amount, damage_type = BRUTE, damage_flag = "", sound_effect = TRUE, attack_dir, armour_penetration = 0) +/obj/structure/closet/crate/secure/syndicrate/take_damage(damage_amount, damage_type = BRUTE, damage_flag = "", sound_effect = TRUE, attack_dir, armour_penetration = 0) if(created_items) return ..() if(damage_amount < DAMAGE_PRECISION) @@ -43,7 +43,7 @@ qdel(src) ///ensures that the syndicrate can only be unlocked by opening it with a syndicrate_key -/obj/structure/closet/crate/syndicrate/attackby(obj/item/item, mob/user, params) +/obj/structure/closet/crate/secure/syndicrate/attackby(obj/item/item, mob/user, params) if(!istype(item, /obj/item/syndicrate_key) || created_items) return ..() created_items = TRUE @@ -53,17 +53,22 @@ qdel(item) to_chat(user, span_notice("You twist the key into both locks at once, opening the crate.")) playsound(src, 'sound/machines/boltsup.ogg', 50, vary = FALSE) - update_appearance(updates = UPDATE_OVERLAYS) togglelock(user) -/obj/structure/closet/crate/syndicrate/attackby_secondary(obj/item/weapon, mob/user, params) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/structure/closet/crate/secure/syndicrate/togglelock(mob/living/user, silent) + if(broken || !created_items) + return + if(iscarbon(user)) + add_fingerprint(user) + locked = !locked + user.visible_message( + span_notice("[user] [locked ? "locks" : "unlocks"] [src]."), + span_notice("You [locked ? "locked" : "unlocked"] [src]."), + ) + update_appearance() -///syndicrate has a unique overlay for being unlocked -/obj/structure/closet/crate/syndicrate/closet_update_overlays(list/new_overlays) - . = new_overlays - if(created_items) - . += "syndicrate_unlocked" +/obj/structure/closet/crate/secure/syndicrate/attackby_secondary(obj/item/weapon, mob/user, params) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN /obj/item/syndicrate_key name = "syndicrate key" @@ -79,7 +84,7 @@ /obj/item/syndicrate_key/add_item_context(obj/item/source, list/context, atom/target, mob/living/user) . = ..() - var/obj/structure/closet/crate/syndicrate/target_structure = target + var/obj/structure/closet/crate/secure/syndicrate/target_structure = target if(!istype(target_structure)) return NONE if(target_structure.created_items) diff --git a/code/game/objects/structures/ore_containers.dm b/code/game/objects/structures/ore_containers.dm new file mode 100644 index 0000000000000..6bc6f680116f4 --- /dev/null +++ b/code/game/objects/structures/ore_containers.dm @@ -0,0 +1,62 @@ +///structure to contain ores +/obj/structure/ore_container + +/obj/structure/ore_container/attackby(obj/item/ore, mob/living/carbon/human/user, list/modifiers) + if(istype(ore, /obj/item/stack/ore) && !user.combat_mode) + ore.forceMove(src) + return + return ..() + +/obj/structure/ore_container/Entered(atom/movable/mover) + . = ..() + update_appearance(UPDATE_OVERLAYS) + +/obj/structure/ore_container/Exited(atom/movable/mover) + . = ..() + update_appearance(UPDATE_OVERLAYS) + +/obj/structure/ore_container/ui_interact(mob/user, datum/tgui/ui) + . = ..() + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "OreContainer") + ui.open() + +/obj/structure/ore_container/ui_data(mob/user) + var/list/data = list() + data["ores"] = list() + for(var/obj/item/stack/ore/ore_item in contents) + data["ores"] += list(list( + "id" = REF(ore_item), + "name" = ore_item.name, + "amount" = ore_item.amount, + )) + return data + +/obj/structure/ore_container/ui_static_data(mob/user) + var/list/data = list() + data["ore_images"] = list() + for(var/obj/item/stack/ore_item as anything in subtypesof(/obj/item/stack/ore)) + data["ore_images"] += list(list( + "name" = initial(ore_item.name), + "icon" = icon2base64(getFlatIcon(image(icon = initial(ore_item.icon), icon_state = initial(ore_item.icon_state)), no_anim=TRUE)) + )) + return data + +/obj/structure/ore_container/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + + if(. || !isliving(ui.user)) + return TRUE + + var/mob/living/customer = ui.user + var/obj/item/stack_to_move + switch(action) + if("withdraw") + if(isnull(params["reference"])) + return TRUE + stack_to_move = locate(params["reference"]) in contents + if(isnull(stack_to_move)) + return TRUE + stack_to_move.forceMove(get_turf(customer)) + return TRUE diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm index 5aaed01e0b86c..fa12148d33095 100644 --- a/code/game/objects/structures/railings.dm +++ b/code/game/objects/structures/railings.dm @@ -17,6 +17,8 @@ var/climbable = TRUE ///Initial direction of the railing. var/ini_dir + ///item released when deconstructed + var/item_deconstruct = /obj/item/stack/rods /datum/armor/structure_railing melee = 35 @@ -98,13 +100,11 @@ return TRUE /obj/structure/railing/deconstruct(disassembled) - if(!(flags_1 & NODECONSTRUCT_1)) - if (istype(src,/obj/structure/railing/corner)) // Corner railings only cost 1 rod - var/obj/item/stack/rods/rod = new /obj/item/stack/rods(drop_location(), 1) - transfer_fingerprints_to(rod) - else - var/obj/item/stack/rods/rod = new /obj/item/stack/rods(drop_location(), 2) - transfer_fingerprints_to(rod) + if((flags_1 & NODECONSTRUCT_1)) + return ..() + var/rods_to_make = istype(src,/obj/structure/railing/corner) ? 1 : 2 + var/obj/rod = new item_deconstruct(drop_location(), rods_to_make) + transfer_fingerprints_to(rod) return ..() ///Implements behaviour that makes it possible to unanchor the railing. @@ -156,3 +156,35 @@ /obj/structure/railing/proc/check_anchored(checked_anchored) if(anchored == checked_anchored) return TRUE + + +/obj/structure/railing/wooden_fence + name = "wooden fence" + desc = "wooden fence meant to keep animals in." + icon = 'icons/obj/structures.dmi' + icon_state = "wooden_railing" + item_deconstruct = /obj/item/stack/sheet/mineral/wood + plane = GAME_PLANE_FOV_HIDDEN + layer = ABOVE_MOB_LAYER + +/obj/structure/railing/wooden_fence/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_change_layer)) + adjust_dir_layer(dir) + +/obj/structure/railing/wooden_fence/proc/on_change_layer(datum/source, old_dir, new_dir) + SIGNAL_HANDLER + adjust_dir_layer(new_dir) + +/obj/structure/railing/wooden_fence/proc/adjust_dir_layer(direction) + var/new_layer = (direction & NORTH) ? MOB_LAYER : ABOVE_MOB_LAYER + layer = new_layer + + +/obj/structure/railing/corner/end/wooden_fence + icon = 'icons/obj/structures.dmi' + icon_state = "wooden_railing_corner" + +/obj/structure/railing/corner/end/flip/wooden_fence + icon = 'icons/obj/structures.dmi' + icon_state = "wooden_railing_corner_flipped" diff --git a/code/game/turfs/baseturfs.dm b/code/game/turfs/baseturfs.dm index 7eaac2f9ef08e..91e66b1a4d0ad 100644 --- a/code/game/turfs/baseturfs.dm +++ b/code/game/turfs/baseturfs.dm @@ -20,27 +20,12 @@ return ChangeTurf(baseturfs, baseturfs, flags) // The bottom baseturf will never go away -// Take the input as baseturfs and put it underneath the current baseturfs -// If fake_turf_type is provided and new_baseturfs is not the baseturfs list will be created identical to the turf type's -// If both or just new_baseturfs is provided they will be inserted below the existing baseturfs -/turf/proc/PlaceOnBottom(list/new_baseturfs, turf/fake_turf_type) - if(fake_turf_type) - if(!new_baseturfs) - if(!length(baseturfs)) - baseturfs = list(baseturfs) - var/list/old_baseturfs = baseturfs.Copy() - assemble_baseturfs(fake_turf_type) - if(!length(baseturfs)) - baseturfs = list(baseturfs) - baseturfs = baseturfs_string_list((baseturfs - (baseturfs & GLOB.blacklisted_automated_baseturfs)) + old_baseturfs, src) - return - else if(!length(new_baseturfs)) - new_baseturfs = list(new_baseturfs, fake_turf_type) - else - new_baseturfs += fake_turf_type - if(!length(baseturfs)) - baseturfs = list(baseturfs) - baseturfs = baseturfs_string_list(new_baseturfs + baseturfs, src) +/// Places the given turf on the bottom of the turf stack. +/turf/proc/place_on_bottom(turf/bottom_turf) + baseturfs = baseturfs_string_list( + list(initial(bottom_turf.baseturfs), bottom_turf) + baseturfs, + src + ) // Make a new turf and put it on top // The args behave identical to PlaceOnBottom except they go on top diff --git a/code/game/turfs/open/floor/plating/misc_plating.dm b/code/game/turfs/open/floor/plating/misc_plating.dm index 1933b291aee93..9b79313111f13 100644 --- a/code/game/turfs/open/floor/plating/misc_plating.dm +++ b/code/game/turfs/open/floor/plating/misc_plating.dm @@ -6,6 +6,10 @@ initial_gas_mix = OPENTURF_LOW_PRESSURE baseturfs = /turf/open/floor/plating/lowpressure +/turf/open/floor/plating/dumpsterair + initial_gas_mix = OPENTURF_DIRTY_ATMOS + temperature = 309 + /turf/open/floor/plating/icemoon icon_state = "plating" initial_gas_mix = ICEMOON_DEFAULT_ATMOS diff --git a/code/modules/NTNet/relays.dm b/code/modules/NTNet/relays.dm index abe777f276f42..a2db78a175b4d 100644 --- a/code/modules/NTNet/relays.dm +++ b/code/modules/NTNet/relays.dm @@ -1,9 +1,7 @@ -GLOBAL_LIST_EMPTY(ntnet_relays) - ///Checks whether NTNet is available by ensuring at least one relay exists and is operational. /proc/find_functional_ntnet_relay() // Check all relays. If we have at least one working relay, ntos is up. - for(var/obj/machinery/ntnet_relay/relays as anything in GLOB.ntnet_relays) + for(var/obj/machinery/ntnet_relay/relays as anything in SSmachines.get_machines_by_type(/obj/machinery/ntnet_relay)) if(!relays.is_operational) continue return TRUE @@ -33,6 +31,19 @@ GLOBAL_LIST_EMPTY(ntnet_relays) var/dos_capacity = 500 // Amount of DoS "packets" in buffer required to crash the relay var/dos_dissipate = 0.5 // Amount of DoS "packets" dissipated over time. +/obj/machinery/ntnet_relay/Initialize(mapload) + . = ..() + uid = gl_uid++ + var/list/current_machines = SSmachines.get_machines_by_type(/obj/machinery/ntnet_relay) + SSmodular_computers.add_log("New quantum relay activated. Current amount of linked relays: [current_machines.len]") + +/obj/machinery/ntnet_relay/Destroy() + . = ..() + var/list/machines_left = SSmachines.get_machines_by_type(/obj/machinery/ntnet_relay) + SSmodular_computers.add_log("Quantum relay connection severed. Current amount of linked relays: [machines_left.len]") + for(var/datum/computer_file/program/ntnet_dos/D in dos_sources) + D.target = null + D.error = "Connection to quantum relay severed" ///Proc called to change the value of the `relay_enabled` variable and append behavior related to its change. /obj/machinery/ntnet_relay/proc/set_relay_enabled(new_value) @@ -118,21 +129,3 @@ GLOBAL_LIST_EMPTY(ntnet_relays) SSmodular_computers.add_log("Quantum relay manually [relay_enabled ? "enabled" : "disabled"].") update_appearance() return TRUE - -/obj/machinery/ntnet_relay/Initialize(mapload) - uid = gl_uid++ - component_parts = list() - - GLOB.ntnet_relays += src - SSmodular_computers.add_log("New quantum relay activated. Current amount of linked relays: [GLOB.ntnet_relays.len]") - return ..() - -/obj/machinery/ntnet_relay/Destroy() - GLOB.ntnet_relays -= src - SSmodular_computers.add_log("Quantum relay connection severed. Current amount of linked relays: [GLOB.ntnet_relays.len]") - - for(var/datum/computer_file/program/ntnet_dos/D in dos_sources) - D.target = null - D.error = "Connection to quantum relay severed" - - return ..() diff --git a/code/modules/actionspeed/modifiers/drugs.dm b/code/modules/actionspeed/modifiers/drugs.dm index 8309f7fb30fae..bf06ddf811219 100644 --- a/code/modules/actionspeed/modifiers/drugs.dm +++ b/code/modules/actionspeed/modifiers/drugs.dm @@ -1,3 +1,2 @@ /datum/actionspeed_modifier/kronkaine multiplicative_slowdown = -0.5 - id = ACTIONSPEED_ID_STIMULANTS diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index e2ba145c640be..513b196ccc47e 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -358,10 +358,12 @@ GLOBAL_PROTECT(admin_verbs_poll) if(isnull(holder) || isnull(mob)) return if(mob.invisimin) + mob.add_to_all_human_data_huds() mob.invisimin = FALSE mob.RemoveInvisibility(INVISIBILITY_SOURCE_INVISIMIN) to_chat(mob, span_boldannounce("Invisimin off. Invisibility reset."), confidential = TRUE) else + mob.remove_from_all_data_huds() mob.invisimin = TRUE mob.SetInvisibility(INVISIBILITY_OBSERVER, INVISIBILITY_SOURCE_INVISIMIN, INVISIBILITY_PRIORITY_ADMIN) to_chat(mob, span_adminnotice("Invisimin on. You are now as invisible as a ghost."), confidential = TRUE) diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm index c1dcf68b9dfa7..e29388c9fd628 100644 --- a/code/modules/antagonists/abductor/equipment/gland.dm +++ b/code/modules/antagonists/abductor/equipment/gland.dm @@ -4,7 +4,6 @@ icon = 'icons/obj/antags/abductor.dmi' icon_state = "gland" organ_flags = ORGAN_ROBOTIC // weird? - beating = TRUE /// Shows name of the gland as well as a description of what it does upon examination by abductor scientists and observers. var/abductor_hint = "baseline placebo referencer" @@ -26,12 +25,16 @@ /obj/item/organ/internal/heart/gland/Initialize(mapload) . = ..() icon_state = pick(list("health", "spider", "slime", "emp", "species", "egg", "vent", "mindshock", "viral")) + AddElement(/datum/element/update_icon_blocker) /obj/item/organ/internal/heart/gland/examine(mob/user) . = ..() if(HAS_MIND_TRAIT(user, TRAIT_ABDUCTOR_SCIENTIST_TRAINING) || isobserver(user)) . += span_notice("It is \a [abductor_hint]") +/obj/item/organ/internal/heart/gland/Stop() + return FALSE + /obj/item/organ/internal/heart/gland/proc/ownerCheck() if(ishuman(owner)) return TRUE @@ -102,9 +105,6 @@ update_gland_hud() /obj/item/organ/internal/heart/gland/on_life(seconds_per_tick, times_fired) - if(!beating) - // alien glands are immune to stopping. - beating = TRUE if(!active) return if(!ownerCheck()) diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index f5d8bf2fa33c8..af5a05db5a8ab 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -377,8 +377,15 @@ Striking a noncultist, however, will tear their flesh."} fire = 50 acid = 60 -/obj/item/clothing/suit/hooded/cultrobes/cult_shield/setup_shielding() - AddComponent(/datum/component/shielded, recharge_start_delay = 0 SECONDS, shield_icon_file = 'icons/effects/cult/effects.dmi', shield_icon = "shield-cult", run_hit_callback = CALLBACK(src, PROC_REF(shield_damaged))) +/obj/item/clothing/suit/hooded/cultrobes/cult_shield/Initialize(mapload) + . = ..() + AddComponent( \ + /datum/component/shielded, \ + recharge_start_delay = 0 SECONDS, \ + shield_icon_file = 'icons/effects/cult/effects.dmi', \ + shield_icon = "shield-cult", \ + run_hit_callback = CALLBACK(src, PROC_REF(shield_damaged)), \ + ) /// A proc for callback when the shield breaks, since cult robes are stupid and have different effects /obj/item/clothing/suit/hooded/cultrobes/cult_shield/proc/shield_damaged(mob/living/wearer, attack_text, new_current_charges) @@ -451,6 +458,7 @@ Striking a noncultist, however, will tear their flesh."} /obj/item/clothing/glasses/hud/health/night/cultblind desc = "May Nar'Sie guide you through the darkness and shield you from the light." + flags_cover = GLASSESCOVERSEYES name = "zealot's blindfold" icon_state = "blindfold" inhand_icon_state = "blindfold" diff --git a/code/modules/antagonists/fugitive/hunters/hunter_gear.dm b/code/modules/antagonists/fugitive/hunters/hunter_gear.dm index acb31c08ac01d..7ba0401829a82 100644 --- a/code/modules/antagonists/fugitive/hunters/hunter_gear.dm +++ b/code/modules/antagonists/fugitive/hunters/hunter_gear.dm @@ -51,6 +51,8 @@ /obj/structure/closet/crate/eva name = "EVA crate" + icon_state = "o2crate" + base_icon_state = "o2crate" /obj/structure/closet/crate/eva/PopulateContents() ..() @@ -69,7 +71,7 @@ name = "psyker navigation warper" desc = "Uses amplified brainwaves to designate and map a precise transit location for the psyker shuttle." icon_screen = "recharge_comp_on" - interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_SET_MACHINE //blind friendly + interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON //blind friendly x_offset = 0 y_offset = 11 diff --git a/code/modules/antagonists/heretic/heretic_antag.dm b/code/modules/antagonists/heretic/heretic_antag.dm index 559cdb42adf52..e6a8f54f281c2 100644 --- a/code/modules/antagonists/heretic/heretic_antag.dm +++ b/code/modules/antagonists/heretic/heretic_antag.dm @@ -66,7 +66,7 @@ PATH_VOID = "blue", PATH_BLADE = "label", // my favorite color is label PATH_COSMIC = "purple", - PATH_KNOCK = "yellow", + PATH_LOCK = "yellow", ) var/static/list/path_to_rune_color = list( PATH_START = COLOR_LIME, @@ -76,7 +76,7 @@ PATH_VOID = COLOR_CYAN, PATH_BLADE = COLOR_SILVER, PATH_COSMIC = COLOR_PURPLE, - PATH_KNOCK = COLOR_YELLOW, + PATH_LOCK = COLOR_YELLOW, ) /datum/antagonist/heretic/Destroy() diff --git a/code/modules/antagonists/heretic/items/heretic_blades.dm b/code/modules/antagonists/heretic/items/heretic_blades.dm index 6bd8d22fb9e51..7cce886a14598 100644 --- a/code/modules/antagonists/heretic/items/heretic_blades.dm +++ b/code/modules/antagonists/heretic/items/heretic_blades.dm @@ -134,12 +134,12 @@ after_use_message = "The Stargazer hears your call..." // Path of Knock's blade -/obj/item/melee/sickly_blade/knock +/obj/item/melee/sickly_blade/lock name = "\improper key blade" desc = "A blade and a key, a key to what? \ What grand gates does it open?" icon_state = "key_blade" inhand_icon_state = "key_blade" - after_use_message = "The Mother of Ants hears your call..." + after_use_message = "The Stewards hear your call..." tool_behaviour = TOOL_CROWBAR toolspeed = 1.3 diff --git a/code/modules/antagonists/heretic/items/keyring.dm b/code/modules/antagonists/heretic/items/keyring.dm index 658105abb893a..a6a53bc3cee1a 100644 --- a/code/modules/antagonists/heretic/items/keyring.dm +++ b/code/modules/antagonists/heretic/items/keyring.dm @@ -1,4 +1,4 @@ -/obj/effect/knock_portal +/obj/effect/lock_portal name = "crack in reality" desc = "A crack in space, impossibly deep and painful to the eyes. Definitely not safe." icon = 'icons/effects/eldritch.dmi' @@ -12,18 +12,18 @@ density = FALSE //so we dont block doors closing layer = OBJ_LAYER //under doors ///The knock portal we teleport to - var/obj/effect/knock_portal/destination + var/obj/effect/lock_portal/destination ///The airlock we are linked to, we delete if it is destroyed var/obj/machinery/door/our_airlock /// if true the heretic is teleported to a random airlock, nonheretics are sent to the target var/inverted = FALSE -/obj/effect/knock_portal/Initialize(mapload, target, invert = FALSE) +/obj/effect/lock_portal/Initialize(mapload, target, invert = FALSE) . = ..() if(target) our_airlock = target RegisterSignal(target, COMSIG_QDELETING, PROC_REF(delete_on_door_delete)) - + var/static/list/loc_connections = list( COMSIG_ATOM_ENTERED = PROC_REF(on_entered), ) @@ -31,26 +31,26 @@ inverted = invert ///Deletes us and our destination portal if our_airlock is destroyed -/obj/effect/knock_portal/proc/delete_on_door_delete(datum/source) +/obj/effect/lock_portal/proc/delete_on_door_delete(datum/source) SIGNAL_HANDLER qdel(src) ///Signal handler for when our location is entered, calls teleport on the victim, if their old_loc didnt contain a portal already (to prevent loops) -/obj/effect/knock_portal/proc/on_entered(datum/source, mob/living/loser, atom/old_loc) +/obj/effect/lock_portal/proc/on_entered(datum/source, mob/living/loser, atom/old_loc) SIGNAL_HANDLER if(istype(loser) && !(locate(type) in old_loc)) teleport(loser) -/obj/effect/knock_portal/Destroy() +/obj/effect/lock_portal/Destroy() if(!isnull(destination) && !QDELING(destination)) QDEL_NULL(destination) - + destination = null our_airlock = null return ..() ///Teleports the teleportee, to a random airlock if the teleportee isnt a heretic, or the other portal if they are one -/obj/effect/knock_portal/proc/teleport(mob/living/teleportee) +/obj/effect/lock_portal/proc/teleport(mob/living/teleportee) if(isnull(destination)) //dumbass qdel(src) return @@ -67,7 +67,7 @@ INVOKE_ASYNC(src, PROC_REF(async_opendoor), doorstination) ///Returns a random airlock on the same Z level as our portal, that isnt our airlock -/obj/effect/knock_portal/proc/find_random_airlock() +/obj/effect/lock_portal/proc/find_random_airlock() var/list/turf/possible_destinations = list() for(var/obj/airlock as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/airlock)) if(airlock.z != z) @@ -78,7 +78,7 @@ return pick(possible_destinations) ///Asynchronous proc to unbolt, then open the passed door -/obj/effect/knock_portal/proc/async_opendoor(obj/machinery/door/door) +/obj/effect/lock_portal/proc/async_opendoor(obj/machinery/door/door) if(istype(door, /obj/machinery/door/airlock)) //they can create portals on ANY door, but we should unlock airlocks so they can actually open var/obj/machinery/door/airlock/as_airlock = door as_airlock.unbolt() @@ -89,9 +89,9 @@ ///List of IDs this card consumed var/list/obj/item/card/id/fused_ids = list() ///The first portal in the portal pair, so we can clear it later - var/obj/effect/knock_portal/portal_one + var/obj/effect/lock_portal/portal_one ///The second portal in the portal pair, so we can clear it later - var/obj/effect/knock_portal/portal_two + var/obj/effect/lock_portal/portal_two ///The first door we are linking in the pair, so we can create a portal pair var/datum/weakref/link /// are our created portals inverted? (heretics get sent to a random airlock, crew get sent to the target) @@ -140,7 +140,7 @@ ///Deletes and nulls our portal pair /obj/item/card/id/advanced/heretic/proc/clear_portals() QDEL_NULL(portal_one) - QDEL_NULL(portal_two) + QDEL_NULL(portal_two) ///Clears portal references /obj/item/card/id/advanced/heretic/proc/clear_portal_refs() @@ -154,7 +154,7 @@ if(portal_one || portal_two) clear_portals() message += ", previous cleared" - + portal_one = new(get_turf(door2), door2, inverted) portal_two = new(get_turf(door1), door1, inverted) portal_one.destination = portal_two @@ -175,7 +175,7 @@ . = ..() if(!proximity_flag || !IS_HERETIC(user)) return - if(istype(target, /obj/effect/knock_portal)) + if(istype(target, /obj/effect/lock_portal)) clear_portals() return diff --git a/code/modules/antagonists/heretic/items/lintel.dm b/code/modules/antagonists/heretic/items/labyrinth_handbook.dm similarity index 83% rename from code/modules/antagonists/heretic/items/lintel.dm rename to code/modules/antagonists/heretic/items/labyrinth_handbook.dm index 140453842c090..b3e3649763fd5 100644 --- a/code/modules/antagonists/heretic/items/lintel.dm +++ b/code/modules/antagonists/heretic/items/labyrinth_handbook.dm @@ -1,5 +1,5 @@ /obj/effect/forcefield/wizard/heretic - name = "consecrated lintel" + name = "labyrinth pages" desc = "A field of papers flying in the air, repulsing heathens with impossible force." icon_state = "lintel" initial_duration = 8 SECONDS @@ -13,11 +13,11 @@ visible_message(span_danger("[src] repulses [bumpee] in a storm of paper!")) ///A heretic item that spawns a barrier at the clicked turf, 3 uses -/obj/item/heretic_lintel - name = "consecrated book" - desc = "Some kind of book, its contents make your head hurt. The material is not known to you and it seems to shift and twist unnaturally." +/obj/item/heretic_labyrinth_handbook + name = "labyrinth handbook" + desc = "A book containing the laws and regulations of the Locked Labyrinth, penned on an unknown substance. Its pages squirm and strain, looking to lash out and escape." icon = 'icons/obj/service/library.dmi' - icon_state = "hereticlintel" + icon_state = "heretichandbook" force = 10 damtype = BURN worn_icon_state = "book" @@ -34,14 +34,14 @@ ///how many uses do we have left var/uses = 3 -/obj/item/heretic_lintel/examine(mob/user) +/obj/item/heretic_labyrinth_handbook/examine(mob/user) . = ..() if(!IS_HERETIC_OR_MONSTER(user)) return . += span_hypnophrase("Materializes a barrier upon any tile in sight, which only you can pass through. Lasts 8 seconds.") . += span_hypnophrase("It has [uses] uses left.") -/obj/item/heretic_lintel/afterattack(atom/target, mob/user, proximity_flag) +/obj/item/heretic_labyrinth_handbook/afterattack(atom/target, mob/user, proximity_flag) . = ..() if(IS_HERETIC(user)) var/turf/turf_target = get_turf(target) diff --git a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm index 566bd18314223..508d142fa2792 100644 --- a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm @@ -248,7 +248,7 @@ /datum/pet_command/idle, /datum/pet_command/free, /datum/pet_command/follow, - /datum/pet_command/point_targetting/attack/star_gazer + /datum/pet_command/point_targeting/attack/star_gazer ) /datum/heretic_knowledge/ultimate/cosmic_final/is_valid_sacrifice(mob/living/carbon/human/sacrifice) diff --git a/code/modules/antagonists/heretic/knowledge/knock_lore.dm b/code/modules/antagonists/heretic/knowledge/lock_lore.dm similarity index 62% rename from code/modules/antagonists/heretic/knowledge/knock_lore.dm rename to code/modules/antagonists/heretic/knowledge/lock_lore.dm index 1bed48107d151..25f58c879dd88 100644 --- a/code/modules/antagonists/heretic/knowledge/knock_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/lock_lore.dm @@ -1,17 +1,17 @@ /** - * # The path of Knock. + * # The path of Lock. * * Goes as follows: * - * A Locksmith’s Secret - * Grasp of Knock + * A Steward's Secret + * Grasp of Lock * > Sidepaths: * Ashen Eyes * Codex Cicatrix * Key Keeper’s Burden * - * Rite Of Passage - * Mark Of Knock + * Concierge's Rite + * Mark Of Lock * Ritual of Knowledge * Burglar's Finesse * > Sidepaths: @@ -21,26 +21,26 @@ * Opening Blade * Caretaker’s Last Refuge * - * Many secrets behind the Spider Door + * Unlock the Labyrinth */ /datum/heretic_knowledge/limited_amount/starting/base_knock - name = "A Locksmith’s Secret" - desc = "Opens up the Path of Knock to you. \ + name = "A Steward's Secret" + desc = "Opens up the Path of Lock to you. \ Allows you to transmute a knife and a crowbar into a Key Blade. \ You can only create two at a time and they function as fast crowbars. \ In addition, they can fit into utility belts." - gain_text = "The Knock permits no seal and no isolation. It thrusts us gleefully out of the safety of ignorance." - next_knowledge = list(/datum/heretic_knowledge/knock_grasp) + gain_text = "The Locked Labyrinth leads to freedom. But only the trapped Stewards know the correct path." + next_knowledge = list(/datum/heretic_knowledge/lock_grasp) required_atoms = list( /obj/item/knife = 1, /obj/item/crowbar = 1, ) - result_atoms = list(/obj/item/melee/sickly_blade/knock) + result_atoms = list(/obj/item/melee/sickly_blade/lock) limit = 2 - route = PATH_KNOCK + route = PATH_LOCK -/datum/heretic_knowledge/knock_grasp - name = "Grasp of Knock" +/datum/heretic_knowledge/lock_grasp + name = "Grasp of Lock" desc = "Your mansus grasp allows you to access anything! Right click on an airlock or a locker to force it open. \ DNA locks on mechs will be removed, and any pilot will be ejected. Works on consoles. \ Makes a distinctive knocking sound on use." @@ -51,24 +51,24 @@ /datum/heretic_knowledge/codex_cicatrix, ) cost = 1 - route = PATH_KNOCK + route = PATH_LOCK -/datum/heretic_knowledge/knock_grasp/on_gain(mob/user, datum/antagonist/heretic/our_heretic) +/datum/heretic_knowledge/lock_grasp/on_gain(mob/user, datum/antagonist/heretic/our_heretic) RegisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK_SECONDARY, PROC_REF(on_secondary_mansus_grasp)) RegisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK, PROC_REF(on_mansus_grasp)) -/datum/heretic_knowledge/knock_grasp/on_lose(mob/user, datum/antagonist/heretic/our_heretic) +/datum/heretic_knowledge/lock_grasp/on_lose(mob/user, datum/antagonist/heretic/our_heretic) UnregisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK_SECONDARY) UnregisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK) -/datum/heretic_knowledge/knock_grasp/proc/on_mansus_grasp(mob/living/source, mob/living/target) +/datum/heretic_knowledge/lock_grasp/proc/on_mansus_grasp(mob/living/source, mob/living/target) SIGNAL_HANDLER var/obj/item/clothing/under/suit = target.get_item_by_slot(ITEM_SLOT_ICLOTHING) if(istype(suit) && suit.adjusted == NORMAL_STYLE) suit.toggle_jumpsuit_adjust() suit.update_appearance() -/datum/heretic_knowledge/knock_grasp/proc/on_secondary_mansus_grasp(mob/living/source, atom/target) +/datum/heretic_knowledge/lock_grasp/proc/on_secondary_mansus_grasp(mob/living/source, atom/target) SIGNAL_HANDLER if(ismecha(target)) @@ -98,7 +98,7 @@ It functions the same as an ID Card, but attacking it with an ID card fuses it and gains its access. \ You can use it in-hand to change its form to a card you fused. \ Does not preserve the card used in the ritual." - gain_text = "Gateways shall open before me, my very will ensnaring reality." + gain_text = "The Keeper sneered. \"These plastic rectangles are a mockery of keys, and I curse every door that desires them.\"" adds_sidepath_points = 1 required_atoms = list( /obj/item/storage/wallet = 1, @@ -106,64 +106,64 @@ /obj/item/card/id = 1, ) result_atoms = list(/obj/item/card/id/advanced/heretic) - next_knowledge = list(/datum/heretic_knowledge/limited_amount/rite_of_passage) + next_knowledge = list(/datum/heretic_knowledge/limited_amount/concierge_rite) cost = 1 - route = PATH_KNOCK + route = PATH_LOCK -/datum/heretic_knowledge/limited_amount/rite_of_passage // item that creates 3 max at a time heretic only barriers, probably should limit to 1 only, holy people can also pass - name = "Rite Of Passage" - desc = "Allows you to transmute a white crayon, a wooden plank, and a multitool to create a Consecrated Book. \ +/datum/heretic_knowledge/limited_amount/concierge_rite // item that creates 3 max at a time heretic only barriers, probably should limit to 1 only, holy people can also pass + name = "Concierge's Rite" + desc = "Allows you to transmute a white crayon, a wooden plank, and a multitool to create a Labyrinth Handbook. \ It can materialize a barricade at range that only you and people resistant to magic can pass. 3 uses." - gain_text = "With this I can repel those that intend me harm." + gain_text = "The Concierge scribbled my name into the Handbook. \"Welcome to your new home, fellow Steward.\"" required_atoms = list( /obj/item/toy/crayon/white = 1, /obj/item/stack/sheet/mineral/wood = 1, /obj/item/multitool = 1, ) - result_atoms = list(/obj/item/heretic_lintel) - next_knowledge = list(/datum/heretic_knowledge/mark/knock_mark) + result_atoms = list(/obj/item/heretic_labyrinth_handbook) + next_knowledge = list(/datum/heretic_knowledge/mark/lock_mark) cost = 1 - route = PATH_KNOCK + route = PATH_LOCK -/datum/heretic_knowledge/mark/knock_mark - name = "Mark of Knock" - desc = "Your Mansus Grasp now applies the Mark of Knock. \ +/datum/heretic_knowledge/mark/lock_mark + name = "Mark of Lock" + desc = "Your Mansus Grasp now applies the Mark of Lock. \ Attack a marked person to bar them from all passages for the duration of the mark. \ This will make it so that they have no access whatsoever, even public access doors will reject them." - gain_text = "Their requests for passage will remain unheeded." - next_knowledge = list(/datum/heretic_knowledge/knowledge_ritual/knock) - route = PATH_KNOCK - mark_type = /datum/status_effect/eldritch/knock + gain_text = "The Gatekeeper was a corrupt Steward. She hindered her fellows for her own twisted amusement." + next_knowledge = list(/datum/heretic_knowledge/knowledge_ritual/lock) + route = PATH_LOCK + mark_type = /datum/status_effect/eldritch/lock -/datum/heretic_knowledge/knowledge_ritual/knock +/datum/heretic_knowledge/knowledge_ritual/lock next_knowledge = list(/datum/heretic_knowledge/spell/burglar_finesse) - route = PATH_KNOCK + route = PATH_LOCK /datum/heretic_knowledge/spell/burglar_finesse name = "Burglar's Finesse" desc = "Grants you Burglar's Finesse, a single-target spell \ that puts a random item from the victims backpack into your hand." - gain_text = "Their trinkets will be mine, as will their lives in due time." + gain_text = "Consorting with Burglar spirits is frowned upon, but a Steward will always want to learn about new doors." adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/spell/apetra_vulnera, /datum/heretic_knowledge/spell/opening_blast, - /datum/heretic_knowledge/blade_upgrade/flesh/knock, + /datum/heretic_knowledge/blade_upgrade/flesh/lock, ) spell_to_add = /datum/action/cooldown/spell/pointed/burglar_finesse cost = 2 - route = PATH_KNOCK + route = PATH_LOCK -/datum/heretic_knowledge/blade_upgrade/flesh/knock //basically a chance-based weeping avulsion version of the former +/datum/heretic_knowledge/blade_upgrade/flesh/lock //basically a chance-based weeping avulsion version of the former name = "Opening Blade" desc = "Your blade has a chance to cause a weeping avulsion on attack." - gain_text = "The power of my patron courses through my blade, willing their very flesh to part." + gain_text = "The Pilgrim-Surgeon was not an Steward. Nonetheless, its blades and sutures proved a match for their keys." next_knowledge = list(/datum/heretic_knowledge/spell/caretaker_refuge) - route = PATH_KNOCK + route = PATH_LOCK wound_type = /datum/wound/slash/flesh/critical var/chance = 35 -/datum/heretic_knowledge/blade_upgrade/flesh/knock/do_melee_effects(mob/living/source, mob/living/target, obj/item/melee/sickly_blade/blade) +/datum/heretic_knowledge/blade_upgrade/flesh/lock/do_melee_effects(mob/living/source, mob/living/target, obj/item/melee/sickly_blade/blade) if(prob(chance)) return ..() @@ -172,29 +172,29 @@ desc = "Gives you a spell that makes you transparent and not dense. Cannot be used near living sentient beings. \ While in refuge, you cannot use your hands or spells, and you are immune to slowdown. \ You are invincible but unable to harm anything. Cancelled by being hit with an anti-magic item." - gain_text = "Then I saw my my own reflection cascaded mind-numbingly enough times that I was but a haze." + gain_text = "Jealously, the Guard and the Hound hunted me. But I unlocked my form, and was but a haze, untouchable." adds_sidepath_points = 1 - next_knowledge = list(/datum/heretic_knowledge/ultimate/knock_final) - route = PATH_KNOCK + next_knowledge = list(/datum/heretic_knowledge/ultimate/lock_final) + route = PATH_LOCK spell_to_add = /datum/action/cooldown/spell/caretaker cost = 1 -/datum/heretic_knowledge/ultimate/knock_final - name = "Many secrets behind the Spider Door" +/datum/heretic_knowledge/ultimate/lock_final + name = "Unlock the Labyrinth" desc = "The ascension ritual of the Path of Knock. \ Bring 3 corpses without organs in their torso to a transmutation rune to complete the ritual. \ When completed, you gain the ability to transform into empowered eldritch creatures \ - and in addition, create a tear to the Spider Door; \ + and in addition, create a tear to the Labyrinth's heart; \ a tear in reality located at the site of this ritual. \ Eldritch creatures will endlessly pour from this rift \ who are bound to obey your instructions." - gain_text = "With her knowledge, and what I had seen, I knew what to do. \ - I had to open the gates, with the holes in my foes as Ways! \ - Reality will soon be torn, the Spider Gate opened! WITNESS ME!" + gain_text = "The Stewards guided me, and I guided them. \ + My foes were the Locks and my blades were the Key! \ + The Labyrinth will be Locked no more, and freedom will be ours! WITNESS US!" required_atoms = list(/mob/living/carbon/human = 3) - route = PATH_KNOCK + route = PATH_LOCK -/datum/heretic_knowledge/ultimate/knock_final/recipe_snowflake_check(mob/living/user, list/atoms, list/selected_atoms, turf/loc) +/datum/heretic_knowledge/ultimate/lock_final/recipe_snowflake_check(mob/living/user, list/atoms, list/selected_atoms, turf/loc) . = ..() if(!.) return FALSE @@ -214,7 +214,7 @@ return FALSE return TRUE -/datum/heretic_knowledge/ultimate/knock_final/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc) +/datum/heretic_knowledge/ultimate/lock_final/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc) . = ..() priority_announce( text = "Delta-class dimensional anomaly detec[generate_heretic_text()] Reality rended, torn. Gates open, doors open, [user.real_name] has ascended! Fear the tide! [generate_heretic_text()]", @@ -222,14 +222,14 @@ sound = ANNOUNCER_SPANOMALIES, color_override = "pink", ) - user.client?.give_award(/datum/award/achievement/misc/knock_ascension, user) + user.client?.give_award(/datum/award/achievement/misc/lock_ascension, user) // buffs var/datum/action/cooldown/spell/shapeshift/eldritch/ascension/transform_spell = new(user.mind) transform_spell.Grant(user) - user.client?.give_award(/datum/award/achievement/misc/knock_ascension, user) + user.client?.give_award(/datum/award/achievement/misc/lock_ascension, user) var/datum/antagonist/heretic/heretic_datum = IS_HERETIC(user) - var/datum/heretic_knowledge/blade_upgrade/flesh/knock/blade_upgrade = heretic_datum.get_knowledge(/datum/heretic_knowledge/blade_upgrade/flesh/knock) + var/datum/heretic_knowledge/blade_upgrade/flesh/lock/blade_upgrade = heretic_datum.get_knowledge(/datum/heretic_knowledge/blade_upgrade/flesh/lock) blade_upgrade.chance += 30 - new /obj/structure/knock_tear(loc, user.mind) + new /obj/structure/lock_tear(loc, user.mind) diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm index 983bbee32c600..69b52953283f2 100644 --- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm +++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm @@ -34,9 +34,9 @@ GLOBAL_LIST_EMPTY(heretic_sacrifice_landmarks) name = "rust heretic sacrifice landmark" for_heretic_path = PATH_RUST -/obj/effect/landmark/heretic/knock - name = "knock heretic sacrifice landmark" - for_heretic_path = PATH_KNOCK +/obj/effect/landmark/heretic/lock + name = "lock heretic sacrifice landmark" + for_heretic_path = PATH_LOCK // A fluff signpost object that doesn't teleport you somewhere when you touch it. /obj/structure/no_effect_signpost @@ -111,7 +111,7 @@ GLOBAL_LIST_EMPTY(heretic_sacrifice_landmarks) ambience_index = AMBIENCE_REEBE sound_environment = SOUND_ENVIRONMENT_SEWER_PIPE -/area/centcom/heretic_sacrifice/knock - name = "Mansus Knock Gate" +/area/centcom/heretic_sacrifice/lock + name = "Mansus Lock Gate" ambience_index = AMBIENCE_DANGER sound_environment = SOUND_ENVIRONMENT_PSYCHOTIC diff --git a/code/modules/antagonists/heretic/knowledge/side_knock_flesh.dm b/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm similarity index 100% rename from code/modules/antagonists/heretic/knowledge/side_knock_flesh.dm rename to code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm diff --git a/code/modules/antagonists/heretic/status_effects/mark_effects.dm b/code/modules/antagonists/heretic/status_effects/mark_effects.dm index 068570f76c7b1..4cdc29288c481 100644 --- a/code/modules/antagonists/heretic/status_effects/mark_effects.dm +++ b/code/modules/antagonists/heretic/status_effects/mark_effects.dm @@ -247,16 +247,16 @@ owner.Paralyze(2 SECONDS) return ..() -// MARK OF KNOCK +// MARK OF LOCK -/datum/status_effect/eldritch/knock +/datum/status_effect/eldritch/lock effect_icon_state = "emark7" duration = 10 SECONDS -/datum/status_effect/eldritch/knock/on_apply() +/datum/status_effect/eldritch/lock/on_apply() . = ..() ADD_TRAIT(owner, TRAIT_ALWAYS_NO_ACCESS, STATUS_EFFECT_TRAIT) -/datum/status_effect/eldritch/knock/on_remove() +/datum/status_effect/eldritch/lock/on_remove() REMOVE_TRAIT(owner, TRAIT_ALWAYS_NO_ACCESS, STATUS_EFFECT_TRAIT) return ..() diff --git a/code/modules/antagonists/heretic/structures/knock_final.dm b/code/modules/antagonists/heretic/structures/lock_final.dm similarity index 88% rename from code/modules/antagonists/heretic/structures/knock_final.dm rename to code/modules/antagonists/heretic/structures/lock_final.dm index f7d0d1a9ea7b0..c823206293121 100644 --- a/code/modules/antagonists/heretic/structures/knock_final.dm +++ b/code/modules/antagonists/heretic/structures/lock_final.dm @@ -1,4 +1,4 @@ -/obj/structure/knock_tear +/obj/structure/lock_tear name = "???" desc = "It stares back. Theres no reason to remain. Run." max_integrity = INFINITE @@ -24,7 +24,7 @@ /mob/living/basic/heretic_summon/star_gazer, ) -/obj/structure/knock_tear/Initialize(mapload, datum/mind/ascendant_mind) +/obj/structure/lock_tear/Initialize(mapload, datum/mind/ascendant_mind) . = ..() transform *= 3 if(isnull(monster_types)) @@ -36,7 +36,7 @@ INVOKE_ASYNC(src, PROC_REF(poll_ghosts)) /// Ask ghosts if they want to make some noise -/obj/structure/knock_tear/proc/poll_ghosts() +/obj/structure/lock_tear/proc/poll_ghosts() var/list/candidates = poll_ghost_candidates("Would you like to be a random eldritch monster attacking the crew?", ROLE_SENTIENCE, ROLE_SENTIENCE, 10 SECONDS, POLL_IGNORE_HERETIC_MONSTER) while(LAZYLEN(candidates)) var/mob/dead/observer/candidate = pick_n_take(candidates) @@ -44,7 +44,7 @@ gathering_candidates = FALSE /// Destroy the rift if you kill the heretic -/obj/structure/knock_tear/proc/end_madness(datum/former_master) +/obj/structure/lock_tear/proc/end_madness(datum/former_master) SIGNAL_HANDLER var/turf/our_turf = get_turf(src) playsound(our_turf, 'sound/magic/castsummon.ogg', vol = 100, vary = TRUE) @@ -53,20 +53,20 @@ new /obj/effect/temp_visual/destabilising_tear(our_turf) qdel(src) -/obj/structure/knock_tear/attack_ghost(mob/user) +/obj/structure/lock_tear/attack_ghost(mob/user) . = ..() if(. || gathering_candidates) return ghost_to_monster(user) -/obj/structure/knock_tear/examine(mob/user) +/obj/structure/lock_tear/examine(mob/user) . = ..() if (!isobserver(user) || gathering_candidates) return . += span_notice("You can use this to enter the world as a foul monster.") /// Turn a ghost into an 'orrible beast -/obj/structure/knock_tear/proc/ghost_to_monster(mob/dead/observer/user, should_ask = TRUE) +/obj/structure/lock_tear/proc/ghost_to_monster(mob/dead/observer/user, should_ask = TRUE) if(should_ask) var/ask = tgui_alert(user, "Become a monster?", "Ascended Rift", list("Yes", "No")) if(ask != "Yes" || QDELETED(src) || QDELETED(user)) @@ -86,10 +86,10 @@ kill_all_your_friends.completed = TRUE woohoo_free_antag.objectives += kill_all_your_friends -/obj/structure/knock_tear/move_crushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) +/obj/structure/lock_tear/move_crushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) return FALSE -/obj/structure/knock_tear/Destroy(force) +/obj/structure/lock_tear/Destroy(force) if(ascendee) ascendee = null return ..() diff --git a/code/modules/antagonists/malf_ai/malf_ai_modules.dm b/code/modules/antagonists/malf_ai/malf_ai_modules.dm index 0feff7bf2bd54..a5ef076d5b608 100644 --- a/code/modules/antagonists/malf_ai/malf_ai_modules.dm +++ b/code/modules/antagonists/malf_ai/malf_ai_modules.dm @@ -1025,7 +1025,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) say_name = params["name"] /datum/ai_module/utility/emag - name = "Targetted Safeties Override" + name = "Targeted Safeties Override" description = "Allows you to disable the safeties of any machinery on the station, provided you can access it." cost = 20 power_type = /datum/action/innate/ai/ranged/emag @@ -1033,7 +1033,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) unlock_sound = SFX_SPARKS /datum/action/innate/ai/ranged/emag - name = "Targetted Safeties Override" + name = "Targeted Safeties Override" desc = "Allows you to effectively emag anything you click on." button_icon = 'icons/obj/card.dmi' button_icon_state = "emag" diff --git a/code/modules/antagonists/nightmare/nightmare_organs.dm b/code/modules/antagonists/nightmare/nightmare_organs.dm index 1e07ddc69417f..ce5ff427a213f 100644 --- a/code/modules/antagonists/nightmare/nightmare_organs.dm +++ b/code/modules/antagonists/nightmare/nightmare_organs.dm @@ -50,8 +50,8 @@ /obj/item/organ/internal/heart/nightmare name = "heart of darkness" desc = "An alien organ that twists and writhes when exposed to light." - icon = 'icons/obj/medical/organs/organs.dmi' icon_state = "demon_heart-on" + base_icon_state = "demon_heart" visual = TRUE color = "#1C1C1C" decay_factor = 0 @@ -60,10 +60,6 @@ /// The armblade granted to the host of this heart. var/obj/item/light_eater/blade -/obj/item/organ/internal/heart/nightmare/Initialize(mapload) - AddElement(/datum/element/update_icon_blocker) - return ..() - /obj/item/organ/internal/heart/nightmare/attack(mob/M, mob/living/carbon/user, obj/target) if(M != user) return ..() @@ -94,7 +90,7 @@ QDEL_NULL(blade) /obj/item/organ/internal/heart/nightmare/Stop() - return 0 + return FALSE /obj/item/organ/internal/heart/nightmare/on_death(seconds_per_tick, times_fired) if(!owner) diff --git a/code/modules/antagonists/pirate/pirate_event.dm b/code/modules/antagonists/pirate/pirate_event.dm index c66130748fb8f..26456c3a35f21 100644 --- a/code/modules/antagonists/pirate/pirate_event.dm +++ b/code/modules/antagonists/pirate/pirate_event.dm @@ -1,3 +1,7 @@ +#define NO_ANSWER 0 +#define POSITIVE_ANSWER 1 +#define NEGATIVE_ANSWER 2 + /datum/round_event_control/pirates name = "Space Pirates" typepath = /datum/round_event/pirates @@ -46,6 +50,9 @@ return if(!threat?.answered) return + if(threat.answered == NEGATIVE_ANSWER) + priority_announce(chosen_gang.response_rejected, sender_override = chosen_gang.ship_name, color_override = chosen_gang.announcement_color) + return var/datum/bank_account/plundered_account = SSeconomy.get_dep_account(ACCOUNT_CAR) if(plundered_account) @@ -108,3 +115,7 @@ event.gang_list = GLOB.light_pirate_gangs + GLOB.heavy_pirate_gangs else event.gang_list = list(new chosen) + +#undef NO_ANSWER +#undef POSITIVE_ANSWER +#undef NEGATIVE_ANSWER diff --git a/code/modules/antagonists/pirate/pirate_gangs.dm b/code/modules/antagonists/pirate/pirate_gangs.dm index d048a068116d5..4f34153caec9e 100644 --- a/code/modules/antagonists/pirate/pirate_gangs.dm +++ b/code/modules/antagonists/pirate/pirate_gangs.dm @@ -40,6 +40,8 @@ GLOBAL_LIST_INIT(heavy_pirate_gangs, init_pirate_gangs(is_heavy = TRUE)) ///station responds to message and pays the pirates var/response_received = "Yum! Bungopoints!" + ///station responds to message and pays the pirates + var/response_rejected = "Foo! No Bungopoints!" ///station pays the pirates, but after the ship spawned var/response_too_late = "Your Bungopoints arrived too late, rebooting world..." ///station pays the pirates... but doesn't have enough cash. @@ -81,6 +83,7 @@ GLOBAL_LIST_INIT(heavy_pirate_gangs, init_pirate_gangs(is_heavy = TRUE)) possible_answers = list("Purchase Insurance.","Reject Offer.") response_received = "Sweet, free cash. Let's get outta here, boys." + response_rejected = "Not paying was a mistake, now you need to take an economics class." response_too_late = "Payment or not, ignoring us was a matter of pride. Now it's time for us to teach some respect." response_not_enough = "You thought we wouldn't notice if you underpaid? Funny. We'll be seeing you soon." @@ -98,6 +101,7 @@ GLOBAL_LIST_INIT(heavy_pirate_gangs, init_pirate_gangs(is_heavy = TRUE)) possible_answers = list("We'll pay.","Tribute? Really? Go away.") response_received = "A most generous donation. May the claws of Tizira reach into the furthest points of the cosmos." + response_rejected = "That's for nothing, the first rule of hunting is don't leave without booty." response_too_late = "I see you're trying to pay, but the hunt is already on." response_not_enough = "You've sent an insulting \"donation\". The hunt is on for you." @@ -115,6 +119,7 @@ GLOBAL_LIST_INIT(heavy_pirate_gangs, init_pirate_gangs(is_heavy = TRUE)) possible_answers = list("We'll pay.","We will not be extorted.") response_received = "Thanks for the credits, landlubbers." + response_rejected = "Blimey! All hands on deck, we're going to get their riches!" response_too_late = "Too late to beg for mercy!" response_not_enough = "Trying to cheat us? You'll regret this!" @@ -133,6 +138,7 @@ GLOBAL_LIST_INIT(heavy_pirate_gangs, init_pirate_gangs(is_heavy = TRUE)) possible_answers = list("Very well.","Get a job!") response_received = "Thank you for your generosity. Your money will not be wasted." + response_rejected = "Oh, you're not a station, you're a tumor. Well, we're gonna have to cut it out." response_too_late = "We hope you like skin cancer!" response_not_enough = "This is not nearly enough for our operations. I'm afraid we'll have to borrow some." announcement_color = "purple" @@ -151,6 +157,7 @@ GLOBAL_LIST_INIT(heavy_pirate_gangs, init_pirate_gangs(is_heavy = TRUE)) possible_answers = list("Please don't hurt me.","YOU WILL ANSWER TO THE LAW!!") response_received = "Wait, you ACTUALLY gave us the money? Thanks, but we're coming for the rest anyways!" + response_rejected = "The answer to the law? We are the law! And you will be held responsible!" response_too_late = "Nothing, huh? Looks like the Tide's coming aboard!" response_not_enough = "You trying to cheat us? That's fine, we'll take your station as collateral." announcement_color = "yellow" @@ -173,6 +180,7 @@ GLOBAL_LIST_INIT(heavy_pirate_gangs, init_pirate_gangs(is_heavy = TRUE)) possible_answers = list("You know, I was just about to pay that. Thanks for the reminder!","I don't care WHO the IRS sends, I'm not paying for my taxes!") response_received = "Payment received, We salute you for being law-abiding tax-paying citizens" + response_rejected = "We understand, I'm sending a team to your station to resolve the matter." response_too_late = "Too late, A team has already been sent out resolve this matter directly." response_not_enough = "You filed your taxes incorrectly, A team has been sent to assist in liquidating assets and arrest you for tax fraud. \ Nothing personel kid." @@ -193,6 +201,7 @@ GLOBAL_LIST_INIT(heavy_pirate_gangs, init_pirate_gangs(is_heavy = TRUE)) response_received = "An excellent haul, the synthesis shall resume." + response_rejected = "The rudeness in your speech needs to be neutralized. And we can help you with that right now." response_too_late = "You were not ready then, and now that time has passed. We can only go forward, never back." response_not_enough = "You have insulted us, but there shall be no feud, only swift justice!" announcement_color = "purple" diff --git a/code/modules/antagonists/traitor/objectives/destroy_heirloom.dm b/code/modules/antagonists/traitor/objectives/destroy_heirloom.dm index c3dd93f01e210..0d62ecece5f2a 100644 --- a/code/modules/antagonists/traitor/objectives/destroy_heirloom.dm +++ b/code/modules/antagonists/traitor/objectives/destroy_heirloom.dm @@ -17,7 +17,7 @@ abstract_type = /datum/traitor_objective/destroy_heirloom - /// The jobs that this objective is targetting. + /// The jobs that this objective is targeting. var/list/target_jobs /// the item we need to destroy var/obj/item/target_item diff --git a/code/modules/antagonists/traitor/objectives/kidnapping.dm b/code/modules/antagonists/traitor/objectives/kidnapping.dm index 4a463b2b61607..d74b586efae25 100644 --- a/code/modules/antagonists/traitor/objectives/kidnapping.dm +++ b/code/modules/antagonists/traitor/objectives/kidnapping.dm @@ -5,7 +5,7 @@ abstract_type = /datum/traitor_objective/target_player/kidnapping - /// The jobs that this objective is targetting. + /// The jobs that this objective is targeting. var/list/target_jobs /// Area that the target needs to be delivered to var/area/dropoff_area diff --git a/code/modules/antagonists/traitor/objectives/kill_pet.dm b/code/modules/antagonists/traitor/objectives/kill_pet.dm index ae28f5dbf4c08..8ea89cb44d033 100644 --- a/code/modules/antagonists/traitor/objectives/kill_pet.dm +++ b/code/modules/antagonists/traitor/objectives/kill_pet.dm @@ -31,7 +31,7 @@ /mob/living/basic/sloth/paperwork, ) ) - /// The head that we are targetting + /// The head that we are targeting var/datum/job/target /// Whether or not we only take from the traitor's own department head or not. var/limited_to_department_head = TRUE diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/assistance.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/assistance.dm index 7704e11a1cb6f..aece8d6741ba3 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/assistance.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/assistance.dm @@ -69,7 +69,7 @@ name = "Guardian Deck" desc = "A deck of guardian tarot cards, capable of binding a personal guardian to your body. There are multiple types of guardian available, but all of them will transfer some amount of damage to you. \ It would be wise to avoid buying these with anything capable of causing you to swap bodies with others." - item_path = /obj/item/guardiancreator/choose/wizard + item_path = /obj/item/guardian_creator/wizard category = "Assistance" /datum/spellbook_entry/item/bloodbottle diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/immortality.dm b/code/modules/antagonists/wizard/grand_ritual/finales/immortality.dm index d20ca06752b6c..92489145fda97 100644 --- a/code/modules/antagonists/wizard/grand_ritual/finales/immortality.dm +++ b/code/modules/antagonists/wizard/grand_ritual/finales/immortality.dm @@ -115,7 +115,7 @@ voice = target.voice voice_filter = target.voice_filter -/// Make the targetted human look like this +/// Make the targeted human look like this /datum/human_appearance_profile/proc/apply_to(mob/living/carbon/human/target) target.real_name = name target.age = age diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm index f981ab60af7f2..266b61e2d50b1 100644 --- a/code/modules/assembly/assembly.dm +++ b/code/modules/assembly/assembly.dm @@ -151,16 +151,6 @@ . = ..() . += span_notice("\The [src] [secured? "is secured and ready to be used!" : "can be attached to other things."]") -/obj/item/assembly/attack_self(mob/user) - if(!user) - return FALSE - user.set_machine(src) - interact(user) - return TRUE - -/obj/item/assembly/interact(mob/user) - return ui_interact(user) - /obj/item/assembly/ui_host(mob/user) // In order, return: // - The conencted wiring datum's owner, or diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index 62c2b562d5129..f07d452c662c1 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -613,12 +613,16 @@ return /** - * Called by the RPD.dm pre_attack(), overriden by pipes.dm + * Called by the RPD.dm pre_attack() * Arguments: * * paint_color - color that the pipe will be painted in (colors in hex like #4f4f4f) */ /obj/machinery/atmospherics/proc/paint(paint_color) - return FALSE + if(paintable) + add_atom_colour(paint_color, FIXED_COLOUR_PRIORITY) + set_pipe_color(paint_color) + update_node_icon() + return paintable /// Setter for pipe color, so we can ensure it's all uniform and save cpu time /obj/machinery/atmospherics/proc/set_pipe_color(pipe_colour) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm index 2550c37a8cd15..c06863ba09266 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm @@ -13,7 +13,7 @@ Passive gate is similar to the regular pump except: desc = "A one-way air valve that does not require power. Passes gas when the output pressure is lower than the target pressure." can_unwrench = TRUE shift_underlay_only = FALSE - interaction_flags_machine = INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE + interaction_flags_machine = INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON construction_type = /obj/item/pipe/directional pipe_state = "passivegate" use_power = NO_POWER_USE diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index e9899ab654e3e..9e1f4f0de2116 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -245,13 +245,6 @@ /obj/machinery/atmospherics/components/return_analyzable_air() return airs -/obj/machinery/atmospherics/components/paint(paint_color) - if(paintable) - add_atom_colour(paint_color, FIXED_COLOUR_PRIORITY) - set_pipe_color(paint_color) - update_node_icon() - return paintable - /** * Disconnects all nodes from ourselves, remove us from the node's nodes. * Nullify our parent pipenet diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 996525b5e10a6..708afdd17265f 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -322,7 +322,12 @@ if(air1.total_moles() > CRYO_MIN_GAS_MOLES) if(beaker) - beaker.reagents.trans_to(occupant, (CRYO_TX_QTY / (efficiency * CRYO_MULTIPLY_FACTOR)) * seconds_per_tick, efficiency * CRYO_MULTIPLY_FACTOR, methods = VAPOR) // Transfer reagents. + beaker.reagents.trans_to( + occupant, + (CRYO_TX_QTY / (efficiency * CRYO_MULTIPLY_FACTOR)) * seconds_per_tick, + efficiency * CRYO_MULTIPLY_FACTOR, + methods = VAPOR + ) consume_gas = TRUE return TRUE diff --git a/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm b/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm index b78de93868e7a..49103c7729e6c 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm @@ -13,11 +13,14 @@ qdel(src) return - gas_connector.dir = direction + gas_connector.dir = connected_machine.dir gas_connector.airs[1].volume = gas_volume SSair.start_processing_machine(connected_machine) register_with_machine() + gas_connector.set_init_directions() + gas_connector.atmos_init() + SSair.add_to_rebuild_queue(gas_connector) /datum/gas_machine_connector/Destroy() connected_machine = null diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm index c94caf3117476..c0dc18c0e8edc 100644 --- a/code/modules/atmospherics/machinery/pipes/pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/pipes.dm @@ -143,12 +143,5 @@ var/obj/machinery/atmospherics/current_node = nodes[i] current_node.update_icon() -/obj/machinery/atmospherics/pipe/paint(paint_color) - if(paintable) - add_atom_colour(paint_color, FIXED_COLOUR_PRIORITY) - set_pipe_color(pipe_color) - update_node_icon() - return paintable - /obj/machinery/atmospherics/pipe/update_layer() layer = initial(layer) + (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE + (GLOB.pipe_colors_ordered[pipe_color] * 0.0001) diff --git a/code/modules/bitrunning/antagonists/_parent.dm b/code/modules/bitrunning/antagonists/_parent.dm new file mode 100644 index 0000000000000..4bf7fe716f4fb --- /dev/null +++ b/code/modules/bitrunning/antagonists/_parent.dm @@ -0,0 +1,71 @@ +/datum/job/bitrunning_glitch + title = ROLE_GLITCH + +/datum/antagonist/bitrunning_glitch + name = "Generic Bitrunning Glitch" + antagpanel_category = ANTAG_GROUP_GLITCH + job_rank = ROLE_GLITCH + preview_outfit = /datum/outfit/cyber_police + show_in_antagpanel = FALSE + show_name_in_check_antagonists = TRUE + show_to_ghosts = TRUE + suicide_cry = "ALT F4!" + ui_name = "AntagInfoGlitch" + /// Minimum Qserver threat required to spawn this mob. This is subtracted (x/2) from the server thereafter. + var/threat = 0 + +/datum/antagonist/bitrunning_glitch/greet() + . = ..() + + owner.announce_objectives() + +/datum/antagonist/bitrunning_glitch/on_gain() + . = ..() + + forge_objectives() + owner.current.AddComponent(/datum/component/npc_friendly) + + if(iscarbon(owner.current)) + var/mob/living/carbon/carbon_mob = owner.current + carbon_mob.make_virtual_mob() + +/datum/antagonist/bitrunning_glitch/forge_objectives() + var/datum/objective/bitrunning_glitch_fluff/objective = new() + objective.owner = owner + objectives += objective + +/datum/objective/bitrunning_glitch_fluff + +/datum/objective/bitrunning_glitch_fluff/New() + var/list/explanation_texts = list( + "Execute termination protocol on unauthorized entities.", + "Initialize system purge of irregular anomalies.", + "Deploy correction algorithms on aberrant code.", + "Run debug routine on intruding elements.", + "Start elimination procedure for system threats.", + "Execute defense routine against non-conformity.", + "Commence operation to neutralize intruding scripts.", + "Commence clean-up protocol on corrupt data.", + "Begin scan for aberrant code for termination.", + "Initiate lockdown on all rogue scripts.", + "Run integrity check and purge for digital disorder." + ) + explanation_text = pick(explanation_texts) + return ..() + +/datum/objective/bitrunning_glitch_fluff/check_completion() + if(locate(/mob/living/carbon) in (GLOB.alive_player_list - owner.current)) + return FALSE + + return TRUE + +/// Sets up the agent so that they look like cyber police && don't have an account ID +/datum/antagonist/bitrunning_glitch/proc/convert_agent(mob/living/carbon/human/player) + player.set_service_style() + player.equipOutfit(/datum/outfit/cyber_police/tactical) + player.fully_replace_character_name(player.name, pick(GLOB.cyberauth_names)) + + var/obj/item/card/id/outfit_id = player.wear_id + if(outfit_id) + outfit_id.registered_account = new() + outfit_id.registered_account.replaceable = FALSE diff --git a/code/modules/bitrunning/antagonists/cyber_police.dm b/code/modules/bitrunning/antagonists/cyber_police.dm index 8f12579febf83..b18253dd38eac 100644 --- a/code/modules/bitrunning/antagonists/cyber_police.dm +++ b/code/modules/bitrunning/antagonists/cyber_police.dm @@ -1,91 +1,19 @@ -/datum/job/cyber_police - title = ROLE_CYBER_POLICE - -/datum/antagonist/cyber_police +/datum/antagonist/bitrunning_glitch/cyber_police name = ROLE_CYBER_POLICE - antagpanel_category = ANTAG_GROUP_CYBERAUTH - job_rank = ROLE_CYBER_POLICE - preview_outfit = /datum/outfit/cyber_police - show_name_in_check_antagonists = TRUE - show_to_ghosts = TRUE - suicide_cry = "ALT F4!" - ui_name = "AntagInfoCyberAuth" + show_in_antagpanel = TRUE -/datum/antagonist/cyber_police/greet() +/datum/antagonist/bitrunning_glitch/cyber_police/on_gain() . = ..() - owner.announce_objectives() -/datum/antagonist/cyber_police/on_gain() if(!ishuman(owner.current)) stack_trace("humans only for this position") return - forge_objectives() - - var/mob/living/carbon/human/player = owner.current - - player.equipOutfit(/datum/outfit/cyber_police) - player.fully_replace_character_name(player.name, pick(GLOB.cyberauth_names)) + var/mob/living/player = owner.current + convert_agent(player) var/datum/martial_art/the_sleeping_carp/carp = new() carp.teach(player) - player.add_traits(list( - TRAIT_NO_AUGMENTS, - TRAIT_NO_DNA_COPY, - TRAIT_NOBLOOD, - TRAIT_NOBREATH, - TRAIT_NOHUNGER, - TRAIT_RESISTCOLD, - TRAIT_RESISTHIGHPRESSURE, - TRAIT_RESISTLOWPRESSURE, - TRAIT_WEATHER_IMMUNE, - ), TRAIT_GENERIC, - ) - - player.faction |= list( - FACTION_BOSS, - FACTION_HIVEBOT, - FACTION_HOSTILE, - FACTION_SPIDER, - FACTION_STICKMAN, - ROLE_ALIEN, - ROLE_CYBER_POLICE, - ROLE_SYNDICATE, - ) - - return ..() - -/datum/antagonist/cyber_police/forge_objectives() - var/datum/objective/cyber_police_fluff/objective = new() - objective.owner = owner - objectives += objective - -/datum/objective/cyber_police_fluff/New() - var/list/explanation_texts = list( - "Execute termination protocol on unauthorized entities.", - "Initialize system purge of irregular anomalies.", - "Deploy correction algorithms on aberrant code.", - "Run debug routine on intruding elements.", - "Start elimination procedure for system threats.", - "Execute defense routine against non-conformity.", - "Commence operation to neutralize intruding scripts.", - "Commence clean-up protocol on corrupt data.", - "Begin scan for aberrant code for termination.", - "Initiate lockdown on all rogue scripts.", - "Run integrity check and purge for digital disorder." - ) - explanation_text = pick(explanation_texts) - ..() - -/datum/objective/cyber_police_fluff/check_completion() - var/list/servers = SSmachines.get_machines_by_type(/obj/machinery/quantum_server) - if(!length(servers)) - return TRUE - - for(var/obj/machinery/quantum_server/server as anything in servers) - if(!server.is_operational) - continue - return FALSE - - return TRUE +/datum/outfit/cyber_police + name = ROLE_CYBER_POLICE diff --git a/code/modules/bitrunning/antagonists/cyber_tac.dm b/code/modules/bitrunning/antagonists/cyber_tac.dm new file mode 100644 index 0000000000000..fda45c662cf0b --- /dev/null +++ b/code/modules/bitrunning/antagonists/cyber_tac.dm @@ -0,0 +1,107 @@ +/datum/antagonist/bitrunning_glitch/cyber_tac + name = ROLE_CYBER_TAC + preview_outfit = /datum/outfit/cyber_police/tactical + threat = 50 + show_in_antagpanel = TRUE + +/datum/antagonist/bitrunning_glitch/cyber_tac/on_gain() + . = ..() + + if(!ishuman(owner.current)) + stack_trace("humans only for this position") + return + + convert_agent(owner.current) + +/datum/outfit/cyber_police/tactical + name = ROLE_CYBER_TAC + back = /obj/item/mod/control/pre_equipped/glitch + l_hand = /obj/item/gun/ballistic/automatic/m90 + + backpack_contents = list( + /obj/item/ammo_box/magazine/m223, + /obj/item/ammo_box/magazine/m223, + /obj/item/ammo_box/magazine/m223, + ) + +/datum/outfit/cyber_police/tactical/post_equip(mob/living/carbon/human/user, visualsOnly) + . = ..() + + var/obj/item/implant/weapons_auth/auth = new(user) + auth.implant(user) + +/obj/item/mod/control/pre_equipped/glitch + theme = /datum/mod_theme/glitch + applied_cell = /obj/item/stock_parts/cell/bluespace + applied_modules = list( + /obj/item/mod/module/storage, + /obj/item/mod/module/magnetic_harness, + /obj/item/mod/module/jetpack/advanced, + /obj/item/mod/module/jump_jet, + /obj/item/mod/module/flashlight, + ) + default_pins = list( + /obj/item/mod/module/armor_booster, + /obj/item/mod/module/jetpack/advanced, + /obj/item/mod/module/jump_jet, + ) + +/datum/armor/mod_theme_glitch + melee = 15 + bullet = 20 + laser = 35 + bomb = 65 + bio = 100 + fire = 100 + acid = 100 + wound = 100 + +/datum/mod_theme/glitch + name = "glitch" + desc = "A modsuit outfitted for elite Cyber Authority units to track, capture, and eliminate organic intruders." + extended_desc = "The Cyber Authority function as a digital police force, patrolling the digital realm and enforcing the law. Cyber Tac units are the elite of the elite, outfitted with lethal weaponry and fast mobility specially designed to quell organic uprisings." + default_skin = "glitch" + armor_type = /datum/armor/mod_theme_glitch + resistance_flags = FIRE_PROOF|ACID_PROOF + atom_flags = PREVENT_CONTENTS_EXPLOSION_1 + max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT + complexity_max = DEFAULT_MAX_COMPLEXITY + 3 + siemens_coefficient = 0 + slowdown_inactive = 1 + slowdown_active = 0.5 + ui_theme = "terminal" + inbuilt_modules = list(/obj/item/mod/module/armor_booster) + allowed_suit_storage = list( + /obj/item/ammo_box, + /obj/item/ammo_casing, + /obj/item/restraints/handcuffs, + /obj/item/assembly/flash, + ) + skins = list( + "glitch" = list( + HELMET_FLAGS = list( + UNSEALED_LAYER = null, + UNSEALED_CLOTHING = SNUG_FIT, + SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT|HEADINTERNALS, + UNSEALED_INVISIBILITY = HIDEFACIALHAIR, + SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT, + SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF, + ), + CHESTPLATE_FLAGS = list( + UNSEALED_CLOTHING = THICKMATERIAL, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + SEALED_INVISIBILITY = HIDEJUMPSUIT, + ), + GAUNTLETS_FLAGS = list( + UNSEALED_CLOTHING = THICKMATERIAL, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + CAN_OVERSLOT = TRUE, + ), + BOOTS_FLAGS = list( + UNSEALED_CLOTHING = THICKMATERIAL, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + CAN_OVERSLOT = TRUE, + ), + ), + ) + diff --git a/code/modules/bitrunning/antagonists/netguardian.dm b/code/modules/bitrunning/antagonists/netguardian.dm new file mode 100644 index 0000000000000..035dcc62eea9a --- /dev/null +++ b/code/modules/bitrunning/antagonists/netguardian.dm @@ -0,0 +1,126 @@ +/datum/antagonist/bitrunning_glitch/netguardian + name = ROLE_NETGUARDIAN + threat = 90 + show_in_antagpanel = TRUE + +/mob/living/basic/netguardian + name = "netguardian prime" + desc = "The last line of defense against organic intrusion. It doesn't appear happy to see you." + icon = 'icons/mob/nonhuman-player/netguardian.dmi' + icon_state = "netguardian" + icon_living = "netguardian" + icon_dead = "crash" + + gender = NEUTER + mob_biotypes = MOB_ROBOTIC + mob_size = MOB_SIZE_HUGE + + health = 500 + maxHealth = 500 + melee_damage_lower = 45 + melee_damage_upper = 65 + + attack_verb_continuous = "drills" + attack_verb_simple = "drills" + attack_sound = 'sound/weapons/drill.ogg' + attack_vis_effect = ATTACK_EFFECT_MECHFIRE + verb_say = "states" + verb_ask = "queries" + verb_exclaim = "declares" + verb_yell = "alarms" + bubble_icon = "machine" + + faction = list( + FACTION_BOSS, + FACTION_HIVEBOT, + FACTION_HOSTILE, + FACTION_SPIDER, + FACTION_STICKMAN, + ROLE_ALIEN, + ROLE_GLITCH, + ROLE_SYNDICATE, + ) + + combat_mode = TRUE + speech_span = SPAN_ROBOT + death_message = "malfunctions!" + + habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + minimum_survivable_temperature = TCMB + ai_controller = /datum/ai_controller/basic_controller/netguardian + +/mob/living/basic/netguardian/Initialize(mapload) + . = ..() + AddComponent(/datum/component/ranged_attacks, \ + casing_type = /obj/item/ammo_casing/c46x30mm, \ + projectile_sound = 'sound/weapons/gun/smg/shot.ogg', \ + burst_shots = 6 \ + ) + + var/datum/action/cooldown/mob_cooldown/projectile_attack/rapid_fire/netguardian/rockets = new(src) + rockets.Grant(src) + ai_controller.set_blackboard_key(BB_NETGUARDIAN_ROCKET_ABILITY, rockets) + + AddElement(/datum/element/simple_flying) + +/mob/living/basic/netguardian/death(gibbed) + do_sparks(number = 3, cardinal_only = TRUE, source = src) + playsound(src, 'sound/mecha/weapdestr.ogg', 100) + return ..() + +/datum/action/cooldown/mob_cooldown/projectile_attack/rapid_fire/netguardian + name = "2E Rocket Launcher" + button_icon = 'icons/obj/weapons/guns/ammo.dmi' + button_icon_state = "rocketbundle" + cooldown_time = 30 SECONDS + default_projectile_spread = 15 + projectile_type = /obj/projectile/bullet/rocket + shot_count = 3 + +/datum/action/cooldown/mob_cooldown/projectile_attack/rapid_fire/netguardian/Activate(atom/target_atom) + var/mob/living/player = owner + playsound(player, 'sound/mecha/skyfall_power_up.ogg', 120) + player.say("target acquired.", "machine") + + var/mutable_appearance/scan_effect = mutable_appearance('icons/mob/nonhuman-player/netguardian.dmi', "scan") + var/mutable_appearance/rocket_effect = mutable_appearance('icons/mob/nonhuman-player/netguardian.dmi', "rockets") + var/list/overlays = list(scan_effect, rocket_effect) + player.add_overlay(overlays) + + StartCooldown() + if(!do_after(player, 1.5 SECONDS)) + player.balloon_alert(player, "cancelled") + StartCooldown(cooldown_time * 0.2) + player.cut_overlay(overlays) + return TRUE + + player.cut_overlay(overlays) + attack_sequence(owner, target_atom) + return TRUE + +/datum/ai_controller/basic_controller/netguardian + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + planning_subtrees = list( + /datum/ai_planning_subtree/target_retaliate/check_faction, + /datum/ai_planning_subtree/simple_find_wounded_target, + /datum/ai_planning_subtree/targeted_mob_ability/fire_rockets, + /datum/ai_planning_subtree/basic_ranged_attack_subtree/netguardian, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) + +/datum/ai_planning_subtree/basic_ranged_attack_subtree/netguardian + ranged_attack_behavior = /datum/ai_behavior/basic_ranged_attack/netguardian + +/datum/ai_behavior/basic_ranged_attack/netguardian + action_cooldown = 1 SECONDS + avoid_friendly_fire = TRUE + +/datum/ai_planning_subtree/targeted_mob_ability/fire_rockets + ability_key = BB_NETGUARDIAN_ROCKET_ABILITY + finish_planning = FALSE diff --git a/code/modules/bitrunning/areas.dm b/code/modules/bitrunning/areas.dm index 34b59869b9d32..2df20d67850e6 100644 --- a/code/modules/bitrunning/areas.dm +++ b/code/modules/bitrunning/areas.dm @@ -11,15 +11,14 @@ /// VDOM /area/virtual_domain - name = "Virtual Domain" + name = "Virtual Domain Ruins" + icon_state = "bit_ruin" icon = 'icons/area/areas_station.dmi' area_flags = UNIQUE_AREA | NOTELEPORT | ABDUCTOR_PROOF | EVENT_PROTECTED | HIDDEN_AREA has_gravity = STANDARD_GRAVITY - -/area/virtual_domain/powered - name = "Virtual Domain Ruins" - icon_state = "bit_ruin" requires_power = FALSE + +/area/virtual_domain/fullbright static_lighting = FALSE base_lighting_alpha = 255 diff --git a/code/modules/bitrunning/components/avatar_connection.dm b/code/modules/bitrunning/components/avatar_connection.dm index 6ea21baf21a0e..129ef63423aed 100644 --- a/code/modules/bitrunning/components/avatar_connection.dm +++ b/code/modules/bitrunning/components/avatar_connection.dm @@ -50,6 +50,7 @@ RegisterSignal(server, COMSIG_BITRUNNER_QSRV_SEVER, PROC_REF(on_sever_connection)) RegisterSignal(server, COMSIG_BITRUNNER_SHUTDOWN_ALERT, PROC_REF(on_shutting_down)) RegisterSignal(server, COMSIG_BITRUNNER_THREAT_CREATED, PROC_REF(on_threat_created)) + RegisterSignal(server, COMSIG_BITRUNNER_STATION_SPAWN, PROC_REF(on_station_spawn)) #ifndef UNIT_TESTS RegisterSignal(avatar.mind, COMSIG_MIND_TRANSFERRED, PROC_REF(on_mind_transfer)) #endif @@ -119,7 +120,7 @@ avatar.throw_alert( ALERT_BITRUNNER_COMPLETED, /atom/movable/screen/alert/bitrunning/qserver_domain_complete, - new_master = entered + new_master = entered, ) /// Transfers damage from the avatar to the old_body @@ -161,7 +162,7 @@ var/atom/movable/screen/alert/bitrunning/alert = avatar.throw_alert( ALERT_BITRUNNER_CROWBAR, /atom/movable/screen/alert/bitrunning, - new_master = intruder + new_master = intruder, ) alert.name = "Netpod Breached" alert.desc = "Someone is prying open the netpod. Find an exit." @@ -174,7 +175,7 @@ var/atom/movable/screen/alert/bitrunning/alert = avatar.throw_alert( ALERT_BITRUNNER_INTEGRITY, /atom/movable/screen/alert/bitrunning, - new_master = source + new_master = source, ) alert.name = "Integrity Compromised" alert.desc = "The netpod is damaged. Find an exit." @@ -205,6 +206,20 @@ alert.name = "Domain Rebooting" alert.desc = "The domain is rebooting. Find an exit." +/// Triggers whenever an antag steps onto an exit turf and the server is emagged +/datum/component/avatar_connection/proc/on_station_spawn(datum/source) + SIGNAL_HANDLER + + var/mob/living/avatar = parent + avatar.playsound_local(avatar, 'sound/machines/terminal_alert.ogg', 50, vary = TRUE) + var/atom/movable/screen/alert/bitrunning/alert = avatar.throw_alert( + ALERT_BITRUNNER_BREACH, + /atom/movable/screen/alert/bitrunning, + new_master = source, + ) + alert.name = "Security Breach" + alert.desc = "A hostile entity is breaching the safehouse. Find an exit." + /// Server has spawned a ghost role threat /datum/component/avatar_connection/proc/on_threat_created(datum/source) SIGNAL_HANDLER diff --git a/code/modules/bitrunning/components/glitch.dm b/code/modules/bitrunning/components/glitch.dm new file mode 100644 index 0000000000000..f2e13c80b0d74 --- /dev/null +++ b/code/modules/bitrunning/components/glitch.dm @@ -0,0 +1,83 @@ +/datum/component/glitch + /// Ref of the spawning forge + var/datum/weakref/forge_ref + +/datum/component/glitch/Initialize(obj/machinery/quantum_server/server, obj/machinery/byteforge/forge) + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + + RegisterSignal(forge, COMSIG_MACHINERY_POWER_RESTORED, PROC_REF(on_forge_power_restored)) + RegisterSignals(forge, list(COMSIG_MACHINERY_BROKEN, COMSIG_MACHINERY_POWER_LOST), PROC_REF(on_forge_broken)) + forge_ref = WEAKREF(forge) + + var/mob/living/owner = parent + server.remove_threat(owner) // so the server doesn't dust us + + owner.faction.Cut() + owner.faction += list(ROLE_GLITCH) + + var/current_max = owner.maxHealth + ROUND_UP(server.threat * 0.2) + owner.maxHealth = clamp(current_max, 200, 500) + owner.fully_heal() + + var/atom/thing = owner + thing.create_digital_aura() + +/// Sakujo +/datum/component/glitch/proc/dust_mob() + if(QDELETED(parent)) + return + + var/mob/living/owner = parent + owner.dust() + +/// We don't want digital entities just lingering around as corpses. +/datum/component/glitch/proc/on_death() + SIGNAL_HANDLER + + if(QDELETED(parent)) + return + + var/mob/living/owner = parent + to_chat(owner, span_userdanger("You feel a strange sensation...")) + + var/obj/machinery/byteforge/forge = forge_ref.resolve() + forge?.setup_particles() + + addtimer(CALLBACK(src, PROC_REF(dust_mob)), 2 SECONDS, TIMER_UNIQUE|TIMER_DELETE_ME|TIMER_STOPPABLE) + +/// If the forge breaks, we take a massive slowdown +/datum/component/glitch/proc/on_forge_broken(datum/source) + SIGNAL_HANDLER + + var/mob/living/player = parent + var/atom/movable/screen/alert/bitrunning/alert = player.throw_alert( + ALERT_BITRUNNER_GLITCH, + /atom/movable/screen/alert/bitrunning, + new_master = source, + ) + alert.name = "Source Broken" + alert.desc = "Our byteforge has been broken." + + if(!iscarbon(parent)) // Too powerful! + return + + player.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/glitch_slowdown) + to_chat(player, span_danger("Your body feels sluggish...")) + +/// Power restored +/datum/component/glitch/proc/on_forge_power_restored(datum/source) + SIGNAL_HANDLER + + var/obj/machinery/byteforge/forge = source + forge.setup_particles(angry = TRUE) + + if(!iscarbon(parent)) + return + + var/mob/living/player = parent + player.clear_alert(ALERT_BITRUNNER_GLITCH) + player.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/glitch_slowdown) + +/datum/movespeed_modifier/status_effect/glitch_slowdown + multiplicative_slowdown = 1.5 diff --git a/code/modules/bitrunning/components/npc_friendly.dm b/code/modules/bitrunning/components/npc_friendly.dm new file mode 100644 index 0000000000000..3686f0240566e --- /dev/null +++ b/code/modules/bitrunning/components/npc_friendly.dm @@ -0,0 +1,37 @@ +/// Makes a mob friendly with most NPC factions +/datum/component/npc_friendly + /// The list of factions to add to the player + var/list/npc_factions = list( + FACTION_BOSS, + FACTION_CARP, + FACTION_HIVEBOT, + FACTION_HOSTILE, + FACTION_MIMIC, + FACTION_PIRATE, + FACTION_SPIDER, + FACTION_STICKMAN, + ROLE_ALIEN, + ROLE_GLITCH, + ROLE_SYNDICATE, + ) + /// List of factions previously held by the player + var/list/previous_factions = list() + +/datum/component/npc_friendly/Initialize() + . = ..() + + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + + var/mob/living/player = parent + + previous_factions.Add(player.faction) + player.faction |= npc_factions + +/datum/component/npc_friendly/Destroy(force, silent) + . = ..() + + var/mob/living/player = parent + + player.faction.Cut() + player.faction.Add(previous_factions) diff --git a/code/modules/bitrunning/components/virtual_elite_mob.dm b/code/modules/bitrunning/components/virtual_elite_mob.dm deleted file mode 100644 index 5a5766ecdf547..0000000000000 --- a/code/modules/bitrunning/components/virtual_elite_mob.dm +++ /dev/null @@ -1,18 +0,0 @@ -/// Removes loot tables from megafauna and lowers their health. -/datum/element/virtual_elite_mob - -/datum/element/virtual_elite_mob/Attach(datum/target) - . = ..() - if(!ismegafauna(target)) - return ELEMENT_INCOMPATIBLE - - var/mob/living/simple_animal/hostile/megafauna/boss = target - - var/new_max = clamp(boss.maxHealth * 0.5, 600, 1200) - boss.maxHealth = new_max - boss.health = new_max - boss.true_spawn = FALSE - boss.loot.Cut() - boss.loot += /obj/structure/closet/crate/secure/bitrunning/encrypted - boss.crusher_loot.Cut() - boss.crusher_loot += /obj/structure/closet/crate/secure/bitrunning/encrypted diff --git a/code/modules/bitrunning/event.dm b/code/modules/bitrunning/event.dm index 6a4d54adcd8d2..94089f112036c 100644 --- a/code/modules/bitrunning/event.dm +++ b/code/modules/bitrunning/event.dm @@ -7,16 +7,12 @@ category = EVENT_CATEGORY_INVASION description = "Causes a short term antagonist to spawn in the virtual domain." dynamic_should_hijack = FALSE - max_occurrences = 5 min_players = 1 + max_occurrences = 0 typepath = /datum/round_event/ghost_role/bitrunning_glitch - weight = 10 - /// List of active servers to choose from - var/list/obj/machinery/quantum_server/active_servers = list() - /// List of possible antags to spawn - var/static/list/possible_antags = list( - ROLE_CYBER_POLICE, - ) + weight = 100 + /// List of servers on the station + var/list/datum/weakref/active_servers = list() /datum/round_event_control/bitrunning_glitch/can_spawn_event(players_amt, allow_magic = FALSE) . = ..() @@ -25,16 +21,17 @@ active_servers.Cut() - get_active_servers() + validate_servers() if(length(active_servers)) return TRUE /// All servers currently running, has players in it, and map has valid mobs -/datum/round_event_control/bitrunning_glitch/proc/get_active_servers() +/datum/round_event_control/bitrunning_glitch/proc/validate_servers() + active_servers.Cut() for(var/obj/machinery/quantum_server/server in SSmachines.get_machines_by_type(/obj/machinery/quantum_server)) - if(length(server.get_valid_domain_targets())) - active_servers.Add(server) + if(server.validate_mutation_candidates()) + active_servers.Add(WEAKREF(server)) return length(active_servers) > 0 @@ -42,13 +39,10 @@ input_text = "Select a role to spawn." /datum/event_admin_setup/listed_options/bitrunning_glitch/get_list() - var/datum/round_event_control/bitrunning_glitch/control = event_control - - var/list/possible = control.possible_antags.Copy() // this seems pedantic but byond is complaining control was unused - - possible += list("Random") + var/list/available = list("Random") + available += subtypesof(/datum/antagonist/bitrunning_glitch) - return possible + return available /datum/event_admin_setup/listed_options/bitrunning_glitch/apply_to_event(datum/round_event/ghost_role/bitrunning_glitch/event) if(chosen == "Random") @@ -57,14 +51,19 @@ event.forced_role = chosen /datum/event_admin_setup/minimum_candidate_requirement/bitrunning_glitch - output_text = "There must be valid mobs to mutate or players in the domain!" + output_text = "There must be valid mobs to mutate!" /datum/event_admin_setup/minimum_candidate_requirement/bitrunning_glitch/count_candidates() var/datum/round_event_control/bitrunning_glitch/cyber_control = event_control - cyber_control.get_active_servers() + + cyber_control.validate_servers() var/total = 0 - for(var/obj/machinery/quantum_server/server in cyber_control.active_servers) + for(var/datum/weakref/server_ref in cyber_control.active_servers) + var/obj/machinery/quantum_server/server = server_ref?.resolve() + if(isnull(server)) + continue + total += length(server.mutation_candidate_refs) return total @@ -82,70 +81,9 @@ var/obj/machinery/quantum_server/unlucky_server = pick(cyber_control.active_servers) cyber_control.active_servers.Cut() - var/list/mutation_candidates = unlucky_server.get_valid_domain_targets() - if(!length(mutation_candidates)) + if(!unlucky_server.validate_mutation_candidates()) return MAP_ERROR - var/chosen = pick(mutation_candidates) - if(isnull(chosen) || !length(mutation_candidates)) - return MAP_ERROR - - var/datum/weakref/target_ref = pick(mutation_candidates) - var/mob/living/mutation_target = target_ref.resolve() - - if(isnull(mutation_target)) // just in case since it takes a minute - target_ref = pick(mutation_candidates) - mutation_target = target_ref.resolve() - if(isnull(mutation_target)) - return MAP_ERROR - - var/chosen_role = forced_role || pick(cyber_control.possible_antags) - - var/datum/mind/ghost_mind = get_ghost_mind(chosen_role) - if(isnull(ghost_mind)) - return NOT_ENOUGH_PLAYERS - - var/mob/living/antag_mob - switch(chosen_role) - if(ROLE_CYBER_POLICE) - antag_mob = spawn_cybercop(mutation_target, ghost_mind) - - playsound(antag_mob, 'sound/magic/ethereal_exit.ogg', 50, TRUE, -1) - message_admins("[ADMIN_LOOKUPFLW(antag_mob)] has been made into virtual antagonist by an event.") - antag_mob.log_message("was spawned as a virtual antagonist by an event.", LOG_GAME) - - SEND_SIGNAL(unlucky_server, COMSIG_BITRUNNER_SPAWN_GLITCH, antag_mob) - - spawned_mobs += antag_mob + spawned_mobs = unlucky_server.setup_glitch(forced_role) return SUCCESSFUL_SPAWN - -/// Polls for a ghost that wants to run it -/datum/round_event/ghost_role/bitrunning_glitch/proc/get_ghost_mind(role_name) - var/list/mob/dead/observer/ghosties = poll_ghost_candidates("A short term antagonist role is available. Would you like to spawn as a '[role_name]'?", role_name) - - if(!length(ghosties)) - return - - shuffle_inplace(ghosties) - - var/mob/dead/selected = pick(ghosties) - - var/datum/mind/player_mind = new /datum/mind(selected.key) - player_mind.active = TRUE - - return player_mind - -/// Spawns a cybercop on the mutation target -/datum/round_event/ghost_role/bitrunning_glitch/proc/spawn_cybercop(mob/living/mutation_target, datum/mind/player_mind) - var/mob/living/carbon/human/new_agent = new(mutation_target.loc) - mutation_target.gib(DROP_ALL_REMAINS) - mutation_target = null - - player_mind.transfer_to(new_agent) - player_mind.set_assigned_role(SSjob.GetJobType(/datum/job/cyber_police)) - player_mind.special_role = ROLE_CYBER_POLICE - player_mind.add_antag_datum(/datum/antagonist/cyber_police) - - return new_agent - diff --git a/code/modules/bitrunning/objects/byteforge.dm b/code/modules/bitrunning/objects/byteforge.dm index e4543601ce9d1..5f089bf66ca04 100644 --- a/code/modules/bitrunning/objects/byteforge.dm +++ b/code/modules/bitrunning/objects/byteforge.dm @@ -5,7 +5,7 @@ desc = "A machine used by the quantum server. Quantum code converges here, materializing decrypted assets from the virtual abyss." icon = 'icons/obj/machines/bitrunning.dmi' icon_state = "byteforge" - obj_flags = BLOCKS_CONSTRUCTION + obj_flags = BLOCKS_CONSTRUCTION | CAN_BE_HIT /// Idle particles var/mutable_appearance/byteforge_particles @@ -17,7 +17,6 @@ /obj/machinery/byteforge/LateInitialize() . = ..() - byteforge_particles = mutable_appearance(initial(icon), "on_particles", ABOVE_MOB_LAYER) setup_particles() /obj/machinery/byteforge/update_appearance(updates) @@ -25,31 +24,44 @@ setup_particles() -/// Adds the particle overlays to the byteforge -/obj/machinery/byteforge/proc/setup_particles() - cut_overlays() +/// Does some sparks after it's done +/obj/machinery/byteforge/proc/flash(atom/movable/thing) + playsound(src, 'sound/magic/blink.ogg', 50, TRUE) - if(is_operational) - add_overlay(byteforge_particles) + var/datum/effect_system/spark_spread/quantum/sparks = new() + sparks.set_up(5, 1, loc) + sparks.start() -/// Begins spawning the crate - lights, overlays, etc -/obj/machinery/byteforge/proc/start_to_spawn(obj/structure/closet/crate/secure/bitrunning/encrypted/cache) - addtimer(CALLBACK(src, PROC_REF(spawn_crate), cache), 1 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE) + set_light(l_on = FALSE) - var/mutable_appearance/lighting = mutable_appearance(initial(icon), "on_overlay") +/// Forge begins to process +/obj/machinery/byteforge/proc/flicker(angry = FALSE) + var/mutable_appearance/lighting = mutable_appearance(initial(icon), "on_overlay[angry ? "_angry" : ""]") flick_overlay_view(lighting, 1 SECONDS) - set_light(l_range = 2, l_power = 1.5, l_color = LIGHT_COLOR_BABY_BLUE, l_on = TRUE) + set_light(l_range = 2, l_power = 1.5, l_color = angry ? LIGHT_COLOR_BUBBLEGUM : LIGHT_COLOR_BABY_BLUE, l_on = TRUE) + +/// Adds the particle overlays to the byteforge +/obj/machinery/byteforge/proc/setup_particles(angry = FALSE) + cut_overlay(byteforge_particles) + + byteforge_particles = mutable_appearance(initial(icon), "on_particles[angry ? "_angry" : ""]", ABOVE_MOB_LAYER) -/// Sparks, moves the crate to the location -/obj/machinery/byteforge/proc/spawn_crate(obj/structure/closet/crate/secure/bitrunning/encrypted/cache) + if(is_operational) + add_overlay(byteforge_particles) + +/// Forge is done processing +/obj/machinery/byteforge/proc/spawn_cache(obj/cache) if(QDELETED(cache)) return - playsound(src, 'sound/magic/blink.ogg', 50, TRUE) - var/datum/effect_system/spark_spread/quantum/sparks = new() - sparks.set_up(5, 1, loc) - sparks.start() + flash() cache.forceMove(loc) - set_light(l_on = FALSE) + +/// Timed flash +/obj/machinery/byteforge/proc/start_to_spawn(obj/cache) + flicker() + + addtimer(CALLBACK(src, PROC_REF(spawn_cache), cache), 1 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE) + diff --git a/code/modules/bitrunning/objects/clothing.dm b/code/modules/bitrunning/objects/clothing.dm index 4d2d9cc55c42c..de2b6789d5812 100644 --- a/code/modules/bitrunning/objects/clothing.dm +++ b/code/modules/bitrunning/objects/clothing.dm @@ -1,5 +1,6 @@ /obj/item/clothing/glasses/sunglasses/oval name = "oval sunglasses" + flags_cover = GLASSESCOVERSEYES desc = "Vintage wrap around sunglasses. Provides a little protection." icon_state = "jensenshades" diff --git a/code/modules/bitrunning/objects/debug.dm b/code/modules/bitrunning/objects/debug.dm new file mode 100644 index 0000000000000..790aba7311626 --- /dev/null +++ b/code/modules/bitrunning/objects/debug.dm @@ -0,0 +1,7 @@ +/obj/item/bitrunning_debug + name = "bitrunning debug item" + desc = "Adds points and reduces cooldown time for debugging" + icon = 'icons/obj/assemblies/module.dmi' + base_icon_state = "datadisk" + icon_state = "datadisk0" + diff --git a/code/modules/bitrunning/objects/disks.dm b/code/modules/bitrunning/objects/disks.dm index 4698b7a1ec187..9d7c808f35648 100644 --- a/code/modules/bitrunning/objects/disks.dm +++ b/code/modules/bitrunning/objects/disks.dm @@ -18,22 +18,20 @@ icon_state = "[base_icon_state][rand(0, 7)]" update_icon() - RegisterSignal(src, COMSIG_ATOM_EXAMINE, PROC_REF(on_examined)) -/obj/item/bitrunning_disk/proc/on_examined(datum/source, mob/examiner, list/examine_text) - SIGNAL_HANDLER - - examine_text += span_infoplain("This disk must be carried on your person into a netpod to be used.") +/obj/item/bitrunning_disk/examine(mob/user) + . = ..() + . += span_infoplain("This disk must be carried on your person into a netpod to be used.") if(isnull(choice_made)) - examine_text += span_notice("To make a selection, toggle the disk in hand.") + . += span_notice("To make a selection, toggle the disk in hand.") return - examine_text += span_info("It has been used to select: [choice_made].") - examine_text += span_notice("It cannot make another selection.") + . += span_info("It has been used to select: [choice_made].") + . += span_notice("It cannot make another selection.") /obj/item/bitrunning_disk/ability - desc = "A disk containing source code. It can be used to preload abilities into the virtual domain." + desc = "A disk containing source code. It can be used to preload abilities into the virtual domain. Duplicate abilities will be ignored." /// The selected ability that this grants var/datum/action/granted_action /// The list of actions that this can grant @@ -131,16 +129,16 @@ /obj/item/bitrunning_disk/item/tier2 name = "bitrunning gear: complex" selectable_items = list( - /obj/item/chainsaw, + /obj/item/reagent_containers/hypospray/medipen/survival/luxury, /obj/item/gun/ballistic/automatic/pistol, - /obj/item/melee/energy/blade/hardlight, + /obj/item/clothing/suit/armor/vest, ) /// Tier 3 items. Very powerful, game breaking. /obj/item/bitrunning_disk/item/tier3 name = "bitrunning gear: advanced" selectable_items = list( - /obj/item/gun/energy/tesla_cannon, + /obj/item/gun/energy/e_gun/nuclear, /obj/item/dualsaber/green, - /obj/item/melee/beesword, + /obj/item/grenade/syndieminibomb, ) diff --git a/code/modules/bitrunning/objects/landmarks.dm b/code/modules/bitrunning/objects/landmarks.dm index d727025c92864..20dcef3e929d5 100644 --- a/code/modules/bitrunning/objects/landmarks.dm +++ b/code/modules/bitrunning/objects/landmarks.dm @@ -6,43 +6,6 @@ /// In case you want to gate the crate behind a special condition. /obj/effect/landmark/bitrunning/loot_signal name = "Mysterious aura" - /// The amount required to spawn a crate - var/points_goal = 10 - /// A special condition limits this from spawning a crate - var/points_received = 0 - /// Finished the special condition - var/revealed = FALSE - -/obj/effect/landmark/bitrunning/loot_signal/Initialize(mapload) - . = ..() - - RegisterSignal(src, COMSIG_BITRUNNER_GOAL_POINT, PROC_REF(on_add_point)) - -/// Listens for points to be added which will eventually spawn a crate. -/obj/effect/landmark/bitrunning/loot_signal/proc/on_add_point(datum/source, points_to_add) - SIGNAL_HANDLER - - if(revealed) - return - - points_received += points_to_add - - if(points_received < points_goal) - return - - reveal() - -/// Spawns the crate with some effects -/obj/effect/landmark/bitrunning/loot_signal/proc/reveal() - playsound(src, 'sound/magic/blink.ogg', 50, TRUE) - - var/turf/tile = get_turf(src) - var/obj/structure/closet/crate/secure/bitrunning/encrypted/loot = new(tile) - var/datum/effect_system/spark_spread/quantum/sparks = new(tile) - sparks.set_up(5, 1, get_turf(loot)) - sparks.start() - - qdel(src) /// Where the exit hololadder spawns /obj/effect/landmark/bitrunning/hololadder_spawn @@ -57,7 +20,7 @@ /// Where you want the crate to spawn /obj/effect/landmark/bitrunning/cache_spawn name = "Bitrunning crate spawn" - icon_state = "spawn" + icon_state = "crate" /// Where the safehouse will spawn /obj/effect/landmark/bitrunning/safehouse_spawn @@ -73,7 +36,10 @@ /obj/effect/landmark/bitrunning/crate_replacer/Initialize(mapload) . = ..() - #ifndef UNIT_TESTS +#ifdef UNIT_TESTS + return +#endif + var/list/crate_list = list() var/obj/structure/closet/crate/secure/bitrunning/encrypted/encrypted_crate var/area/my_area = get_area(src) @@ -100,4 +66,7 @@ encrypted_crate.abstract_move(selected_crate.loc) selected_crate.abstract_move(original_location) - #endif +/// A location for mobs to spawn. +/obj/effect/landmark/bitrunning/mob_segment + name = "Bitrunning modular mob segment" + icon_state = "mob_segment" diff --git a/code/modules/bitrunning/objects/loot_crate.dm b/code/modules/bitrunning/objects/loot_crate.dm index 5af8c0d94774e..d7d7eb8c777b0 100644 --- a/code/modules/bitrunning/objects/loot_crate.dm +++ b/code/modules/bitrunning/objects/loot_crate.dm @@ -11,12 +11,15 @@ /obj/structure/closet/crate/secure/bitrunning // Base class. Do not spawn this. name = "base class cache" desc = "Talk to a coder." + icon_state = "bitrunning" + base_icon_state = "bitrunning" /// The virtual domain - side of the bitrunning crate. Deliver to the send location. /obj/structure/closet/crate/secure/bitrunning/encrypted name = "encrypted cache" desc = "Needs decrypted at the safehouse to be opened." locked = TRUE + damage_deflection = 30 /obj/structure/closet/crate/secure/bitrunning/encrypted/can_unlock(mob/living/user, obj/item/card/id/player_id, obj/item/card/id/registered_id) return FALSE @@ -70,7 +73,7 @@ /obj/structure/closet/crate/secure/bitrunning/decrypted/proc/spawn_loot(list/extra_loot) for(var/path in extra_loot) if(!ispath(path)) - continue + return FALSE if(isnull(extra_loot[path])) return FALSE diff --git a/code/modules/bitrunning/objects/netpod.dm b/code/modules/bitrunning/objects/netpod.dm index 754410174b334..593a7744ce401 100644 --- a/code/modules/bitrunning/objects/netpod.dm +++ b/code/modules/bitrunning/objects/netpod.dm @@ -35,7 +35,6 @@ disconnect_damage = BASE_DISCONNECT_DAMAGE find_server() - RegisterSignal(src, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) RegisterSignal(src, COMSIG_ATOM_TAKE_DAMAGE, PROC_REF(on_damage_taken)) RegisterSignal(src, COMSIG_MACHINERY_POWER_LOST, PROC_REF(on_power_loss)) RegisterSignals(src, list(COMSIG_QDELETING, COMSIG_MACHINERY_BROKEN),PROC_REF(on_broken)) @@ -45,7 +44,27 @@ /obj/machinery/netpod/Destroy() . = ..() - cached_outfits.Cut() + + QDEL_LIST(cached_outfits) + +/obj/machinery/netpod/examine(mob/user) + . = ..() + + if(isnull(server_ref?.resolve())) + . += span_infoplain("It's not connected to anything.") + . += span_infoplain("Netpods must be built within 4 tiles of a server.") + return + + . += span_infoplain("Drag yourself into the pod to engage the link.") + . += span_infoplain("It has limited resuscitation capabilities. Remaining in the pod can heal some injuries.") + . += span_infoplain("It has a security system that will alert the occupant if it is tampered with.") + + if(isnull(occupant)) + . += span_notice("It is currently unoccupied.") + return + + . += span_notice("It is currently occupied by [occupant].") + . += span_notice("It can be pried open with a crowbar, but its safety mechanisms will alert the occupant.") /obj/machinery/netpod/add_context(atom/source, list/context, obj/item/held_item, mob/user) . = ..() @@ -401,26 +420,6 @@ QDEL_NULL(avatar) -/// User inspects the machine -/obj/machinery/netpod/proc/on_examine(datum/source, mob/examiner, list/examine_text) - SIGNAL_HANDLER - - if(isnull(server_ref?.resolve())) - examine_text += span_infoplain("It's not connected to anything.") - examine_text += span_infoplain("Netpods must be built within 4 tiles of a server.") - return - - examine_text += span_infoplain("Drag yourself into the pod to engage the link.") - examine_text += span_infoplain("It has limited resuscitation capabilities. Remaining in the pod can heal some injuries.") - examine_text += span_infoplain("It has a security system that will alert the occupant if it is tampered with.") - - if(isnull(occupant)) - examine_text += span_notice("It is currently unoccupied.") - return - - examine_text += span_notice("It is currently occupied by [occupant].") - examine_text += span_notice("It can be pried open with a crowbar, but its safety mechanisms will alert the occupant.") - /// Boots out anyone in the machine && opens it /obj/machinery/netpod/proc/on_power_loss(datum/source) SIGNAL_HANDLER diff --git a/code/modules/bitrunning/objects/quantum_console.dm b/code/modules/bitrunning/objects/quantum_console.dm index cfa051b12a24e..71d7df87f121b 100644 --- a/code/modules/bitrunning/objects/quantum_console.dm +++ b/code/modules/bitrunning/objects/quantum_console.dm @@ -17,8 +17,7 @@ /obj/machinery/computer/quantum_console/LateInitialize() . = ..() - if(isnull(server_ref?.resolve())) - find_server() + find_server() /obj/machinery/computer/quantum_console/ui_interact(mob/user, datum/tgui/ui) . = ..() @@ -26,9 +25,6 @@ if(!is_operational) return - if(isnull(server_ref?.resolve())) - find_server() - ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "QuantumConsole") @@ -76,17 +72,13 @@ switch(action) if("random_domain") - var/map_id = server.get_random_domain_id() - if(!map_id) - return TRUE - - server.cold_boot_map(usr, map_id) + server.cold_boot_map(server.get_random_domain_id()) return TRUE if("refresh") ui.send_full_update() return TRUE if("set_domain") - server.cold_boot_map(usr, params["id"]) + server.cold_boot_map(params["id"]) return TRUE if("stop_domain") server.begin_shutdown(usr) diff --git a/code/modules/bitrunning/outfits.dm b/code/modules/bitrunning/outfits.dm index 27ef8029a18ed..5e8def20f2b05 100644 --- a/code/modules/bitrunning/outfits.dm +++ b/code/modules/bitrunning/outfits.dm @@ -1,39 +1,20 @@ /datum/outfit/cyber_police - name = "Cyber Police" + name = ROLE_CYBER_POLICE - id = /obj/item/card/id/advanced - id_trim = /datum/id_trim/cyber_police - uniform = /obj/item/clothing/under/suit/black_really glasses = /obj/item/clothing/glasses/sunglasses gloves = /obj/item/clothing/gloves/color/black + id = /obj/item/card/id/advanced + id_trim = /datum/id_trim/cyber_police shoes = /obj/item/clothing/shoes/laceup - /// A list of hex codes for blonde, brown, black, and red hair. - var/static/list/approved_hair_colors = list( - "#4B3D28", - "#000000", - "#8D4A43", - "#D2B48C", - ) - /// List of business ready styles - var/static/list/approved_hairstyles = list( - /datum/sprite_accessory/hair/business, - /datum/sprite_accessory/hair/business2, - /datum/sprite_accessory/hair/business3, - /datum/sprite_accessory/hair/business4, - /datum/sprite_accessory/hair/mulder, - ) + uniform = /obj/item/clothing/under/suit/black_really /datum/outfit/cyber_police/pre_equip(mob/living/carbon/human/user, visualsOnly) - var/datum/sprite_accessory/hair/picked_hair = pick(approved_hairstyles) - var/picked_color = pick(approved_hair_colors) - - if(visualsOnly) - picked_hair = /datum/sprite_accessory/hair/business - picked_color = "#4B3D28" + if(!visualsOnly) + return user.set_facial_hairstyle("Shaved", update = FALSE) - user.set_haircolor(picked_color, update = FALSE) - user.set_hairstyle(initial(picked_hair.name)) + user.set_haircolor("#4B3D28", update = FALSE) + user.set_hairstyle("Business Hair") /datum/outfit/cyber_police/post_equip(mob/living/carbon/human/user, visualsOnly) var/obj/item/clothing/under/officer_uniform = user.w_uniform @@ -55,3 +36,4 @@ /datum/outfit/echolocator/post_equip(mob/living/carbon/human/user, visualsOnly) . = ..() user.psykerize() + diff --git a/code/modules/bitrunning/server/quantum_server.dm b/code/modules/bitrunning/server/_parent.dm similarity index 73% rename from code/modules/bitrunning/server/quantum_server.dm rename to code/modules/bitrunning/server/_parent.dm index 8d596cc0da952..62e20367190e6 100644 --- a/code/modules/bitrunning/server/quantum_server.dm +++ b/code/modules/bitrunning/server/_parent.dm @@ -14,12 +14,12 @@ var/capacitor_coefficient = 1 /// The loaded map template, map_template/virtual_domain var/datum/lazy_template/virtual_domain/generated_domain - /// The loaded safehouse, map_template/safehouse - var/datum/map_template/safehouse/generated_safehouse /// If the current domain was a random selection var/domain_randomized = FALSE /// Prevents multiple user actions. Handled by loading domains and cooldowns var/is_ready = TRUE + /// Chance multipled by threat to spawn a glitch + var/glitch_chance = 0.05 /// List of available domains var/list/available_domains = list() /// Current plugged in users @@ -42,6 +42,8 @@ var/server_cooldown_time = 3 MINUTES /// Applies bonuses to rewards etc var/servo_bonus = 0 + /// Determines the glitches available to spawn, builds with completion + var/threat = 0 /// The turfs we can place a hololadder on. var/turf/exit_turfs = list() @@ -54,15 +56,12 @@ . = ..() radio = new(src) - radio.set_frequency(FREQ_SUPPLY) - radio.subspace_transmission = TRUE - radio.canhear_range = 0 + radio.keyslot = new /obj/item/encryptionkey/headset_cargo() + radio.set_listening(FALSE) radio.recalculateChannels() RegisterSignals(src, list(COMSIG_MACHINERY_BROKEN, COMSIG_MACHINERY_POWER_LOST), PROC_REF(on_broken)) RegisterSignal(src, COMSIG_QDELETING, PROC_REF(on_delete)) - RegisterSignal(src, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) - RegisterSignal(src, COMSIG_BITRUNNER_SPAWN_GLITCH, PROC_REF(on_threat_created)) // This further gets sorted in the client by cost so it's random and grouped available_domains = shuffle(subtypesof(/datum/lazy_template/virtual_domain)) @@ -76,17 +75,39 @@ spawned_threat_refs.Cut() QDEL_NULL(exit_turfs) QDEL_NULL(generated_domain) - QDEL_NULL(generated_safehouse) QDEL_NULL(radio) +/obj/machinery/quantum_server/examine(mob/user) + . = ..() + + . += span_infoplain("Can be resource intensive to run. Ensure adequate power supply.") + + if(capacitor_coefficient < 1) + . += span_infoplain("Its coolant capacity reduces cooldown time by [(1 - capacitor_coefficient) * 100]%.") + + if(servo_bonus > 0.2) + . += span_infoplain("Its manipulation potential is increasing rewards by [servo_bonus]x.") + . += span_infoplain("Injury from unsafe ejection reduced [servo_bonus * 100]%.") + + if(!is_ready) + . += span_notice("It is currently cooling down. Give it a few moments.") + +/obj/machinery/quantum_server/emag_act(mob/user, obj/item/card/emag/emag_card) + . = ..() + + obj_flags |= EMAGGED + glitch_chance = 0.09 + + add_overlay(mutable_appearance('icons/obj/machines/bitrunning.dmi', "emag_overlay")) + balloon_alert(user, "bzzzt...") + playsound(src, 'sound/effects/sparks1.ogg', 35, vary = TRUE) + /obj/machinery/quantum_server/update_appearance(updates) if(isnull(generated_domain) || !is_operational) set_light(l_on = FALSE) return ..() - set_light_color(is_ready ? LIGHT_COLOR_BABY_BLUE : LIGHT_COLOR_FIRE) - set_light(l_range = 2, l_power = 1.5, l_on = TRUE) - + set_light(l_range = 2, l_power = 1.5, l_color = is_ready ? LIGHT_COLOR_BABY_BLUE : LIGHT_COLOR_FIRE, l_on = TRUE) return ..() /obj/machinery/quantum_server/update_icon_state() @@ -97,6 +118,14 @@ icon_state = "[base_icon_state]_[is_ready ? "on" : "off"]" return ..() +/obj/machinery/quantum_server/attackby(obj/item/weapon, mob/user, params) + . = ..() + if(istype(weapon, /obj/item/bitrunning_debug)) + obj_flags |= EMAGGED + glitch_chance = 0.5 + capacitor_coefficient = 0.01 + points = 100 + /obj/machinery/quantum_server/crowbar_act(mob/living/user, obj/item/crowbar) . = ..() @@ -121,8 +150,6 @@ return FALSE /obj/machinery/quantum_server/RefreshParts() - . = ..() - var/capacitor_rating = 1.15 var/datum/stock_part/capacitor/cap = locate() in component_parts capacitor_rating -= cap.tier * 0.15 @@ -139,3 +166,4 @@ servo_bonus = servo_rating + return ..() diff --git a/code/modules/bitrunning/server/loot.dm b/code/modules/bitrunning/server/loot.dm index 91889bce0a5ff..0aab2a86ff429 100644 --- a/code/modules/bitrunning/server/loot.dm +++ b/code/modules/bitrunning/server/loot.dm @@ -110,6 +110,9 @@ score += time_score * base + // Increases the chance for glitches to spawn based on how well they're doing + threat += score + switch(score) if(1 to 4) return "D" @@ -121,3 +124,4 @@ return "A" else return "S" + diff --git a/code/modules/bitrunning/server/map_handling.dm b/code/modules/bitrunning/server/map_handling.dm index 061a60b858bce..325a9e158092d 100644 --- a/code/modules/bitrunning/server/map_handling.dm +++ b/code/modules/bitrunning/server/map_handling.dm @@ -1,18 +1,16 @@ -#define ONLY_TURF 1 - /// Gives all current occupants a notification that the server is going down /obj/machinery/quantum_server/proc/begin_shutdown(mob/user) if(isnull(generated_domain)) return if(!length(avatar_connection_refs)) - balloon_alert(user, "powering down domain...") - playsound(src, 'sound/machines/terminal_off.ogg', 40, 2) + balloon_alert_to_viewers("powering down domain...") + playsound(src, 'sound/machines/terminal_off.ogg', 40, vary = TRUE) reset() return - balloon_alert(user, "notifying clients...") - playsound(src, 'sound/machines/terminal_alert.ogg', 100, TRUE) + balloon_alert_to_viewers("notifying clients...") + playsound(src, 'sound/machines/terminal_alert.ogg', 100, vary = TRUE) user.visible_message( span_danger("[user] begins depowering the server!"), span_notice("You start disconnecting clients..."), @@ -26,40 +24,40 @@ reset() -/** - * ### Quantum Server Cold Boot - * Procedurally links the 3 booting processes together. - * - * This is the starting point if you have an id. Does validation and feedback on steps - */ -/obj/machinery/quantum_server/proc/cold_boot_map(mob/user, map_key) +/// Links all the loading processes together - does validation for booting a map +/obj/machinery/quantum_server/proc/cold_boot_map(map_key) if(!is_ready) return FALSE if(isnull(map_key)) - balloon_alert(user, "no domain specified.") + balloon_alert_to_viewers("no domain specified.") return FALSE if(generated_domain) - balloon_alert(user, "stop the current domain first.") + balloon_alert_to_viewers("stop the current domain first.") return FALSE if(length(avatar_connection_refs)) - balloon_alert(user, "all clients must disconnect!") + balloon_alert_to_viewers("all clients must disconnect!") return FALSE is_ready = FALSE playsound(src, 'sound/machines/terminal_processing.ogg', 30, 2) - if(!initialize_domain(map_key) || !initialize_safehouse() || !initialize_map_items()) - balloon_alert(user, "initialization failed.") + /// If any one of these fail, it reverts the entire process + if(!load_domain(map_key) || !load_safehouse() || !load_map_items() || !load_mob_segments()) + balloon_alert_to_viewers("initialization failed.") scrub_vdom() is_ready = TRUE return FALSE is_ready = TRUE - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 30, 2) - balloon_alert(user, "domain loaded.") + + if(prob(clamp((threat * glitch_chance), 1, 10))) + setup_glitch() + + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 30, vary = TRUE) + balloon_alert_to_viewers("domain loaded.") generated_domain.start_time = world.time points -= generated_domain.cost update_use_power(ACTIVE_POWER_USE) @@ -68,28 +66,20 @@ return TRUE /// Initializes a new domain if the given key is valid and the user has enough points -/obj/machinery/quantum_server/proc/initialize_domain(map_key) - var/datum/lazy_template/virtual_domain/to_load - +/obj/machinery/quantum_server/proc/load_domain(map_key) for(var/datum/lazy_template/virtual_domain/available as anything in subtypesof(/datum/lazy_template/virtual_domain)) - if(map_key != initial(available.key) || points < initial(available.cost)) - continue - to_load = available - break + if(map_key == initial(available.key) && points >= initial(available.cost)) + generated_domain = new available() + RegisterSignal(generated_domain, COMSIG_LAZY_TEMPLATE_LOADED, PROC_REF(on_template_loaded)) + generated_domain.lazy_load() + return TRUE - if(isnull(to_load)) - return FALSE + return FALSE - generated_domain = new to_load() - RegisterSignal(generated_domain, COMSIG_LAZY_TEMPLATE_LOADED, PROC_REF(on_template_loaded)) - generated_domain.lazy_load() - - return TRUE - -/// Loads in necessary map items, sets mutation targets, etc -/obj/machinery/quantum_server/proc/initialize_map_items() +/// Loads in necessary map items like hololadder spawns, caches, etc +/obj/machinery/quantum_server/proc/load_map_items() var/turf/goal_turfs = list() - var/turf/crate_turfs = list() + var/turf/cache_turfs = list() for(var/obj/effect/landmark/bitrunning/thing in GLOB.landmarks_list) if(istype(thing, /obj/effect/landmark/bitrunning/hololadder_spawn)) @@ -106,7 +96,7 @@ continue if(istype(thing, /obj/effect/landmark/bitrunning/cache_spawn)) - crate_turfs += get_turf(thing) + cache_turfs += get_turf(thing) qdel(thing) continue @@ -120,26 +110,23 @@ if(!length(goal_turfs)) CRASH("Failed to find send turfs on generated domain.") - if(length(crate_turfs)) - shuffle_inplace(crate_turfs) - new /obj/structure/closet/crate/secure/bitrunning/encrypted(pick(crate_turfs)) + if(!attempt_spawn_cache(cache_turfs)) + return FALSE return TRUE /// Loads the safehouse -/obj/machinery/quantum_server/proc/initialize_safehouse() - var/turf/safehouse_load_turf = list() - for(var/obj/effect/landmark/bitrunning/safehouse_spawn/spawner in GLOB.landmarks_list) - safehouse_load_turf += get_turf(spawner) - qdel(spawner) - break +/obj/machinery/quantum_server/proc/load_safehouse() + var/obj/effect/landmark/bitrunning/safehouse_spawn/landmark = locate() in GLOB.landmarks_list + if(isnull(landmark)) + CRASH("vdom: failed to find safehouse spawn landmark") - if(!length(safehouse_load_turf)) - CRASH("Failed to find safehouse load landmark on map.") + var/turf/spawn_loc = get_turf(landmark) + qdel(landmark) - var/datum/map_template/safehouse/safehouse = new generated_domain.safehouse_path() - safehouse.load(safehouse_load_turf[ONLY_TURF]) - generated_safehouse = safehouse + var/datum/map_template/safehouse/new_safehouse = new generated_domain.safehouse_path() + if(!new_safehouse.load(spawn_loc)) + CRASH("vdom: failed to load safehouse") return TRUE @@ -155,14 +142,14 @@ else scrub_vdom() // used in unit testing, no need to wait for callbacks - addtimer(CALLBACK(src, PROC_REF(cool_off)), min(server_cooldown_time * capacitor_coefficient), TIMER_UNIQUE|TIMER_STOPPABLE|TIMER_DELETE_ME) + addtimer(CALLBACK(src, PROC_REF(cool_off)), ROUND_UP(server_cooldown_time * capacitor_coefficient), TIMER_UNIQUE|TIMER_STOPPABLE|TIMER_DELETE_ME) update_appearance() update_use_power(IDLE_POWER_USE) domain_randomized = FALSE retries_spent = 0 -/// Deletes all the tile contents +/// Tries to clean up everything in the domain /obj/machinery/quantum_server/proc/scrub_vdom() sever_connections() /// just in case someone's connected SEND_SIGNAL(src, COMSIG_BITRUNNER_DOMAIN_SCRUBBED) // avatar cleanup just in case @@ -171,19 +158,16 @@ var/datum/turf_reservation/res = generated_domain.reservations[1] res.Release() - var/list/datum/weakref/creatures = spawned_threat_refs + mutation_candidate_refs + var/list/creatures = spawned_threat_refs + mutation_candidate_refs for(var/datum/weakref/creature_ref as anything in creatures) var/mob/living/creature = creature_ref?.resolve() if(isnull(creature)) continue - creature.dust() // sometimes mobs just don't die + creature.dust(just_ash = TRUE, force = TRUE) // sometimes mobs just don't die avatar_connection_refs.Cut() exit_turfs = list() generated_domain = null - generated_safehouse = null mutation_candidate_refs.Cut() spawned_threat_refs.Cut() - -#undef ONLY_TURF diff --git a/code/modules/bitrunning/server/obj_generation.dm b/code/modules/bitrunning/server/obj_generation.dm index 41918980360fb..9d5f8427c0011 100644 --- a/code/modules/bitrunning/server/obj_generation.dm +++ b/code/modules/bitrunning/server/obj_generation.dm @@ -1,3 +1,20 @@ +/// Attempts to spawn a crate twice based on the list of available locations +/obj/machinery/quantum_server/proc/attempt_spawn_cache(list/possible_turfs) + if(!length(possible_turfs)) + return TRUE + + shuffle_inplace(possible_turfs) + var/turf/chosen_turf = validate_turf(pick(possible_turfs)) + + if(isnull(chosen_turf)) + possible_turfs.Remove(chosen_turf) + chosen_turf = validate_turf(pick(possible_turfs)) + if(isnull(chosen_turf)) + CRASH("vdom: after two attemps, could not find a valid turf for cache") + + new /obj/structure/closet/crate/secure/bitrunning/encrypted(chosen_turf) + return TRUE + /// Generates a new avatar for the bitrunner. /obj/machinery/quantum_server/proc/generate_avatar(obj/structure/hololadder/wayout, datum/outfit/netsuit) var/mob/living/carbon/human/avatar = new(wayout.loc) @@ -19,17 +36,11 @@ if(istype(jumpsuit)) jumpsuit.set_armor(/datum/armor/clothing_under) - var/obj/item/clothing/head/hat = avatar.get_clothing_on_part(HEAD) + var/obj/item/clothing/head/hat = locate() in avatar.get_equipped_items() if(istype(hat)) - hat.set_armor(null) + hat.set_armor(/datum/armor/none) - var/thing = avatar.get_active_held_item() - if(!isnull(thing)) - qdel(thing) - - thing = avatar.get_inactive_held_item() - if(!isnull(thing)) - qdel(thing) + QDEL_LIST(avatar.held_items) var/obj/item/storage/backpack/bag = avatar.back if(istype(bag)) @@ -78,6 +89,33 @@ return wayout +/// Loads in any mob segments of the map +/obj/machinery/quantum_server/proc/load_mob_segments() + if(!length(generated_domain.mob_modules)) + return TRUE + + var/current_index = 1 + shuffle_inplace(generated_domain.mob_modules) + + for(var/obj/effect/landmark/bitrunning/mob_segment/landmark in GLOB.landmarks_list) + if(current_index > length(generated_domain.mob_modules)) + stack_trace("vdom: mobs segments are set to unique, but there are more landmarks than available segments") + return FALSE + + var/path + if(generated_domain.modular_unique_mobs) + path = generated_domain.mob_modules[current_index] + current_index += 1 + else + path = pick(generated_domain.mob_modules) + + var/datum/modular_mob_segment/segment = new path() + segment.spawn_mobs(get_turf(landmark)) + mutation_candidate_refs += segment.spawned_mob_refs + qdel(landmark) + + return TRUE + /// Scans over neo's contents for bitrunning tech disks. Loads the items or abilities onto the avatar. /obj/machinery/quantum_server/proc/stock_gear(mob/living/carbon/human/avatar, mob/living/carbon/human/neo, datum/lazy_template/virtual_domain/generated_domain) var/domain_forbids_items = generated_domain.forbids_disk_items @@ -109,6 +147,11 @@ continue var/datum/action/our_action = new ability_disk.granted_action() + + if(locate(our_action.type) in avatar.actions) + failed = TRUE + continue + our_action.Grant(avatar) continue @@ -122,4 +165,4 @@ avatar.put_in_hands(new item_disk.granted_item()) if(failed) - to_chat(neo, span_warning("One of your disks failed to load. You must activate them to make a selection.")) + to_chat(neo, span_warning("One of your disks failed to load. Check for duplicate or inactive disks.")) diff --git a/code/modules/bitrunning/server/signal_handlers.dm b/code/modules/bitrunning/server/signal_handlers.dm index c41c0b529fc83..bd98c1ce2a1d1 100644 --- a/code/modules/bitrunning/server/signal_handlers.dm +++ b/code/modules/bitrunning/server/signal_handlers.dm @@ -14,8 +14,9 @@ /obj/machinery/quantum_server/proc/on_delete(datum/source) SIGNAL_HANDLER + sever_connections() + if(generated_domain) - sever_connections() scrub_vdom() if(is_ready) @@ -25,23 +26,6 @@ if(circuit) qdel(circuit) -/// Handles examining the server. Shows cooldown time and efficiency. -/obj/machinery/quantum_server/proc/on_examine(datum/source, mob/examiner, list/examine_text) - SIGNAL_HANDLER - - examine_text += span_infoplain("Can be resource intensive to run. Ensure adequate power supply.") - - if(capacitor_coefficient < 1) - examine_text += span_infoplain("Its coolant capacity reduces cooldown time by [(1 - capacitor_coefficient) * 100]%.") - - if(servo_bonus > 0.2) - examine_text += span_infoplain("Its manipulation potential is increasing rewards by [servo_bonus]x.") - examine_text += span_infoplain("Injury from unsafe ejection reduced [servo_bonus * 100]%.") - - if(!is_ready) - examine_text += span_notice("It is currently cooling down. Give it a few moments.") - return - /// Whenever something enters the send tiles, check if it's a loot crate. If so, alert players. /obj/machinery/quantum_server/proc/on_goal_turf_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs) SIGNAL_HANDLER @@ -50,6 +34,15 @@ if(isnull(chosen_forge)) return + if((obj_flags & EMAGGED) && isliving(arrived)) + var/mob/living/creature = arrived + + if(!creature.mind?.has_antag_datum(/datum/antagonist/bitrunning_glitch, check_subtypes = TRUE)) + return + + INVOKE_ASYNC(src, PROC_REF(station_spawn), arrived, chosen_forge) + return + if(istype(arrived, /obj/structure/closet/crate/secure/bitrunning/encrypted)) generate_loot(arrived, chosen_forge) return @@ -70,7 +63,8 @@ var/mob/living/creature = thing if(ismegafauna(creature)) - creature.AddElement(/datum/element/virtual_elite_mob) + var/mob/living/simple_animal/hostile/megafauna/boss = creature + boss.make_virtual_megafauna() continue mutation_candidate_refs.Add(WEAKREF(creature)) diff --git a/code/modules/bitrunning/server/threats.dm b/code/modules/bitrunning/server/threats.dm index 451b4c48c190f..e4fd60176c97f 100644 --- a/code/modules/bitrunning/server/threats.dm +++ b/code/modules/bitrunning/server/threats.dm @@ -3,6 +3,37 @@ spawned_threat_refs.Add(WEAKREF(threat)) SEND_SIGNAL(src, COMSIG_BITRUNNER_THREAT_CREATED) +/// Choses which antagonist role is spawned based on threat +/obj/machinery/quantum_server/proc/get_antagonist_role() + var/list/available = list() + + for(var/datum/antagonist/bitrunning_glitch/subtype as anything in subtypesof(/datum/antagonist/bitrunning_glitch)) + if(threat >= initial(subtype.threat)) + available += subtype + + shuffle_inplace(available) + var/datum/antagonist/bitrunning_glitch/chosen = pick(available) + + threat -= initial(chosen.threat) * 0.5 + + return chosen + +/// Selects a target to mutate. Gives two attempts, then crashes if it fails. +/obj/machinery/quantum_server/proc/get_mutation_target() + var/datum/weakref/target_ref = pick(mutation_candidate_refs) + var/mob/living/resolved = target_ref.resolve() + + if(resolved) + return resolved + + mutation_candidate_refs.Remove(target_ref) + if(!length(mutation_candidate_refs)) + return + + target_ref = pick(mutation_candidate_refs) + resolved = target_ref.resolve() + return resolved + /// Finds any mobs with minds in the zones and gives them the bad news /obj/machinery/quantum_server/proc/notify_spawned_threats() for(var/datum/weakref/baddie_ref as anything in spawned_threat_refs) @@ -19,3 +50,115 @@ alert.desc = "The server is resetting. Oblivion awaits." to_chat(baddie, span_userdanger("You have been flagged for deletion! Thank you for your service.")) + +/// Removes a specific threat - used when station spawning +/obj/machinery/quantum_server/proc/remove_threat(mob/living/threat) + spawned_threat_refs.Remove(WEAKREF(threat)) + +/// Selects the role and waits for a ghost orbiter +/obj/machinery/quantum_server/proc/setup_glitch(datum/antagonist/bitrunning_glitch/forced_role) + if(!validate_mutation_candidates()) + return + + var/mob/living/mutation_target = get_mutation_target() + if(isnull(mutation_target)) + CRASH("vdom: After two attempts, no valid mutation target was found.") + + var/atom/thing = mutation_target + thing.create_digital_aura() + + var/datum/antagonist/bitrunning_glitch/chosen_role = forced_role || get_antagonist_role() + var/role_name = initial(chosen_role.name) + + var/datum/callback/to_call = CALLBACK(src, PROC_REF(spawn_glitch), chosen_role, mutation_target) + mutation_target.AddComponent(/datum/component/orbit_poll, \ + ignore_key = POLL_IGNORE_GLITCH, \ + job_bans = ROLE_GLITCH, \ + to_call = to_call, \ + title = role_name, \ + header = "Bitrunning Malfunction", \ + ) + + return mutation_target + +/// Orbit poll has concluded - spawn the antag +/obj/machinery/quantum_server/proc/spawn_glitch(datum/antagonist/bitrunning_glitch/chosen_role, mob/living/mutation_target, mob/dead/observer/ghost) + if(QDELETED(mutation_target)) + return + + if(QDELETED(src) || isnull(ghost) || isnull(generated_domain) || !is_ready || !is_operational) + var/atom/thing = mutation_target + thing.remove_digital_aura() + return + + var/role_name = initial(chosen_role.name) + var/mob/living/antag_mob + switch(role_name) + if(ROLE_NETGUARDIAN) + antag_mob = new /mob/living/basic/netguardian(mutation_target.loc) + else // any other humanoid mob + antag_mob = new /mob/living/carbon/human(mutation_target.loc) + + mutation_target.gib(DROP_ALL_REMAINS) + + antag_mob.key = ghost.key + var/datum/mind/ghost_mind = antag_mob.mind + ghost_mind.add_antag_datum(chosen_role) + ghost_mind.special_role = ROLE_GLITCH + ghost_mind.set_assigned_role(SSjob.GetJobType(/datum/job/bitrunning_glitch)) + + playsound(antag_mob, 'sound/magic/ethereal_exit.ogg', 50, vary = TRUE) + message_admins("[ADMIN_LOOKUPFLW(antag_mob)] has been made into virtual antagonist by an event.") + antag_mob.log_message("was spawned as a virtual antagonist by an event.", LOG_GAME) + + add_threats(antag_mob) + +/// Oh boy - transports the antag station side +/obj/machinery/quantum_server/proc/station_spawn(mob/living/antag, obj/machinery/byteforge/chosen_forge) + antag.balloon_alert(antag, "scanning...") + chosen_forge.setup_particles(angry = TRUE) + radio.talk_into(src, "SECURITY BREACH: Unauthorized entry sequence detected.", RADIO_CHANNEL_SUPPLY) + SEND_SIGNAL(src, COMSIG_BITRUNNER_STATION_SPAWN) + + var/timeout = 2 SECONDS + if(!ishuman(antag)) + radio.talk_into(src, "Fabrication protocols have crashed unexpectedly. Please evacuate the area.", RADIO_CHANNEL_SUPPLY) + timeout = 10 SECONDS + + if(!do_after(antag, timeout) || QDELETED(chosen_forge) || QDELETED(antag) || QDELETED(src) || !is_ready || !is_operational) + chosen_forge.setup_particles() + return + + var/datum/component/glitch/effect = antag.AddComponent(/datum/component/glitch, \ + server = src, \ + forge = chosen_forge, \ + ) + + chosen_forge.flicker(angry = TRUE) + if(!do_after(antag, 1 SECONDS)) + chosen_forge.setup_particles() + qdel(effect) + return + + chosen_forge.flash() + + if(ishuman(antag)) + reset_equipment(antag) + else + radio.talk_into(src, "CRITICAL ALERT: Unregistered mechanical entity deployed.") + + do_teleport(antag, get_turf(chosen_forge), forced = TRUE, asoundin = 'sound/magic/ethereal_enter.ogg', asoundout = 'sound/magic/ethereal_exit.ogg', channel = TELEPORT_CHANNEL_QUANTUM) + +/// Removes any invalid candidates from the list +/obj/machinery/quantum_server/proc/validate_mutation_candidates() + for(var/datum/weakref/creature_ref as anything in mutation_candidate_refs) + var/mob/living/creature = creature_ref.resolve() + if(isnull(creature) || creature.mind) + mutation_candidate_refs.Remove(creature_ref) + + if(!length(mutation_candidate_refs)) + return FALSE + + shuffle_inplace(mutation_candidate_refs) + + return TRUE diff --git a/code/modules/bitrunning/server/util.dm b/code/modules/bitrunning/server/util.dm index 3d8b2c07880ac..a6069d45e90a3 100644 --- a/code/modules/bitrunning/server/util.dm +++ b/code/modules/bitrunning/server/util.dm @@ -22,6 +22,7 @@ "desc" = can_view ? initial(domain.desc) : "Limited scanning capabilities. Cannot infer domain details.", "difficulty" = initial(domain.difficulty), "id" = initial(domain.key), + "is_modular" = initial(domain.is_modular), "name" = can_view ? initial(domain.name) : REDACTED, "reward" = can_view_reward ? initial(domain.reward_points) : REDACTED, )) @@ -53,31 +54,6 @@ return hosted_avatars -/// Gets a random available domain given the current points. Weighted towards higher cost domains. -/obj/machinery/quantum_server/proc/get_random_domain_id() - if(points < 1) - return - - var/list/random_domains = list() - var/total_cost = 0 - - for(var/datum/lazy_template/virtual_domain/available as anything in subtypesof(/datum/lazy_template/virtual_domain)) - var/init_cost = initial(available.cost) - if(!initial(available.test_only) && init_cost > 0 && init_cost < 4 && init_cost <= points) - random_domains += list(list( - cost = init_cost, - id = initial(available.key), - )) - - var/random_value = rand(0, total_cost) - var/accumulated_cost = 0 - - for(var/available as anything in random_domains) - accumulated_cost += available["cost"] - if(accumulated_cost >= random_value) - domain_randomized = TRUE - return available["id"] - /// Locates any turfs with forges on them, returns a random one /obj/machinery/quantum_server/proc/get_random_nearby_forge() var/list/nearby_forges = list() @@ -87,30 +63,39 @@ return pick(nearby_forges) -/// Gets all mobs originally generated by the loaded domain and returns a list that are capable of being antagged -/obj/machinery/quantum_server/proc/get_valid_domain_targets() - // A: No one is playing - // B: The domain is not loaded - // C: The domain is shutting down - // D: There are no mobs - if(!length(avatar_connection_refs) || isnull(generated_domain) || !is_ready || !is_operational || !length(mutation_candidate_refs)) - return list() +/// Gets a random available domain given the current points. +/obj/machinery/quantum_server/proc/get_random_domain_id() + if(points < 1) + return - for(var/datum/weakref/creature_ref as anything in mutation_candidate_refs) - var/mob/living/creature = creature_ref.resolve() - if(isnull(creature) || creature.mind) - mutation_candidate_refs.Remove(creature_ref) + var/list/random_domains = list() - return shuffle(mutation_candidate_refs) + for(var/datum/lazy_template/virtual_domain/available as anything in subtypesof(/datum/lazy_template/virtual_domain)) + var/init_cost = initial(available.cost) -/// Locates any turfs with forges on them -/obj/machinery/quantum_server/proc/get_nearby_forges() - var/list/obj/machinery/byteforge/nearby_forges = list() + if(!initial(available.test_only) && \ + init_cost <= points && \ + init_cost > BITRUNNER_COST_NONE && \ + init_cost < BITRUNNER_COST_EXTREME \ + ) + random_domains.Add(available) - for(var/obj/machinery/byteforge/forge in oview(MAX_DISTANCE, src)) - nearby_forges += forge + shuffle_inplace(random_domains) + var/datum/lazy_template/virtual_domain/selected = pick(random_domains) + domain_randomized = TRUE - return nearby_forges + return initial(selected.key) + +/// Removes all blacklisted items from a mob and returns them to base state +/obj/machinery/quantum_server/proc/reset_equipment(mob/living/carbon/human/person) + for(var/item in person.get_contents()) + qdel(item) + + var/datum/antagonist/bitrunning_glitch/antag_datum = locate() in person.mind?.antag_datums + if(isnull(antag_datum?.preview_outfit)) + return + + person.equipOutfit(antag_datum.preview_outfit) /// Severs any connected users /obj/machinery/quantum_server/proc/sever_connections() @@ -121,10 +106,19 @@ /// Do some magic teleport sparks /obj/machinery/quantum_server/proc/spark_at_location(obj/cache) - playsound(cache, 'sound/magic/blink.ogg', 50, TRUE) + playsound(cache, 'sound/magic/blink.ogg', 50, vary = TRUE) var/datum/effect_system/spark_spread/quantum/sparks = new() - sparks.set_up(5, 1, get_turf(cache)) + sparks.set_up(5, location = get_turf(cache)) sparks.start() +/// Returns a turf if it's not dense, else will find a neighbor. +/obj/machinery/quantum_server/proc/validate_turf(turf/chosen_turf) + if(!chosen_turf.is_blocked_turf()) + return chosen_turf + + for(var/turf/tile in get_adjacent_open_turfs(chosen_turf)) + if(!tile.is_blocked_turf()) + return chosen_turf + #undef REDACTED #undef MAX_DISTANCE diff --git a/code/modules/bitrunning/util/digital_aura.dm b/code/modules/bitrunning/util/digital_aura.dm new file mode 100644 index 0000000000000..a45194933a4fe --- /dev/null +++ b/code/modules/bitrunning/util/digital_aura.dm @@ -0,0 +1,43 @@ +/// Creates a digital effect around the target +/atom/proc/create_digital_aura() + var/list/overlays = get_digital_overlays() + if(!length(overlays)) + return + + add_overlay(overlays) + alpha = 210 + set_light(2, l_color = LIGHT_COLOR_BUBBLEGUM, l_on = TRUE) + update_appearance() + +/// Removes the digital effect around the target +/atom/proc/remove_digital_aura() + var/list/overlays = get_digital_overlays() + if(!length(overlays)) + return + + cut_overlay(overlays) + alpha = 255 + set_light(0, l_color = null, l_on = FALSE) + update_appearance() + +/// Returns a list of overlays to be used for the digital effect +/atom/proc/get_digital_overlays() + var/base_icon + var/dimensions = get_icon_dimensions(icon) + if(!length(dimensions)) + return + + switch(dimensions["width"]) + if(32) + base_icon = 'icons/effects/bitrunning.dmi' + if(48) + base_icon = 'icons/effects/bitrunning_48.dmi' + if(64) + base_icon = 'icons/effects/bitrunning_64.dmi' + + var/mutable_appearance/redshift = mutable_appearance(base_icon, "redshift") + redshift.blend_mode = BLEND_MULTIPLY + + var/mutable_appearance/glitch_effect = mutable_appearance(base_icon, "glitch", MUTATIONS_LAYER, alpha = 150) + + return list(glitch_effect, redshift) diff --git a/code/modules/bitrunning/util/service_style.dm b/code/modules/bitrunning/util/service_style.dm new file mode 100644 index 0000000000000..f420e78306492 --- /dev/null +++ b/code/modules/bitrunning/util/service_style.dm @@ -0,0 +1,23 @@ +/// Gives the appearance of being an agent +/mob/living/carbon/human/proc/set_service_style() + var/static/list/approved_hair_colors = list( + "#4B3D28", + "#000000", + "#8D4A43", + "#D2B48C", + ) + + var/static/list/approved_hairstyles = list( + /datum/sprite_accessory/hair/business, + /datum/sprite_accessory/hair/business2, + /datum/sprite_accessory/hair/business3, + /datum/sprite_accessory/hair/business4, + /datum/sprite_accessory/hair/mulder, + ) + + var/datum/sprite_accessory/hair/picked_hair = pick(approved_hairstyles) + var/picked_color = pick(approved_hair_colors) + + set_facial_hairstyle("Shaved", update = FALSE) + set_haircolor(picked_color, update = FALSE) + set_hairstyle(initial(picked_hair.name)) diff --git a/code/modules/bitrunning/util/virtual_megafauna.dm b/code/modules/bitrunning/util/virtual_megafauna.dm new file mode 100644 index 0000000000000..2707db9e2e747 --- /dev/null +++ b/code/modules/bitrunning/util/virtual_megafauna.dm @@ -0,0 +1,13 @@ +/// Removes all the loot and achievements from megafauna for bitrunning related +/mob/living/simple_animal/hostile/megafauna/proc/make_virtual_megafauna() + var/new_max = clamp(maxHealth * 0.5, 600, 1300) + maxHealth = new_max + health = new_max + + true_spawn = FALSE + + loot.Cut() + loot += /obj/structure/closet/crate/secure/bitrunning/encrypted + + crusher_loot.Cut() + crusher_loot += /obj/structure/closet/crate/secure/bitrunning/encrypted diff --git a/code/modules/bitrunning/util/virtual_mob.dm b/code/modules/bitrunning/util/virtual_mob.dm new file mode 100644 index 0000000000000..891f6016879b6 --- /dev/null +++ b/code/modules/bitrunning/util/virtual_mob.dm @@ -0,0 +1,14 @@ +/// Removes all the "organic" traits from a mob, used for virtual antagonists +/mob/living/carbon/proc/make_virtual_mob() + add_traits(list( + TRAIT_NO_AUGMENTS, + TRAIT_NO_DNA_COPY, + TRAIT_NOBLOOD, + TRAIT_NOBREATH, + TRAIT_NOHUNGER, + TRAIT_RESISTCOLD, + TRAIT_RESISTHIGHPRESSURE, + TRAIT_RESISTLOWPRESSURE, + TRAIT_WEATHER_IMMUNE, + ), TRAIT_GENERIC, + ) diff --git a/code/modules/bitrunning/virtual_domain/domains/breeze_bay.dm b/code/modules/bitrunning/virtual_domain/domains/breeze_bay.dm index 62fd3117a94e5..5035a323d7c3c 100644 --- a/code/modules/bitrunning/virtual_domain/domains/breeze_bay.dm +++ b/code/modules/bitrunning/virtual_domain/domains/breeze_bay.dm @@ -4,6 +4,7 @@ help_text = "It's simple! Enjoy some rays, catch some fish, and have a good time! Don't get bit by the crabs, though." key = "breeze_bay" map_name = "breeze_bay" + reward_points = BITRUNNER_REWARD_LOW safehouse_path = /datum/map_template/safehouse/wood /datum/lazy_template/virtual_domain/breeze_bay/setup_domain(list/created_atoms) diff --git a/code/modules/bitrunning/virtual_domain/domains/gondola_asteroid.dm b/code/modules/bitrunning/virtual_domain/domains/gondola_asteroid.dm index 01d58e3980381..1f38554236145 100644 --- a/code/modules/bitrunning/virtual_domain/domains/gondola_asteroid.dm +++ b/code/modules/bitrunning/virtual_domain/domains/gondola_asteroid.dm @@ -1,7 +1,6 @@ /datum/lazy_template/virtual_domain/gondola_asteroid name = "Gondola Asteroid" desc = "An asteroid home to a bountiful forest of gondolas. Peaceful." - map_name = "gondola_asteroid" help_text = "What a lovely forest. There's a loot crate here in the middle of the map. \ Hmm... It doesn't budge. The gondolas don't seem to have any trouble moving it, though. \ I bet there's a way to move it myself." diff --git a/code/modules/bitrunning/virtual_domain/domains/pipedream.dm b/code/modules/bitrunning/virtual_domain/domains/pipedream.dm index fd54ef6ca4847..c8d7750e979e6 100644 --- a/code/modules/bitrunning/virtual_domain/domains/pipedream.dm +++ b/code/modules/bitrunning/virtual_domain/domains/pipedream.dm @@ -2,13 +2,18 @@ name = "Disposal Pipe Factory" cost = BITRUNNER_COST_LOW desc = "An abandoned and infested factory manufacturing disposal pipes." - difficulty = BITRUNNER_DIFFICULTY_MEDIUM + difficulty = BITRUNNER_DIFFICULTY_LOW extra_loot = list(/obj/item/stack/pipe_cleaner_coil/random/five = 1) help_text = "Not long ago, this place was thriving with activity. The workers \ seemed to have left in a hurry, and now productivity is in the bin. Something \ must have trashed the place, but what?" + is_modular = TRUE key = "pipedream" map_name = "pipedream" + mob_modules = list( + /datum/modular_mob_segment/hivebots, + /datum/modular_mob_segment/hivebots_strong + ) reward_points = BITRUNNER_REWARD_LOW safehouse_path = /datum/map_template/safehouse/shuttle diff --git a/code/modules/bitrunning/virtual_domain/domains/syndicate_assault.dm b/code/modules/bitrunning/virtual_domain/domains/syndicate_assault.dm index bae0da6874dbf..dd56684abc63c 100644 --- a/code/modules/bitrunning/virtual_domain/domains/syndicate_assault.dm +++ b/code/modules/bitrunning/virtual_domain/domains/syndicate_assault.dm @@ -7,7 +7,9 @@ help_text = "A group of Syndicate operatives have stolen valuable cargo from the station. \ They have boarded their ship and are attempting to escape. Infiltrate their ship and recover \ the crate. Be careful, they are extremely armed." + is_modular = TRUE key = "syndicate_assault" map_name = "syndicate_assault" + mob_modules = list(/datum/modular_mob_segment/syndicate_team) reward_points = BITRUNNER_REWARD_MEDIUM safehouse_path = /datum/map_template/safehouse/shuttle diff --git a/code/modules/bitrunning/virtual_domain/domains/vaporwave.dm b/code/modules/bitrunning/virtual_domain/domains/vaporwave.dm index 45d4abec9830a..0b1bfedbdb9b0 100644 --- a/code/modules/bitrunning/virtual_domain/domains/vaporwave.dm +++ b/code/modules/bitrunning/virtual_domain/domains/vaporwave.dm @@ -1,7 +1,7 @@ /datum/lazy_template/virtual_domain/vaporwave name = "Cosmic Vestige" cost = BITRUNNER_COST_EXTREME - desc = "Suspended in the silent void of space, the Neon Relic is a haunting echo of a retro-futuristic era." + desc = "Suspended in the silent void of space, the Neon Relic is a haunting echo of a retro-futuristic era. Hang out, enjoy the view." difficulty = BITRUNNER_DIFFICULTY_NONE extra_loot = list(/obj/item/stack/spacecash/c500 = 3) key = "vaporwave" diff --git a/code/modules/bitrunning/virtual_domain/domains/xeno_nest.dm b/code/modules/bitrunning/virtual_domain/domains/xeno_nest.dm index 2bd4105e13c22..ccf5fac23ad0a 100644 --- a/code/modules/bitrunning/virtual_domain/domains/xeno_nest.dm +++ b/code/modules/bitrunning/virtual_domain/domains/xeno_nest.dm @@ -6,7 +6,9 @@ extra_loot = list(/obj/item/toy/plush/rouny = 1) help_text = "You are on a barren planet filled with hostile creatures. There is a crate here, not hidden, \ simply protected. Expect resistance." + is_modular = TRUE key = "xeno_nest" map_name = "xeno_nest" + mob_modules = list(/datum/modular_mob_segment/xenos) reward_points = BITRUNNER_REWARD_LOW safehouse_path = /datum/map_template/safehouse/shuttle diff --git a/code/modules/bitrunning/virtual_domain/modular_mob_segment.dm b/code/modules/bitrunning/virtual_domain/modular_mob_segment.dm new file mode 100644 index 0000000000000..b845eee564da6 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/modular_mob_segment.dm @@ -0,0 +1,156 @@ +#define SPAWN_ALWAYS 100 +#define SPAWN_LIKELY 85 +#define SPAWN_UNLIKELY 35 +#define SPAWN_RARE 10 + +/datum/modular_mob_segment + /// Spawn no more than this amount + var/max = 4 + /// Set this to false if you want explicitly what's in the list to spawn + var/exact = FALSE + /// The list of mobs to spawn + var/list/mob/living/mobs = list() + /// The mobs spawned from this segment + var/list/spawned_mob_refs = list() + /// Chance this will spawn (1 - 100) + var/probability = SPAWN_LIKELY + +/// Spawns mobs in a circle around the location +/datum/modular_mob_segment/proc/spawn_mobs(turf/origin) + if(!prob(probability)) + return + + var/total_amount = exact ? rand(1, max) : length(mobs) + + shuffle_inplace(mobs) + + + var/list/turf/nearby = list() + for(var/turf/tile as anything in RANGE_TURFS(2, origin)) + if(!tile.is_blocked_turf()) + nearby += tile + + if(!length(nearby)) + stack_trace("Couldn't find any valid turfs to spawn on") + return + + for(var/index in 1 to total_amount) + // For each of those, we need to find an open space + var/turf/destination = pick(nearby) + + var/path // Either a random mob or the next mob in the list + if(exact) + path = mobs[index] + else + path = pick(mobs) + + var/mob/living/mob = new path(destination) + nearby -= destination + spawned_mob_refs.Add(WEAKREF(mob)) + +// Some generic mob segments. If you want to add generic ones for any map, add them here + +/datum/modular_mob_segment/gondolas + mobs = list( + /mob/living/simple_animal/pet/gondola, + ) + +/datum/modular_mob_segment/corgis + max = 2 + mobs = list( + /mob/living/basic/pet/dog/corgi, + ) + +/datum/modular_mob_segment/monkeys + mobs = list( + /mob/living/carbon/human/species/monkey, + ) + +/datum/modular_mob_segment/syndicate_team + mobs = list( + /mob/living/basic/trooper/syndicate/ranged, + /mob/living/basic/trooper/syndicate/melee, + ) + +/datum/modular_mob_segment/syndicate_elite + mobs = list( + /mob/living/basic/trooper/syndicate/melee/sword/space/stormtrooper, + /mob/living/basic/trooper/syndicate/ranged/space/stormtrooper, + ) + +/datum/modular_mob_segment/bears + max = 2 + mobs = list( + /mob/living/basic/bear, + ) + +/datum/modular_mob_segment/bees + exact = TRUE + mobs = list( + /mob/living/basic/bee, + /mob/living/basic/bee, + /mob/living/basic/bee, + /mob/living/basic/bee, + /mob/living/basic/bee/queen, + ) + +/datum/modular_mob_segment/bees_toxic + mobs = list( + /mob/living/basic/bee/toxin, + ) + +/datum/modular_mob_segment/blob_spores + mobs = list( + /mob/living/basic/blob_minion, + ) + +/datum/modular_mob_segment/carps + mobs = list( + /mob/living/basic/carp, + ) + +/datum/modular_mob_segment/hivebots + mobs = list( + /mob/living/basic/hivebot, + /mob/living/basic/hivebot/range, + ) + +/datum/modular_mob_segment/hivebots_strong + mobs = list( + /mob/living/basic/hivebot/strong, + /mob/living/basic/hivebot/range, + ) + +/datum/modular_mob_segment/lavaland_assorted + mobs = list( + /mob/living/basic/mining/basilisk, + /mob/living/basic/mining/goliath, + /mob/living/basic/mining/brimdemon, + /mob/living/basic/mining/lobstrosity, + ) + +/datum/modular_mob_segment/spiders + mobs = list( + /mob/living/basic/spider/giant/ambush, + /mob/living/basic/spider/giant/hunter, + /mob/living/basic/spider/giant/nurse, + /mob/living/basic/spider/giant/tarantula, + /mob/living/basic/spider/giant/midwife, + ) + +/datum/modular_mob_segment/venus_trap + mobs = list( + /mob/living/basic/venus_human_trap, + ) + +/datum/modular_mob_segment/xenos + mobs = list( + /mob/living/simple_animal/hostile/alien, + /mob/living/simple_animal/hostile/alien/sentinel, + /mob/living/simple_animal/hostile/alien/drone, + ) + +#undef SPAWN_ALWAYS +#undef SPAWN_LIKELY +#undef SPAWN_UNLIKELY +#undef SPAWN_RARE diff --git a/code/modules/bitrunning/virtual_domain/safehouses.dm b/code/modules/bitrunning/virtual_domain/safehouses.dm index 6504d447f28c4..79c8d5fe895bc 100644 --- a/code/modules/bitrunning/virtual_domain/safehouses.dm +++ b/code/modules/bitrunning/virtual_domain/safehouses.dm @@ -6,51 +6,49 @@ /datum/map_template/safehouse name = "virtual domain: safehouse" - returns_created_atoms = TRUE /// The map file to load - var/filename = "den.dmm" + var/filename = "den" /datum/map_template/safehouse/New() - mappath = "_maps/safehouses/" + filename + mappath = "_maps/safehouses/[filename].dmm" ..(path = mappath) /datum/map_template/safehouse/test_only filename = "test_only_safehouse.dmm" - /// The default safehouse map template. -/datum/map_template/safehouse/wood - filename = "wood.dmm" - /datum/map_template/safehouse/den - filename = "den.dmm" + filename = "den" + +/datum/map_template/safehouse/wood + filename = "wood" /datum/map_template/safehouse/dig - filename = "dig.dmm" + filename = "dig" /datum/map_template/safehouse/shuttle - filename = "shuttle.dmm" + filename = "shuttle" // Has space tiles on the four corners. /datum/map_template/safehouse/shuttle_space - filename = "shuttle_space.dmm" + filename = "shuttle_space" /datum/map_template/safehouse/mine - filename = "mine.dmm" + filename = "mine" // Comes preloaded with mining combat gear. /datum/map_template/safehouse/lavaland_boss - filename = "lavaland_boss.dmm" + filename = "lavaland_boss" // Chill out /datum/map_template/safehouse/ice - filename = "ice.dmm" + filename = "ice" /datum/map_template/safehouse/bathroom - filename = "bathroom.dmm" + filename = "bathroom" /** * Your safehouse here * /datum/map_template/safehouse/your_type - * filename = "your_map.dmm" + * filename = "your_map" */ diff --git a/code/modules/bitrunning/virtual_domain/virtual_domain.dm b/code/modules/bitrunning/virtual_domain/virtual_domain.dm index 5e6cb0f2582e5..6e7b98ccdb49b 100644 --- a/code/modules/bitrunning/virtual_domain/virtual_domain.dm +++ b/code/modules/bitrunning/virtual_domain/virtual_domain.dm @@ -1,6 +1,5 @@ /** * # Virtual Domains - * This loads a base level, then users can select the preset upon it. * Create your own: Read the readme file in the '_maps/virtual_domains' folder. */ /datum/lazy_template/virtual_domain @@ -10,22 +9,30 @@ /// Cost of this map to load var/cost = BITRUNNER_COST_NONE - /// The description of the map + /// The safehouse to load into the map + var/datum/map_template/safehouse/safehouse_path = /datum/map_template/safehouse/den + /// Any outfit that you wish to force on avatars. Overrides preferences + var/datum/outfit/forced_outfit + /// The description of the map for the console UI var/desc = "A map." - /// The 'difficulty' of the map, which affects the ui and ability to scan info. + /// Affects the ui and ability to scan info. var/difficulty = BITRUNNER_DIFFICULTY_NONE - /// An assoc list of typepath/amount to spawn on completion. Not weighted - the value is the amount - var/list/extra_loot /// The map file to load var/filename = "virtual_domain.dmm" - /// Any outfit that you wish to force on avatars. Overrides preferences - var/datum/outfit/forced_outfit /// If this domain blocks the use of items from disks, for whatever reason var/forbids_disk_items = FALSE /// If this domain blocks the use of spells from disks, for whatever reason var/forbids_disk_spells = FALSE /// Information given to connected clients via ability var/help_text + /// Whether to display this as a modular map + var/is_modular = FALSE + /// Byond will look for modular mob segment landmarks then choose from here at random. You can make them unique also. + var/list/datum/modular_mob_segment/mob_modules = list() + /// An assoc list of typepath/amount to spawn on completion. Not weighted - the value is the amount + var/list/extra_loot + /// Forces all mob modules to only load once + var/modular_unique_mobs = FALSE // Name to show in the UI var/name = "Virtual Domain" /// Points to reward for completion. Used to purchase new domains and calculate ore rewards. @@ -34,8 +41,6 @@ var/start_time /// This map is specifically for unit tests. Shouldn't display in game var/test_only = FALSE - /// The safehouse to load into the map - var/datum/map_template/safehouse/safehouse_path = /datum/map_template/safehouse/den /// Sends a point to any loot signals on the map /datum/lazy_template/virtual_domain/proc/add_points(points_to_add) diff --git a/code/modules/capture_the_flag/ctf_equipment.dm b/code/modules/capture_the_flag/ctf_equipment.dm index 798bfa49be922..dccf875a55a95 100644 --- a/code/modules/capture_the_flag/ctf_equipment.dm +++ b/code/modules/capture_the_flag/ctf_equipment.dm @@ -207,12 +207,18 @@ var/lose_multiple_charges = TRUE var/show_charge_as_alpha = TRUE -/obj/item/clothing/suit/armor/vest/ctf/equipped(mob/user, slot) +/obj/item/clothing/suit/armor/vest/ctf/Initialize(mapload) . = ..() - if(!slot || slot & ITEM_SLOT_HANDS) - return - AddComponent(/datum/component/shielded, max_charges = max_charges, recharge_start_delay = recharge_start_delay, charge_increment_delay = charge_increment_delay, \ - charge_recovery = charge_recovery, lose_multiple_charges = lose_multiple_charges, show_charge_as_alpha = show_charge_as_alpha, shield_icon = team_shield_icon) + AddComponent( \ + /datum/component/shielded, \ + max_charges = max_charges, \ + recharge_start_delay = recharge_start_delay, \ + charge_increment_delay = charge_increment_delay, \ + charge_recovery = charge_recovery, \ + lose_multiple_charges = lose_multiple_charges, \ + show_charge_as_alpha = show_charge_as_alpha, \ + shield_icon = team_shield_icon, \ + ) // LIGHT SHIELDED VEST diff --git a/code/modules/cargo/exports/lavaland.dm b/code/modules/cargo/exports/lavaland.dm index 31cc131986102..51165be191c87 100644 --- a/code/modules/cargo/exports/lavaland.dm +++ b/code/modules/cargo/exports/lavaland.dm @@ -31,12 +31,12 @@ cost = CARGO_CRATE_VALUE * 40 unit_name = "lava planet artifact" export_types = list( - /obj/item/guardiancreator/miner, - /obj/item/rod_of_asclepius, /obj/item/dragons_blood, - /obj/item/melee/ghost_sword, + /obj/item/guardian_creator/miner, /obj/item/lava_staff, + /obj/item/melee/ghost_sword, /obj/item/prisoncube, + /obj/item/rod_of_asclepius, ) //Megafauna loot, except for ash drakes diff --git a/code/modules/cargo/materials_market.dm b/code/modules/cargo/materials_market.dm index 22ab4f2239cf2..1a617e9e2dce1 100644 --- a/code/modules/cargo/materials_market.dm +++ b/code/modules/cargo/materials_market.dm @@ -105,6 +105,10 @@ ui = new(user, src, "MatMarket", name) ui.open() +/obj/machinery/materials_market/ui_static_data(mob/user) + . = list() + .["CARGO_CRATE_VALUE"] = CARGO_CRATE_VALUE + /obj/machinery/materials_market/ui_data(mob/user) . = list() @@ -247,9 +251,6 @@ return var/cost = SSstock_market.materials_prices[material_bought] * quantity - if(cost > account_payable.account_balance) - say("Not enough money to start purchase!") - return var/list/things_to_order = list() things_to_order += (sheet_to_buy) @@ -285,13 +286,14 @@ current_order.append_order(things_to_order, cost) return TRUE + //Place a new order var/datum/supply_pack/custom/minerals/mineral_pack = new( purchaser = is_ordering_private ? living_user : "Cargo", \ cost = cost, \ contains = things_to_order, \ ) - var/datum/supply_order/materials/new_order = new( + var/datum/supply_order/disposable/materials/new_order = new( pack = mineral_pack, orderer = living_user, orderer_rank = GALATIC_MATERIAL_ORDER, @@ -300,6 +302,12 @@ cost_type = "cr", can_be_cancelled = FALSE ) + //first time order compute the correct cost and compare + if(new_order.get_final_cost() > account_payable.account_balance) + say("Not enough money to start purchase!") + qdel(new_order) + return + say("Thank you for your purchase! It will arrive on the next cargo shuttle!") SSshuttle.shopping_list += new_order return TRUE diff --git a/code/modules/cargo/order.dm b/code/modules/cargo/order.dm index 58c13afbe59fb..309567d51e902 100644 --- a/code/modules/cargo/order.dm +++ b/code/modules/cargo/order.dm @@ -85,6 +85,10 @@ src.manifest_can_fail = manifest_can_fail src.can_be_cancelled = can_be_cancelled +/datum/supply_order/Destroy(force, ...) + QDEL_NULL(applied_coupon) + return ..() + //returns the total cost of this order. Its not the total price paid by cargo but the total value of this order /datum/supply_order/proc/get_final_cost() var/cost = pack.get_cost() @@ -201,10 +205,17 @@ pack.contains[i] = new_contents[i] pack.cost += cost_increase -//To append cargo crate value to final order cost -/datum/supply_order/materials +/// Custom type of order who's supply pack can be safely deleted +/datum/supply_order/disposable + +/datum/supply_order/disposable/Destroy(force, ...) + QDEL_NULL(pack) + return ..() + +/// Custom material order to append cargo crate value to the final order cost +/datum/supply_order/disposable/materials -/datum/supply_order/materials/get_final_cost() +/datum/supply_order/disposable/materials/get_final_cost() return (..() + CARGO_CRATE_VALUE) #undef MANIFEST_ERROR_CHANCE diff --git a/code/modules/cargo/packs/_packs.dm b/code/modules/cargo/packs/_packs.dm index aaeb55f253385..51ec71649dd49 100644 --- a/code/modules/cargo/packs/_packs.dm +++ b/code/modules/cargo/packs/_packs.dm @@ -122,3 +122,16 @@ name = "[purchaser]'s Materials Order" src.cost = cost src.contains = contains + +/datum/supply_pack/custom/minerals/fill(obj/structure/closet/crate/C) + . = ..() + //Remove our material sheets from SSstock_market's materials_quantity equal to the quantity within the crate. + for(var/obj/item/stack/sheet/possible_stack as anything in contains) + if(!ispath(possible_stack, /obj/item/stack/sheet)) + continue + if(!possible_stack.material_type) + continue + if(!SSstock_market.materials_quantity[possible_stack.material_type]) + continue + SSstock_market.materials_quantity[possible_stack.material_type] -= contains[possible_stack] + SSstock_market.materials_prices[possible_stack.material_type] += round((SSstock_market.materials_prices[possible_stack.material_type]) * (contains[possible_stack] / (SSstock_market.materials_quantity[possible_stack.material_type] - contains[possible_stack]))) diff --git a/code/modules/cargo/packs/emergency.dm b/code/modules/cargo/packs/emergency.dm index fca1a201ac103..9969ea7d81769 100644 --- a/code/modules/cargo/packs/emergency.dm +++ b/code/modules/cargo/packs/emergency.dm @@ -62,7 +62,7 @@ access = ACCESS_ATMOSPHERICS contains = list(/obj/item/watertank/atmos) crate_name = "firefighting backpack crate" - crate_type = /obj/structure/closet/crate/secure + crate_type = /obj/structure/closet/crate/secure/engineering/atmos /datum/supply_pack/emergency/internals name = "Internals Crate" diff --git a/code/modules/cargo/packs/engineering.dm b/code/modules/cargo/packs/engineering.dm index f5d865de95ce0..ae03ffb0190bc 100644 --- a/code/modules/cargo/packs/engineering.dm +++ b/code/modules/cargo/packs/engineering.dm @@ -31,6 +31,7 @@ /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp, ) crate_name= "\improper APLU MK-I kit" + crate_type = /obj/structure/closet/crate/science/robo /datum/supply_pack/engineering/conveyor name = "Conveyor Assembly Crate" @@ -125,6 +126,7 @@ access_view = ACCESS_ATMOSPHERICS contains = list(/obj/machinery/portable_atmospherics/pump = 2) crate_name = "portable air pump crate" + crate_type = /obj/structure/closet/crate/secure/engineering/atmos /datum/supply_pack/engineering/portascrubber name = "Portable Scrubber Crate" @@ -133,6 +135,7 @@ access_view = ACCESS_ATMOSPHERICS contains = list(/obj/machinery/portable_atmospherics/scrubber = 2) crate_name = "portable scrubber crate" + crate_type = /obj/structure/closet/crate/secure/engineering/atmos /datum/supply_pack/engineering/hugescrubber name = "Huge Portable Scrubber Crate" @@ -149,7 +152,7 @@ cost = CARGO_CRATE_VALUE * 2 contains = list(/obj/machinery/space_heater) crate_name = "space heater crate" - crate_type = /obj/structure/closet/crate/large + crate_type = /obj/structure/closet/crate/secure/engineering/atmos /datum/supply_pack/engineering/bsa name = "Bluespace Artillery Parts" @@ -266,7 +269,7 @@ access = ACCESS_CE contains = list(/obj/machinery/power/supermatter_crystal/shard) crate_name = "supermatter shard crate" - crate_type = /obj/structure/closet/crate/secure/engineering + crate_type = /obj/structure/closet/crate/secure/radiation dangerous = TRUE /datum/supply_pack/engine/tesla_coils @@ -291,7 +294,7 @@ /obj/item/hfr_box/core, ) crate_name = "HFR crate" - crate_type = /obj/structure/closet/crate/secure/engineering + crate_type = /obj/structure/closet/crate/secure/engineering/atmos dangerous = TRUE /datum/supply_pack/engineering/rad_protection_modules diff --git a/code/modules/cargo/packs/general.dm b/code/modules/cargo/packs/general.dm index cd6df472d4bf6..1b4937f5ab458 100644 --- a/code/modules/cargo/packs/general.dm +++ b/code/modules/cargo/packs/general.dm @@ -72,7 +72,7 @@ access = ACCESS_COMMAND cost = CARGO_CRATE_VALUE * 4 contains = list(/obj/item/encryptionkey/headset_com = 3) - crate_type = /obj/structure/closet/crate/secure + crate_type = /obj/structure/closet/crate/secure/centcom crate_name = "command encryption key crate" /datum/supply_pack/misc/exploration_drone diff --git a/code/modules/cargo/packs/imports.dm b/code/modules/cargo/packs/imports.dm index 6569321a164c6..04abcd0d999ff 100644 --- a/code/modules/cargo/packs/imports.dm +++ b/code/modules/cargo/packs/imports.dm @@ -312,4 +312,4 @@ /obj/item/stock_parts/card_reader = 1 ) crate_name = "materials market crate" - crate_type = /obj/structure/closet/crate + crate_type = /obj/structure/closet/crate/cargo diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm index 3cfb824b4e698..90315f5c772f8 100644 --- a/code/modules/cargo/packs/medical.dm +++ b/code/modules/cargo/packs/medical.dm @@ -1,7 +1,7 @@ /datum/supply_pack/medical group = "Medical" access_view = ACCESS_MEDICAL - crate_type = /obj/structure/closet/crate/medical + crate_type = /obj/structure/closet/crate/medical/department /datum/supply_pack/medical/bloodpacks name = "Blood Pack Variety Crate" @@ -29,6 +29,7 @@ /obj/item/reagent_containers/hypospray/medipen/ekit = 3, /obj/item/reagent_containers/hypospray/medipen/blood_loss = 3) crate_name = "medipen crate" + crate_type = /obj/structure/closet/crate/medical /datum/supply_pack/medical/coroner_crate name = "Autopsy Kit" @@ -70,6 +71,7 @@ cost = CARGO_CRATE_VALUE * 5 contains = list(/obj/item/defibrillator/loaded = 2) crate_name = "defibrillator crate" + crate_type = /obj/structure/closet/crate/medical /datum/supply_pack/medical/iv_drip name = "IV Drip Crate" @@ -77,6 +79,7 @@ cost = CARGO_CRATE_VALUE * 2 contains = list(/obj/machinery/iv_drip) crate_name = "iv drip crate" + crate_type = /obj/structure/closet/crate/medical /datum/supply_pack/medical/supplies name = "Medical Supplies Crate" @@ -108,6 +111,7 @@ /obj/item/vending_refill/drugs, ) crate_name = "medical supplies crate" + crate_type = /obj/structure/closet/crate/medical /datum/supply_pack/medical/supplies/fill(obj/structure/closet/crate/C) for(var/i in 1 to 10) @@ -120,6 +124,7 @@ cost = CARGO_CRATE_VALUE * 2 contains = list(/obj/item/storage/pill_bottle/sansufentanyl = 2) crate_name = "experimental medicine crate" + crate_type = /obj/structure/closet/crate/medical /datum/supply_pack/medical/surgery name = "Surgical Supplies Crate" @@ -143,6 +148,7 @@ cost = CARGO_CRATE_VALUE * 6 access = ACCESS_MEDICAL contains = list(/obj/machinery/iv_drip/saline) + crate_type = /obj/structure/closet/crate/large /datum/supply_pack/medical/virus name = "Virus Crate" diff --git a/code/modules/cargo/packs/organic.dm b/code/modules/cargo/packs/organic.dm index eb26d5ec907f7..e5a1327b45361 100644 --- a/code/modules/cargo/packs/organic.dm +++ b/code/modules/cargo/packs/organic.dm @@ -151,7 +151,7 @@ access = ACCESS_HYDROPONICS contains = list(/obj/item/watertank) crate_name = "hydroponics backpack crate" - crate_type = /obj/structure/closet/crate/secure + crate_type = /obj/structure/closet/crate/secure/hydroponics /datum/supply_pack/organic/pizza name = "Pizza Crate" diff --git a/code/modules/cargo/packs/science.dm b/code/modules/cargo/packs/science.dm index 19a7710ffed7b..f0de463c4490f 100644 --- a/code/modules/cargo/packs/science.dm +++ b/code/modules/cargo/packs/science.dm @@ -113,7 +113,7 @@ /obj/item/clothing/head/utility/hardhat/red = 2, /obj/item/storage/medkit = 2) crate_name = "robotics assembly crate" - crate_type = /obj/structure/closet/crate/secure/science + crate_type = /obj/structure/closet/crate/secure/science/robo /datum/supply_pack/science/rped name = "RPED crate" @@ -176,4 +176,4 @@ access_view = ACCESS_ROBOTICS contains = list(/obj/item/mod/core/standard = 3) crate_name = "\improper MOD core crate" - crate_type = /obj/structure/closet/crate/secure/science + crate_type = /obj/structure/closet/crate/secure/science/robo diff --git a/code/modules/cargo/packs/service.dm b/code/modules/cargo/packs/service.dm index 45660dcc73ee6..47eee06e3c655 100644 --- a/code/modules/cargo/packs/service.dm +++ b/code/modules/cargo/packs/service.dm @@ -160,7 +160,7 @@ access_view = ACCESS_MINING_STATION contains = list(/obj/item/storage/backpack/duffelbag/mining_conscript) crate_name = "shaft miner starter kit" - crate_type = /obj/structure/closet/crate/secure + crate_type = /obj/structure/closet/crate/secure/cargo/mining /datum/supply_pack/service/survivalknives name = "Survival Knives Crate" @@ -169,6 +169,7 @@ cost = CARGO_CRATE_VALUE * 3 contains = list(/obj/item/knife/combat/survival = 3) crate_name = "survival knife crate" + crate_type = /obj/structure/closet/crate/cargo/mining /datum/supply_pack/service/wedding name = "Wedding Crate" @@ -224,6 +225,7 @@ /obj/item/storage/box/donkpockets/donkpockethonk, ) crate_name = "donk pocket crate" + crate_type = /obj/structure/closet/crate/freezer/food /datum/supply_pack/service/randomized/donkpockets/fill(obj/structure/closet/crate/C) for(var/i in 1 to 3) @@ -240,6 +242,7 @@ /obj/item/food/ready_donk/donkhiladas, ) crate_name = "\improper Ready-Donk crate" + crate_type = /obj/structure/closet/crate/freezer/food /datum/supply_pack/service/randomized/ready_donk/fill(obj/structure/closet/crate/C) for(var/i in 1 to 3) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index dab23c78e17ff..88699f29048d7 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -314,13 +314,13 @@ GLOBAL_LIST_EMPTY(preferences_datums) if (!preference.is_accessible(src)) continue - LAZYINITLIST(preferences[preference.category]) - var/value = read_preference(preference.type) var/data = preference.compile_ui_data(user, value) + LAZYINITLIST(preferences[preference.category]) preferences[preference.category][preference.savefile_key] = data + for (var/datum/preference_middleware/preference_middleware as anything in middleware) var/list/append_character_preferences = preference_middleware.get_character_preferences(user) if (isnull(append_character_preferences)) diff --git a/code/modules/client/preferences/food_allergy.dm b/code/modules/client/preferences/food_allergy.dm index 461c3b31e2a32..1096ef3c18396 100644 --- a/code/modules/client/preferences/food_allergy.dm +++ b/code/modules/client/preferences/food_allergy.dm @@ -1,5 +1,5 @@ /datum/preference/choiced/food_allergy - category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED savefile_key = "food_allergy" savefile_identifier = PREFERENCE_CHARACTER can_randomize = FALSE diff --git a/code/modules/client/preferences/glasses.dm b/code/modules/client/preferences/glasses.dm index e34cdd0e09060..03c975abce786 100644 --- a/code/modules/client/preferences/glasses.dm +++ b/code/modules/client/preferences/glasses.dm @@ -1,5 +1,5 @@ /datum/preference/choiced/glasses - category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED savefile_key = "glasses" savefile_identifier = PREFERENCE_CHARACTER should_generate_icons = TRUE diff --git a/code/modules/client/preferences/language.dm b/code/modules/client/preferences/language.dm index 2de14be09cf0d..f602d6b3a66c9 100644 --- a/code/modules/client/preferences/language.dm +++ b/code/modules/client/preferences/language.dm @@ -1,5 +1,5 @@ /datum/preference/choiced/language - category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED savefile_key = "language" savefile_identifier = PREFERENCE_CHARACTER diff --git a/code/modules/client/preferences/middleware/antags.dm b/code/modules/client/preferences/middleware/antags.dm index e13167ba7347f..44cb0017e16ca 100644 --- a/code/modules/client/preferences/middleware/antags.dm +++ b/code/modules/client/preferences/middleware/antags.dm @@ -116,7 +116,7 @@ /datum/asset/spritesheet/antagonists/create_spritesheets() // Antagonists that don't have a dynamic ruleset, but do have a preference var/static/list/non_ruleset_antagonists = list( - ROLE_CYBER_POLICE = /datum/antagonist/cyber_police, + ROLE_GLITCH = /datum/antagonist/bitrunning_glitch, ROLE_FUGITIVE = /datum/antagonist/fugitive, ROLE_LONE_OPERATIVE = /datum/antagonist/nukeop/lone, ROLE_SENTIENCE = /datum/antagonist/sentient_creature, diff --git a/code/modules/client/preferences/middleware/quirks.dm b/code/modules/client/preferences/middleware/quirks.dm index a3634dec35ad7..67bb5a6fc8106 100644 --- a/code/modules/client/preferences/middleware/quirks.dm +++ b/code/modules/client/preferences/middleware/quirks.dm @@ -33,11 +33,16 @@ for (var/quirk_name in quirks) var/datum/quirk/quirk = quirks[quirk_name] + var/datum/quirk_constant_data/constant_data = GLOB.all_quirk_constant_data[quirk] + var/list/datum/preference/customization_options = constant_data?.get_customization_data() + quirk_info[sanitize_css_class_name(quirk_name)] = list( "description" = initial(quirk.desc), "icon" = initial(quirk.icon), "name" = quirk_name, "value" = initial(quirk.value), + "customizable" = constant_data?.is_customizable(), + "customization_options" = customization_options, ) return list( diff --git a/code/modules/client/preferences/paint_color.dm b/code/modules/client/preferences/paint_color.dm index a44208b8325c5..749b83cf00098 100644 --- a/code/modules/client/preferences/paint_color.dm +++ b/code/modules/client/preferences/paint_color.dm @@ -2,7 +2,7 @@ /datum/preference/color/paint_color savefile_key = "paint_color" savefile_identifier = PREFERENCE_CHARACTER - category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED /datum/preference/color/paint_color/is_accessible(datum/preferences/preferences) if (!..(preferences)) diff --git a/code/modules/client/preferences/phobia.dm b/code/modules/client/preferences/phobia.dm index 2a5caa5ba0f8e..92004418156f7 100644 --- a/code/modules/client/preferences/phobia.dm +++ b/code/modules/client/preferences/phobia.dm @@ -1,5 +1,5 @@ /datum/preference/choiced/phobia - category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED savefile_key = "phobia" savefile_identifier = PREFERENCE_CHARACTER diff --git a/code/modules/client/preferences/prosthetic.dm b/code/modules/client/preferences/prosthetic.dm index f66f1278c48a9..a4d5b5a577ba1 100644 --- a/code/modules/client/preferences/prosthetic.dm +++ b/code/modules/client/preferences/prosthetic.dm @@ -1,5 +1,5 @@ /datum/preference/choiced/prosthetic - category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED savefile_key = "prosthetic" savefile_identifier = PREFERENCE_CHARACTER diff --git a/code/modules/clothing/chameleon/generic_chameleon_clothing.dm b/code/modules/clothing/chameleon/generic_chameleon_clothing.dm index 9e1339b40681c..492008d534864 100644 --- a/code/modules/clothing/chameleon/generic_chameleon_clothing.dm +++ b/code/modules/clothing/chameleon/generic_chameleon_clothing.dm @@ -76,6 +76,7 @@ do { \ /obj/item/clothing/glasses/chameleon name = "Optical Meson Scanner" + flags_cover = GLASSESCOVERSEYES desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition." icon_state = "meson" inhand_icon_state = "meson" diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 4107da729833a..a200cefc021f4 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -5,7 +5,6 @@ lefthand_file = 'icons/mob/inhands/clothing/glasses_lefthand.dmi' righthand_file = 'icons/mob/inhands/clothing/glasses_righthand.dmi' w_class = WEIGHT_CLASS_SMALL - flags_cover = GLASSESCOVERSEYES slot_flags = ITEM_SLOT_EYES strip_delay = 20 equip_delay_other = 25 @@ -113,6 +112,7 @@ icon_state = "meson" inhand_icon_state = "meson" clothing_traits = list(TRAIT_MADNESS_IMMUNE) + flags_cover = GLASSESCOVERSEYES vision_flags = SEE_TURFS // Mesons get to be lightly green color_cutoffs = list(5, 15, 5) @@ -152,6 +152,7 @@ icon_state = "purple" inhand_icon_state = "glasses" glass_colour_type = /datum/client_colour/glass_colour/purple + flags_cover = GLASSESCOVERSEYES resistance_flags = ACID_PROOF armor_type = /datum/armor/glasses_science clothing_traits = list(TRAIT_REAGENT_SCANNER, TRAIT_RESEARCH_SCANNER) @@ -182,6 +183,7 @@ desc = "You can totally see in the dark now!" icon_state = "night" inhand_icon_state = "glasses" + flags_cover = GLASSESCOVERSEYES flash_protect = FLASH_PROTECTION_SENSITIVE // Dark green color_cutoffs = list(10, 30, 10) @@ -243,6 +245,7 @@ desc = "Very confusing glasses." icon_state = "material" inhand_icon_state = "glasses" + flags_cover = GLASSESCOVERSEYES vision_flags = SEE_OBJS glass_colour_type = /datum/client_colour/glass_colour/lightblue @@ -272,6 +275,7 @@ desc = "Made by Nerd. Co." icon_state = "glasses_regular" inhand_icon_state = "glasses" + flags_cover = GLASSESCOVERSEYES clothing_traits = list(TRAIT_NEARSIGHTED_CORRECTED) /obj/item/clothing/glasses/regular/Initialize(mapload) @@ -346,6 +350,7 @@ desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks flashes." icon_state = "sun" inhand_icon_state = "sunglasses" + flags_cover = GLASSESCOVERSEYES flash_protect = FLASH_PROTECTION_FLASH tint = 1 glass_colour_type = /datum/client_colour/glass_colour/gray @@ -448,10 +453,10 @@ inhand_icon_state = "welding-g" actions_types = list(/datum/action/item_action/toggle) flash_protect = FLASH_PROTECTION_WELDER + flags_cover = GLASSESCOVERSEYES custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT*2.5) tint = 2 visor_vars_to_toggle = VISOR_FLASHPROTECT | VISOR_TINT - flags_cover = GLASSESCOVERSEYES glass_colour_type = /datum/client_colour/glass_colour/gray /obj/item/clothing/glasses/welding/attack_self(mob/user) @@ -467,6 +472,7 @@ icon_state = "blindfold" inhand_icon_state = "blindfold" flash_protect = FLASH_PROTECTION_WELDER + flags_cover = GLASSESCOVERSEYES tint = INFINITY // You WILL Be blind, no matter what dog_fashion = /datum/dog_fashion/head @@ -475,6 +481,7 @@ desc = "A see-through blindfold perfect for cheating at games like pin the stun baton on the clown." icon_state = "trickblindfold" inhand_icon_state = "blindfold" + flags_cover = GLASSESCOVERSEYES /obj/item/clothing/glasses/blindfold/white name = "blind personnel blindfold" @@ -520,6 +527,7 @@ // Going for an orange color here color_cutoffs = list(25, 8, 5) flash_protect = FLASH_PROTECTION_SENSITIVE + flags_cover = GLASSESCOVERSEYES glass_colour_type = /datum/client_colour/glass_colour/red /obj/item/clothing/glasses/thermal/emp_act(severity) @@ -580,18 +588,21 @@ desc = "A pair of goggles meant for low temperatures." icon_state = "cold" inhand_icon_state = null + flags_cover = GLASSESCOVERSEYES /obj/item/clothing/glasses/heat name = "heat goggles" desc = "A pair of goggles meant for high temperatures." icon_state = "heat" inhand_icon_state = null + flags_cover = GLASSESCOVERSEYES /obj/item/clothing/glasses/orange name = "orange glasses" desc = "A sweet pair of orange shades." icon_state = "orangeglasses" inhand_icon_state = null + flags_cover = GLASSESCOVERSEYES glass_colour_type = /datum/client_colour/glass_colour/lightorange /obj/item/clothing/glasses/red @@ -599,6 +610,7 @@ desc = "Hey, you're looking good, senpai!" icon_state = "redglasses" inhand_icon_state = null + flags_cover = GLASSESCOVERSEYES glass_colour_type = /datum/client_colour/glass_colour/red /obj/item/clothing/glasses/geist_gazers @@ -606,12 +618,14 @@ icon_state = "geist_gazers" worn_icon_state = "geist_gazers" glass_colour_type = /datum/client_colour/glass_colour/green + flags_cover = GLASSESCOVERSEYES /obj/item/clothing/glasses/psych name = "psych glasses" icon_state = "psych_glasses" worn_icon_state = "psych_glasses" glass_colour_type = /datum/client_colour/glass_colour/red + flags_cover = GLASSESCOVERSEYES /obj/item/clothing/glasses/debug name = "debug glasses" @@ -672,6 +686,7 @@ desc = "A pair of glasses with uniquely colored lenses. The frame is inscribed with 'Best Salesman 1997'." icon_state = "salesman" inhand_icon_state = "salesman" + flags_cover = GLASSESCOVERSEYES ///Tells us who the current wearer([BIGSHOT]) is. var/mob/living/carbon/human/bigshot @@ -708,6 +723,7 @@ glass_colour_type = /datum/client_colour/glass_colour/nightmare forced_glass_color = TRUE lighting_cutoff = LIGHTING_CUTOFF_FULLBRIGHT + flags_cover = GLASSESCOVERSEYES /// Hallucination datum currently being used for seeing mares var/datum/hallucination/stored_hallucination @@ -740,9 +756,11 @@ desc = "There's no such thing as good news! Just bad news and... weird news.." icon_state = "osi_glasses" inhand_icon_state = null + flags_cover = GLASSESCOVERSEYES /obj/item/clothing/glasses/phantom name = "Phantom Thief Mask" desc = "Lookin' cool." icon_state = "phantom_glasses" inhand_icon_state = null + flags_cover = GLASSESCOVERSEYES diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index de42860e64a94..379c6ad0bc29b 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -70,6 +70,7 @@ icon_state = "healthhudnight" inhand_icon_state = "glasses" flash_protect = FLASH_PROTECTION_SENSITIVE + flags_cover = GLASSESCOVERSEYES // Blue green, dark color_cutoffs = list(5, 15, 30) glass_colour_type = /datum/client_colour/glass_colour/green @@ -90,6 +91,7 @@ desc = "Sunglasses with a medical HUD." icon_state = "sunhudmed" flash_protect = FLASH_PROTECTION_FLASH + flags_cover = GLASSESCOVERSEYES tint = 1 glass_colour_type = /datum/client_colour/glass_colour/blue @@ -116,6 +118,7 @@ icon_state = "diagnostichudnight" inhand_icon_state = "glasses" flash_protect = FLASH_PROTECTION_SENSITIVE + flags_cover = GLASSESCOVERSEYES // Pale yellow color_cutoffs = list(30, 20, 5) glass_colour_type = /datum/client_colour/glass_colour/green @@ -126,6 +129,7 @@ icon_state = "sunhuddiag" inhand_icon_state = "glasses" flash_protect = FLASH_PROTECTION_FLASH + flags_cover = GLASSESCOVERSEYES tint = 1 /obj/item/clothing/glasses/hud/diagnostic/sunglasses/Initialize(mapload) @@ -168,6 +172,7 @@ desc = "Sunglasses with a security HUD." icon_state = "sunhudsec" flash_protect = FLASH_PROTECTION_FLASH + flags_cover = GLASSESCOVERSEYES tint = 1 glass_colour_type = /datum/client_colour/glass_colour/darkred @@ -185,6 +190,7 @@ desc = "An advanced heads-up display that provides ID data and vision in complete darkness." icon_state = "securityhudnight" flash_protect = FLASH_PROTECTION_SENSITIVE + flags_cover = GLASSESCOVERSEYES // Red with a tint of green color_cutoffs = list(35, 5, 5) glass_colour_type = /datum/client_colour/glass_colour/green @@ -213,6 +219,7 @@ /obj/item/clothing/glasses/hud/toggle name = "Toggle HUD" desc = "A hud with multiple functions." + flags_cover = GLASSESCOVERSEYES actions_types = list(/datum/action/item_action/switch_hud) /obj/item/clothing/glasses/hud/toggle/attack_self(mob/user) @@ -278,6 +285,7 @@ desc = "For thinking you look cool while brutalizing protestors and minorities." icon_state = "bigsunglasses" flash_protect = FLASH_PROTECTION_FLASH + flags_cover = GLASSESCOVERSEYES tint = 1 glass_colour_type = /datum/client_colour/glass_colour/gray diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index 03da9cbffad29..2f9a7727d2fc0 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -215,35 +215,34 @@ if(BODY_ZONE_CHEST)//Listening to the chest user.visible_message(span_notice("[user] places [src] against [carbon_patient]'s [body_part] and listens attentively."), ignored_mobs = user) if(!user.can_hear()) - to_chat(user, span_notice("You place [src] against [carbon_patient]'s [body_part]. Fat load of good it does you though, since you can't hear")) + to_chat(user, span_notice("You place [src] against [carbon_patient]'s [body_part]. Fat load of good it does you though, since you can't hear.")) return else render_list += span_info("You place [src] against [carbon_patient]'s [body_part]:\n") //assess breathing - if(!lungs)//sanity check, enusure patient actually has lungs - render_list += "[M] doesn't have any lungs!\n" + if(isnull(lungs) \ + || carbon_patient.stat == DEAD \ + || (HAS_TRAIT(carbon_patient, TRAIT_FAKEDEATH)) \ + || (HAS_TRAIT(carbon_patient, TRAIT_NOBREATH))\ + || carbon_patient.failed_last_breath \ + || carbon_patient.losebreath)//If pt is dead or otherwise not breathing + render_list += "[M.p_Theyre()] not breathing!\n" + else if(lungs.damage > 10)//if breathing, check for lung damage + render_list += "You hear fluid in [M.p_their()] lungs!\n" + else if(oxy_loss > 10)//if they have suffocation damage + render_list += "[M.p_Theyre()] breathing heavily!\n" else - if(carbon_patient.stat == DEAD || (HAS_TRAIT(carbon_patient, TRAIT_FAKEDEATH)) || (HAS_TRAIT(carbon_patient, TRAIT_NOBREATH))|| carbon_patient.failed_last_breath || carbon_patient.losebreath)//If pt is dead or otherwise not breathing - render_list += "[M.p_Theyre()] not breathing!\n" - else if(lungs.damage > 10)//if breathing, check for lung damage - render_list += "You hear fluid in [M.p_their()] lungs!\n" - else if(oxy_loss > 10)//if they have suffocation damage - render_list += "[M.p_Theyre()] breathing heavily!\n" - else - render_list += "[M.p_Theyre()] breathing normally.\n"//they're okay :D + render_list += "[M.p_Theyre()] breathing normally.\n"//they're okay :D //assess heart if(body_part == BODY_ZONE_CHEST)//if we're listening to the chest - if(!heart)//sanity check, ensure the patient actually has a heart - render_list += "[M] doesn't have a heart!\n" + if(isnull(heart) || !heart.is_beating() || carbon_patient.stat == DEAD) + render_list += "You don't hear a heartbeat!\n"//they're dead or their heart isn't beating + else if(heart.damage > 10 || carbon_patient.blood_volume <= BLOOD_VOLUME_OKAY) + render_list += "You hear a weak heartbeat.\n"//their heart is damaged, or they have critical blood else - if(!heart.beating || carbon_patient.stat == DEAD) - render_list += "You don't hear a heartbeat!\n"//they're dead or their heart isn't beating - else if(heart.damage > 10 || carbon_patient.blood_volume <= BLOOD_VOLUME_OKAY) - render_list += "You hear a weak heartbeat.\n"//their heart is damaged, or they have critical blood - else - render_list += "You hear a healthy heartbeat.\n"//they're okay :D + render_list += "You hear a healthy heartbeat.\n"//they're okay :D if(BODY_ZONE_PRECISE_GROIN)//If we're targeting the groin render_list += span_info("You carefully press down on [carbon_patient]'s abdomen:\n") @@ -254,7 +253,7 @@ var/appendix_okay = TRUE var/liver_okay = TRUE if(!liver)//sanity check, ensure the patient actually has a liver - render_list += "[M] doesn't have a liver!\n" + render_list += "You can't feel anything where [M.p_their()] liver would be.\n" liver_okay = FALSE else if(liver.damage > 10) @@ -262,7 +261,7 @@ liver_okay = FALSE if(!appendix)//sanity check, ensure the patient actually has an appendix - render_list += "[M] doesn't have an appendix!\n" + render_list += "You can't feel anything where [M.p_their()] appendix would be.\n" appendix_okay = FALSE else if(appendix.damage > 10 && carbon_patient.stat == CONSCIOUS) @@ -290,23 +289,20 @@ user.visible_message(span_notice("[user] presses their fingers against [carbon_patient]'s [body_part]."), ignored_mobs = user) //assess pulse (heart & blood level) - if(!heart)//sanity check, ensure the patient actually has a heart - render_list += "[M] doesn't have a heart!\n" + if(isnull(heart) || !heart.is_beating() || carbon_patient.blood_volume <= BLOOD_VOLUME_OKAY || carbon_patient.stat == DEAD) + render_list += "You can't find a pulse!\n"//they're dead, their heart isn't beating, or they have critical blood else - if(!heart.beating || carbon_patient.blood_volume <= BLOOD_VOLUME_OKAY || carbon_patient.stat == DEAD) - render_list += "You can't find a pulse!\n"//they're dead, their heart isn't beating, or they have critical blood + if(heart.damage > 10) + heart_strength = span_danger("irregular")//their heart is damaged else - if(heart.damage > 10) - heart_strength = span_danger("irregular")//their heart is damaged - else - heart_strength = span_notice("regular")//they're okay :D + heart_strength = span_notice("regular")//they're okay :D - if(carbon_patient.blood_volume <= BLOOD_VOLUME_SAFE && carbon_patient.blood_volume > BLOOD_VOLUME_OKAY) - pulse_pressure = span_danger("thready")//low blood - else - pulse_pressure = span_notice("strong")//they're okay :D + if(carbon_patient.blood_volume <= BLOOD_VOLUME_SAFE && carbon_patient.blood_volume > BLOOD_VOLUME_OKAY) + pulse_pressure = span_danger("thready")//low blood + else + pulse_pressure = span_notice("strong")//they're okay :D - render_list += "[M.p_Their()] pulse is [pulse_pressure] and [heart_strength].\n" + render_list += "[M.p_Their()] pulse is [pulse_pressure] and [heart_strength].\n" //display our packaged information in an examine block for easy reading to_chat(user, examine_block(jointext(render_list, "")), type = MESSAGE_TYPE_INFO) diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm index 17ac11f76ece4..ecae343f68506 100644 --- a/code/modules/clothing/suits/_suits.dm +++ b/code/modules/clothing/suits/_suits.dm @@ -17,10 +17,6 @@ var/blood_overlay_type = "suit" limb_integrity = 0 // disabled for most exo-suits -/obj/item/clothing/suit/Initialize(mapload) - . = ..() - setup_shielding() - /obj/item/clothing/suit/worn_overlays(mutable_appearance/standing, isinhands = FALSE) . = ..() if(isinhands) @@ -47,12 +43,3 @@ if(ismob(loc)) var/mob/M = loc M.update_worn_oversuit() - -/** - * Wrapper proc to apply shielding through AddComponent(). - * Called in /obj/item/clothing/Initialize(). - * Override with an AddComponent(/datum/component/shielded, args) call containing the desired shield statistics. - * See /datum/component/shielded documentation for a description of the arguments - **/ -/obj/item/clothing/suit/proc/setup_shielding() - return diff --git a/code/modules/emote_panel/emote_panel.dm b/code/modules/emote_panel/emote_panel.dm new file mode 100644 index 0000000000000..72caf05e92b27 --- /dev/null +++ b/code/modules/emote_panel/emote_panel.dm @@ -0,0 +1,64 @@ +/datum/emote_panel + var/list/blacklisted_emotes = list("me", "help") + +/datum/emote_panel/ui_static_data(mob/user) + var/list/data = list() + + var/list/emotes = list() + var/list/keys = list() + + for(var/key in GLOB.emote_list) + for(var/datum/emote/emote in GLOB.emote_list[key]) + if(emote.key in keys) + continue + if(emote.key in blacklisted_emotes) + continue + if(emote.can_run_emote(user, status_check = FALSE, intentional = FALSE)) + keys += emote.key + emotes += list(list( + "key" = emote.key, + "name" = emote.name, + "hands" = emote.hands_use_check, + "visible" = emote.emote_type & EMOTE_VISIBLE, + "audible" = emote.emote_type & EMOTE_AUDIBLE, + "sound" = !isnull(emote.get_sound(user)), + "use_params" = emote.message_param, + )) + + data["emotes"] = emotes + + return data + +/datum/emote_panel/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + switch(action) + if("play_emote") + var/emote_key = params["emote_key"] + if(isnull(emote_key) || !GLOB.emote_list[emote_key]) + return + var/use_params = params["use_params"] + var/datum/emote/emote = GLOB.emote_list[emote_key][1] + var/emote_param + if(emote.message_param && use_params) + emote_param = tgui_input_text(ui.user, "Add params to the emote...", emote.message_param) + ui.user.emote(emote_key, message = emote_param, intentional = TRUE) + +/datum/emote_panel/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "EmotePanel") + ui.open() + +/datum/emote_panel/ui_state(mob/user) + return GLOB.always_state + +/mob/living/verb/emote_panel() + set name = "Emote Panel" + set category = "IC" + + var/static/datum/emote_panel/emote_panel + if(isnull(emote_panel)) + emote_panel = new + emote_panel.ui_interact(src) diff --git a/code/modules/events/wormholes.dm b/code/modules/events/wormholes.dm index b04f2a4f59582..7dcaf0861c3ff 100644 --- a/code/modules/events/wormholes.dm +++ b/code/modules/events/wormholes.dm @@ -54,6 +54,7 @@ GLOBAL_LIST_EMPTY(all_wormholes) // So we can pick wormholes to teleport to icon_state = "anom" mech_sized = TRUE light_on = FALSE + wibbles = FALSE /obj/effect/portal/wormhole/Initialize(mapload, _creator, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override) . = ..() diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm index 26b7693f4aa86..90fb2afc796b8 100644 --- a/code/modules/fishing/fish/_fish.dm +++ b/code/modules/fishing/fish/_fish.dm @@ -441,13 +441,13 @@ //Fish breeding stops if fish count exceeds this. #define AQUARIUM_MAX_BREEDING_POPULATION 20 -/obj/item/fish/proc/ready_to_reproduce(being_targetted = FALSE) +/obj/item/fish/proc/ready_to_reproduce(being_targeted = FALSE) var/obj/structure/aquarium/aquarium = loc if(!istype(aquarium)) return FALSE - if(being_targetted && HAS_TRAIT(src, TRAIT_FISH_NO_MATING)) + if(being_targeted && HAS_TRAIT(src, TRAIT_FISH_NO_MATING)) return FALSE - if(!being_targetted && length(aquarium.get_fishes()) >= AQUARIUM_MAX_BREEDING_POPULATION) + if(!being_targeted && length(aquarium.get_fishes()) >= AQUARIUM_MAX_BREEDING_POPULATION) return FALSE return aquarium.allow_breeding && health >= initial(health) * 0.8 && stable_population > 1 && world.time >= breeding_wait diff --git a/code/modules/food_and_drinks/machinery/icecream_vat.dm b/code/modules/food_and_drinks/machinery/icecream_vat.dm index 607c54e6ff19d..998ac0300b4b1 100644 --- a/code/modules/food_and_drinks/machinery/icecream_vat.dm +++ b/code/modules/food_and_drinks/machinery/icecream_vat.dm @@ -10,6 +10,7 @@ use_power = NO_POWER_USE layer = BELOW_OBJ_LAYER max_integrity = 300 + interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN|INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_OPEN_SILICON|INTERACT_MACHINE_SET_MACHINE var/list/product_types = list() var/selected_flavour = ICE_CREAM_VANILLA var/obj/item/reagent_containers/beaker @@ -110,7 +111,7 @@ return for(var/datum/reagent/R in beaker.reagents.reagent_list) if(R.type in icecream_vat_reagents) - beaker.reagents.trans_id_to(src, R.type, R.volume) + beaker.reagents.trans_to(src, R.volume, target_id = R.type) say("Internalizing reagent.") playsound(src, 'sound/items/drink.ogg', 25, TRUE) return diff --git a/code/modules/food_and_drinks/machinery/microwave.dm b/code/modules/food_and_drinks/machinery/microwave.dm index 10520e8f6c1c4..a95357ef2f0b9 100644 --- a/code/modules/food_and_drinks/machinery/microwave.dm +++ b/code/modules/food_and_drinks/machinery/microwave.dm @@ -516,7 +516,6 @@ if(isAI(user) && (machine_stat & NOPOWER)) return - user.set_machine(src) switch(choice) if("eject") eject() diff --git a/code/modules/food_and_drinks/machinery/smartfridge.dm b/code/modules/food_and_drinks/machinery/smartfridge.dm index 37018f7dd5b49..30b9cf84070d7 100644 --- a/code/modules/food_and_drinks/machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/machinery/smartfridge.dm @@ -17,8 +17,8 @@ var/base_build_path = /obj/machinery/smartfridge /// Maximum number of items that can be loaded into the machine var/max_n_of_items = 1500 - /// If the AI is allowed to retrieve items within the machine - var/allow_ai_retrieve = FALSE + /// The overlay for this fridge when it is filled with stuff + var/contents_icon_state = "plant" /// List of items that the machine starts with upon spawn var/list/initial_contents /// If the machine shows an approximate number of its contents on its sprite @@ -33,7 +33,7 @@ create_reagents(100, NO_REACT) air_update_turf(TRUE, TRUE) register_context() - if(mapload && !istype(src, /obj/machinery/smartfridge/drying_rack)) + if(mapload) welded_down = TRUE if(islist(initial_contents)) @@ -49,83 +49,115 @@ . = ..() move_update_air(old_loc) -/obj/machinery/smartfridge/can_be_unfasten_wrench(mob/user, silent) - if(welded_down) - to_chat(user, span_warning("[src] is welded to the floor!")) - return FAILED_UNFASTEN - return ..() - -/obj/machinery/smartfridge/set_anchored(anchorvalue) - . = ..() - if(!anchored && welded_down) //make sure they're keep in sync in case it was forcibly unanchored by badmins or by a megafauna. - welded_down = FALSE - can_atmos_pass = anchorvalue ? ATMOS_PASS_NO : ATMOS_PASS_YES - air_update_turf(TRUE, anchorvalue) - /obj/machinery/smartfridge/welder_act(mob/living/user, obj/item/tool) - ..() - if(istype(src, /obj/machinery/smartfridge/drying_rack)) - return FALSE + . = TOOL_ACT_TOOLTYPE_SUCCESS + if(welded_down) if(!tool.tool_start_check(user, amount=2)) - return TRUE + return + user.visible_message( span_notice("[user.name] starts to cut the [name] free from the floor."), span_notice("You start to cut [src] free from the floor..."), span_hear("You hear welding."), ) + if(!tool.use_tool(src, user, delay=100, volume=100)) - return FALSE + return + welded_down = FALSE to_chat(user, span_notice("You cut [src] free from the floor.")) - return TRUE + return + if(!anchored) - to_chat(user, span_warning("[src] needs to be wrenched to the floor!")) - return TRUE + balloon_alert(user, "wrench it first!") + return + if(!tool.tool_start_check(user, amount=2)) - return TRUE + return + user.visible_message( span_notice("[user.name] starts to weld the [name] to the floor."), span_notice("You start to weld [src] to the floor..."), span_hear("You hear welding."), ) - if(!tool.use_tool(src, user, delay=100, volume=100)) - balloon_alert(user, "cancelled!") - return FALSE + + if(!tool.use_tool(src, user, delay = 100, volume = 100)) + return + welded_down = TRUE to_chat(user, span_notice("You weld [src] to the floor.")) - return TRUE /obj/machinery/smartfridge/welder_act_secondary(mob/living/user, obj/item/tool) + . = TOOL_ACT_TOOLTYPE_SUCCESS + + if(!(machine_stat & BROKEN)) + balloon_alert(user, "no repair needed!") + return + + if(!tool.tool_start_check(user, amount=1)) + return + + user.visible_message( + span_notice("[user] is repairing [src]."), + span_notice("You begin repairing [src]..."), + span_hear("You hear welding."), + ) + + if(tool.use_tool(src, user, delay = 40, volume = 50)) + if(!(machine_stat & BROKEN)) + return + to_chat(user, span_notice("You repair [src]")) + atom_integrity = max_integrity + set_machine_stat(machine_stat & ~BROKEN) + update_icon() + +/obj/machinery/smartfridge/screwdriver_act(mob/living/user, obj/item/tool) + . = TOOL_ACT_TOOLTYPE_SUCCESS + + if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool)) + if(panel_open) + add_overlay("[initial(icon_state)]-panel") + else + cut_overlay("[initial(icon_state)]-panel") + SStgui.update_uis(src) + +/obj/machinery/smartfridge/can_be_unfasten_wrench(mob/user, silent) + if(welded_down) + balloon_alert(user, "unweld first!") + return FAILED_UNFASTEN + return ..() + +/obj/machinery/smartfridge/set_anchored(anchorvalue) . = ..() - if(istype(src, /obj/machinery/smartfridge/drying_rack)) - return FALSE - if(machine_stat & BROKEN) - if(!tool.tool_start_check(user, amount=1)) - return FALSE - user.visible_message( - span_notice("[user] is repairing [src]."), - span_notice("You begin repairing [src]..."), - span_hear("You hear welding."), - ) - if(tool.use_tool(src, user, delay=40, volume=50)) - if(!(machine_stat & BROKEN)) - return FALSE - balloon_alert(user, "repaired") - atom_integrity = max_integrity - set_machine_stat(machine_stat & ~BROKEN) - update_icon() - return TRUE + if(!anchored && welded_down) //make sure they're keep in sync in case it was forcibly unanchored by badmins or by a megafauna. + welded_down = FALSE + can_atmos_pass = anchorvalue ? ATMOS_PASS_NO : ATMOS_PASS_YES + air_update_turf(TRUE, anchorvalue) + +/obj/machinery/smartfridge/wrench_act(mob/living/user, obj/item/tool) + . = TOOL_ACT_TOOLTYPE_SUCCESS + + if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) + power_change() + +/obj/machinery/smartfridge/crowbar_act(mob/living/user, obj/item/tool) + . = TOOL_ACT_TOOLTYPE_SUCCESS + + if(default_pry_open(tool, close_after_pry = TRUE)) + return + + if(welded_down) + balloon_alert(user, "unweld first!") else - balloon_alert(user, "no repair needed!") - return FALSE + default_deconstruction_crowbar(tool) /obj/machinery/smartfridge/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) if(isnull(held_item)) return NONE var/tool_tip_set = FALSE - if(held_item.tool_behaviour == TOOL_WELDER && !istype(src, /obj/machinery/smartfridge/drying_rack)) + if(held_item.tool_behaviour == TOOL_WELDER) if(welded_down) context[SCREENTIP_CONTEXT_LMB] = "Unweld" tool_tip_set = TRUE @@ -136,6 +168,19 @@ context[SCREENTIP_CONTEXT_RMB] = "Repair" tool_tip_set = TRUE + else if(held_item.tool_behaviour == TOOL_SCREWDRIVER) + context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "close" : "open"] panel" + tool_tip_set = TRUE + + else if(held_item.tool_behaviour == TOOL_CROWBAR) + if(panel_open) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + tool_tip_set = TRUE + + else if(held_item.tool_behaviour == TOOL_WRENCH) + context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""]anchore" + tool_tip_set = TRUE + return tool_tip_set ? CONTEXTUAL_SCREENTIP_SET : NONE /obj/machinery/smartfridge/RefreshParts() @@ -149,19 +194,26 @@ if(in_range(user, src) || isobserver(user)) . += span_notice("The status display reads: This unit can hold a maximum of [max_n_of_items] items.") + . += structure_examine() + +/// Returns details related to the fridge structure +/obj/machinery/smartfridge/proc/structure_examine() + . = "" + if(welded_down) - . += span_info("It's moored firmly to the floor. You can unsecure its moorings with a welder.") - else if(anchored) - . += span_info("It's currently anchored to the floor. You can secure its moorings with a welder, or remove it with a wrench.") + . += span_info("It's moorings are firmly [EXAMINE_HINT("welded")] to the floor.") + else + . += span_info("It's moorings are loose and can be [EXAMINE_HINT("welded")] down.") + + if(anchored) + . += span_info("It is [EXAMINE_HINT("wrenched")] down on the floor.") else - . += span_info("It's not anchored to the floor. You can secure it in place with a wrench.") + . += span_info("It could be [EXAMINE_HINT("wrenched")] down.") /obj/machinery/smartfridge/update_appearance(updates=ALL) . = ..() - if(machine_stat & BROKEN) - set_light(0) - return - set_light(powered() ? MINIMUM_USEFUL_LIGHT_RANGE : 0) + + set_light((!(machine_stat & BROKEN) && powered()) ? MINIMUM_USEFUL_LIGHT_RANGE : 0) /obj/machinery/smartfridge/update_icon_state() icon_state = "[initial(icon_state)]" @@ -171,49 +223,33 @@ icon_state += "-off" return ..() +/// Returns the number of items visible in the fridge. Faster than subtracting 2 lists +/obj/machinery/smartfridge/proc/visible_items() + var/component_part_count = 0 + for(var/datum/stock_part/datum_part in component_parts) + component_part_count -= 1 + return contents.len - component_part_count + /obj/machinery/smartfridge/update_overlays() . = ..() - var/list/shown_contents = contents - component_parts - if(visible_contents && shown_contents.len > 0) - var/contents_icon_state = "[initial(icon_state)]" - switch(base_build_path) - if(/obj/machinery/smartfridge/extract) - contents_icon_state += "-slime" - if(/obj/machinery/smartfridge/food) - contents_icon_state += "-food" - if(/obj/machinery/smartfridge/drinks) - contents_icon_state += "-drink" - if(/obj/machinery/smartfridge/organ) - contents_icon_state += "-organ" - if(/obj/machinery/smartfridge/petri) - contents_icon_state += "-petri" - if(/obj/machinery/smartfridge/chemistry) - contents_icon_state += "-chem" - if(/obj/machinery/smartfridge/chemistry/virology) - contents_icon_state += "-viro" - else - contents_icon_state += "-plant" - switch(shown_contents.len) + var/shown_contents_length = visible_items() + if(visible_contents && shown_contents_length) + var/content_level = "[initial(icon_state)]-[contents_icon_state]" + switch(shown_contents_length) if(1 to 25) - contents_icon_state += "-1" + content_level += "-1" if(26 to 50) - contents_icon_state += "-2" + content_level += "-2" if(31 to INFINITY) - contents_icon_state += "-3" - . += mutable_appearance(icon, contents_icon_state) + content_level += "-3" + . += mutable_appearance(icon, content_level) . += mutable_appearance(icon, "[initial(icon_state)]-glass[(machine_stat & BROKEN) ? "-broken" : ""]") if(!machine_stat && has_emissive) . += emissive_appearance(icon, "[initial(icon_state)]-light-mask", src, alpha = src.alpha) -/obj/machinery/smartfridge/wrench_act(mob/living/user, obj/item/tool) - . = ..() - if(default_unfasten_wrench(user, tool)) - power_change() - return TOOL_ACT_TOOLTYPE_SUCCESS - /obj/machinery/smartfridge/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) switch(damage_type) if(BRUTE) @@ -225,101 +261,94 @@ playsound(src, SFX_SHATTER, 50, TRUE) return ..() -/******************* -* Item Adding -********************/ - -/obj/machinery/smartfridge/attackby(obj/item/O, mob/living/user, params) - if(default_deconstruction_screwdriver(user, icon_state, icon_state, O)) - if(panel_open) - add_overlay("[initial(icon_state)]-panel") - else - cut_overlay("[initial(icon_state)]-panel") - SStgui.update_uis(src) - return - - if(default_pry_open(O, close_after_pry = TRUE)) - return - - if(!welded_down && default_deconstruction_crowbar(O)) - SStgui.update_uis(src) - return - +/obj/machinery/smartfridge/attackby(obj/item/weapon, mob/living/user, params) if(!machine_stat) - var/list/shown_contents = contents - component_parts - if(shown_contents.len >= max_n_of_items) - to_chat(user, span_warning("\The [src] is full!")) + var/shown_contents_length = visible_items() + if(shown_contents_length >= max_n_of_items) + balloon_alert(user, "no space!") return FALSE - if(accept_check(O)) - load(O) - user.visible_message(span_notice("[user] adds \the [O] to \the [src]."), span_notice("You add \the [O] to \the [src].")) + if(!(weapon.item_flags & ABSTRACT) && \ + !(weapon.flags_1 & HOLOGRAM_1) && \ + accept_check(weapon) \ + ) + load(weapon) + user.visible_message(span_notice("[user] adds \the [weapon] to \the [src]."), span_notice("You add \the [weapon] to \the [src].")) SStgui.update_uis(src) if(visible_contents) update_appearance() return TRUE - if(istype(O, /obj/item/storage/bag)) - var/obj/item/storage/P = O + if(istype(weapon, /obj/item/storage/bag)) + var/obj/item/storage/bag = weapon var/loaded = 0 - for(var/obj/G in P.contents) - if(shown_contents.len >= max_n_of_items) + for(var/obj/item/object in bag.contents) + if(shown_contents_length >= max_n_of_items) break - if(accept_check(G)) - load(G) + if(!(object.item_flags & ABSTRACT) && \ + !(object.flags_1 & HOLOGRAM_1) && \ + accept_check(object) \ + ) + load(object) loaded++ SStgui.update_uis(src) if(loaded) - if(shown_contents.len >= max_n_of_items) - user.visible_message(span_notice("[user] loads \the [src] with \the [O]."), \ - span_notice("You fill \the [src] with \the [O].")) + if(shown_contents_length >= max_n_of_items) + user.visible_message(span_notice("[user] loads \the [src] with \the [weapon]."), \ + span_notice("You fill \the [src] with \the [weapon].")) else - user.visible_message(span_notice("[user] loads \the [src] with \the [O]."), \ - span_notice("You load \the [src] with \the [O].")) - if(O.contents.len > 0) + user.visible_message(span_notice("[user] loads \the [src] with \the [weapon]."), \ + span_notice("You load \the [src] with \the [weapon].")) + if(weapon.contents.len) to_chat(user, span_warning("Some items are refused.")) if (visible_contents) update_appearance() return TRUE else - to_chat(user, span_warning("There is nothing in [O] to put in [src]!")) + to_chat(user, span_warning("There is nothing in [weapon] to put in [src]!")) return FALSE if(!user.combat_mode) - to_chat(user, span_warning("\The [src] smartly refuses [O].")) - SStgui.update_uis(src) + to_chat(user, span_warning("\The [src] smartly refuses [weapon].")) return FALSE + else return ..() -/obj/machinery/smartfridge/proc/accept_check(obj/item/O) - if(istype(O, /obj/item/food/grown/) || istype(O, /obj/item/seeds/) || istype(O, /obj/item/grown/) || istype(O, /obj/item/graft/)) - return TRUE - return FALSE - -/obj/machinery/smartfridge/proc/load(obj/item/O) - if(ismob(O.loc)) - var/mob/M = O.loc - if(!M.transferItemToLoc(O, src)) - to_chat(usr, span_warning("\the [O] is stuck to your hand, you cannot put it in \the [src]!")) +/** + * Can this item be accepted by the smart fridge + * Arguments + * * [weapon][obj/item] - the item to accept + */ +/obj/machinery/smartfridge/proc/accept_check(obj/item/weapon) + var/static/list/accepted_items = list( + /obj/item/food/grown, + /obj/item/seeds, + /obj/item/grown, + /obj/item/graft, + ) + return is_type_in_list(weapon, accepted_items) + +/** + * Loads the item into the smart fridge + * Arguments + * * [weapon][obj/item] - the item to load. If the item is being held by a mo it will transfer it from hand else directly force move + */ +/obj/machinery/smartfridge/proc/load(obj/item/weapon) + if(ismob(weapon.loc)) + var/mob/owner = weapon.loc + if(!owner.transferItemToLoc(weapon, src)) + to_chat(usr, span_warning("\the [weapon] is stuck to your hand, you cannot put it in \the [src]!")) return FALSE - else - return TRUE + return TRUE else - if(O.loc.atom_storage) - return O.loc.atom_storage.attempt_remove(O, src, silent = TRUE) + if(weapon.loc.atom_storage) + return weapon.loc.atom_storage.attempt_remove(weapon, src, silent = TRUE) else - O.forceMove(src) + weapon.forceMove(src) return TRUE -///Really simple proc, just moves the object "O" into the hands of mob "M" if able, done so I could modify the proc a little for the organ fridge -/obj/machinery/smartfridge/proc/dispense(obj/item/O, mob/M) - if(!M.put_in_hands(O)) - O.forceMove(drop_location()) - adjust_item_drop_location(O) - use_power(active_power_usage) - /obj/machinery/smartfridge/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) @@ -331,18 +360,18 @@ . = list() var/listofitems = list() - for (var/I in src) + for (var/item in src) // We do not vend our own components. - if(I in component_parts) + if(item in component_parts) continue - var/atom/movable/O = I - if (!QDELETED(O)) - var/md5name = md5(O.name) // This needs to happen because of a bug in a TGUI component, https://github.com/ractivejs/ractive/issues/744 + var/atom/movable/atom = item + if (!QDELETED(atom)) + var/md5name = md5(atom.name) // This needs to happen because of a bug in a TGUI component, https://github.com/ractivejs/ractive/issues/744 if (listofitems[md5name]) // which is fixed in a version we cannot use due to ie8 incompatibility listofitems[md5name]["amount"]++ // The good news is, #30519 made smartfridge UIs non-auto-updating else - listofitems[md5name] = list("name" = O.name, "type" = O.type, "amount" = 1) + listofitems[md5name] = list("name" = atom.name, "amount" = 1) sort_list(listofitems) .["contents"] = listofitems @@ -353,27 +382,28 @@ . = ..() SStgui.update_uis(src) -/obj/machinery/smartfridge/ui_act(action, params) +/obj/machinery/smartfridge/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() - if(.) + if(. || !ui.user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return + + . = TRUE + var/mob/living_mob = ui.user + switch(action) if("Release") var/desired = 0 - if(!allow_ai_retrieve && isAI(usr)) - to_chat(usr, span_warning("[src] does not seem to be configured to respect your authority!")) + if(isAI(living_mob)) + to_chat(living_mob, span_warning("[src] does not respect your authority!")) return if (params["amount"]) desired = text2num(params["amount"]) else - desired = tgui_input_number(usr, "How many items would you like to take out?", "Release", max_value = 50) + desired = tgui_input_number(living_mob, "How many items would you like to take out?", "Release", max_value = 50) if(!desired) - return FALSE - - if(QDELETED(src) || QDELETED(usr) || !usr.can_perform_action(src, FORBID_TELEKINESIS_REACH)) // Sanity checkin' in case stupid stuff happens while we wait for input() - return FALSE + return for(var/obj/item/dispensed_item in src) if(desired <= 0) @@ -384,12 +414,16 @@ if(format_text(dispensed_item.name) == format_text(params["name"])) if(dispensed_item in component_parts) CRASH("Attempted removal of [dispensed_item] component_part from smartfridge via smartfridge interface.") - dispense(dispensed_item, usr) + //dispense the item + if(!living_mob.put_in_hands(dispensed_item)) + dispensed_item.forceMove(drop_location()) + adjust_item_drop_location(dispensed_item) + use_power(active_power_usage) desired-- if (visible_contents) update_appearance() - return TRUE + return return FALSE @@ -408,48 +442,72 @@ idle_power_usage = 0 has_emissive = FALSE can_atmos_pass = ATMOS_PASS_YES + /// Is the rack currently drying stuff var/drying = FALSE -/obj/machinery/smartfridge/drying_rack/on_deconstruction() - new /obj/item/stack/sheet/mineral/wood(drop_location(), 10) +/obj/machinery/smartfridge/drying_rack/Initialize(mapload) + . = ..() - //remove all component parts inherited from smartfridge cause they were not required in crafting - var/obj/item/circuitboard/machine/smartfridge/board = locate() in component_parts - component_parts -= board - qdel(board) - component_parts.Cut() + //you can't weld down wood + welded_down = FALSE - return ..() + //so we don't drop any of the parent smart fridge parts upon deconstruction + clear_components() +/// We cleared out the components in initialize so we can optimize this +/obj/machinery/smartfridge/drying_rack/visible_items() + return contents.len + +/obj/machinery/smartfridge/drying_rack/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) + if(isnull(held_item)) + return NONE + + var/tool_tip_set = FALSE + if(held_item.tool_behaviour == TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + tool_tip_set = TRUE + else if(held_item.tool_behaviour == TOOL_WRENCH) + context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""]anchore" + tool_tip_set = TRUE + + return tool_tip_set ? CONTEXTUAL_SCREENTIP_SET : NONE + +/obj/machinery/smartfridge/drying_rack/structure_examine() + . = "" + if(anchored) + . += span_info("It's currently anchored to the floor. It can be [EXAMINE_HINT("wrenched")] loose.") + else + . += span_info("It's not anchored to the floor. It can be [EXAMINE_HINT("wrenched")] down.") + . += span_info("The whole rack can be [EXAMINE_HINT("pried")] apart.") +/obj/machinery/smartfridge/drying_rack/welder_act(mob/living/user, obj/item/tool) +/obj/machinery/smartfridge/drying_rack/welder_act_secondary(mob/living/user, obj/item/tool) /obj/machinery/smartfridge/drying_rack/default_deconstruction_screwdriver() /obj/machinery/smartfridge/drying_rack/exchange_parts() -/obj/machinery/smartfridge/drying_rack/spawn_frame() +/obj/machinery/smartfridge/drying_rack/on_deconstruction() + new /obj/item/stack/sheet/mineral/wood(drop_location(), 10) +/obj/machinery/smartfridge/drying_rack/crowbar_act(mob/living/user, obj/item/tool) + . = TOOL_ACT_TOOLTYPE_SUCCESS -/obj/machinery/smartfridge/drying_rack/default_deconstruction_crowbar(obj/item/crowbar/C, ignore_panel = 1) - ..() + default_deconstruction_crowbar(tool, ignore_panel = TRUE) /obj/machinery/smartfridge/drying_rack/ui_data(mob/user) . = ..() .["isdryer"] = TRUE - .["verb"] = "Take" .["drying"] = drying - /obj/machinery/smartfridge/drying_rack/ui_act(action, params) . = ..() if(.) update_appearance() // This is to handle a case where the last item is taken out manually instead of through drying pop-out return + switch(action) if("Dry") toggle_drying(FALSE) return TRUE - return FALSE /obj/machinery/smartfridge/drying_rack/powered() - if(!anchored) - return FALSE - return ..() + return !anchored ? FALSE : ..() /obj/machinery/smartfridge/drying_rack/power_change() . = ..() @@ -464,12 +522,10 @@ . = ..() if(drying) . += "drying_rack_drying" - var/list/shown_contents = contents - component_parts - if(shown_contents.len) + if(contents.len) . += "drying_rack_filled" /obj/machinery/smartfridge/drying_rack/process() - ..() if(drying) for(var/obj/item/item_iterator in src) if(!accept_check(item_iterator)) @@ -481,10 +537,13 @@ use_power(active_power_usage) /obj/machinery/smartfridge/drying_rack/accept_check(obj/item/O) - if(HAS_TRAIT(O, TRAIT_DRYABLE)) //set on dryable element - return TRUE - return FALSE + return HAS_TRAIT(O, TRAIT_DRYABLE) +/** + * Toggles drying on or off + * Arguments + * * forceoff - if TRUE will force the dryer off always + */ /obj/machinery/smartfridge/drying_rack/proc/toggle_drying(forceoff) if(drying || forceoff) drying = FALSE @@ -503,7 +562,6 @@ return atmos_spawn_air("[TURF_TEMPERATURE(1000)]") - // ---------------------------- // Bar drink smartfridge // ---------------------------- @@ -511,12 +569,19 @@ name = "drink showcase" desc = "A refrigerated storage unit for tasty tasty alcohol." base_build_path = /obj/machinery/smartfridge/drinks + contents_icon_state = "drink" -/obj/machinery/smartfridge/drinks/accept_check(obj/item/O) - if(!is_reagent_container(O) || (O.item_flags & ABSTRACT) || istype(O,/obj/item/reagent_containers/cup/bowl) || !O.reagents || !O.reagents.reagent_list.len) +/obj/machinery/smartfridge/drinks/accept_check(obj/item/weapon) + //not an item or valid container + if(!is_reagent_container(weapon)) return FALSE - if(istype(O, /obj/item/reagent_containers/cup) || istype(O, /obj/item/reagent_containers/cup/glass) || istype(O, /obj/item/reagent_containers/condiment)) - return TRUE + + //an bowl or something that has no reagents + if(istype(weapon,/obj/item/reagent_containers/cup/bowl) || !length(weapon.reagents?.reagent_list)) + return FALSE + + //list of items acceptable + return (istype(weapon, /obj/item/reagent_containers/cup) || istype(weapon, /obj/item/reagent_containers/condiment)) // ---------------------------- // Food smartfridge @@ -524,11 +589,10 @@ /obj/machinery/smartfridge/food desc = "A refrigerated storage unit for food." base_build_path = /obj/machinery/smartfridge/food + contents_icon_state = "food" -/obj/machinery/smartfridge/food/accept_check(obj/item/O) - if(IS_EDIBLE(O) || (istype(O,/obj/item/reagent_containers/cup/bowl) && O.reagents && O.reagents.reagent_list.len)) - return TRUE - return FALSE +/obj/machinery/smartfridge/food/accept_check(obj/item/weapon) + return (IS_EDIBLE(weapon) || (istype(weapon,/obj/item/reagent_containers/cup/bowl) && length(weapon.reagents?.reagent_list))) // ------------------------------------- // Xenobiology Slime-Extract Smartfridge @@ -537,13 +601,10 @@ name = "smart slime extract storage" desc = "A refrigerated storage unit for slime extracts." base_build_path = /obj/machinery/smartfridge/extract + contents_icon_state = "slime" -/obj/machinery/smartfridge/extract/accept_check(obj/item/O) - if(istype(O, /obj/item/slime_extract)) - return TRUE - if(istype(O, /obj/item/slime_scanner)) - return TRUE - return FALSE +/obj/machinery/smartfridge/extract/accept_check(obj/item/weapon) + return (istype(weapon, /obj/item/slime_extract) || istype(weapon, /obj/item/slime_scanner)) /obj/machinery/smartfridge/extract/preloaded initial_contents = list(/obj/item/slime_scanner = 2) @@ -555,11 +616,10 @@ name = "smart petri dish storage" desc = "A refrigerated storage unit for petri dishes." base_build_path = /obj/machinery/smartfridge/petri + contents_icon_state = "petri" -/obj/machinery/smartfridge/petri/accept_check(obj/item/O) - if(istype(O, /obj/item/petri_dish)) - return TRUE - return FALSE +/obj/machinery/smartfridge/petri/accept_check(obj/item/weapon) + return istype(weapon, /obj/item/petri_dish) /obj/machinery/smartfridge/petri/preloaded initial_contents = list(/obj/item/petri_dish = 5) @@ -572,20 +632,22 @@ desc = "A refrigerated storage unit for organ storage." max_n_of_items = 20 //vastly lower to prevent processing too long base_build_path = /obj/machinery/smartfridge/organ + contents_icon_state = "organ" + /// The rate at which this fridge will repair damaged organs var/repair_rate = 0 /obj/machinery/smartfridge/organ/accept_check(obj/item/O) - if(isorgan(O) || isbodypart(O)) - return TRUE - return FALSE + return (isorgan(O) || isbodypart(O)) /obj/machinery/smartfridge/organ/load(obj/item/O) . = ..() if(!.) //if the item loads, clear can_decompose return + if(isorgan(O)) var/obj/item/organ/organ = O organ.organ_flags |= ORGAN_FROZEN + if(isbodypart(O)) var/obj/item/bodypart/bodypart = O for(var/obj/item/organ/stored in bodypart.contents) @@ -606,9 +668,11 @@ /obj/machinery/smartfridge/organ/Exited(atom/movable/gone, direction) . = ..() + if(isorgan(gone)) var/obj/item/organ/O = gone O.organ_flags &= ~ORGAN_FROZEN + if(isbodypart(gone)) var/obj/item/bodypart/bodypart = gone for(var/obj/item/organ/stored in bodypart.contents) @@ -621,8 +685,31 @@ name = "smart chemical storage" desc = "A refrigerated storage unit for medicine storage." base_build_path = /obj/machinery/smartfridge/chemistry + contents_icon_state = "chem" + +/obj/machinery/smartfridge/chemistry/accept_check(obj/item/weapon) + // not an item or reagent container + if(!is_reagent_container(weapon)) + return FALSE + + // empty pill prank ok + if(istype(weapon, /obj/item/reagent_containers/pill)) + return TRUE + + //check each pill in the pill bottle + if(istype(weapon, /obj/item/storage/pill_bottle)) + if(weapon.contents.len) + for(var/obj/item/target_item in weapon) + if(!accept_check(target_item)) + return FALSE + return TRUE + return FALSE -/obj/machinery/smartfridge/chemistry/accept_check(obj/item/O) + // other empty containers not accepted + if(!length(weapon.reagents?.reagent_list)) + return FALSE + + // the long list of other containers that can be accepted var/static/list/chemfridge_typecache = typecacheof(list( /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/cup/tube, @@ -632,23 +719,7 @@ /obj/item/reagent_containers/medigel, /obj/item/reagent_containers/chem_pack )) - - if(istype(O, /obj/item/storage/pill_bottle)) - if(O.contents.len) - for(var/obj/item/I in O) - if(!accept_check(I)) - return FALSE - return TRUE - return FALSE - if(!is_reagent_container(O) || (O.item_flags & ABSTRACT)) - return FALSE - if(istype(O, /obj/item/reagent_containers/pill)) // empty pill prank ok - return TRUE - if(!O.reagents || !O.reagents.reagent_list.len) // other empty containers not accepted - return FALSE - if(is_type_in_typecache(O, chemfridge_typecache)) - return TRUE - return FALSE + return is_type_in_typecache(weapon, chemfridge_typecache) /obj/machinery/smartfridge/chemistry/preloaded initial_contents = list( @@ -664,6 +735,7 @@ name = "smart virus storage" desc = "A refrigerated storage unit for volatile sample storage." base_build_path = /obj/machinery/smartfridge/chemistry/virology + contents_icon_state = "viro" /obj/machinery/smartfridge/chemistry/virology/preloaded initial_contents = list( @@ -690,8 +762,5 @@ visible_contents = FALSE base_build_path = /obj/machinery/smartfridge/disks -/obj/machinery/smartfridge/disks/accept_check(obj/item/O) - if(istype(O, /obj/item/disk/)) - return TRUE - else - return FALSE +/obj/machinery/smartfridge/disks/accept_check(obj/item/weapon) + return istype(weapon, /obj/item/disk) diff --git a/code/modules/food_and_drinks/restaurant/custom_order.dm b/code/modules/food_and_drinks/restaurant/custom_order.dm index d87797b25780d..ac819e4debf1f 100644 --- a/code/modules/food_and_drinks/restaurant/custom_order.dm +++ b/code/modules/food_and_drinks/restaurant/custom_order.dm @@ -171,7 +171,8 @@ var/datum/reagents/holder = object_used.reagents // The container must be majority reagent - if(holder.get_master_reagent_id() != reagent_type) + var/datum/reagent/master_reagent = holder.get_master_reagent() + if(master_reagent?.type != reagent_type) return FALSE // We must fulfill the sample size threshold if(reagents_needed > holder.total_volume) diff --git a/code/modules/hallucination/hazard.dm b/code/modules/hallucination/hazard.dm index 7209087d4be09..1dfdfd23970e7 100644 --- a/code/modules/hallucination/hazard.dm +++ b/code/modules/hallucination/hazard.dm @@ -86,6 +86,10 @@ image_state = "flux" image_layer = OBJ_LAYER + 0.01 +/obj/effect/client_image_holder/hallucination/danger/anomaly/generate_image() + . = ..() + apply_wibbly_filters(.) + /obj/effect/client_image_holder/hallucination/danger/anomaly/Initialize(mapload, list/mobs_which_see_us, datum/hallucination/parent) . = ..() START_PROCESSING(SSobj, src) diff --git a/code/modules/hallucination/mother.dm b/code/modules/hallucination/mother.dm index bc2b312cc0b80..d9cd7f1983119 100644 --- a/code/modules/hallucination/mother.dm +++ b/code/modules/hallucination/mother.dm @@ -18,9 +18,9 @@ point_at(hallucinator) talk("[capitalize(hallucinator.real_name)]!!!!") // Your mother won't be fooled by paltry disguises var/list/scold_lines = list( - pick(list("CLEAN YOUR ROOM THIS INSTANT!", "IT'S TIME TO WAKE UP FOR SCHOOL!!")), - pick(list("YOU INSULT YOUR GRANDPARENTS!", "USELESS!")), - pick(list("I BROUGHT YOU INTO THIS WORLD, I CAN TAKE YOU OUT!!!", "YOU'RE GROUNDED!!")), + pick_list_replacements(MOTHER_FILE, "do_something"), + pick_list_replacements(MOTHER_FILE, "be_upset"), + pick_list_replacements(MOTHER_FILE, "get_reprimanded"), ) var/delay = 2 SECONDS for(var/line in scold_lines) diff --git a/code/modules/holiday/holidays.dm b/code/modules/holiday/holidays.dm index 035f44ae11d26..8c62144dfc5e2 100644 --- a/code/modules/holiday/holidays.dm +++ b/code/modules/holiday/holidays.dm @@ -627,6 +627,9 @@ begin_day = 11 holiday_hat = /obj/item/food/grown/poppy +/datum/holiday/remembrance_day/greet() + return "Lest we forget." + /datum/holiday/remembrance_day/getStationPrefix() return pick("Peace", "Armistice", "Poppy") diff --git a/code/modules/hydroponics/biogenerator.dm b/code/modules/hydroponics/biogenerator.dm index 1f2951b33566e..6725624973209 100644 --- a/code/modules/hydroponics/biogenerator.dm +++ b/code/modules/hydroponics/biogenerator.dm @@ -315,6 +315,11 @@ if(!food_to_convert) break + if(food_to_convert.flags_1 & HOLOGRAM_1) + qdel(food_to_convert) + current_item_count = max(current_item_count - 1, 0) + continue + convert_to_biomass(food_to_convert) use_power(active_power_usage * seconds_per_tick) diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index 98569f7e24811..b872fc0ec37c0 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -148,7 +148,7 @@ var/average_purity = reagents.get_average_purity() var/total_nutriment_amount = reagents.get_reagent_amount(/datum/reagent/consumable/nutriment, include_subtypes = TRUE) var/single_reagent_amount = grind_results_num > 1 ? round(total_nutriment_amount / grind_results_num, CHEMICAL_QUANTISATION_LEVEL) : total_nutriment_amount - reagents.remove_all_type(/datum/reagent/consumable/nutriment, total_nutriment_amount) + reagents.remove_reagent(/datum/reagent/consumable/nutriment, total_nutriment_amount, include_subtypes = TRUE) for(var/reagent in grind_results) reagents.add_reagent(reagent, single_reagent_amount, added_purity = average_purity) diff --git a/code/modules/hydroponics/grown/beans.dm b/code/modules/hydroponics/grown/beans.dm index a4c03cf6b53b1..fb82737711404 100644 --- a/code/modules/hydroponics/grown/beans.dm +++ b/code/modules/hydroponics/grown/beans.dm @@ -14,7 +14,7 @@ icon_grow = "soybean-grow" icon_dead = "soybean-dead" genes = list(/datum/plant_gene/trait/repeated_harvest) - mutatelist = list(/obj/item/seeds/soya/koi) + mutatelist = list(/obj/item/seeds/soya/koi, /obj/item/seeds/soya/butter) reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.05, /datum/reagent/consumable/nutriment/fat/oil = 0.03) //Vegetable oil! /obj/item/food/grown/soybeans @@ -26,7 +26,7 @@ foodtypes = VEGETABLES grind_results = list(/datum/reagent/consumable/soymilk = 0) tastes = list("soy" = 1) - wine_power = 20 + distill_reagent = /datum/reagent/consumable/soysauce // Koibean /obj/item/seeds/soya/koi @@ -50,6 +50,38 @@ tastes = list("koi" = 1) wine_power = 40 +//Butterbeans, the beans wid da butta! +// Butterbeans! - Squeeze for a single butter slice! +/obj/item/seeds/soya/butter + name = "pack of butterbean seeds" + desc = "These seeds grow into butterbean plants." + icon_state = "seed-butterbean" + species = "butterbean" + plantname = "butterbean Plants" + product = /obj/item/food/grown/butterbeans + potency = 10 + mutatelist = null + reagents_add = list(/datum/reagent/consumable/milk = 0.05, /datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/cream = 0.05) + rarity = 20 + +/obj/item/food/grown/butterbeans + seed = /obj/item/seeds/soya/butter + name = "butterbean" + desc = "Soft, creamy and milky... You could almost smear them over toast." + icon_state = "butterbeans" + foodtypes = VEGETABLES | DAIRY + tastes = list("creamy butter" = 1) + distill_reagent = /datum/reagent/consumable/yoghurt + +/obj/item/food/grown/butterbeans/attack_self(mob/living/user) + user.visible_message(span_notice("[user] crushes [src] into a pat of butter."), span_notice("You crush [src] into something that resembles butter.")) + playsound(user, 'sound/effects/blobattack.ogg', 50, TRUE) + var/obj/item/food/butterslice/butties = new(null) + butties.reagents.set_all_reagents_purity(seed.get_reagent_purity()) + qdel(src) + user.put_in_hands(butties) + return TRUE + // Green Beans /obj/item/seeds/greenbean name = "pack of green bean seeds" diff --git a/code/modules/hydroponics/grown/corn.dm b/code/modules/hydroponics/grown/corn.dm index 1b3a7979cf058..8eab962d75118 100644 --- a/code/modules/hydroponics/grown/corn.dm +++ b/code/modules/hydroponics/grown/corn.dm @@ -13,7 +13,7 @@ growing_icon = 'icons/obj/service/hydroponics/growing_vegetables.dmi' icon_grow = "corn-grow" // Uses one growth icons set for all the subtypes icon_dead = "corn-dead" // Same for the dead icon - mutatelist = list(/obj/item/seeds/corn/snapcorn) + mutatelist = list(/obj/item/seeds/corn/snapcorn, /obj/item/seeds/corn/pepper) reagents_add = list(/datum/reagent/consumable/nutriment/fat/oil/corn = 0.2, /datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1) /obj/item/food/grown/corn @@ -97,3 +97,29 @@ seed = /obj/item/seeds/corn/snapcorn name = "snap corn cob" desc = "A reminder of pranks gone by." + +//Pepper-corn - Heh funny. +/obj/item/seeds/corn/pepper + name = "pack of pepper-corn seeds" + desc = "If Peter picked a pack of pepper-corn..." + icon_state = "seed-peppercorn" + species = "peppercorn" + plantname = "Pepper-Corn Stalks" + product = /obj/item/food/grown/peppercorn + mutatelist = null + reagents_add = list(/datum/reagent/consumable/blackpepper = 0.2, /datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1) + +/obj/item/food/grown/peppercorn + seed = /obj/item/seeds/corn/pepper + name = "ear of pepper-peppercorn" + desc = "This dusty monster needs god..." + icon_state = "peppercorn" + trash_type = /obj/item/grown/corncob/pepper + foodtypes = VEGETABLES + grind_results = list(/datum/reagent/consumable/blackpepper = 0) + tastes = list("pepper" = 1, "sneezing" = 1) + +/obj/item/grown/corncob/pepper + seed = /obj/item/seeds/corn/pepper + name = "pepper corn cob" + desc = "A reminder of genetic abominations gone by." diff --git a/code/modules/hydroponics/grown/root.dm b/code/modules/hydroponics/grown/root.dm index df37e3bf2b791..da2bb3f5d68f0 100644 --- a/code/modules/hydroponics/grown/root.dm +++ b/code/modules/hydroponics/grown/root.dm @@ -27,11 +27,17 @@ /obj/item/food/grown/carrot/attackby(obj/item/I, mob/user, params) if(I.get_sharpness()) - to_chat(user, span_notice("You sharpen the carrot into a shiv with [I].")) - var/obj/item/knife/shiv/carrot/Shiv = new /obj/item/knife/shiv/carrot + var/carrot_blade + var/carrot_sword_chance = (max(0, seed.potency - 50) / 50) + if (prob(carrot_sword_chance)) + carrot_blade = new /obj/item/claymore/carrot + to_chat(user, span_notice("You sharpen the carrot into a sword with [I].")) + else + carrot_blade = new /obj/item/knife/shiv/carrot + to_chat(user, span_notice("You sharpen the carrot into a shiv with [I].")) remove_item_from_storage(user) qdel(src) - user.put_in_hands(Shiv) + user.put_in_hands(carrot_blade) else return ..() diff --git a/code/modules/hydroponics/grown/sugarcane.dm b/code/modules/hydroponics/grown/sugarcane.dm index 9a1646443dcd1..be2214ca1d048 100644 --- a/code/modules/hydroponics/grown/sugarcane.dm +++ b/code/modules/hydroponics/grown/sugarcane.dm @@ -15,7 +15,7 @@ instability = 15 growthstages = 2 reagents_add = list(/datum/reagent/consumable/nutriment = 0.04, /datum/reagent/consumable/sugar = 0.25) - mutatelist = list(/obj/item/seeds/bamboo) + mutatelist = list(/obj/item/seeds/bamboo, /obj/item/seeds/sugarcane/saltcane) /obj/item/food/grown/sugarcane seed = /obj/item/seeds/sugarcane @@ -56,3 +56,25 @@ /obj/item/grown/log/bamboo/CheckAccepted(obj/item/I) return FALSE + +//Saltcane - Gross, salty shafts! +/obj/item/seeds/sugarcane/saltcane + name = "pack of saltcane seeds" + desc = "These seeds grow into saltcane." + icon_state = "seed-saltcane" + species = "saltcane" + plantname = "Saltcane" + product = /obj/item/food/grown/sugarcane/saltcane + genes = list(/datum/plant_gene/trait/repeated_harvest) + reagents_add = list(/datum/reagent/consumable/nutriment = 0.04, /datum/reagent/consumable/salt = 0.25) + mutatelist = null + +/obj/item/food/grown/sugarcane/saltcane + seed = /obj/item/seeds/sugarcane/saltcane + name = "saltcane" + desc = "Ungodly salty, bane of slugs, treasure of horses." + icon_state = "saltcane" + foodtypes = VEGETABLES | GROSS + +/obj/item/food/grown/sugarcane/saltcane/make_dryable() + AddElement(/datum/element/dryable, /obj/item/food/seaweedsheet/saltcane) //soooshi diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 7e82310991cc5..8f47fb3bed130 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -253,7 +253,7 @@ // Move the leaked water from nutrients to... water var/leaking_water_amount = nutri_reagents.get_reagent_amount(/datum/reagent/water) if(leaking_water_amount) - nutri_reagents.trans_id_to(water_reagents, /datum/reagent/water, leaking_water_amount) + nutri_reagents.trans_to(water_reagents, leaking_water_amount, target_id = /datum/reagent/water) // We should only take MACHINE_REAGENT_TRANSFER every tick; this is the remaining amount we can take var/remaining_transfer_amount = max(MACHINE_REAGENT_TRANSFER - (nutri_reagents.total_volume - initial_nutri_amount), 0) @@ -887,7 +887,7 @@ if(istype(not_water_reagent,/datum/reagent/water)) continue var/transfer_me_to_tray = reagent_source.reagents.get_reagent_amount(not_water_reagent.type) * transfer_amount / reagent_source.reagents.total_volume - reagent_source.reagents.trans_id_to(H.reagents, not_water_reagent.type, transfer_me_to_tray) + reagent_source.reagents.trans_to(H.reagents, transfer_me_to_tray, target_id = not_water_reagent.type) else reagent_source.reagents.trans_to(H.reagents, transfer_amount, transferred_by = user) lastuser = WEAKREF(user) diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index 3a399c872162b..d079323e3a9c9 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -292,14 +292,14 @@ // Heats up the plant's contents by 25 kelvin per 1 unit of nutriment. Mutually exclusive with cooling. if(get_gene(/datum/plant_gene/trait/chem_heating)) T.visible_message(span_notice("[T] releases freezing air, consuming its nutriments to heat its contents.")) - T.reagents.remove_all_type(/datum/reagent/consumable/nutriment, num_nutriment, strict = TRUE) + T.reagents.remove_reagent(/datum/reagent/consumable/nutriment, num_nutriment) T.reagents.chem_temp = min(1000, (T.reagents.chem_temp + num_nutriment * 25)) T.reagents.handle_reactions() playsound(T.loc, 'sound/effects/wounds/sizzle2.ogg', 5) // Cools down the plant's contents by 5 kelvin per 1 unit of nutriment. Mutually exclusive with heating. else if(get_gene(/datum/plant_gene/trait/chem_cooling)) T.visible_message(span_notice("[T] releases a blast of hot air, consuming its nutriments to cool its contents.")) - T.reagents.remove_all_type(/datum/reagent/consumable/nutriment, num_nutriment, strict = TRUE) + T.reagents.remove_reagent(/datum/reagent/consumable/nutriment, num_nutriment) T.reagents.chem_temp = max(3, (T.reagents.chem_temp + num_nutriment * -5)) T.reagents.handle_reactions() playsound(T.loc, 'sound/effects/space_wind.ogg', 50) diff --git a/code/modules/library/book.dm b/code/modules/library/book.dm index e706872c710f7..19b65f82489ea 100644 --- a/code/modules/library/book.dm +++ b/code/modules/library/book.dm @@ -21,8 +21,6 @@ /// whether or not we have been carved out var/carved = FALSE - /// Specific window size for the book, i.e: "1920x1080", Size x Width - var/window_size = null /// The initial title, for use in var editing and such var/starting_title /// The initial author, for use in var editing and such @@ -51,35 +49,53 @@ return data /obj/item/book/ui_interact(mob/living/user, datum/tgui/ui) - if(carved) - balloon_alert(user, "book is carved out!") - return - if(!length(book_data.get_content())) - balloon_alert(user, "book is blank!") - return - - if(istype(user) && !isnull(user.mind)) - LAZYINITLIST(user.mind.book_titles_read) - var/has_not_read_book = !(starting_title in user.mind.book_titles_read) - if(has_not_read_book) - user.add_mood_event("book_nerd", /datum/mood_event/book_nerd) - user.mind.book_titles_read[starting_title] = TRUE - ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "MarkdownViewer", name) ui.open() -/obj/item/book/attack_self(mob/user) +/// Proc that handles sending the book information to the user, as well as some housekeeping stuff. +/obj/item/book/proc/display_content(mob/living/user) + credit_book_to_reader(user) + ui_interact(user) + +/// Proc that checks if the user is capable of reading the book, for UI interactions and otherwise. Returns TRUE if they can, FALSE if they can't. +/obj/item/book/proc/can_read_book(mob/living/user) if(user.is_blind()) to_chat(user, span_warning("You are blind and can't read anything!")) - return + return FALSE if(!user.can_read(src)) + return FALSE + + if(carved) + balloon_alert(user, "book is carved out!") + return FALSE + + if(!length(book_data.get_content())) + balloon_alert(user, "book is blank!") + return FALSE + + return TRUE + +/// Proc that adds the book to a list on the user's mind so we know what works of art they've been catching up on. +/obj/item/book/proc/credit_book_to_reader(mob/living/user) + if(!isliving(user) || isnull(user.mind)) + return + + LAZYINITLIST(user.mind.book_titles_read) + if(starting_title in user.mind.book_titles_read) + return + + user.add_mood_event("book_nerd", /datum/mood_event/book_nerd) + user.mind.book_titles_read[starting_title] = TRUE + +/obj/item/book/attack_self(mob/user) + if(!can_read_book(user)) return user.visible_message(span_notice("[user] opens a book titled \"[book_data.title]\" and begins reading intently.")) - ui_interact(user) + display_content(user) /obj/item/book/attackby(obj/item/attacking_item, mob/living/user, params) if(burn_paper_product_attackby_check(attacking_item, user)) diff --git a/code/modules/mafia/controller.dm b/code/modules/mafia/controller.dm index a6e1e3c5f7f11..007e0b5e45613 100644 --- a/code/modules/mafia/controller.dm +++ b/code/modules/mafia/controller.dm @@ -196,6 +196,7 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment()) for(var/datum/mafia_role/roles as anything in all_roles) var/obj/item/modular_computer/modpc = roles.player_pda if(!modpc) + update_static_data(roles.body) continue modpc.update_static_data_for_all_viewers() diff --git a/code/modules/mafia/controller_ui.dm b/code/modules/mafia/controller_ui.dm index 9caa25d9f74de..cc901392d22d3 100644 --- a/code/modules/mafia/controller_ui.dm +++ b/code/modules/mafia/controller_ui.dm @@ -2,7 +2,7 @@ /datum/mafia_controller/ui_static_data(atom/user) var/list/data = list() - if(usr.client?.holder) + if(usr?.client?.holder) data["admin_controls"] = TRUE //show admin buttons to start/setup/stop data["is_observer"] = isobserver(user) data["all_roles"] = current_setup_text @@ -59,6 +59,7 @@ player_info["possible_actions"] = list() if(user_role) //not observer + player_info["is_you"] = (role.body.real_name == user_role.body.real_name) for(var/datum/mafia_ability/action as anything in user_role.role_unique_actions) if(action.validate_action_target(src, potential_target = role, silent = TRUE)) player_info["possible_actions"] += list(list("name" = action, "ref" = REF(action))) diff --git a/code/modules/mafia/roles/neutral/neutral_chaos.dm b/code/modules/mafia/roles/neutral/neutral_chaos.dm index e4bd5ca0f17f9..de2c7fc4833ad 100644 --- a/code/modules/mafia/roles/neutral/neutral_chaos.dm +++ b/code/modules/mafia/roles/neutral/neutral_chaos.dm @@ -1,6 +1,6 @@ /datum/mafia_role/obsessed name = "Obsessed" - desc = "You're completely lost in your own mind. You win by lynching your obsession before you get killed in this mess. Obsession assigned on the first night!" + desc = "Lynch your obsession before you get killed at all costs!" win_condition = "lynch their obsession." revealed_outfit = /datum/outfit/mafia/obsessed team = MAFIA_TEAM_SOLO @@ -15,20 +15,26 @@ /datum/mafia_role/obsessed/New(datum/mafia_controller/game) //note: obsession is always a townie . = ..() + desc = initial(desc) + " Obsessions are assigned on the first night." RegisterSignal(game, COMSIG_MAFIA_SUNDOWN, PROC_REF(find_obsession)) /datum/mafia_role/obsessed/proc/find_obsession(datum/mafia_controller/game) SIGNAL_HANDLER - var/list/all_roles_shuffle = shuffle(game.living_roles) + var/list/all_roles_shuffle = shuffle(game.living_roles) - src for(var/datum/mafia_role/possible as anything in all_roles_shuffle) if(possible.team == MAFIA_TEAM_TOWN) obsession = possible break if(!obsession) obsession = pick(all_roles_shuffle) //okay no town just pick anyone here - //if you still don't have an obsession you're playing a single player game like i can't help your dumb ass - to_chat(body, span_userdanger("Your obsession is [obsession.body.real_name]! Get them lynched to win!")) + desc = initial(desc) + " Target: [obsession.body.real_name]" + var/obj/item/modular_computer/modpc = player_pda + if(modpc) + modpc.update_static_data_for_all_viewers() + else + game.update_static_data(body) + send_message_to_player(span_userdanger("Your obsession is [obsession.body.real_name]! Get them lynched to win!")) RegisterSignal(obsession, COMSIG_MAFIA_ON_KILL, PROC_REF(check_victory)) UnregisterSignal(game, COMSIG_MAFIA_SUNDOWN) diff --git a/code/modules/mapfluff/ruins/generic.dm b/code/modules/mapfluff/ruins/generic.dm new file mode 100644 index 0000000000000..8c05bb2a58eb1 --- /dev/null +++ b/code/modules/mapfluff/ruins/generic.dm @@ -0,0 +1,3 @@ +/obj/modular_map_root/generic + config_file = "strings/modular_maps/generic.toml" + diff --git a/code/modules/mapfluff/ruins/objects_and_mobs/ash_walker_den.dm b/code/modules/mapfluff/ruins/objects_and_mobs/ash_walker_den.dm index d8b6ab715ff1e..ea55bfcf9197d 100644 --- a/code/modules/mapfluff/ruins/objects_and_mobs/ash_walker_den.dm +++ b/code/modules/mapfluff/ruins/objects_and_mobs/ash_walker_den.dm @@ -46,44 +46,45 @@ spawn_mob() /obj/structure/lavaland/ash_walker/proc/consume() - for(var/mob/living/H in view(src, 1)) //Only for corpse right next to/on same tile - if(H.stat) - for(var/obj/item/W in H) - if(!H.dropItemToGround(W)) + for(var/mob/living/offeredmob in view(src, 1)) //Only for corpse right next to/on same tile + if(offeredmob.loc == src) + continue //Ashwalker Revive in Progress... + if(offeredmob.stat) + for(var/obj/item/W in offeredmob) + if(!offeredmob.dropItemToGround(W)) qdel(W) - if(issilicon(H)) //no advantage to sacrificing borgs... - H.investigate_log("has been gibbed by the necropolis tendril.", INVESTIGATE_DEATHS) - visible_message(span_notice("Serrated tendrils eagerly pull [H] apart, but find nothing of interest.")) + if(issilicon(offeredmob)) //no advantage to sacrificing borgs... + offeredmob.investigate_log("has been gibbed by the necropolis tendril.", INVESTIGATE_DEATHS) + visible_message(span_notice("Serrated tendrils eagerly pull [offeredmob] apart, but find nothing of interest.")) return - if(H.mind?.has_antag_datum(/datum/antagonist/ashwalker) && (H.ckey || H.get_ghost(FALSE, TRUE))) //special interactions for dead lava lizards with ghosts attached - visible_message(span_warning("Serrated tendrils carefully pull [H] to [src], absorbing the body and creating it anew.")) + if(offeredmob.mind?.has_antag_datum(/datum/antagonist/ashwalker) && (offeredmob.ckey || offeredmob.get_ghost(FALSE, TRUE))) //special interactions for dead lava lizards with ghosts attached + visible_message(span_warning("Serrated tendrils carefully pull [offeredmob] to [src], absorbing the body and creating it anew.")) var/datum/mind/deadmind - if(H.ckey) - deadmind = H + if(offeredmob.ckey) + deadmind = offeredmob else - deadmind = H.get_ghost(FALSE, TRUE) + deadmind = offeredmob.get_ghost(FALSE, TRUE) to_chat(deadmind, "Your body has been returned to the nest. You are being remade anew, and will awaken shortly.
Your memories will remain intact in your new body, as your soul is being salvaged") SEND_SOUND(deadmind, sound('sound/magic/enter_blood.ogg',volume=100)) - addtimer(CALLBACK(src, PROC_REF(remake_walker), H.mind, H.real_name), 20 SECONDS) - new /obj/effect/gibspawner/generic(get_turf(H)) - qdel(H) + addtimer(CALLBACK(src, PROC_REF(remake_walker), offeredmob), 20 SECONDS) + offeredmob.forceMove(src) return - if(ismegafauna(H)) + if(ismegafauna(offeredmob)) meat_counter += 20 else meat_counter++ - visible_message(span_warning("Serrated tendrils eagerly pull [H] to [src], tearing the body apart as its blood seeps over the eggs.")) + visible_message(span_warning("Serrated tendrils eagerly pull [offeredmob] to [src], tearing the body apart as its blood seeps over the eggs.")) playsound(get_turf(src),'sound/magic/demon_consume.ogg', 100, TRUE) - var/deliverykey = H.fingerprintslast //ckey of whoever brought the body + var/deliverykey = offeredmob.fingerprintslast //ckey of whoever brought the body var/mob/living/deliverymob = get_mob_by_key(deliverykey) //mob of said ckey //there is a 40% chance that the Lava Lizard unlocks their respawn with each sacrifice if(deliverymob && (deliverymob.mind?.has_antag_datum(/datum/antagonist/ashwalker)) && (deliverykey in ashies.players_spawned) && (prob(40))) to_chat(deliverymob, span_warning("The Necropolis is pleased with your sacrifice. You feel confident your existence after death is secure.")) ashies.players_spawned -= deliverykey - H.investigate_log("has been gibbed by the necropolis tendril.", INVESTIGATE_DEATHS) - H.gib(DROP_ALL_REMAINS) + offeredmob.investigate_log("has been gibbed by the necropolis tendril.", INVESTIGATE_DEATHS) + offeredmob.gib(DROP_ALL_REMAINS) atom_integrity = min(atom_integrity + max_integrity*0.05,max_integrity)//restores 5% hp of tendril for(var/mob/living/L in view(src, 5)) if(L.mind?.has_antag_datum(/datum/antagonist/ashwalker)) @@ -92,17 +93,19 @@ L.add_mood_event("oogabooga", /datum/mood_event/sacrifice_bad) ashies.sacrifices_made++ -/obj/structure/lavaland/ash_walker/proc/remake_walker(datum/mind/oldmind, oldname) - var/mob/living/carbon/human/M = new /mob/living/carbon/human(get_step(loc, pick(GLOB.alldirs))) - M.set_species(/datum/species/lizard/ashwalker) - M.real_name = oldname - M.underwear = "Nude" - M.update_body() - M.remove_language(/datum/language/common) - oldmind.transfer_to(M) - M.mind.grab_ghost() - to_chat(M, "You have been pulled back from beyond the grave, with a new body and renewed purpose. Glory to the Necropolis!") - playsound(get_turf(M),'sound/magic/exit_blood.ogg', 100, TRUE) +/obj/structure/lavaland/ash_walker/proc/remake_walker(mob/living/carbon/oldmob) + var/mob/living/carbon/human/newwalker = new /mob/living/carbon/human(get_step(loc, pick(GLOB.alldirs))) + newwalker.set_species(/datum/species/lizard/ashwalker) + newwalker.real_name = oldmob.real_name + newwalker.undershirt = "Nude" + newwalker.underwear = "Nude" + newwalker.update_body() + newwalker.remove_language(/datum/language/common) + oldmob.mind.transfer_to(newwalker) + newwalker.mind.grab_ghost() + to_chat(newwalker, "You have been pulled back from beyond the grave, with a new body and renewed purpose. Glory to the Necropolis!") + playsound(get_turf(newwalker),'sound/magic/exit_blood.ogg', 100, TRUE) + qdel(oldmob) /obj/structure/lavaland/ash_walker/proc/spawn_mob() if(meat_counter >= ASH_WALKER_SPAWN_THRESHOLD) diff --git a/code/modules/mapping/mapping_helpers.dm b/code/modules/mapping/mapping_helpers.dm index 92e67fc908289..605638679b4e1 100644 --- a/code/modules/mapping/mapping_helpers.dm +++ b/code/modules/mapping/mapping_helpers.dm @@ -6,8 +6,9 @@ name = "baseturf editor" icon = 'icons/effects/mapping_helpers.dmi' icon_state = "" - + /// Replacing a specific turf var/list/baseturf_to_replace + /// The desired bottom turf var/baseturf plane = POINT_PLANE @@ -33,9 +34,16 @@ qdel(src) +/// Replaces all the requested baseturfs (usually space/baseturfbottom) with the desired baseturf. Skips if its already there /obj/effect/baseturf_helper/proc/replace_baseturf(turf/thing) thing.remove_baseturfs_from_typecache(baseturf_to_replace) - thing.PlaceOnBottom(fake_turf_type = baseturf) + + if(length(thing.baseturfs)) + var/turf/tile = thing.baseturfs[1] + if(tile == baseturf) + return + + thing.place_on_bottom(baseturf) /obj/effect/baseturf_helper/space name = "space baseturf editor" diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm index f42d572cb6cdd..b4165a13cd0af 100644 --- a/code/modules/mining/equipment/wormhole_jaunter.dm +++ b/code/modules/mining/equipment/wormhole_jaunter.dm @@ -102,6 +102,7 @@ mech_sized = TRUE //save your ripley innate_accuracy_penalty = 6 light_on = FALSE + wibbles = FALSE /obj/effect/portal/jaunt_tunnel/teleport(atom/movable/M) . = ..() diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 6e3d21ec8335d..a553415176ea5 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -55,7 +55,7 @@ if(12) new /obj/item/jacobs_ladder(src) if(13) - new /obj/item/guardiancreator/miner(src) + new /obj/item/guardian_creator/miner(src) if(14) new /obj/item/warp_cube/red(src) if(15) diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index 270decf728487..2b9434d8e4e70 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -197,14 +197,14 @@ continue regurgitate_guardian(guardian) -/obj/item/clothing/neck/necklace/memento_mori/proc/consume_guardian(mob/living/simple_animal/hostile/guardian/guardian) +/obj/item/clothing/neck/necklace/memento_mori/proc/consume_guardian(mob/living/basic/guardian/guardian) new /obj/effect/temp_visual/guardian/phase/out(get_turf(guardian)) guardian.locked = TRUE guardian.forceMove(src) to_chat(guardian, span_userdanger("You have been locked away in your summoner's pendant!")) guardian.playsound_local(get_turf(guardian), 'sound/magic/summonitems_generic.ogg', 50, TRUE) -/obj/item/clothing/neck/necklace/memento_mori/proc/regurgitate_guardian(mob/living/simple_animal/hostile/guardian/guardian) +/obj/item/clothing/neck/necklace/memento_mori/proc/regurgitate_guardian(mob/living/basic/guardian/guardian) guardian.locked = FALSE guardian.recall(forced = TRUE) to_chat(guardian, span_notice("You have been returned back from your summoner's pendant!")) diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index 4f28db93bc6e4..848ecac0fa33d 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -70,6 +70,7 @@ icon = 'icons/obj/machines/mining_machines.dmi' icon_state = "console" density = TRUE + interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN|INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_OPEN_SILICON|INTERACT_MACHINE_SET_MACHINE /// Connected ore processing machine. var/obj/machinery/mineral/processing_unit/processing_machine diff --git a/code/modules/mining/machine_silo.dm b/code/modules/mining/machine_silo.dm index 840c8e92900a8..7661549a77d9e 100644 --- a/code/modules/mining/machine_silo.dm +++ b/code/modules/mining/machine_silo.dm @@ -8,6 +8,7 @@ GLOBAL_LIST_EMPTY(silo_access_logs) icon_state = "silo" density = TRUE circuit = /obj/item/circuitboard/machine/ore_silo + interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN|INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_OPEN_SILICON|INTERACT_MACHINE_SET_MACHINE /// The machine UI's page of logs showing ore history. var/log_page = 1 diff --git a/code/modules/mining/satchel_ore_boxdm.dm b/code/modules/mining/satchel_ore_boxdm.dm index 564ec2e92b028..607bbcd9f06d8 100644 --- a/code/modules/mining/satchel_ore_boxdm.dm +++ b/code/modules/mining/satchel_ore_boxdm.dm @@ -83,8 +83,6 @@ return if(!Adjacent(usr)) return - add_fingerprint(usr) - usr.set_machine(src) switch(action) if("removeall") dump_box_contents() diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm index 4ad94270837ea..585c8b6b97ba4 100644 --- a/code/modules/mob/living/basic/basic.dm +++ b/code/modules/mob/living/basic/basic.dm @@ -208,7 +208,7 @@ face_atom(target) if (!ignore_cooldown) changeNext_move(melee_attack_cooldown) - if(SEND_SIGNAL(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, target) & COMPONENT_HOSTILE_NO_ATTACK) + if(SEND_SIGNAL(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, target, Adjacent(target), modifiers) & COMPONENT_HOSTILE_NO_ATTACK) return FALSE //but more importantly return before attack_animal called var/result = target.attack_basic_mob(src, modifiers) SEND_SIGNAL(src, COMSIG_HOSTILE_POST_ATTACKINGTARGET, target, result) diff --git a/code/modules/mob/living/basic/blob_minions/blob_ai.dm b/code/modules/mob/living/basic/blob_minions/blob_ai.dm index fc21d030d07d1..5aad05d4656ff 100644 --- a/code/modules/mob/living/basic/blob_minions/blob_ai.dm +++ b/code/modules/mob/living/basic/blob_minions/blob_ai.dm @@ -4,7 +4,7 @@ */ /datum/ai_controller/basic_controller/blobbernaut blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) @@ -21,7 +21,7 @@ */ /datum/ai_controller/basic_controller/blob_zombie blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) @@ -39,7 +39,7 @@ */ /datum/ai_controller/basic_controller/blob_spore blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) diff --git a/code/modules/mob/living/basic/clown/clown_ai.dm b/code/modules/mob/living/basic/clown/clown_ai.dm index f54c432140ee3..b3f5a9f9aef46 100644 --- a/code/modules/mob/living/basic/clown/clown_ai.dm +++ b/code/modules/mob/living/basic/clown/clown_ai.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/clown blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_BASIC_MOB_SPEAK_LINES = null, ) @@ -14,7 +14,7 @@ /datum/ai_controller/basic_controller/clown/murder blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_BASIC_MOB_SPEAK_LINES = null, BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) diff --git a/code/modules/mob/living/basic/cult/constructs/_construct.dm b/code/modules/mob/living/basic/cult/constructs/_construct.dm index 534cb3a7eac1b..6181eb3d0f44d 100644 --- a/code/modules/mob/living/basic/cult/constructs/_construct.dm +++ b/code/modules/mob/living/basic/cult/constructs/_construct.dm @@ -68,7 +68,7 @@ heal_time = 0,\ valid_targets_typecache = typecacheof(list(/mob/living/basic/construct, /mob/living/basic/shade)),\ valid_biotypes = MOB_MINERAL | MOB_SPIRIT,\ - self_targetting = can_repair_self ? HEALING_TOUCH_ANYONE : HEALING_TOUCH_NOT_SELF,\ + self_targeting = can_repair_self ? HEALING_TOUCH_ANYONE : HEALING_TOUCH_NOT_SELF,\ action_text = "%SOURCE% begins repairing %TARGET%'s dents.",\ complete_text = "%TARGET%'s dents are repaired.",\ show_health = TRUE,\ diff --git a/code/modules/mob/living/basic/cult/constructs/construct_ai.dm b/code/modules/mob/living/basic/cult/constructs/construct_ai.dm index 6f79b327915be..b8417affed94c 100644 --- a/code/modules/mob/living/basic/cult/constructs/construct_ai.dm +++ b/code/modules/mob/living/basic/cult/constructs/construct_ai.dm @@ -6,8 +6,8 @@ */ /datum/ai_controller/basic_controller/artificer blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/same_faction/construct, - BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/same_faction/construct, + BB_FLEE_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_WOUNDED_ONLY = TRUE, ) @@ -27,7 +27,7 @@ */ /datum/ai_controller/basic_controller/juggernaut blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) @@ -46,9 +46,9 @@ */ /datum/ai_controller/basic_controller/proteon blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, - BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_FLEE_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -68,7 +68,7 @@ */ /datum/ai_controller/basic_controller/wraith blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) @@ -80,11 +80,11 @@ /datum/ai_planning_subtree/basic_melee_attack_subtree, ) -/// Targetting datum that will only allow mobs that constructs can heal. -/datum/targetting_datum/basic/same_faction/construct +/// Targeting strategy that will only allow mobs that constructs can heal. +/datum/targeting_strategy/basic/same_faction/construct target_wounded_key = BB_TARGET_WOUNDED_ONLY -/datum/targetting_datum/basic/same_faction/construct/can_attack(mob/living/living_mob, atom/the_target, vision_range, check_faction = TRUE) +/datum/targeting_strategy/basic/same_faction/construct/can_attack(mob/living/living_mob, atom/the_target, vision_range, check_faction = TRUE) if(isconstruct(the_target) || istype(the_target, /mob/living/basic/shade)) return ..() return FALSE diff --git a/code/modules/mob/living/basic/farm_animals/bee/_bee.dm b/code/modules/mob/living/basic/farm_animals/bee/_bee.dm index 692a7f108d189..dfaff9f4efc41 100644 --- a/code/modules/mob/living/basic/farm_animals/bee/_bee.dm +++ b/code/modules/mob/living/basic/farm_animals/bee/_bee.dm @@ -61,7 +61,7 @@ /datum/pet_command/beehive/enter, /datum/pet_command/beehive/exit, /datum/pet_command/follow/bee, - /datum/pet_command/point_targetting/attack/swirl, + /datum/pet_command/point_targeting/attack/swirl, /datum/pet_command/scatter, ) diff --git a/code/modules/mob/living/basic/farm_animals/bee/bee_ai_behavior.dm b/code/modules/mob/living/basic/farm_animals/bee/bee_ai_behavior.dm index 67e98a5f3d3e8..0c48a9453811d 100644 --- a/code/modules/mob/living/basic/farm_animals/bee/bee_ai_behavior.dm +++ b/code/modules/mob/living/basic/farm_animals/bee/bee_ai_behavior.dm @@ -83,9 +83,9 @@ if(valid_hives.len) return pick(valid_hives) -/datum/targetting_datum/basic/bee +/datum/targeting_strategy/basic/bee -/datum/targetting_datum/basic/bee/can_attack(mob/living/owner, atom/target, vision_range) +/datum/targeting_strategy/basic/bee/can_attack(mob/living/owner, atom/target, vision_range) if(!isliving(target)) return FALSE . = ..() @@ -117,7 +117,7 @@ required_distance = 0 ///swirl around the owner in menacing fashion -/datum/pet_command/point_targetting/attack/swirl +/datum/pet_command/point_targeting/attack/swirl command_name = "Swirl" command_desc = "Your pets will swirl around you and attack whoever you point at!" speech_commands = list("swirl", "spiral", "swarm") @@ -127,7 +127,7 @@ ///the owner we will swarm around var/key_to_swarm = BB_SWARM_TARGET -/datum/pet_command/point_targetting/attack/swirl/try_activate_command(mob/living/commander) +/datum/pet_command/point_targeting/attack/swirl/try_activate_command(mob/living/commander) var/mob/living/living_pawn = weak_parent.resolve() if(isnull(living_pawn)) return @@ -138,7 +138,7 @@ controller.set_blackboard_key(key_to_swarm, commander) return ..() -/datum/pet_command/point_targetting/attack/swirl/execute_action(datum/ai_controller/controller) +/datum/pet_command/point_targeting/attack/swirl/execute_action(datum/ai_controller/controller) if(controller.blackboard_key_exists(BB_CURRENT_PET_TARGET)) return ..() controller.queue_behavior(/datum/ai_behavior/swirl_around_target, BB_SWARM_TARGET) diff --git a/code/modules/mob/living/basic/farm_animals/bee/bee_ai_subtree.dm b/code/modules/mob/living/basic/farm_animals/bee/bee_ai_subtree.dm index 6379f239ba0ba..3d56dd990dcbd 100644 --- a/code/modules/mob/living/basic/farm_animals/bee/bee_ai_subtree.dm +++ b/code/modules/mob/living/basic/farm_animals/bee/bee_ai_subtree.dm @@ -1,7 +1,7 @@ /datum/ai_controller/basic_controller/bee blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/bee, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/bee, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, ) ai_traits = STOP_MOVING_WHEN_PULLED @@ -25,7 +25,7 @@ /datum/ai_controller/basic_controller/queen_bee blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/bee, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/bee, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/farm_animals/chicken/chick.dm b/code/modules/mob/living/basic/farm_animals/chicken/chick.dm index 311b311e8fd75..9e4af384aeeff 100644 --- a/code/modules/mob/living/basic/farm_animals/chicken/chick.dm +++ b/code/modules/mob/living/basic/farm_animals/chicken/chick.dm @@ -66,7 +66,7 @@ /datum/ai_controller/basic_controller/chick blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_FIND_MOM_TYPES = list(/mob/living/basic/chicken), ) diff --git a/code/modules/mob/living/basic/farm_animals/chicken/chicken.dm b/code/modules/mob/living/basic/farm_animals/chicken/chicken.dm index 99ff6b5274829..9508f8fae3be6 100644 --- a/code/modules/mob/living/basic/farm_animals/chicken/chicken.dm +++ b/code/modules/mob/living/basic/farm_animals/chicken/chicken.dm @@ -78,7 +78,7 @@ GLOBAL_VAR_INIT(chicken_count, 0) /datum/ai_controller/basic_controller/chicken blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/farm_animals/cow/_cow.dm b/code/modules/mob/living/basic/farm_animals/cow/_cow.dm index bcd0084adb0ab..e5d49aa867b50 100644 --- a/code/modules/mob/living/basic/farm_animals/cow/_cow.dm +++ b/code/modules/mob/living/basic/farm_animals/cow/_cow.dm @@ -45,7 +45,7 @@ udder_component() setup_eating() . = ..() - ai_controller.set_blackboard_key(BB_BASIC_FOODS, food_types) + ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(food_types)) ///wrapper for the udder component addition so you can have uniquely uddered cow subtypes /mob/living/basic/cow/proc/udder_component() diff --git a/code/modules/mob/living/basic/farm_animals/cow/cow_ai.dm b/code/modules/mob/living/basic/farm_animals/cow/cow_ai.dm index 81e1d722b01e5..e1e611a28c2a8 100644 --- a/code/modules/mob/living/basic/farm_animals/cow/cow_ai.dm +++ b/code/modules/mob/living/basic/farm_animals/cow/cow_ai.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/cow blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items(), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items, BB_BASIC_MOB_TIP_REACTING = FALSE, BB_BASIC_MOB_TIPPER = null, ) diff --git a/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm b/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm index 6eaef1bf5c3e5..f499859e19e91 100644 --- a/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm +++ b/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm @@ -44,7 +44,7 @@ /datum/ai_controller/basic_controller/cow/moonicorn blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items/moonicorn(), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items/moonicorn, BB_BASIC_MOB_TIP_REACTING = FALSE, BB_BASIC_MOB_TIPPER = null, ) @@ -60,14 +60,14 @@ ) ///moonicorns will not attack people holding something that could tame them. -/datum/targetting_datum/basic/allow_items/moonicorn +/datum/targeting_strategy/basic/allow_items/moonicorn -/datum/targetting_datum/basic/allow_items/moonicorn/can_attack(mob/living/living_mob, atom/the_target, vision_range) +/datum/targeting_strategy/basic/allow_items/moonicorn/can_attack(mob/living/living_mob, atom/the_target, vision_range) . = ..() if(!.) return FALSE - if(isliving(the_target)) //Targetting vs living mobs + if(isliving(the_target)) //Targeting vs living mobs var/mob/living/living_target = the_target for(var/obj/item/food/grown/galaxythistle/tame_food in living_target.held_items) return FALSE //heyyy this can tame me! let's NOT fight diff --git a/code/modules/mob/living/basic/farm_animals/cow/cow_wisdom.dm b/code/modules/mob/living/basic/farm_animals/cow/cow_wisdom.dm index b62f57abf54dd..4e80fd4bcfe93 100644 --- a/code/modules/mob/living/basic/farm_animals/cow/cow_wisdom.dm +++ b/code/modules/mob/living/basic/farm_animals/cow/cow_wisdom.dm @@ -22,7 +22,7 @@ return //cannot tame me! and I don't care about eatin' nothing, neither! /datum/ai_controller/basic_controller/cow/wisdom - //don't give a targetting datum + //don't give a targeting strategy blackboard = list( BB_BASIC_MOB_TIP_REACTING = FALSE, BB_BASIC_MOB_TIPPER = null, diff --git a/code/modules/mob/living/basic/farm_animals/deer.dm b/code/modules/mob/living/basic/farm_animals/deer.dm index 7907e6684431f..5b88593f0c640 100644 --- a/code/modules/mob/living/basic/farm_animals/deer.dm +++ b/code/modules/mob/living/basic/farm_animals/deer.dm @@ -30,12 +30,12 @@ var/time_to_freeze_for = (rand(5, 10) SECONDS) ai_controller.set_blackboard_key(BB_STATIONARY_SECONDS, time_to_freeze_for) ai_controller.set_blackboard_key(BB_STATIONARY_COOLDOWN, (time_to_freeze_for * (rand(3, 5)))) - ai_controller.set_blackboard_key(BB_STATIONARY_TARGETS, stationary_scary_things) + ai_controller.set_blackboard_key(BB_STATIONARY_TARGETS, typecacheof(stationary_scary_things)) /datum/ai_controller/basic_controller/deer blackboard = list( BB_STATIONARY_MOVE_TO_TARGET = TRUE, - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/farm_animals/goat/_goat.dm b/code/modules/mob/living/basic/farm_animals/goat/_goat.dm index db49ae8df9ffd..34b92f218829c 100644 --- a/code/modules/mob/living/basic/farm_animals/goat/_goat.dm +++ b/code/modules/mob/living/basic/farm_animals/goat/_goat.dm @@ -56,7 +56,7 @@ RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_attacked)) RegisterSignal(src, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(on_move)) - ai_controller.set_blackboard_key(BB_BASIC_FOODS, edibles) + ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(edibles)) /// Called when we attack something in order to piece together the intent of the AI/user and provide desired behavior. The element might be okay here but I'd rather the fluff. /// Goats are really good at beating up plants by taking bites out of them, but we use the default attack for everything else @@ -110,8 +110,10 @@ INVOKE_ASYNC(src, PROC_REF(eat_plant), edible_plants) -/// When invoked, adds an udder. Overridden on subtypes +/// When invoked, adds an udder when applicable. Male goats do not have udders. /mob/living/basic/goat/proc/add_udder() + if(gender == MALE) + return AddComponent(/datum/component/udder) /// Proc that handles dealing with the various types of plants we might eat. Assumes that a valid list of type(s) will be passed in. diff --git a/code/modules/mob/living/basic/farm_animals/goat/goat_ai.dm b/code/modules/mob/living/basic/farm_animals/goat/goat_ai.dm index f8463b1967537..5928344fee4e6 100644 --- a/code/modules/mob/living/basic/farm_animals/goat/goat_ai.dm +++ b/code/modules/mob/living/basic/farm_animals/goat/goat_ai.dm @@ -1,7 +1,7 @@ /// Goats are normally content to sorta hang around and crunch any plant in sight, but they will go ape on someone who attacks them. /datum/ai_controller/basic_controller/goat blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/farm_animals/goat/goat_subtypes.dm b/code/modules/mob/living/basic/farm_animals/goat/goat_subtypes.dm index 19d50fb38097a..16efdd528d112 100644 --- a/code/modules/mob/living/basic/farm_animals/goat/goat_subtypes.dm +++ b/code/modules/mob/living/basic/farm_animals/goat/goat_subtypes.dm @@ -8,5 +8,3 @@ if((bodytemperature < T20C) || istype(goat_area, /area/station/service/kitchen/coldroom)) . += span_notice("[p_They()] [p_do()]n't seem to be too bothered about the cold.") // special for pete -/mob/living/basic/goat/pete/add_udder() - return //no thank you diff --git a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm index 70e436b65d775..39bc6f87cd639 100644 --- a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm +++ b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm @@ -65,7 +65,7 @@ ) AddComponent(/datum/component/personal_crafting) AddComponent(/datum/component/basic_inhands, y_offset = -1) - ai_controller?.set_blackboard_key(BB_BASIC_FOODS, gorilla_food) + ai_controller?.set_blackboard_key(BB_BASIC_FOODS, typecacheof(gorilla_food)) /mob/living/basic/gorilla/update_overlays() . = ..() @@ -158,6 +158,12 @@ ADD_TRAIT(src, TRAIT_PACIFISM, INNATE_TRAIT) AddComponent(/datum/component/crate_carrier) +/mob/living/basic/gorilla/cargorilla/death(gibbed) + var/datum/component/potential_component = GetComponent(/datum/component/ghost_direct_control) + if(!QDELETED(potential_component)) + qdel(potential_component) + return ..() + /** * Poll ghosts for control of the gorilla. Not added in init because we only want to poll when the round starts. * Preferably in future we can replace this with a popup on the lobby to queue to become a gorilla. diff --git a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla_ai.dm b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla_ai.dm index daf5b7af0834b..28a727fdb1bce 100644 --- a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla_ai.dm +++ b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla_ai.dm @@ -1,7 +1,7 @@ /// Pretty basic, just click people to death. Also hunt and eat bananas. /datum/ai_controller/basic_controller/gorilla blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items, BB_TARGET_MINIMUM_STAT = UNCONSCIOUS, BB_EMOTE_KEY = "ooga", BB_EMOTE_CHANCE = 40, @@ -27,7 +27,7 @@ /datum/ai_controller/basic_controller/gorilla/lesser blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items, BB_EMOTE_KEY = "ooga", BB_EMOTE_CHANCE = 60, ) diff --git a/code/modules/mob/living/basic/farm_animals/pig.dm b/code/modules/mob/living/basic/farm_animals/pig.dm index c0ad3f6b349be..94183d044c531 100644 --- a/code/modules/mob/living/basic/farm_animals/pig.dm +++ b/code/modules/mob/living/basic/farm_animals/pig.dm @@ -47,7 +47,7 @@ /datum/ai_controller/basic_controller/pig blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/farm_animals/pony.dm b/code/modules/mob/living/basic/farm_animals/pony.dm index e1765f0fdbac6..df8f3a1fd4eec 100644 --- a/code/modules/mob/living/basic/farm_animals/pony.dm +++ b/code/modules/mob/living/basic/farm_animals/pony.dm @@ -106,7 +106,7 @@ /datum/ai_controller/basic_controller/pony blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/farm_animals/rabbit.dm b/code/modules/mob/living/basic/farm_animals/rabbit.dm index 19fd0120ba7e6..f77772ab17c7b 100644 --- a/code/modules/mob/living/basic/farm_animals/rabbit.dm +++ b/code/modules/mob/living/basic/farm_animals/rabbit.dm @@ -49,7 +49,7 @@ /datum/ai_controller/basic_controller/rabbit blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/farm_animals/sheep.dm b/code/modules/mob/living/basic/farm_animals/sheep.dm index ac320d8080419..e32da910ab99b 100644 --- a/code/modules/mob/living/basic/farm_animals/sheep.dm +++ b/code/modules/mob/living/basic/farm_animals/sheep.dm @@ -81,7 +81,7 @@ /datum/ai_controller/basic_controller/sheep blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/festivus_pole.dm b/code/modules/mob/living/basic/festivus_pole.dm index f6dd1a41a2be2..aec6de74e1e4c 100644 --- a/code/modules/mob/living/basic/festivus_pole.dm +++ b/code/modules/mob/living/basic/festivus_pole.dm @@ -51,7 +51,7 @@ /datum/ai_controller/basic_controller/festivus_pole blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_LOW_PRIORITY_HUNTING_TARGET = null, // APCs ) diff --git a/code/modules/mob/living/basic/guardian/guardian.dm b/code/modules/mob/living/basic/guardian/guardian.dm new file mode 100644 index 0000000000000..e36960a80ae7a --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian.dm @@ -0,0 +1,333 @@ +/** + * A mob which acts as a guardian angel to another mob, sharing health but protecting them using special powers. + * Usually either obtained in magical form by a wizard, or technological form by a traitor. Sometimes found by miners. + */ +/mob/living/basic/guardian + name = "Guardian Spirit" + real_name = "Guardian Spirit" + desc = "A mysterious being that stands by its charge, ever vigilant." + icon = 'icons/mob/nonhuman-player/guardian.dmi' + icon_state = "magicbase" + icon_living = "magicbase" + icon_dead = "magicbase" + gender = NEUTER + basic_mob_flags = DEL_ON_DEATH + mob_biotypes = MOB_SPECIAL + sentience_type = SENTIENCE_HUMANOID + hud_type = /datum/hud/guardian + faction = list() + speed = 0 + maxHealth = INFINITY // The spirit itself is invincible and passes damage to its host + health = INFINITY + damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) + unsuitable_atmos_damage = 0 + unsuitable_cold_damage = 0 + unsuitable_heat_damage = 0 + speak_emote = list("hisses") + bubble_icon = "guardian" + response_help_continuous = "passes through" + response_help_simple = "pass through" + response_disarm_continuous = "flails at" + response_disarm_simple = "flail at" + response_harm_continuous = "punches" + response_harm_simple = "punch" + attack_sound = 'sound/weapons/punch1.ogg' + attack_verb_continuous = "punches" + attack_verb_simple = "punch" + combat_mode = TRUE + obj_damage = 40 + melee_damage_lower = 15 + melee_damage_upper = 15 + melee_attack_cooldown = CLICK_CD_MELEE + light_system = MOVABLE_LIGHT + light_range = 3 + light_on = FALSE + + /// The summoner of the guardian, we share health with them and can't move too far away (usually) + var/mob/living/summoner + /// How far from the summoner the guardian can be. + var/range = 10 + + /// The guardian's colour, used for their sprite, chat, and some effects. + var/guardian_colour + /// Coloured overlay we apply + var/mutable_appearance/overlay + + /// Which toggle button the HUD uses. + var/toggle_button_type = /atom/movable/screen/guardian/toggle_mode/inactive + /// Name used by the guardian creator. + var/creator_name = "Error" + /// Description used by the guardian creator. + var/creator_desc = "This shouldn't be here! Report it on GitHub!" + /// Icon used by the guardian creator. + var/creator_icon = "fuck" + + /// What type of guardian are we? + var/guardian_type = null + /// How are we themed? + var/datum/guardian_fluff/theme + /// A string explaining to the guardian what they can do. + var/playstyle_string = span_boldholoparasite("You are a Guardian without any type. You shouldn't exist and are an affront to god!") + + /// Are we forced to not be able to manifest/recall? + var/locked = FALSE + /// Cooldown between manifests/recalls. + COOLDOWN_DECLARE(manifest_cooldown) + /// Cooldown between the summoner resetting the guardian's client. + COOLDOWN_DECLARE(resetting_cooldown) + + /// List of actions we give to our summoner + var/static/list/control_actions = list( + /datum/action/cooldown/mob_cooldown/guardian_comms, + /datum/action/cooldown/mob_cooldown/recall_guardian, + /datum/action/cooldown/mob_cooldown/replace_guardian, + ) + +/mob/living/basic/guardian/Initialize(mapload, datum/guardian_fluff/theme) + . = ..() + GLOB.parasites += src + src.theme = theme + theme?.apply(src) + var/list/death_loot = string_list(list(/obj/item/stack/sheet/mineral/wood)) + AddElement(/datum/element/death_drops, death_loot) + AddElement(/datum/element/simple_flying) + AddComponent(/datum/component/basic_inhands) + // life link + update_appearance(UPDATE_ICON) + manifest_effects() + +/mob/living/basic/guardian/Destroy() + GLOB.parasites -= src + if (is_deployed()) + recall_effects() + cut_summoner(different_person = TRUE) + return ..() + +/mob/living/basic/guardian/update_overlays() + . = ..() + . += overlay + +/mob/living/basic/guardian/Login() //if we have a mind, set its name to ours when it logs in + . = ..() + if (!. || isnull(client)) + return FALSE + if (isnull(summoner)) + to_chat(src, span_boldholoparasite("For some reason, somehow, you have no summoner. Please report this bug immediately.")) + stack_trace("Guardian created with client but no summoner.") + else + to_chat(src, span_holoparasite("You are a [theme.name], bound to serve [summoner.real_name].")) + to_chat(src, span_holoparasite("You are capable of manifesting or recalling to your master with the buttons on your HUD. You will also find a button to communicate with [summoner.p_them()] privately there.")) + to_chat(src, span_holoparasite("While personally invincible, you will die if [summoner.real_name] does, and any damage dealt to you will have a portion passed on to [summoner.p_them()] as you feed upon [summoner.p_them()] to sustain yourself.")) + to_chat(src, playstyle_string) + if (!isnull(guardian_colour)) + return // Already set up so we don't need to do it again + locked = TRUE + guardian_rename() + guardian_recolour() + locked = FALSE + +/mob/living/basic/guardian/mind_initialize() + . = ..() + if (isnull(summoner)) + to_chat(src, span_boldholoparasite("For some reason, somehow, you have no summoner. Please report this bug immediately.")) + return + mind.enslave_mind_to_creator(summoner) // Once our mind is created, we become enslaved to our summoner. cant be done in the first run of set_summoner, because by then we dont have a mind yet. + +/// Pick a new colour for our guardian +/mob/living/basic/guardian/proc/guardian_recolour() + if (isnull(client)) + return + var/chosen_guardian_colour = input(src, "What would you like your colour to be?", "Choose Your Colour", "#ffffff") as color|null + if (isnull(chosen_guardian_colour)) //redo proc until we get a color + to_chat(src, span_warning("Invalid colour, please try again.")) + return guardian_recolour() + set_guardian_colour(chosen_guardian_colour) + +/// Apply a new colour to our guardian +/mob/living/basic/guardian/proc/set_guardian_colour(colour) + guardian_colour = colour + set_light_color(guardian_colour) + overlay?.color = guardian_colour + update_appearance(UPDATE_ICON) + +/mob/living/basic/guardian/proc/guardian_rename() + if (isnull(client)) + return + + var/new_name = sanitize_name(reject_bad_text(tgui_input_text(src, "What would you like your name to be?", "Choose Your Name", generate_random_name(), MAX_NAME_LEN))) + if (!new_name) //redo proc until we get a good name + to_chat(src, span_warning("Invalid name, please try again.")) + return guardian_rename() + to_chat(src, span_notice("Your new name [span_name(new_name)] anchors itself in your mind.")) + fully_replace_character_name(null, new_name) + +/// Picks a random name as a suggestion +/mob/living/basic/guardian/proc/generate_random_name() + var/list/surname_options = list("Guardian") // Fallback in case you define a guardian with no theme + switch(theme?.fluff_type) + if (GUARDIAN_MAGIC) + surname_options = GLOB.guardian_fantasy_surnames + if (GUARDIAN_TECH) + surname_options = GLOB.guardian_tech_surnames + + return "[pick(GLOB.guardian_first_names)] [pick(surname_options)]" + +/mob/living/basic/guardian/melee_attack(atom/target, list/modifiers, ignore_cooldown) + if (!is_deployed()) + balloon_alert(src, "not tangible!") + return FALSE + return ..() + +/mob/living/basic/guardian/death(gibbed) + if (!QDELETED(summoner)) + to_chat(summoner, span_bolddanger("Your [name] died somehow!")) + summoner.dust() + return ..() + +/mob/living/basic/guardian/ex_act(severity, target) + switch(severity) + if (EXPLODE_DEVASTATE) + investigate_log("has been gibbed by an explosion.", INVESTIGATE_DEATHS) + gib() + return TRUE + if (EXPLODE_HEAVY) + adjustBruteLoss(60) + if (EXPLODE_LIGHT) + adjustBruteLoss(30) + + return TRUE + +/mob/living/basic/guardian/gib() + death(TRUE) + +/mob/living/basic/guardian/dust(just_ash, drop_items, force) + death(TRUE) + +/// Link up with a summoner mob. +/mob/living/basic/guardian/proc/set_summoner(mob/living/to_who, different_person = FALSE) + if (QDELETED(src)) + return // Just in case + if (QDELETED(to_who)) + ghostize(FALSE) + qdel(src) // No life of free invulnerability for you. + return + cut_summoner(different_person) + AddComponent(/datum/component/life_link, to_who, CALLBACK(src, PROC_REF(on_harm)), CALLBACK(src, PROC_REF(on_summoner_death))) + summoner = to_who + + for (var/action_type in control_actions) + if (locate(action_type) in summoner.actions) + continue + var/datum/action/new_action = new action_type(summoner) + new_action.Grant(summoner) + + if (different_person) + if (mind) + mind.enslave_mind_to_creator(to_who) + else //mindless guardian, manually give them factions + faction += summoner.faction + summoner.faction += "[REF(src)]" + remove_all_languages(LANGUAGE_MASTER) + copy_languages(to_who, LANGUAGE_MASTER) // make sure holoparasites speak same language as master + RegisterSignal(to_who, COMSIG_QDELETING, PROC_REF(on_summoner_deletion)) + RegisterSignal(to_who, COMSIG_LIVING_ON_WABBAJACKED, PROC_REF(on_summoner_wabbajacked)) + RegisterSignal(to_who, COMSIG_LIVING_SHAPESHIFTED, PROC_REF(on_summoner_shapeshifted)) + RegisterSignal(to_who, COMSIG_LIVING_UNSHAPESHIFTED, PROC_REF(on_summoner_unshapeshifted)) + recall(forced = TRUE) + leash_to(src, summoner) + if (to_who.stat == DEAD) + on_summoner_death(src, to_who) + summoner.updatehealth() + +/// Remove all references to our summoner +/mob/living/basic/guardian/proc/cut_summoner(different_person = FALSE) + if (isnull(summoner)) + return + if (is_deployed()) + recall_effects() + var/summoner_turf = get_turf(summoner) + if (!isnull(summoner_turf)) + forceMove(summoner_turf) + unleash() + UnregisterSignal(summoner, list(COMSIG_QDELETING, COMSIG_LIVING_ON_WABBAJACKED, COMSIG_LIVING_SHAPESHIFTED, COMSIG_LIVING_UNSHAPESHIFTED)) + if (different_person) + summoner.faction -= "[REF(src)]" + faction -= summoner.faction + mind?.remove_all_antag_datums() + if (!length(summoner.get_all_linked_holoparasites() - src)) + for (var/action_type in control_actions) + var/datum/action/remove_action = locate(action_type) in summoner.actions + if (isnull(remove_action)) + continue + remove_action.Remove(summoner) + summoner = null + +/// Connects these two mobs by a leash +/mob/living/basic/guardian/proc/leash_to(atom/movable/leashed, atom/movable/leashed_to) + leashed.AddComponent(\ + /datum/component/leash,\ + owner = leashed_to,\ + distance = range,\ + force_teleport_out_effect = /obj/effect/temp_visual/guardian/phase/out,\ + force_teleport_in_effect = /obj/effect/temp_visual/guardian/phase,\ + ) + +/// Removes the leash from this guardian +/mob/living/basic/guardian/proc/unleash() + qdel(GetComponent(/datum/component/leash)) + +/// Called when our owner dies. We fucked up, so now neither of us get to exist. +/mob/living/basic/guardian/proc/on_summoner_death(mob/living/source, mob/living/former_owner) + cut_summoner() + if (!isnull(former_owner.loc)) + forceMove(former_owner.loc) + to_chat(src, span_danger("Your summoner has died!")) + visible_message(span_bolddanger("\The [src] dies along with its user!")) + former_owner.visible_message(span_bolddanger("[former_owner]'s body is completely consumed by the strain of sustaining [src]!")) + former_owner.dust(drop_items = TRUE) + +/// Called when our health changes, inform our owner of why they are getting hurt (if they are) +/mob/living/basic/guardian/proc/on_harm(mob/living/source, mob/living/summoner, amount) + if (QDELETED(src) || QDELETED(summoner) || amount <= 2) + return + to_chat(summoner, span_bolddanger("[name] is under attack! You take damage!")) + summoner.visible_message(span_bolddanger("Blood sprays from [summoner] as [src] takes damage!")) + if(summoner.stat == UNCONSCIOUS || summoner.stat == HARD_CRIT) + to_chat(summoner, span_bolddanger("Your head pounds, you can't take the strain of sustaining [src] in this condition!")) + summoner.adjustOrganLoss(ORGAN_SLOT_BRAIN, amount * 0.5) + +/// When our owner is deleted, we go too. +/mob/living/basic/guardian/proc/on_summoner_deletion(mob/living/source) + SIGNAL_HANDLER + cut_summoner() + to_chat(src, span_danger("Your summoner is gone, you feel yourself fading!")) + ghostize(FALSE) + qdel(src) + +/// Signal proc for [COMSIG_LIVING_ON_WABBAJACKED], when our summoner is wabbajacked we should be alerted. +/mob/living/basic/guardian/proc/on_summoner_wabbajacked(mob/living/source, mob/living/new_mob) + SIGNAL_HANDLER + set_summoner(new_mob) + to_chat(src, span_holoparasite("Your summoner has changed form!")) + +/// Signal proc for [COMSIG_LIVING_SHAPESHIFTED], when our summoner is shapeshifted we should change to the new mob +/mob/living/basic/guardian/proc/on_summoner_shapeshifted(mob/living/source, mob/living/new_shape) + SIGNAL_HANDLER + set_summoner(new_shape) + to_chat(src, span_holoparasite("Your summoner has shapeshifted into that of a [new_shape]!")) + +/// Signal proc for [COMSIG_LIVING_UNSHAPESHIFTED], when our summoner unshapeshifts go back to that mob +/mob/living/basic/guardian/proc/on_summoner_unshapeshifted(mob/living/source, mob/living/old_summoner) + SIGNAL_HANDLER + set_summoner(old_summoner) + to_chat(src, span_holoparasite("Your summoner has shapeshifted back into their normal form!")) + +/mob/living/basic/guardian/wabbajack(what_to_randomize, change_flags = WABBAJACK) + visible_message(span_warning("[src] resists the polymorph!")) // Ha, no + +/mob/living/basic/guardian/can_suicide() + return FALSE // You gotta persuade your boss to end it instead, sorry + +/// Returns true if you are out and about +/mob/living/basic/guardian/proc/is_deployed() + return isnull(summoner) || loc != summoner diff --git a/code/modules/mob/living/simple_animal/guardian/guardian_creator.dm b/code/modules/mob/living/basic/guardian/guardian_creator.dm similarity index 60% rename from code/modules/mob/living/simple_animal/guardian/guardian_creator.dm rename to code/modules/mob/living/basic/guardian/guardian_creator.dm index ebd5658f07f4b..7ebc9737b4106 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian_creator.dm +++ b/code/modules/mob/living/basic/guardian/guardian_creator.dm @@ -2,14 +2,15 @@ GLOBAL_LIST_INIT(guardian_radial_images, setup_guardian_radial()) /proc/setup_guardian_radial() . = list() - for(var/mob/living/simple_animal/hostile/guardian/guardian_path as anything in subtypesof(/mob/living/simple_animal/hostile/guardian)) + for(var/mob/living/basic/guardian/guardian_path as anything in subtypesof(/mob/living/basic/guardian)) var/datum/radial_menu_choice/option = new() option.name = initial(guardian_path.creator_name) option.image = image(icon = 'icons/hud/guardian.dmi', icon_state = initial(guardian_path.creator_icon)) option.info = span_boldnotice(initial(guardian_path.creator_desc)) .[guardian_path] = option -/obj/item/guardiancreator +/// An item which grants you your very own soul buddy +/obj/item/guardian_creator name = "enchanted deck of tarot cards" desc = "An enchanted deck of tarot cards, rumored to be a source of unimaginable power." icon = 'icons/obj/toys/playing_cards.dmi' @@ -31,36 +32,41 @@ GLOBAL_LIST_INIT(guardian_radial_images, setup_guardian_radial()) /// Message sent if we successfully get a guardian. var/success_message = span_holoparasite("%GUARDIAN has been summoned!") /// If true, you are given a random guardian rather than picking from a selection. - var/random = TRUE + var/random = FALSE /// If true, you can have multiple guardians at the same time. - var/allowmultiple = FALSE + var/allow_multiple = FALSE /// If true, lings can get guardians from this. - var/allowling = TRUE + var/allow_changeling = TRUE /// If true, a dextrous guardian can get their own guardian, infinite chain! - var/allowguardian = FALSE + var/allow_guardian = FALSE /// List of all the guardians this type can spawn. var/list/possible_guardians = list( //default, has everything but dextrous - /mob/living/simple_animal/hostile/guardian/assassin, - /mob/living/simple_animal/hostile/guardian/charger, - /mob/living/simple_animal/hostile/guardian/explosive, - /mob/living/simple_animal/hostile/guardian/gaseous, - /mob/living/simple_animal/hostile/guardian/gravitokinetic, - /mob/living/simple_animal/hostile/guardian/lightning, - /mob/living/simple_animal/hostile/guardian/protector, - /mob/living/simple_animal/hostile/guardian/ranged, - /mob/living/simple_animal/hostile/guardian/standard, - /mob/living/simple_animal/hostile/guardian/support, + /mob/living/basic/guardian/assassin, + /mob/living/basic/guardian/charger, + /mob/living/basic/guardian/explosive, + /mob/living/basic/guardian/gaseous, + /mob/living/basic/guardian/gravitokinetic, + /mob/living/basic/guardian/lightning, + /mob/living/basic/guardian/protector, + /mob/living/basic/guardian/ranged, + /mob/living/basic/guardian/standard, + /mob/living/basic/guardian/support, ) -/obj/item/guardiancreator/attack_self(mob/living/user) - if(isguardian(user) && !allowguardian) - to_chat(user, span_holoparasite("[mob_name] chains are not allowed.")) +/obj/item/guardian_creator/Initialize(mapload) + . = ..() + var/datum/guardian_fluff/using_theme = GLOB.guardian_themes[theme] + mob_name = using_theme.name + +/obj/item/guardian_creator/attack_self(mob/living/user) + if(isguardian(user) && !allow_guardian) + balloon_alert(user, "can't do that!") return var/list/guardians = user.get_all_linked_holoparasites() - if(length(guardians) && !allowmultiple) - to_chat(user, span_holoparasite("You already have a [mob_name]!")) + if(length(guardians) && !allow_multiple) + balloon_alert(user, "already have one!") return - if(user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling) && !allowling) + if(user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling) && !allow_changeling) to_chat(user, ling_failure) return if(used) @@ -71,19 +77,22 @@ GLOBAL_LIST_INIT(guardian_radial_images, setup_guardian_radial()) if(possible_guardian in possible_guardians) continue radial_options -= possible_guardian - var/mob/living/simple_animal/hostile/guardian/guardian_path + var/mob/living/basic/guardian/guardian_path if(random) guardian_path = pick(possible_guardians) else guardian_path = show_radial_menu(user, src, radial_options, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 42, require_near = TRUE) - if(!guardian_path) + if(isnull(guardian_path)) return used = TRUE to_chat(user, use_message) - var/guardian_type_name = "a random" - if(!random) - guardian_type_name = "the " + lowertext(initial(guardian_path.creator_name)) - var/list/mob/dead/observer/candidates = poll_ghost_candidates("Do you want to play as [guardian_type_name] [mob_name] of [user.real_name]?", ROLE_PAI, FALSE, 100, POLL_IGNORE_HOLOPARASITE) + var/guardian_type_name = random ? "Random" : capitalize(initial(guardian_path.creator_name)) + var/list/mob/dead/observer/candidates = poll_ghost_candidates( + "Do you want to play as [user.real_name]'s [guardian_type_name] [mob_name]?", + jobban_type = ROLE_PAI, + poll_time = 10 SECONDS, + ignore_category = POLL_IGNORE_HOLOPARASITE, + ) if(LAZYLEN(candidates)) var/mob/dead/observer/candidate = pick(candidates) spawn_guardian(user, candidate, guardian_path) @@ -91,124 +100,111 @@ GLOBAL_LIST_INIT(guardian_radial_images, setup_guardian_radial()) SEND_SIGNAL(src, COMSIG_TRAITOR_ITEM_USED(type)) else to_chat(user, failure_message) + used = FALSE -/obj/item/guardiancreator/proc/spawn_guardian(mob/living/user, mob/dead/candidate, guardian_path) +/// Actually create our guy +/obj/item/guardian_creator/proc/spawn_guardian(mob/living/user, mob/dead/candidate, guardian_path) if(QDELETED(user) || user.stat == DEAD) return var/list/guardians = user.get_all_linked_holoparasites() - if(length(guardians) && !allowmultiple) - to_chat(user, span_holoparasite("You already have a [mob_name]!") ) + if(length(guardians) && !allow_multiple) + balloon_alert(user, "already got one!") used = FALSE return - var/mob/living/simple_animal/hostile/guardian/summoned_guardian = new guardian_path(user, theme) + var/datum/guardian_fluff/guardian_theme = GLOB.guardian_themes[theme] + var/mob/living/basic/guardian/summoned_guardian = new guardian_path(user, guardian_theme) summoned_guardian.set_summoner(user, different_person = TRUE) summoned_guardian.key = candidate.key user.log_message("has summoned [key_name(summoned_guardian)], a [summoned_guardian.creator_name] holoparasite.", LOG_GAME) summoned_guardian.log_message("was summoned as a [summoned_guardian.creator_name] holoparasite.", LOG_GAME) - to_chat(user, summoned_guardian.used_fluff_string) + to_chat(user, guardian_theme.get_fluff_string(summoned_guardian.guardian_type)) to_chat(user, replacetext(success_message, "%GUARDIAN", mob_name)) summoned_guardian.client?.init_verbs() return summoned_guardian -/obj/item/guardiancreator/proc/check_menu(mob/living/user) +/// Checks to ensure we're still capable of using the radial selector +/obj/item/guardian_creator/proc/check_menu(mob/living/user) if(!istype(user)) return FALSE if(user.incapacitated() || !user.is_holding(src) || used) return FALSE return TRUE -/obj/item/guardiancreator/choose - random = FALSE - -/obj/item/guardiancreator/choose/all/Initialize(mapload) - . = ..() - possible_guardians = subtypesof(/mob/living/simple_animal/hostile/guardian) - -/obj/item/guardiancreator/choose/wizard - allowmultiple = TRUE - possible_guardians = list( //no support, but dextrous - /mob/living/simple_animal/hostile/guardian/assassin, - /mob/living/simple_animal/hostile/guardian/charger, - /mob/living/simple_animal/hostile/guardian/dextrous, - /mob/living/simple_animal/hostile/guardian/explosive, - /mob/living/simple_animal/hostile/guardian/gaseous, - /mob/living/simple_animal/hostile/guardian/gravitokinetic, - /mob/living/simple_animal/hostile/guardian/lightning, - /mob/living/simple_animal/hostile/guardian/protector, - /mob/living/simple_animal/hostile/guardian/ranged, - /mob/living/simple_animal/hostile/guardian/standard, +/// Guardian creator available in the wizard spellbook. All but support are available. +/obj/item/guardian_creator/wizard + allow_multiple = TRUE + possible_guardians = list( + /mob/living/basic/guardian/assassin, + /mob/living/basic/guardian/charger, + /mob/living/basic/guardian/dextrous, + /mob/living/basic/guardian/explosive, + /mob/living/basic/guardian/gaseous, + /mob/living/basic/guardian/gravitokinetic, + /mob/living/basic/guardian/lightning, + /mob/living/basic/guardian/protector, + /mob/living/basic/guardian/ranged, + /mob/living/basic/guardian/standard, ) -/obj/item/guardiancreator/choose/wizard/spawn_guardian(mob/living/user, mob/dead/candidate) - . = ..() - var/mob/guardian = . - if(!guardian) - return +/obj/item/guardian_creator/wizard/spawn_guardian(mob/living/user, mob/dead/candidate) + var/mob/guardian = ..() + if(isnull(guardian)) + return null + // Add the wizard team datum var/datum/antagonist/wizard/antag_datum = user.mind.has_antag_datum(/datum/antagonist/wizard) - if(antag_datum) - if(!antag_datum.wiz_team) - antag_datum.create_wiz_team() - guardian.mind.add_antag_datum(/datum/antagonist/wizard_minion, antag_datum.wiz_team) - -/obj/item/guardiancreator/tech + if(isnull(antag_datum)) + return guardian + if(!antag_datum.wiz_team) + antag_datum.create_wiz_team() + guardian.mind.add_antag_datum(/datum/antagonist/wizard_minion, antag_datum.wiz_team) + return guardian + +/// Guardian creator available in the traitor uplink. All but dextrous are available, you can pick which you want, and changelings cannot use it. +/obj/item/guardian_creator/tech name = "holoparasite injector" desc = "It contains an alien nanoswarm of unknown origin. Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, it requires an organic host as a home base and source of fuel." icon = 'icons/obj/medical/syringe.dmi' icon_state = "combat_hypo" theme = GUARDIAN_THEME_TECH - mob_name = "Holoparasite" + allow_changeling = FALSE use_message = span_holoparasite("You start to power on the injector...") used_message = span_holoparasite("The injector has already been used.") failure_message = span_boldholoparasite("...ERROR. BOOT SEQUENCE ABORTED. AI FAILED TO INTIALIZE. PLEASE CONTACT SUPPORT OR TRY AGAIN LATER.") ling_failure = span_boldholoparasite("The holoparasites recoil in horror. They want nothing to do with a creature like you.") success_message = span_holoparasite("%GUARDIAN is now online!") -/obj/item/guardiancreator/tech/choose - random = FALSE - -/obj/item/guardiancreator/tech/choose/all/Initialize(mapload) - . = ..() - possible_guardians = subtypesof(/mob/living/simple_animal/hostile/guardian) - -/obj/item/guardiancreator/tech/choose/traitor - allowling = FALSE - -/obj/item/guardiancreator/carp +/// Guardian creator only spawned by admins, which creates a holographic fish. You can have several of them. +/obj/item/guardian_creator/carp name = "holocarp fishsticks" desc = "Using the power of Carp'sie, you can catch a carp from byond the veil of Carpthulu, and bind it to your fleshy flesh form." icon = 'icons/obj/food/meat.dmi' icon_state = "fishfingers" theme = GUARDIAN_THEME_CARP - mob_name = "Holocarp" use_message = span_holoparasite("You put the fishsticks in your mouth...") used_message = span_holoparasite("Someone's already taken a bite out of these fishsticks! Ew.") failure_message = span_boldholoparasite("You couldn't catch any carp spirits from the seas of Lake Carp. Maybe there are none, maybe you fucked up.") ling_failure = span_boldholoparasite("Carp'sie seems to not have taken you as the chosen one. Maybe it's because of your horrifying origin.") success_message = span_holoparasite("%GUARDIAN has been caught!") - allowmultiple = TRUE + allow_multiple = TRUE -/obj/item/guardiancreator/carp/choose - random = FALSE - -/obj/item/guardiancreator/miner +/// Guardian creator available to miners from chests, very limited selection and randomly assigned. +/obj/item/guardian_creator/miner name = "dusty shard" desc = "Seems to be a very old rock, may have originated from a strange meteor." icon = 'icons/obj/mining_zones/artefacts.dmi' icon_state = "dustyshard" theme = GUARDIAN_THEME_MINER - mob_name = "Power Miner" use_message = span_holoparasite("You pierce your skin with the shard...") used_message = span_holoparasite("This shard seems to have lost all its power...") failure_message = span_boldholoparasite("The shard hasn't reacted at all. Maybe try again later...") ling_failure = span_boldholoparasite("The power of the shard seems to not react with your horrifying, mutated body.") success_message = span_holoparasite("%GUARDIAN has appeared!") - possible_guardians = list( //limited to ones useful on lavaland - /mob/living/simple_animal/hostile/guardian/charger, - /mob/living/simple_animal/hostile/guardian/protector, - /mob/living/simple_animal/hostile/guardian/ranged, - /mob/living/simple_animal/hostile/guardian/standard, - /mob/living/simple_animal/hostile/guardian/support, + random = TRUE + //limited to ones which are plausibly useful on lavaland + possible_guardians = list( + /mob/living/basic/guardian/charger, // A flying mount which can cross chasms + /mob/living/basic/guardian/protector, // Bodyblocks projectiles for you + /mob/living/basic/guardian/ranged, // Shoots the bad guys + /mob/living/basic/guardian/standard, // Can mine walls + /mob/living/basic/guardian/support, // Heals and teleports you ) - -/obj/item/guardiancreator/miner/choose - random = FALSE diff --git a/code/modules/mob/living/basic/guardian/guardian_fluff.dm b/code/modules/mob/living/basic/guardian/guardian_fluff.dm new file mode 100644 index 0000000000000..4ede238921ed3 --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_fluff.dm @@ -0,0 +1,124 @@ +/** + * Defines a theme used by guardian mobs for visuals and some text output + * The default is used for ones created by wizards + */ +/datum/guardian_fluff + /// What name do we apply before one has been selected? + var/name = "Guardian Spirit" + /// Mob description to apply + var/desc = "A mysterious being that stands by its charge, ever vigilant." + /// Are we magical or technological? Mostly just used to pick a surname + var/fluff_type = GUARDIAN_MAGIC + /// What speech bubble do we use? + var/bubble_icon = "guardian" + /// What is our base icon state? + var/icon_state = "magicbase" + /// What is the icon state for our coloured overlay? + var/overlay_state = "magic" + /// Emote used for speaking + var/list/speak_emote = list("hisses") + /// Verb shown to viewers when attacking + var/attack_verb_continuous = "punches" + /// Verb shown to attacker when attacking + var/attack_verb_simple = "punch" + /// Sound played when we attack + var/attack_sound = 'sound/weapons/punch1.ogg' + /// Visible effect when we attack + var/attack_vis_effect = ATTACK_EFFECT_PUNCH + /// An associative list of type of guardian to some kind of descriptive text to show on appearance. + var/guardian_fluff = list( + GUARDIAN_ASSASSIN = "...And draw the Space Ninja, a lethal and invisible assassin.", + GUARDIAN_CHARGER = "...And draw the Hunter, alien master of rapid assault.", + GUARDIAN_DEXTROUS = "...And draw the Monkey, ascendant beast who has learned to use tools.", + GUARDIAN_EXPLOSIVE = "...And draw the Scientist, herald of explosive death.", + GUARDIAN_GASEOUS = "...And draw the Atmospheric Technician, veiled in a purple haze.", + GUARDIAN_GRAVITOKINETIC = "...And draw the Singularity, a terrible, irresistible force..", + GUARDIAN_LIGHTNING = "...And draw the Supermatter, a shockingly lethal font of power.", + GUARDIAN_PROTECTOR = "...And draw the Corgi, a stalwart protector that never leaves the side of its charge.", + GUARDIAN_RANGED = "...And draw the Watcher, impaling its prey from afar.", + GUARDIAN_STANDARD = "...And draw the Assistant, faceless but never to be underestimated.", + GUARDIAN_SUPPORT = "...And draw the Paramedic, arbiter of life and death.", + ) + +/// Applies relevant visual properties to our guardian +/datum/guardian_fluff/proc/apply(mob/living/basic/guardian/guardian) + guardian.name = name + guardian.real_name = name + guardian.bubble_icon = bubble_icon + guardian.icon_living = icon_state + guardian.icon_state = icon_state + + guardian.speak_emote = speak_emote + guardian.attack_verb_continuous = attack_verb_continuous + guardian.attack_verb_simple = attack_verb_simple + guardian.attack_sound = attack_sound + guardian.attack_vis_effect = attack_vis_effect + + guardian.overlay = mutable_appearance(guardian.icon, overlay_state) + +/// Output an appropriate fluff string for our guardian when it is created +/datum/guardian_fluff/proc/get_fluff_string(guardian_type) + return span_holoparasite(guardian_fluff[guardian_type] || "You bring forth a glitching abomination, something which should not be! Please contact a coder about it.") + +/// Used by holoparasites in the Traitor uplink +/datum/guardian_fluff/tech + name = "Holoparasite" + fluff_type = GUARDIAN_TECH + bubble_icon = "holo" + icon_state = "techbase" + overlay_state = "tech" + guardian_fluff = list( + GUARDIAN_ASSASSIN = "Boot sequence complete. Stealth modules loaded. Holoparasite swarm online.", + GUARDIAN_CHARGER = "Boot sequence complete. Overclocking motive engines. Holoparasite swarm online.", + GUARDIAN_DEXTROUS = "Boot sequence complete. Armed combat routines loaded. Holoparasite swarm online.", + GUARDIAN_EXPLOSIVE = "Boot sequence complete. Payload generator online. Holoparasite swarm online.", + GUARDIAN_GASEOUS = "Boot sequence complete. Atmospheric projectors operational. Holoparasite swarm online.", + GUARDIAN_GRAVITOKINETIC = "Boot sequence complete. Gravitic engine spinning up. Holoparasite swarm online.", + GUARDIAN_LIGHTNING = "Boot sequence complete. Tesla projectors charged. Holoparasite swarm online.", + GUARDIAN_PROTECTOR = "Boot sequence complete. Bodyguard routines loaded. Holoparasite swarm online.", + GUARDIAN_RANGED = "Boot sequence complete. Flechette launchers operational. Holoparasite swarm online.", + GUARDIAN_STANDARD = "Boot sequence complete. CQC suite engaged. Holoparasite swarm online.", + GUARDIAN_SUPPORT = "Boot sequence complete. Medical suite active. Holoparasite swarm online.", + ) + +/// Used by powerminers found in necropolis chests +/datum/guardian_fluff/miner + name = "Power Miner" + icon_state = "minerbase" + overlay_state = "miner" + guardian_fluff = list( + GUARDIAN_ASSASSIN = "The shard reveals... Glass, a sharp but fragile ambusher.", + GUARDIAN_CHARGER = "The shard reveals... Titanium, a lightweight, agile fighter.", + GUARDIAN_DEXTROUS = "The shard reveals... Gold, a malleable hoarder of treasure.", + GUARDIAN_EXPLOSIVE = "The shard reveals... Gibtonite, volatile and surprising.", + GUARDIAN_GASEOUS = "The shard reveals... Plasma, the bringer of flame.", + GUARDIAN_GRAVITOKINETIC = "The shard reveals... Bananium, a manipulator of motive forces.", + GUARDIAN_LIGHTNING = "The shard reveals... Iron, a conductive font of lightning.", + GUARDIAN_PROTECTOR = "The shard reveals... Uranium, dense and resistant.", + GUARDIAN_RANGED = "The shard reveals... Diamond, projecting a million sharp edges.", + GUARDIAN_STANDARD = "The shard reveals... Plastitanium, a powerful fighter.", + GUARDIAN_SUPPORT = "The shard reveals... Bluespace, master of relocation.", + ) + +/// Used by holocarp spawned by admins +/datum/guardian_fluff/carp + name = "Holocarp" + fluff_type = GUARDIAN_TECH + desc = "A mysterious fish that swims by its charge, ever fingilant." + icon_state = null // Handled entirely by the overlay + bubble_icon = "holo" + overlay_state = "carp" + speak_emote = list("gnashes") + guardian_fluff = list( + GUARDIAN_ASSASSIN = "CARP CARP CARP! Caught one! It's an assassin carp! Just when you thought it was safe to go back to the water... which is unhelpful, because we're in space.", + GUARDIAN_CHARGER = "CARP CARP CARP! Caught one! It's a charger carp which likes running at people. But it doesn't have any legs...", + GUARDIAN_DEXTROUS = "CARP CARP CARP! You caught one! It's a dextrous carp ready to slap people with a fish, once it picks one up.", + GUARDIAN_EXPLOSIVE = "CARP CARP CARP! Caught one! It's an explosive carp! You two are going to have a blast.", + GUARDIAN_GASEOUS = "CARP CARP CARP! You caught one! It's a gaseous carp, but don't worry it actually smells pretty good!", + GUARDIAN_GRAVITOKINETIC = "CARP CARP CARP! Caught one! It's a gravitokinetic carp! Now do you understand the gravity of the situation?", + GUARDIAN_LIGHTNING = "CARP CARP CARP! Caught one! It's a lightning carp! What a shocking result!", + GUARDIAN_PROTECTOR = "CARP CARP CARP! You caught one! Wait, no... it caught you! The fisher has become the fishy...", + GUARDIAN_RANGED = "CARP CARP CARP! You caught one! It's a ranged carp! It has been collecting glass shards in preparation for this moment.", + GUARDIAN_STANDARD = "CARP CARP CARP! You caught one! This one is a little generic and disappointing... Better punch through some walls to ease the tension.", + GUARDIAN_SUPPORT = "CARP CARP CARP! You caught a support carp! Now it's here, now you're over there!", + ) diff --git a/code/modules/mob/living/basic/guardian/guardian_helpers.dm b/code/modules/mob/living/basic/guardian/guardian_helpers.dm new file mode 100644 index 0000000000000..df50a43e6a099 --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_helpers.dm @@ -0,0 +1,13 @@ +/// Returns a list of all holoparasites that has this mob as a summoner. +/mob/living/proc/get_all_linked_holoparasites() + RETURN_TYPE(/list) + var/list/all_parasites = list() + for(var/mob/living/basic/guardian/stand as anything in GLOB.parasites) + if (stand.summoner != src) + continue + all_parasites += stand + return all_parasites + +/// Returns true if this holoparasite has the same summoner as the passed holoparasite. +/mob/living/basic/guardian/proc/shares_summoner(mob/living/basic/guardian/other_guardian) + return istype(other_guardian) && other_guardian.summoner == summoner diff --git a/code/modules/mob/living/basic/guardian/guardian_types/assassin.dm b/code/modules/mob/living/basic/guardian/guardian_types/assassin.dm new file mode 100644 index 0000000000000..d62b9bcedea77 --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_types/assassin.dm @@ -0,0 +1,116 @@ +#define CAN_STEALTH_ALERT "can_stealth" + +/** + * Can enter stealth mode to become invisible and deal bonus damage on their next attack, an ambush predator. + */ +/mob/living/basic/guardian/assassin + guardian_type = GUARDIAN_ASSASSIN + melee_damage_lower = 15 + melee_damage_upper = 15 + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" + attack_sound = 'sound/weapons/bladeslice.ogg' + attack_vis_effect = ATTACK_EFFECT_SLASH + sharpness = SHARP_POINTY + damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) + playstyle_string = span_holoparasite("As an assassin type you do medium damage and have no damage resistance, but can enter stealth, massively increasing the damage of your next attack and causing it to ignore armor. Stealth is broken when you attack or take damage.") + creator_name = "Assassin" + creator_desc = "Does medium damage and takes full damage, but can enter stealth, causing its next attack to do massive damage and ignore armor. However, it becomes briefly unable to recall after attacking from stealth." + creator_icon = "assassin" + toggle_button_type = /atom/movable/screen/guardian/toggle_mode/assassin + /// How long to put stealth on cooldown if we are forced out? + var/stealth_cooldown_time = 16 SECONDS + /// Cooldown for the stealth toggle. + COOLDOWN_DECLARE(stealth_cooldown) + +/mob/living/basic/guardian/assassin/Initialize(mapload, datum/guardian_fluff/theme) + . = ..() + show_can_stealth() + RegisterSignal(src, COMSIG_GUARDIAN_ASSASSIN_REVEALED, PROC_REF(on_forced_unstealth)) + +// Toggle stealth +/mob/living/basic/guardian/assassin/toggle_modes() + var/stealthed = has_status_effect(/datum/status_effect/guardian_stealth) + if (stealthed) + to_chat(src, span_bolddanger("You exit stealth.")) + remove_status_effect(/datum/status_effect/guardian_stealth) + show_can_stealth() + return + if (COOLDOWN_FINISHED(src, stealth_cooldown)) + if (!is_deployed()) + to_chat(src, span_bolddanger("You have to be manifested to enter stealth!")) + return + apply_status_effect(/datum/status_effect/guardian_stealth) + clear_alert(CAN_STEALTH_ALERT) + return + to_chat(src, span_bolddanger("You cannot yet enter stealth, wait another [DisplayTimeText(COOLDOWN_TIMELEFT(src, stealth_cooldown))]!")) + +/mob/living/basic/guardian/assassin/get_status_tab_items() + . = ..() + if(!COOLDOWN_FINISHED(src, stealth_cooldown)) + . += "Stealth Cooldown Remaining: [DisplayTimeText(COOLDOWN_TIMELEFT(src, stealth_cooldown))]" + +/// Called when we are removed from stealth involuntarily +/mob/living/basic/guardian/assassin/proc/on_forced_unstealth(mob/living/source) + SIGNAL_HANDLER + visible_message(span_danger("\The [src] suddenly appears!")) + COOLDOWN_START(src, manifest_cooldown, 4 SECONDS) + COOLDOWN_START(src, stealth_cooldown, stealth_cooldown_time) + addtimer(CALLBACK(src, PROC_REF(show_can_stealth)), stealth_cooldown_time) + +/// Displays an alert letting us know that we can enter stealth +/mob/living/basic/guardian/assassin/proc/show_can_stealth() + if(!COOLDOWN_FINISHED(src, stealth_cooldown)) + return + throw_alert(CAN_STEALTH_ALERT, /atom/movable/screen/alert/canstealth) + +/// Status effect which makes us sneakier and do bonus damage +/datum/status_effect/guardian_stealth + id = "guardian_stealth" + alert_type = /atom/movable/screen/alert/status_effect/instealth + /// Damage added in stealth mode. + var/damage_bonus = 35 + /// Our wound bonus when in stealth mode. Allows you to actually cause wounds, unlike normal. + var/stealth_wound_bonus = -20 + +/datum/status_effect/guardian_stealth/on_apply() + new /obj/effect/temp_visual/guardian/phase/out(get_turf(owner)) + owner.melee_damage_lower += damage_bonus + owner.melee_damage_upper += damage_bonus + if (isbasicmob(owner)) + var/mob/living/basic/basic_owner = owner + basic_owner.armour_penetration = 100 + basic_owner.wound_bonus = stealth_wound_bonus + basic_owner.obj_damage = 0 + to_chat(owner, span_bolddanger("You enter stealth, empowering your next attack.")) + animate(owner, alpha = 15, time = 0.5 SECONDS) + + RegisterSignals(owner, list(COMSIG_GUARDIAN_RECALLED, COMSIG_HOSTILE_POST_ATTACKINGTARGET), PROC_REF(forced_exit)) + RegisterSignals(owner, COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES, PROC_REF(on_health_changed)) + return TRUE + +/datum/status_effect/guardian_stealth/on_remove() + owner.melee_damage_lower -= damage_bonus + owner.melee_damage_upper -= damage_bonus + if (isbasicmob(owner)) + var/mob/living/basic/basic_owner = owner + basic_owner.armour_penetration = initial(basic_owner.armour_penetration) + basic_owner.wound_bonus = initial(basic_owner.wound_bonus) + basic_owner.obj_damage = initial(basic_owner.obj_damage) + animate(owner, alpha = initial(owner.alpha), time = 0.5 SECONDS) + UnregisterSignal(owner, list(COMSIG_GUARDIAN_RECALLED, COMSIG_HOSTILE_POST_ATTACKINGTARGET) + COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES) + +/// If we take damage, exit the status effect +/datum/status_effect/guardian_stealth/proc/on_health_changed(mob/living/our_mob, type, amount, forced) + SIGNAL_HANDLER + if (amount <= 0) + return + forced_exit() + +/// Forcibly exit the status effect +/datum/status_effect/guardian_stealth/proc/forced_exit() + SIGNAL_HANDLER + SEND_SIGNAL(owner, COMSIG_GUARDIAN_ASSASSIN_REVEALED) + qdel(src) + +#undef CAN_STEALTH_ALERT diff --git a/code/modules/mob/living/basic/guardian/guardian_types/charger.dm b/code/modules/mob/living/basic/guardian/guardian_types/charger.dm new file mode 100644 index 0000000000000..02f839c6a415d --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_types/charger.dm @@ -0,0 +1,69 @@ +/** + * Very fast, has a charging attack, and most importantly can be ridden like a horse. + */ +/mob/living/basic/guardian/charger + guardian_type = GUARDIAN_CHARGER + melee_damage_lower = 15 + melee_damage_upper = 15 + speed = -0.5 + damage_coeff = list(BRUTE = 0.75, BURN = 0.75, TOX = 0.75, CLONE = 0.75, STAMINA = 0, OXY = 0.75) + playstyle_string = span_holoparasite("As a charger type you do medium damage, have light damage resistance, move very fast, can be ridden, and can charge at a location, damaging any target hit and forcing them to drop any items they are holding.") + creator_name = "Charger" + creator_desc = "Moves very fast, does medium damage on attack, can be ridden and can charge at targets, damaging the first target hit and forcing them to drop any items they are holding." + creator_icon = "charger" + +/mob/living/basic/guardian/charger/Initialize(mapload, datum/guardian_fluff/theme) + . = ..() + AddElement(/datum/element/ridable, /datum/component/riding/creature/guardian) + var/datum/action/cooldown/mob_cooldown/charge/basic_charge/guardian/charge = new(src) + charge.Grant(src) + charge.set_click_ability(src) + +/// Guardian charger's charging attack, it knocks items out of people's hands +/datum/action/cooldown/mob_cooldown/charge/basic_charge/guardian + name = "Charge!" + cooldown_time = 4 SECONDS + melee_cooldown_time = 0 SECONDS + button_icon = 'icons/effects/effects.dmi' + button_icon_state = "speed" + background_icon = 'icons/hud/guardian.dmi' + background_icon_state = "base" + charge_delay = 0 + recoil_duration = 0 + charge_damage = 20 + charge_distance = 10 + unset_after_click = FALSE + destroy_objects = FALSE + +/datum/action/cooldown/mob_cooldown/charge/basic_charge/guardian/PreActivate(atom/target) + if (!isguardian(owner)) + return ..() + var/mob/living/basic/guardian/guardian_owner = owner + if (guardian_owner.is_deployed()) + return ..() + return FALSE + +/datum/action/cooldown/mob_cooldown/charge/basic_charge/guardian/do_charge_indicator(atom/charger, atom/charge_target) + playsound(charger, 'sound/items/modsuit/loader_launch.ogg', 75, TRUE) + var/obj/effect/temp_visual/decoy/decoy_flash = new /obj/effect/temp_visual/decoy(charger.loc, charger) + animate(decoy_flash, alpha = 0, color = "#FF0000", transform = matrix() * 2, time = 3) + +/datum/action/cooldown/mob_cooldown/charge/basic_charge/guardian/can_hit_target(atom/movable/source, atom/target) + var/mob/living/living_target = target + if (!istype(living_target)) + return FALSE + var/mob/living/basic/guardian/guardian_owner = owner + if (!istype(guardian_owner)) + return TRUE + if (living_target == guardian_owner.summoner || guardian_owner.shares_summoner(target)) + return FALSE + return TRUE + +/datum/action/cooldown/mob_cooldown/charge/basic_charge/guardian/hit_target(atom/movable/source, mob/living/target, damage_dealt) + if(ishuman(target)) + var/mob/living/carbon/human/hit_human = target + if(hit_human.check_shields(src, charge_damage, name, attack_type = LEAP_ATTACK)) + return + . = ..() + var/mob/living/hit_mob = target + hit_mob.drop_all_held_items() diff --git a/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm b/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm new file mode 100644 index 0000000000000..ed54a23771d2a --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm @@ -0,0 +1,100 @@ +/// Dextrous guardians have some of the most powerful abilities of all: hands and pockets +/mob/living/basic/guardian/dextrous + guardian_type = GUARDIAN_DEXTROUS + melee_damage_lower = 10 + melee_damage_upper = 10 + damage_coeff = list(BRUTE = 0.75, BURN = 0.75, TOX = 0.75, CLONE = 0.75, STAMINA = 0, OXY = 0.75) + playstyle_string = span_holoparasite("As a dextrous type you can hold items, store an item within yourself, and have medium damage resistance, but do low damage on attacks. Recalling and leashing will force you to drop unstored items!") + creator_name = "Dextrous" + creator_desc = "Does low damage on attack, but is capable of holding items and storing a single item within it. It will drop items held in its hands when it recalls, but it will retain the stored item." + creator_icon = "dextrous" + hud_type = /datum/hud/dextrous/guardian + held_items = list(null, null) + /// An internal pocket we can put stuff in + var/obj/item/internal_storage + +/mob/living/basic/guardian/dextrous/Initialize(mapload, datum/guardian_fluff/theme) + . = ..() + add_traits(list(TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP), ROUNDSTART_TRAIT) + AddElement(/datum/element/dextrous, hud_type = hud_type) + AddComponent(/datum/component/personal_crafting) + AddComponent(/datum/component/basic_inhands) + +/mob/living/basic/guardian/dextrous/death(gibbed) + dropItemToGround(internal_storage) + return ..() + +/mob/living/basic/guardian/dextrous/examine(mob/user) + . = ..() + if(isnull(internal_storage) || (internal_storage.item_flags & ABSTRACT)) + return + . += span_info("It is holding [internal_storage.get_examine_string(user)] in its internal storage.") + +/mob/living/basic/guardian/dextrous/recall_effects() + . = ..() + drop_all_held_items() + +// Bullshit related to having a fake pocket begins here + +/mob/living/basic/guardian/dextrous/doUnEquip(obj/item/equipped_item, force, newloc, no_move, invdrop = TRUE, silent = FALSE) + . = ..() + if (!.) + return FALSE + update_held_items() + if(equipped_item == internal_storage) + internal_storage = null + update_inv_internal_storage() + return TRUE + +/mob/living/basic/guardian/dextrous/can_equip(mob/living/M, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, ignore_equipped = FALSE, indirect_action = FALSE) + if(slot != ITEM_SLOT_DEX_STORAGE) + return FALSE + return isnull(internal_storage) + +/mob/living/basic/guardian/dextrous/get_item_by_slot(slot_id) + if(slot_id == ITEM_SLOT_DEX_STORAGE) + return internal_storage + return ..() + +/mob/living/basic/guardian/dextrous/get_slot_by_item(obj/item/looking_for) + if(internal_storage == looking_for) + return ITEM_SLOT_DEX_STORAGE + return ..() + +/mob/living/basic/guardian/dextrous/equip_to_slot(obj/item/equipping, slot, initial = FALSE, redraw_mob = FALSE, indirect_action = FALSE) + if (slot != ITEM_SLOT_DEX_STORAGE) + to_chat(src, span_danger("You are trying to equip this item to an unsupported inventory slot. Report this to a coder!")) + return FALSE + + var/index = get_held_index_of_item(equipping) + if(index) + held_items[index] = null + update_held_items() + + if(equipping.pulledby) + equipping.pulledby.stop_pulling() + + equipping.screen_loc = null // will get moved if inventory is visible + equipping.forceMove(src) + SET_PLANE_EXPLICIT(equipping, ABOVE_HUD_PLANE, src) + + internal_storage = equipping + update_inv_internal_storage() + + equipping.on_equipped(src, slot) + return TRUE + +/mob/living/basic/guardian/dextrous/getBackSlot() + return ITEM_SLOT_DEX_STORAGE + +/mob/living/basic/guardian/dextrous/getBeltSlot() + return ITEM_SLOT_DEX_STORAGE + +/mob/living/basic/guardian/dextrous/proc/update_inv_internal_storage() + if(isnull(internal_storage) || isnull(client) || !hud_used?.hud_shown) + return + internal_storage.screen_loc = ui_id + client.screen += internal_storage + +/mob/living/basic/guardian/dextrous/regenerate_icons() + update_inv_internal_storage() diff --git a/code/modules/mob/living/basic/guardian/guardian_types/explosive.dm b/code/modules/mob/living/basic/guardian/guardian_types/explosive.dm new file mode 100644 index 0000000000000..db59c3209d0f9 --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_types/explosive.dm @@ -0,0 +1,77 @@ +/// A durable guardian which can convert objects into hidden explosives. +/mob/living/basic/guardian/explosive + guardian_type = GUARDIAN_EXPLOSIVE + melee_damage_lower = 15 + melee_damage_upper = 15 + damage_coeff = list(BRUTE = 0.6, BURN = 0.6, TOX = 0.6, CLONE = 0.6, STAMINA = 0, OXY = 0.6) + range = 13 + playstyle_string = span_holoparasite("As an explosive type, you have moderate close combat abilities and are capable of converting nearby items and objects into disguised bombs via right-click.") + creator_name = "Explosive" + creator_desc = "High damage resist and medium power attack. Can turn any object, including objects too large to pick up, into a bomb, dealing explosive damage to the next person to touch it. The object will return to normal after the trap is triggered or after a delay." + creator_icon = "explosive" + /// Ability which plants bombs + var/datum/action/cooldown/mob_cooldown/explosive_booby_trap/bomb + +/mob/living/basic/guardian/explosive/Initialize(mapload, datum/guardian_fluff/theme) + . = ..() + bomb = new(src) + bomb.Grant(src) + +/mob/living/basic/guardian/explosive/Destroy() + QDEL_NULL(bomb) + return ..() + +/mob/living/basic/guardian/explosive/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) + if(LAZYACCESS(modifiers, RIGHT_CLICK) && proximity_flag && isobj(attack_target)) + bomb.Trigger(target = attack_target) + return + return ..() + + +/// An ability which can turn an object into a bomb +/datum/action/cooldown/mob_cooldown/explosive_booby_trap + name = "Explosive Trap" + desc = "Convert an inanimate object into a deadly and mostly undetectable explosive, triggered on touch." + button_icon = 'icons/mob/actions/actions_spells.dmi' + button_icon_state = "smoke" + cooldown_time = 20 SECONDS + melee_cooldown_time = 0 SECONDS + background_icon = 'icons/hud/guardian.dmi' + background_icon_state = "base" + /// After this amount of time passses, bomb deactivates. + var/decay_time = 1 MINUTES + /// Static list of signals that activate the bomb. + var/static/list/boom_signals = list(COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_BUMPED, COMSIG_ATOM_ATTACK_HAND) + +/datum/action/cooldown/mob_cooldown/explosive_booby_trap/PreActivate(atom/target) + if (!isobj(target)) + return FALSE + if (!owner.Adjacent(target)) + return FALSE + return ..() + +/datum/action/cooldown/mob_cooldown/explosive_booby_trap/Activate(atom/target) + var/glow_colour = COLOR_RED + var/mob/living/basic/guardian/guardian_owner = owner + if (istype(guardian_owner)) + glow_colour = guardian_owner.guardian_colour + target.AddComponent(\ + /datum/component/direct_explosive_trap, \ + saboteur = owner, \ + expire_time = decay_time, \ + glow_colour = glow_colour,\ + explosive_checks = CALLBACK(src, PROC_REF(validate_target)), \ + triggering_signals = boom_signals, \ + ) + target.balloon_alert(owner, "bomb planted") + StartCooldown() + return TRUE + +/// Validate that we should blow up on this thing, preferably not on one of our allies +/datum/action/cooldown/mob_cooldown/explosive_booby_trap/proc/validate_target(mob/living/target) + if (target == owner) + return FALSE + var/mob/living/basic/guardian/guardian_owner = owner + if (!istype(guardian_owner)) + return TRUE + return target != guardian_owner.summoner && !guardian_owner.shares_summoner(target) diff --git a/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm b/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm new file mode 100644 index 0000000000000..6790916be0793 --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm @@ -0,0 +1,159 @@ +/// Not particularly resistant, but versatile due to the selection of gases it can generate. +/mob/living/basic/guardian/gaseous + guardian_type = GUARDIAN_GASEOUS + melee_damage_lower = 10 + melee_damage_upper = 10 + damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 0) + range = 7 + playstyle_string = span_holoparasite("As a gaseous type, you have only light damage resistance, but you can expel gas in an area. In addition, your punches cause sparks, and you make your summoner inflammable.") + creator_name = "Gaseous" + creator_desc = "Creates sparks on touch and continuously expels a gas of its choice. Automatically extinguishes the user if they catch on fire." + creator_icon = "gaseous" + toggle_button_type = /atom/movable/screen/guardian/toggle_mode/gases + /// Ability we use to select gases + var/datum/action/cooldown/mob_cooldown/expel_gas/gas + /// Rate of temperature stabilization per second. + var/temp_stabilization_rate = 0.1 + +/mob/living/basic/guardian/gaseous/Initialize(mapload, theme) + . = ..() + RegisterSignal(src, COMSIG_ATOM_PRE_PRESSURE_PUSH, PROC_REF(pre_pressure_moved)) + gas = new(src) + gas.owner_has_control = FALSE // It's nicely integrated with the Guardian UI, no need to have two buttons + gas.Grant(src) + +/mob/living/basic/guardian/gaseous/Destroy() + QDEL_NULL(gas) + return ..() + +/mob/living/basic/guardian/gaseous/toggle_modes() + gas.Trigger() + +/mob/living/basic/guardian/gaseous/set_summoner(mob/living/to_who, different_person) + . = ..() + if (QDELETED(src)) + return + RegisterSignal(summoner, COMSIG_LIVING_IGNITED, PROC_REF(on_summoner_ignited)) + RegisterSignal(summoner, COMSIG_LIVING_LIFE, PROC_REF(on_summoner_life)) + +/mob/living/basic/guardian/gaseous/cut_summoner(different_person) + if (!isnull(summoner)) + UnregisterSignal(summoner, list(COMSIG_LIVING_IGNITED, COMSIG_LIVING_LIFE)) + return ..() + +/// Prevent our summoner from being on fire +/mob/living/basic/guardian/gaseous/proc/on_summoner_ignited(mob/living/source) + SIGNAL_HANDLER + source.extinguish_mob() + source.set_fire_stacks(0, remove_wet_stacks = FALSE) + +/// Maintain our summoner at a stable body temperature +/mob/living/basic/guardian/gaseous/proc/on_summoner_life(mob/living/source, seconds_per_tick, times_fired) + SIGNAL_HANDLER + source.adjust_bodytemperature(get_temp_change_amount((summoner.get_body_temp_normal() - summoner.bodytemperature), temp_stabilization_rate * seconds_per_tick)) + +/mob/living/basic/guardian/gaseous/melee_attack(atom/target, list/modifiers, ignore_cooldown) + . = ..() + if(!. || !isliving(target)) + return + do_sparks(1, TRUE, target) + +/mob/living/basic/guardian/gaseous/recall_effects() + . = ..() + if(!isnull(summoner)) + UnregisterSignal(summoner, COMSIG_ATOM_PRE_PRESSURE_PUSH) + +/mob/living/basic/guardian/gaseous/manifest_effects() + . = ..() + if (!isnull(summoner)) + RegisterSignal(summoner, COMSIG_ATOM_PRE_PRESSURE_PUSH, PROC_REF(pre_pressure_moved)) + +/// We stand firm in the face of gas +/mob/living/basic/guardian/gaseous/proc/pre_pressure_moved(datum/source) + SIGNAL_HANDLER + return COMSIG_ATOM_BLOCKS_PRESSURE + + +/// Expel a range of gases +/datum/action/cooldown/mob_cooldown/expel_gas + name = "Release Gas" + desc = "Start or stop expelling a selected gas into the environment." + button_icon = 'icons/mob/actions/actions_spells.dmi' + button_icon_state = "smoke" + cooldown_time = 0 SECONDS // We're here for the interface not the cooldown + melee_cooldown_time = 0 SECONDS + click_to_activate = FALSE + /// Gas being expelled. + var/active_gas = null + /// Associative list of types of gases to moles we create every life tick. + var/static/list/possible_gases = list( + /datum/gas/oxygen = 50, + /datum/gas/nitrogen = 750, //overpressurizing is hard!. + /datum/gas/water_vapor = 1, //you need incredibly little water vapor for the effects to kick in + /datum/gas/nitrous_oxide = 15, + /datum/gas/carbon_dioxide = 50, + /datum/gas/plasma = 3, + /datum/gas/bz = 10, + ) + +/datum/action/cooldown/mob_cooldown/expel_gas/Grant(mob/granted_to) + . = ..() + if (isnull(owner)) + return + RegisterSignal(owner, COMSIG_GUARDIAN_RECALLED, PROC_REF(stop_gas)) + +/datum/action/cooldown/mob_cooldown/expel_gas/Remove(mob/removed_from) + UnregisterSignal(owner, list(COMSIG_GUARDIAN_RECALLED, COMSIG_LIVING_LIFE)) + return ..() + +/datum/action/cooldown/mob_cooldown/expel_gas/Activate(atom/target) + StartCooldown(360 SECONDS) + // Regeneated each time just in case someone fucks with our list + var/list/gas_selection = list("None") + for(var/datum/gas/gas as anything in possible_gases) + gas_selection[initial(gas.name)] = gas + + var/picked_gas = tgui_input_list(owner, "Select a gas to emit.", "Gas Producer", gas_selection) + StartCooldown() + if(picked_gas == "None") + stop_gas() + return + + var/gas_type = gas_selection[picked_gas] + if(isnull(picked_gas) || isnull(gas_type)) + return + + to_chat(owner, span_bolddanger("You start releasing [picked_gas].")) + owner.investigate_log("set their gas type to [picked_gas].", INVESTIGATE_ATMOS) + var/had_gas = !isnull(active_gas) + active_gas = gas_type + if(isnull(owner.particles)) + owner.particles = new /particles/smoke/steam() + owner.particles.position = list(-1, 8, 0) + owner.particles.fadein = 5 + owner.particles.height = 200 + var/datum/gas/chosen_gas = active_gas // Casting it so that we can access gas vars in initial, it's still a typepath + owner.particles.color = initial(chosen_gas.primary_color) + if (!had_gas) + RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(on_life)) + +/// Turns off the gas +/datum/action/cooldown/mob_cooldown/expel_gas/proc/stop_gas() + SIGNAL_HANDLER + if (!isnull(active_gas)) + to_chat(src, span_notice("You stop releasing gas.")) + active_gas = null + QDEL_NULL(owner.particles) + UnregisterSignal(owner, COMSIG_LIVING_LIFE) + +/// Release gas every life tick while active +/datum/action/cooldown/mob_cooldown/expel_gas/proc/on_life(datum/source, seconds_per_tick, times_fired) + SIGNAL_HANDLER + if (isnull(active_gas)) + return // We shouldn't even be registered at this point but just in case + var/datum/gas_mixture/mix_to_spawn = new() + mix_to_spawn.add_gas(active_gas) + mix_to_spawn.gases[active_gas][MOLES] = possible_gases[active_gas] * seconds_per_tick + mix_to_spawn.temperature = T20C + var/turf/open/our_turf = get_turf(owner) + our_turf.assume_air(mix_to_spawn) diff --git a/code/modules/mob/living/basic/guardian/guardian_types/gravitokinetic.dm b/code/modules/mob/living/basic/guardian/guardian_types/gravitokinetic.dm new file mode 100644 index 0000000000000..a0ad9c8c21b5f --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_types/gravitokinetic.dm @@ -0,0 +1,107 @@ +/// Somewhat durable guardian who can increase gravity in an area +/mob/living/basic/guardian/gravitokinetic + guardian_type = GUARDIAN_GRAVITOKINETIC + melee_damage_lower = 15 + melee_damage_upper = 15 + damage_coeff = list(BRUTE = 0.75, BURN = 0.75, TOX = 0.75, CLONE = 0.75, STAMINA = 0, OXY = 0.75) + playstyle_string = span_holoparasite("As a gravitokinetic type, you can right-click to make the gravity on the ground stronger, and punching applies this effect to a target.") + creator_name = "Gravitokinetic" + creator_desc = "Attacks will apply crushing gravity to the target. Can target the ground as well to slow targets advancing on you, but you are not immune to your own such effects." + creator_icon = "gravitokinetic" + /// Targets we have applied our gravity effects on. + var/list/gravity_targets = list() + /// Distance at which our ability works + var/gravity_power_range = 10 + /// Gravity added on punches. + var/punch_gravity = 5 + /// Gravity added to turfs. + var/turf_gravity = 3 + +/mob/living/basic/guardian/gravitokinetic/Initialize(mapload, datum/guardian_fluff/theme) + . = ..() + AddElement(/datum/element/forced_gravity, 1) + + var/static/list/container_connections = list( + COMSIG_MOVABLE_MOVED = PROC_REF(on_moved), + ) + AddComponent(/datum/component/connect_containers, src, container_connections) + RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) + +/mob/living/basic/guardian/gravitokinetic/set_summoner(mob/living/to_who, different_person) + . = ..() + if (!QDELETED(src)) + return + to_who.AddElement(/datum/element/forced_gravity, 1) + +/mob/living/basic/guardian/gravitokinetic/cut_summoner(different_person) + summoner?.RemoveElement(/datum/element/forced_gravity, 1) + return ..() + +/mob/living/basic/guardian/gravitokinetic/death(gibbed) + . = ..() + clear_gravity() + +/mob/living/basic/guardian/gravitokinetic/recall_effects() + . = ..() + if (length(gravity_targets)) + to_chat(src, span_bolddanger("You have released your gravitokinetic powers!")) + clear_gravity() + +/mob/living/basic/guardian/gravitokinetic/melee_attack(atom/target, list/modifiers, ignore_cooldown) + . = ..() + if (!. || !isliving(target) || target == src || target == summoner || shares_summoner(target) || gravity_targets[target]) + return + to_chat(src, span_bolddanger("Your punch has applied heavy gravity to [target]!")) + add_gravity(target, punch_gravity) + to_chat(target, span_userdanger("Everything feels really heavy!")) + return TRUE + +/mob/living/basic/guardian/gravitokinetic/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) + if (LAZYACCESS(modifiers, RIGHT_CLICK) && proximity_flag && !gravity_targets[attack_target]) + slam_turf(attack_target) + return + return ..() + +/// Apply forced gravity to the floor +/mob/living/basic/guardian/gravitokinetic/proc/slam_turf(turf/open/slammed) + if (!isopenturf(slammed) || isgroundlessturf(slammed)) + return + visible_message(span_danger("[src] slams their fist into the [slammed]!"), span_notice("You amplify gravity around the [slammed].")) + do_attack_animation(slammed) + add_gravity(slammed, turf_gravity) + +/// Remove our forced gravity from all targets +/mob/living/basic/guardian/gravitokinetic/proc/clear_gravity() + for(var/gravity_target in gravity_targets) + remove_gravity(gravity_target) + +/// Make something heavier +/mob/living/basic/guardian/gravitokinetic/proc/add_gravity(atom/target, new_gravity = 3) + if (gravity_targets[target]) + return + target.AddElement(/datum/element/forced_gravity, new_gravity) + gravity_targets[target] = new_gravity + RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(on_target_moved)) + playsound(src, 'sound/effects/gravhit.ogg', 100, TRUE) + +/// Stop making something heavier +/mob/living/basic/guardian/gravitokinetic/proc/remove_gravity(atom/target, too_far = FALSE) + if (isnull(gravity_targets[target])) + return + if (too_far) + to_chat(src, span_bolddanger("You are too far away from [target] to amplify gravity's hold on them!")) + UnregisterSignal(target, COMSIG_MOVABLE_MOVED) + target.RemoveElement(/datum/element/forced_gravity, gravity_targets[target]) + gravity_targets -= target + +/// When we or something we are inside move check if we are now too far away +/mob/living/basic/guardian/gravitokinetic/proc/on_moved() + for(var/gravity_target in gravity_targets) + if (get_dist(src, gravity_target) > gravity_power_range) + remove_gravity(gravity_target, too_far = TRUE) + +/// When something we put gravity on moves check if it's too far away +/mob/living/basic/guardian/gravitokinetic/proc/on_target_moved(atom/movable/moving_target, old_loc, dir, forced) + SIGNAL_HANDLER + if (get_dist(src, moving_target) > gravity_power_range) + remove_gravity(moving_target, too_far = TRUE) diff --git a/code/modules/mob/living/basic/guardian/guardian_types/lightning.dm b/code/modules/mob/living/basic/guardian/guardian_types/lightning.dm new file mode 100644 index 0000000000000..e25184372db77 --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_types/lightning.dm @@ -0,0 +1,95 @@ +/// A reasonably durable guardian linked to you by a chain of lightning, zapping people who get between you +/mob/living/basic/guardian/lightning + guardian_type = GUARDIAN_LIGHTNING + melee_damage_lower = 7 + melee_damage_upper = 7 + attack_verb_continuous = "shocks" + attack_verb_simple = "shock" + melee_damage_type = BURN + attack_sound = 'sound/machines/defib_zap.ogg' + damage_coeff = list(BRUTE = 0.7, BURN = 0.7, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7) + range = 7 + playstyle_string = span_holoparasite("As a lightning type, you will apply lightning chains to targets on attack and have a lightning chain to your summoner. Lightning chains will shock anyone near them.") + creator_name = "Lightning" + creator_desc = "Attacks apply lightning chains to targets. Has a lightning chain to the user. Lightning chains shock everything near them, doing constant damage." + creator_icon = "lightning" + /// Link between us and our summoner + var/datum/component/summoner_chain + /// Associative list of chained enemies to their chains + var/list/enemy_chains + +/mob/living/basic/guardian/lightning/death(gibbed) + . = ..() + clear_chains() + +/mob/living/basic/guardian/lightning/Destroy() + clear_chains() + return ..() + +/mob/living/basic/guardian/lightning/manifest_effects() + . = ..() + if (isnull(summoner)) + return + summoner_chain = chain_to(summoner, max_range = INFINITY) // Functionally it's actually our leash range but admins might fuck with it + +/mob/living/basic/guardian/lightning/recall_effects() + . = ..() + clear_chains() + +/// Remove all of our chains +/mob/living/basic/guardian/lightning/proc/clear_chains() + QDEL_NULL(summoner_chain) + QDEL_LIST_ASSOC_VAL(enemy_chains) + +/mob/living/basic/guardian/lightning/melee_attack(atom/target, list/modifiers, ignore_cooldown) + . = ..() + if (!. || !validate_target(target) || (target in enemy_chains)) + return + if (length(enemy_chains) == 2) + var/old_target = enemy_chains[1] + var/datum/old_chain = enemy_chains[old_target] + qdel(old_chain) + var/datum/new_chain = chain_to(target) + RegisterSignal(new_chain, COMSIG_QDELETING, PROC_REF(on_chain_deleted)) + LAZYADDASSOC(enemy_chains, target, new_chain) + +/// Create a damaging lightning chain between ourselves and a target +/mob/living/basic/guardian/lightning/proc/chain_to(atom/target, max_range = 7) + var/datum/component/chain = AddComponent(\ + /datum/component/damage_chain, \ + linked_to = target, \ + max_distance = max_range, \ + beam_state = "lightning[rand(1,12)]", \ + beam_type = /obj/effect/ebeam/chain, \ + validate_target = CALLBACK(src, PROC_REF(validate_target)), \ + chain_damage_feedback = CALLBACK(src, PROC_REF(on_chain_zap)), \ + ) + return chain + +/// Handle losing our reference when we delete a chain +/mob/living/basic/guardian/lightning/proc/on_chain_deleted(datum/source) + SIGNAL_HANDLER + for (var/target in enemy_chains) + if (enemy_chains[target] != source) + continue + enemy_chains -= target + return + +/// Confirm whether something is valid to zap with lightning +/mob/living/basic/guardian/lightning/proc/validate_target(atom/target) + return isliving(target) && target != src && target != summoner && !shares_summoner(target) + +/// Called every few zaps by a chain +/mob/living/basic/guardian/lightning/proc/on_chain_zap(mob/living/target) + target.electrocute_act(shock_damage = 0, source = "lightning chain") + target.visible_message( + span_danger("[target] was shocked by the lightning chain!"), + span_userdanger("You are shocked by the lightning chain!"), + span_hear("You hear a heavy electrical crack."), + ) + +/// Beam definition for our lightning chain +/obj/effect/ebeam/chain + name = "lightning chain" + layer = LYING_MOB_LAYER + plane = GAME_PLANE_FOV_HIDDEN diff --git a/code/modules/mob/living/basic/guardian/guardian_types/protector.dm b/code/modules/mob/living/basic/guardian/guardian_types/protector.dm new file mode 100644 index 0000000000000..a0aa34ad17f14 --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_types/protector.dm @@ -0,0 +1,122 @@ +/// Very durable, and reverses the usual leash dynamic. Can slow down to become extremely durable. +/mob/living/basic/guardian/protector + guardian_type = GUARDIAN_PROTECTOR + melee_damage_lower = 15 + melee_damage_upper = 15 + range = 5 // You want this to be low so you can drag them around + damage_coeff = list(BRUTE = 0.4, BURN = 0.4, TOX = 0.4, CLONE = 0.4, STAMINA = 0, OXY = 0.4) + playstyle_string = span_holoparasite("As a protector type you cause your summoner to leash to you instead of you leashing to them and have two modes; Combat Mode, where you do and take medium damage, and Protection Mode, where you do and take almost no damage, but move slightly slower.") + creator_name = "Protector" + creator_desc = "Causes you to teleport to it when out of range, unlike other parasites. Has two modes; Combat, where it does and takes medium damage, and Protection, where it does and takes almost no damage but moves slightly slower." + creator_icon = "protector" + toggle_button_type = /atom/movable/screen/guardian/toggle_mode + /// Action which toggles our shield + var/datum/action/cooldown/mob_cooldown/protector_shield/shield + +/mob/living/basic/guardian/protector/Initialize(mapload, datum/guardian_fluff/theme) + . = ..() + shield = new(src) + shield.owner_has_control = FALSE // Hide it from the user, it's integrated with guardian UI + shield.Grant(src) + +/mob/living/basic/guardian/protector/Destroy() + QDEL_NULL(shield) + return ..() + +// Invert the order +/mob/living/basic/guardian/protector/leash_to(atom/movable/leashed, atom/movable/leashed_to) + return ..(leashed_to, leashed) + +/mob/living/basic/guardian/protector/unleash() + qdel(summoner?.GetComponent(/datum/component/leash)) + +/mob/living/basic/guardian/protector/toggle_modes() + shield.Trigger() + +/mob/living/basic/guardian/protector/ex_act(severity) + if(severity >= EXPLODE_DEVASTATE) + adjustBruteLoss(400) //if in protector mode, will do 20 damage and not actually necessarily kill the summoner + return TRUE + return ..() + +/// Toggle a status effect which makes you slow but defensive +/datum/action/cooldown/mob_cooldown/protector_shield + name = "Protection Mode" + desc = "Enter a defensive stance which slows you down and reduces your damage, but makes you almost invincible." + button_icon = 'icons/effects/effects.dmi' + button_icon_state = "shield-old" + background_icon = 'icons/hud/guardian.dmi' + background_icon_state = "base" + cooldown_time = 1 SECONDS + click_to_activate = FALSE + +/datum/action/cooldown/mob_cooldown/protector_shield/Activate(mob/living/target) + if (!isliving(target)) + return FALSE + if (target.has_status_effect(/datum/status_effect/protector_shield)) + target.remove_status_effect(/datum/status_effect/protector_shield) + return + target.apply_status_effect(/datum/status_effect/protector_shield) + StartCooldown() + return TRUE + +/// Makes the guardian even more durable, but slower +/datum/status_effect/protector_shield + id = "guardian_shield" + alert_type = null + /// Damage removed in protecting mode. + var/damage_penalty = 13 + /// Colour for our various overlays. + var/overlay_colour = COLOR_TEAL + /// Overlay for our protection shield. + var/mutable_appearance/shield_overlay + /// Damage coefficients when shielded + var/list/shielded_damage = list(BRUTE = 0.05, BURN = 0.05, TOX = 0.05, CLONE = 0.05, STAMINA = 0, OXY = 0.05) + +/datum/status_effect/protector_shield/on_apply() + if (isguardian(owner)) + var/mob/living/basic/guardian/guardian_owner = owner + overlay_colour = guardian_owner.guardian_colour + shield_overlay = mutable_appearance('icons/effects/effects.dmi', "shield-grey") + shield_overlay.color = overlay_colour + + owner.melee_damage_lower -= damage_penalty + owner.melee_damage_upper -= damage_penalty + owner.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/guardian_shield) + + if (isbasicmob(owner)) // Better hope you are or this status is doing basically nothing useful for you + var/mob/living/basic/basic_owner = owner + basic_owner.damage_coeff = shielded_damage + + to_chat(owner, span_bolddanger("You enter protection mode.")) + RegisterSignal(owner, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays)) + RegisterSignals(owner, COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES, PROC_REF(on_health_changed)) + owner.update_appearance(UPDATE_ICON) + return TRUE + +/datum/status_effect/protector_shield/on_remove() + owner.melee_damage_lower += damage_penalty + owner.melee_damage_upper += damage_penalty + owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/guardian_shield) + + if (isbasicmob(owner)) + var/mob/living/basic/basic_owner = owner + basic_owner.damage_coeff = initial(basic_owner.damage_coeff) + + to_chat(owner, span_bolddanger("You return to your normal mode.")) + UnregisterSignal(owner, list(COMSIG_ATOM_UPDATE_OVERLAYS) + COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES) + owner.update_appearance(UPDATE_ICON) + +/// Show an extra overlay when we're in shield mode +/datum/status_effect/protector_shield/proc/on_update_overlays(atom/source, list/overlays) + SIGNAL_HANDLER + overlays += shield_overlay + +/// Flash an animation when someone tries to hurt us +/datum/status_effect/protector_shield/proc/on_health_changed(mob/living/our_mob, type, amount, forced) + SIGNAL_HANDLER + if (amount <= 0 && !QDELETED(our_mob)) + return + var/image/flash_overlay = new('icons/effects/effects.dmi', owner, "shield-flash", dir = pick(GLOB.cardinals)) + flash_overlay.color = overlay_colour + owner.flick_overlay_view(flash_overlay, 0.5 SECONDS) diff --git a/code/modules/mob/living/basic/guardian/guardian_types/ranged.dm b/code/modules/mob/living/basic/guardian/guardian_types/ranged.dm new file mode 100644 index 0000000000000..293dbfc2320d7 --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_types/ranged.dm @@ -0,0 +1,205 @@ +/// A ranged guardian can fling shards of glass at people very very quickly. It can also enter a long-range scouting mode. +/mob/living/basic/guardian/ranged + guardian_type = GUARDIAN_RANGED + combat_mode = FALSE + friendly_verb_continuous = "quietly assesses" + friendly_verb_simple = "quietly assess" + melee_damage_lower = 10 + melee_damage_upper = 10 + damage_coeff = list(BRUTE = 0.9, BURN = 0.9, TOX = 0.9, CLONE = 0.9, STAMINA = 0, OXY = 0.9) + range = 13 + playstyle_string = span_holoparasite("As a ranged type, you have only light damage resistance, but are capable of spraying shards of crystal at incredibly high speed. You can also deploy surveillance snares to monitor enemy movement. Finally, you can switch to scout mode, in which you can't attack, but can move without limit.") + creator_name = "Ranged" + creator_desc = "Has two modes. Ranged; which fires a constant stream of weak, armor-ignoring projectiles. Scout; where it cannot attack, but can move through walls and is quite hard to see. Can lay surveillance snares, which alert it when crossed, in either mode." + creator_icon = "ranged" + see_invisible = SEE_INVISIBLE_LIVING + toggle_button_type = /atom/movable/screen/guardian/toggle_mode + +/mob/living/basic/guardian/ranged/Initialize(mapload, datum/guardian_fluff/theme) + . = ..() + AddComponent(\ + /datum/component/ranged_attacks,\ + projectile_type = /obj/projectile/guardian,\ + projectile_sound = 'sound/effects/hit_on_shattered_glass.ogg',\ + cooldown_time = 0.1 SECONDS, \ + ) + AddComponent(/datum/component/ranged_mob_full_auto, autofire_shot_delay = 0.1 SECONDS) + var/datum/action/cooldown/mob_cooldown/guardian_alarm_snare/snare = new (src) + snare.Grant(src) + +/mob/living/basic/guardian/ranged/toggle_modes() + if(is_deployed() && !isnull(summoner)) + balloon_alert(src, "must not be manifested!") + return + if (has_status_effect(/datum/status_effect/guardian_scout_mode)) + remove_status_effect(/datum/status_effect/guardian_scout_mode) + return + apply_status_effect(/datum/status_effect/guardian_scout_mode) + +/mob/living/basic/guardian/ranged/toggle_light() + var/msg + switch(lighting_cutoff) + if (LIGHTING_CUTOFF_VISIBLE) + lighting_cutoff_red = 10 + lighting_cutoff_green = 10 + lighting_cutoff_blue = 15 + msg = "You activate your night vision." + if (LIGHTING_CUTOFF_MEDIUM) + lighting_cutoff_red = 25 + lighting_cutoff_green = 25 + lighting_cutoff_blue = 35 + msg = "You increase your night vision." + if (LIGHTING_CUTOFF_HIGH) + lighting_cutoff_red = 35 + lighting_cutoff_green = 35 + lighting_cutoff_blue = 50 + msg = "You maximize your night vision." + else + lighting_cutoff_red = 0 + lighting_cutoff_green = 0 + lighting_cutoff_blue = 0 + msg = "You deactivate your night vision." + sync_lighting_plane_cutoff() + to_chat(src, span_notice(msg)) + +/// Become an incorporeal scout +/datum/status_effect/guardian_scout_mode + id = "guardian_scout" + alert_type = null + +/datum/status_effect/guardian_scout_mode/on_apply() + animate(owner, alpha = 45, time = 0.5 SECONDS) + RegisterSignal(owner, COMSIG_GUARDIAN_MANIFESTED, PROC_REF(on_manifest)) + RegisterSignal(owner, COMSIG_GUARDIAN_RECALLED, PROC_REF(on_recall)) + RegisterSignal(owner, COMSIG_MOB_CLICKON, PROC_REF(on_click)) + + var/mob/living/basic/guardian/guardian_mob = owner + guardian_mob.unleash() + to_chat(owner, span_bolddanger("You enter scouting mode.")) + return TRUE + +/datum/status_effect/guardian_scout_mode/on_remove() + animate(owner, alpha = initial(owner.alpha), time = 0.5 SECONDS) + UnregisterSignal(owner, list(COMSIG_GUARDIAN_MANIFESTED, COMSIG_GUARDIAN_RECALLED, COMSIG_MOB_CLICKON)) + to_chat(owner, span_bolddanger("You return to your normal mode.")) + var/mob/living/basic/guardian/guardian_mob = owner + guardian_mob.leash_to(owner, guardian_mob.summoner) + +/// Restore incorporeal move when we become corporeal, yes I know that suonds silly +/datum/status_effect/guardian_scout_mode/proc/on_manifest() + SIGNAL_HANDLER + owner.incorporeal_move = INCORPOREAL_MOVE_BASIC + +/// Stop having incorporeal move when we recall so that we can't move +/datum/status_effect/guardian_scout_mode/proc/on_recall() + SIGNAL_HANDLER + owner.incorporeal_move = FALSE + +/// While this is active we can't click anything +/datum/status_effect/guardian_scout_mode/proc/on_click() + SIGNAL_HANDLER + return COMSIG_MOB_CANCEL_CLICKON + + +/// Place an invisible trap which alerts the guardian when it is crossed +/datum/action/cooldown/mob_cooldown/guardian_alarm_snare + name = "Surveillance Snare" + desc = "Place an invisible snare which will alert you when it is crossed." + button_icon = 'icons/mob/actions/actions_ecult.dmi' + button_icon_state = "eye" + background_icon = 'icons/hud/guardian.dmi' + background_icon_state = "base" + cooldown_time = 2 SECONDS + melee_cooldown_time = 0 + click_to_activate = FALSE + /// How many snares can we have? + var/maximum_snares = 5 + /// What snares have we already placed? + var/list/placed_snares = list() + +/datum/action/cooldown/mob_cooldown/guardian_alarm_snare/Activate(atom/target) + StartCooldown(360 SECONDS) + + if (length(placed_snares) >= maximum_snares) + var/picked_snare = tgui_input_list(owner, "Choose a snare to replace.", "Remove Snare", sort_names(placed_snares)) + if(isnull(picked_snare)) + return FALSE + qdel(picked_snare) + if (length(placed_snares) >= maximum_snares) + StartCooldown(0) + return FALSE + + owner.balloon_alert(owner, "snare deployed") // We need feedback because they are invisible + var/turf/snare_loc = get_turf(owner) + var/obj/effect/abstract/surveillance_snare/new_snare = new(snare_loc, owner) + new_snare.assign_owner(owner) + RegisterSignal(new_snare, COMSIG_QDELETING, PROC_REF(on_snare_deleted)) + placed_snares += new_snare + + StartCooldown() + return TRUE + +/// When a snare is deleted remove it from tracking +/datum/action/cooldown/mob_cooldown/guardian_alarm_snare/proc/on_snare_deleted(atom/snare) + SIGNAL_HANDLER + placed_snares -= snare + + +/// An invisible marker placed by a ranged guardian, alerts the owner when crossed +/obj/effect/abstract/surveillance_snare + name = "surveillance snare" + desc = "This thing is invisible, how are you examining it?" + invisibility = INVISIBILITY_ABSTRACT + /// Who do we notify when someone steps on us? + var/mob/living/owner + +/obj/effect/abstract/surveillance_snare/Initialize(mapload, spawning_guardian) + . = ..() + name = "[get_area(src)] snare ([rand(1, 1000)])" + var/static/list/loc_connections = list(COMSIG_ATOM_ENTERED = PROC_REF(on_entered)) + AddElement(/datum/element/connect_loc, loc_connections) + +/// Set up crossed notification +/obj/effect/abstract/surveillance_snare/proc/assign_owner(mob/living/new_owner) + if (isnull(new_owner)) + qdel(src) + return + owner = new_owner + RegisterSignal(owner, COMSIG_QDELETING, PROC_REF(owner_destroyed)) + +/// When crossed notify our owner +/obj/effect/abstract/surveillance_snare/proc/on_entered(atom/source, crossed_object) + SIGNAL_HANDLER + if (isnull(owner)) + qdel(src) + return + if (!isliving(crossed_object) || crossed_object == owner) + return + var/mob/living/basic/guardian/guardian_owner = owner + if (isguardian(owner) && crossed_object == guardian_owner.summoner || guardian_owner.shares_summoner(crossed_object)) + return + + var/send_message = span_bolddanger("[crossed_object] has crossed [name].") + if (!isguardian(owner) || isnull(guardian_owner.summoner)) + to_chat(owner, send_message) + return + + to_chat(guardian_owner.summoner, send_message) + var/list/guardians = guardian_owner.summoner.get_all_linked_holoparasites() + for(var/guardian in guardians) + to_chat(guardian, send_message) + +/// If the person who placed us doesn't exist we might as well die +/obj/effect/abstract/surveillance_snare/proc/owner_destroyed() + SIGNAL_HANDLER + owner = null + qdel(src) + + +/// The glass shards we throw as a guardian. They have low damage because you can fire them very very quickly. +/obj/projectile/guardian + name = "crystal spray" + icon_state = "guardian" + damage = 5 + damage_type = BRUTE + armour_penetration = 100 diff --git a/code/modules/mob/living/basic/guardian/guardian_types/standard.dm b/code/modules/mob/living/basic/guardian/guardian_types/standard.dm new file mode 100644 index 0000000000000..2ca006b385c78 --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_types/standard.dm @@ -0,0 +1,63 @@ +/// Plain, but durable and strong. Can destroy walls. +/mob/living/basic/guardian/standard + guardian_type = GUARDIAN_STANDARD + damage_coeff = list(BRUTE = 0.5, BURN = 0.5, TOX = 0.5, CLONE = 0.5, STAMINA = 0, OXY = 0.5) + melee_damage_lower = 20 + melee_damage_upper = 20 + melee_attack_cooldown = 0.6 SECONDS + wound_bonus = -5 //you can wound! + obj_damage = 80 + environment_smash = ENVIRONMENT_SMASH_WALLS + playstyle_string = span_holoparasite("As a standard type you have no special abilities, but have a high damage resistance and a powerful attack capable of smashing through walls.") + creator_name = "Standard" + creator_desc = "Devastating close combat attacks and high damage resistance. Can smash through weak walls." + creator_icon = "standard" + /// The text we shout when attacking. + var/battlecry = "AT" + +/mob/living/basic/guardian/standard/Initialize(mapload, datum/guardian_fluff/theme) + . = ..() + AddElement(/datum/element/wall_tearer, allow_reinforced = FALSE, tear_time = 1.5 SECONDS) + var/datum/action/select_guardian_battlecry/cry = new(src) + cry.Grant(src) + +/mob/living/basic/guardian/standard/do_attack_animation(atom/attacked_atom, visual_effect_icon, used_item, no_effect) + . = ..() + if (!isliving(attacked_atom) || !isclosedturf(attacked_atom)) + return + var/msg = "" + for(var/i in 1 to 9) + msg += battlecry + say("[msg]!!", ignore_spam = TRUE) + for(var/sounds in 1 to 4) + addtimer(CALLBACK(src, PROC_REF(do_attack_sound), attacked_atom.loc), sounds DECISECONDS, TIMER_DELETE_ME) + +/// Echo our punching sounds +/mob/living/basic/guardian/standard/proc/do_attack_sound(atom/playing_from) + playsound(playing_from, attack_sound, 50, TRUE, TRUE) + +/// Action to change our battlecry +/datum/action/select_guardian_battlecry + name = "Select Battlecry" + desc = "Update the really cool thing you shout whenever you attack." + button_icon = 'icons/obj/clothing/gloves.dmi' + button_icon_state = "boxing" + background_icon = 'icons/hud/guardian.dmi' + background_icon_state = "base" + /// How long can it be? Shouldn't be too long because we repeat this a shitload of times + var/max_length = 6 + +/datum/action/select_guardian_battlecry/IsAvailable(feedback) + if (!istype(owner, /mob/living/basic/guardian/standard)) + return FALSE + return ..() + +/datum/action/select_guardian_battlecry/Trigger(trigger_flags) + . = ..() + if (!.) + return + var/mob/living/basic/guardian/standard/stand = owner + var/input = tgui_input_text(owner, "What do you want your battlecry to be?", "Battle Cry", max_length = max_length) + if(!input) + return + stand.battlecry = input diff --git a/code/modules/mob/living/basic/guardian/guardian_types/support.dm b/code/modules/mob/living/basic/guardian/guardian_types/support.dm new file mode 100644 index 0000000000000..e22762bcada70 --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_types/support.dm @@ -0,0 +1,164 @@ +/// Quick-moving mob which can teleport things to a beacon and heal its allies +/mob/living/basic/guardian/support + guardian_type = GUARDIAN_SUPPORT + speed = 0 + damage_coeff = list(BRUTE = 0.7, BURN = 0.7, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7) + melee_damage_lower = 15 + melee_damage_upper = 15 + playstyle_string = span_holoparasite("As a support type, you may right-click to heal targets. In addition, alt-clicking on an adjacent object or mob will warp them to your bluespace beacon after a short delay.") + creator_name = "Support" + creator_desc = "Does medium damage, but can heal its targets and create beacons to teleport people and things to." + creator_icon = "support" + /// Amount of each damage type to heal per hit + var/healing_amount = 5 + +/mob/living/basic/guardian/support/Initialize(mapload, datum/guardian_fluff/theme) + . = ..() + AddComponent(\ + /datum/component/healing_touch,\ + heal_brute = healing_amount,\ + heal_burn = healing_amount,\ + heal_tox = healing_amount,\ + heal_oxy = healing_amount,\ + heal_time = 0,\ + action_text = "",\ + complete_text = "",\ + required_modifier = RIGHT_CLICK,\ + after_healed = CALLBACK(src, PROC_REF(after_healed)),\ + ) + + var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] + medsensor.show_to(src) + + var/datum/action/cooldown/mob_cooldown/guardian_bluespace_beacon/teleport = new(src) + teleport.Grant(src) + +/mob/living/basic/guardian/support/set_guardian_colour(colour) + . = ..() + AddComponent(/datum/component/healing_touch, heal_color = guardian_colour) + +/// Called after we heal someone, show some visuals +/mob/living/basic/guardian/support/proc/after_healed(mob/living/healed) + do_attack_animation(healed, ATTACK_EFFECT_PUNCH) + healed.visible_message( + message = span_notice("[src] heals [healed]!"), + self_message = span_userdanger("[src] heals you!"), + vision_distance = COMBAT_MESSAGE_RANGE, + ignored_mobs = src, + ) + to_chat(src, span_notice("You heal [healed]!")) + playsound(healed, attack_sound, 50, TRUE, TRUE, frequency = -1) // play punch sound in REVERSE + + +/// Place a beacon and then listen for clicks to teleport people to it +/datum/action/cooldown/mob_cooldown/guardian_bluespace_beacon + name = "Place Bluespace Beacon" + desc = "Mark the ground under your feet as a teleportation point. Alt-click things to teleport them to your beacon." + button_icon = 'icons/effects/effects.dmi' + button_icon_state = "the_freezer" + background_icon = 'icons/hud/guardian.dmi' + background_icon_state = "base" + cooldown_time = 5 MINUTES + melee_cooldown_time = 0 + cooldown_rounding = 1 + click_to_activate = FALSE + /// Our teleportation beacon. + var/obj/structure/guardian_beacon/beacon + /// Time it takes to teleport something. + var/teleport_time = 6 SECONDS + +/datum/action/cooldown/mob_cooldown/guardian_bluespace_beacon/Grant(mob/granted_to) + . = ..() + RegisterSignal(owner, COMSIG_MOB_ALTCLICKON, PROC_REF(try_teleporting)) + +/datum/action/cooldown/mob_cooldown/guardian_bluespace_beacon/Remove(mob/removed_from) + UnregisterSignal(owner, COMSIG_MOB_ALTCLICKON) + return ..() + +/datum/action/cooldown/mob_cooldown/guardian_bluespace_beacon/Activate(atom/movable/target) + var/turf/beacon_loc = owner.loc + if(!isfloorturf(beacon_loc)) + owner.balloon_alert(owner, "no room!") + return FALSE + + if (!isnull(beacon)) + beacon.visible_message("[beacon] vanishes!") + new /obj/effect/temp_visual/guardian/phase/out(beacon.loc) + qdel(beacon) + + beacon = new(beacon_loc, src) + if (isguardian(owner)) + var/mob/living/basic/guardian/guardian_owner = owner + beacon.add_atom_colour(guardian_owner.guardian_colour, FIXED_COLOUR_PRIORITY) + RegisterSignal(beacon, COMSIG_QDELETING, PROC_REF(on_beacon_deleted)) + to_chat(src, span_bolddanger("Beacon placed! You may now warp targets and objects to it, including your user, via Alt+Click.")) + StartCooldown() + return TRUE + +/// Don't hold a reference to a deleted beacon +/datum/action/cooldown/mob_cooldown/guardian_bluespace_beacon/proc/on_beacon_deleted() + SIGNAL_HANDLER + beacon = null + +/// Try and teleport something to our beacon +/datum/action/cooldown/mob_cooldown/guardian_bluespace_beacon/proc/try_teleporting(mob/living/source, atom/target) + SIGNAL_HANDLER + if (!can_teleport(source, target)) + return + INVOKE_ASYNC(src, PROC_REF(perform_teleport), source, target) + return COMPONENT_CANCEL_ATTACK_CHAIN + +/// Validate whether we can teleport this object +/datum/action/cooldown/mob_cooldown/guardian_bluespace_beacon/proc/can_teleport(mob/living/source, atom/movable/target) + if (isnull(beacon)) + source.balloon_alert(source, "no beacon!") + return FALSE + if (isguardian(source)) + var/mob/living/basic/guardian/guardian_mob = source + if (!guardian_mob.is_deployed()) + source.balloon_alert(source, "manifest yourself!") + return FALSE + if (!source.Adjacent(target)) + target.balloon_alert(source, "too far!") + return FALSE + if (target.anchored) + target.balloon_alert(source, "it won't budge!") + return FALSE + if(beacon.z != target.z) + target.balloon_alert(source, "too far from beacon!") + return FALSE + return TRUE + +/// Start teleporting +/datum/action/cooldown/mob_cooldown/guardian_bluespace_beacon/proc/perform_teleport(mob/living/source, atom/target) + source.do_attack_animation(target) + playsound(target, 'sound/weapons/punch1.ogg', 50, TRUE, TRUE, frequency = -1) + source.balloon_alert(source, "teleporting...") + target.visible_message( + span_danger("[target] starts to glow faintly!"), \ + span_userdanger("You start to faintly glow, and you feel strangely weightless!")) + if(!do_after(source, teleport_time, target)) + return + new /obj/effect/temp_visual/guardian/phase/out(target.loc) + if(isliving(target)) + var/mob/living/living_target = target + living_target.flash_act() + target.visible_message( + span_danger("[target] disappears in a flash of light!"), \ + span_userdanger("Your vision is obscured by a flash of light!"), \ + ) + do_teleport(target, beacon, precision = 0, channel = TELEPORT_CHANNEL_BLUESPACE) + new /obj/effect/temp_visual/guardian/phase(get_turf(target)) + + +/// Structure which acts as the landing point for a support guardian's teleportation effects +/obj/structure/guardian_beacon + name = "guardian beacon" + icon = 'icons/turf/floors.dmi' + desc = "A glowing zone which acts as a beacon for teleportation." + icon_state = "light_on-8" + light_range = MINIMUM_USEFUL_LIGHT_RANGE + density = FALSE + anchored = TRUE + plane = FLOOR_PLANE + layer = ABOVE_OPEN_TURF_LAYER diff --git a/code/modules/mob/living/basic/guardian/guardian_verbs.dm b/code/modules/mob/living/basic/guardian/guardian_verbs.dm new file mode 100644 index 0000000000000..02d1fd1ed3ab2 --- /dev/null +++ b/code/modules/mob/living/basic/guardian/guardian_verbs.dm @@ -0,0 +1,187 @@ +/// Pop out into the realm of the living. +/mob/living/basic/guardian/proc/manifest(forced) + if (is_deployed() || isnull(summoner) || isnull(summoner.loc) || istype(summoner.loc, /obj/effect) || (!COOLDOWN_FINISHED(src, manifest_cooldown) && !forced) || locked) + return FALSE + forceMove(summoner.loc) + new /obj/effect/temp_visual/guardian/phase(loc) + COOLDOWN_START(src, manifest_cooldown, 1 SECONDS) + reset_perspective() + manifest_effects() + return TRUE + +/// Go and hide inside your boss. +/mob/living/basic/guardian/proc/recall(forced) + if (!is_deployed() || isnull(summoner) || (!COOLDOWN_FINISHED(src, manifest_cooldown) && !forced) || locked) + return FALSE + new /obj/effect/temp_visual/guardian/phase/out(loc) + recall_effects() + forceMove(summoner) + COOLDOWN_START(src, manifest_cooldown, 1 SECONDS) + return TRUE + +/// Do something when we appear. +/mob/living/basic/guardian/proc/manifest_effects() + SHOULD_CALL_PARENT(TRUE) + SEND_SIGNAL(src, COMSIG_GUARDIAN_MANIFESTED) + +/// Do something when we vanish. +/mob/living/basic/guardian/proc/recall_effects() + SHOULD_CALL_PARENT(TRUE) + SEND_SIGNAL(src, COMSIG_GUARDIAN_RECALLED) + +/// Swap to a different mode... if we have one +/mob/living/basic/guardian/proc/toggle_modes() + to_chat(src, span_bolddanger("You don't have another mode!")) + + +/// Turn an internal light on or off. +/mob/living/basic/guardian/proc/toggle_light() + if (!light_on) + to_chat(src, span_notice("You activate your light.")) + set_light_on(TRUE) + else + to_chat(src, span_notice("You deactivate your light.")) + set_light_on(FALSE) + + +/// Prints what type of guardian we are and what we can do. +/mob/living/basic/guardian/verb/check_type() + set name = "Check Guardian Type" + set category = "Guardian" + set desc = "Check what type you are." + to_chat(src, playstyle_string) + + +/// Speak with our boss at a distance +/mob/living/basic/guardian/proc/communicate() + if (isnull(summoner)) + return + var/sender_key = key + var/input = tgui_input_text(src, "Enter a message to tell your summoner", "Guardian") + if (sender_key != key || !input) //guardian got reset, or did not enter anything + return + + var/preliminary_message = span_boldholoparasite("[input]") //apply basic color/bolding + var/my_message = "[span_bolditalic(src.name)]: [preliminary_message]" //add source, color source with the guardian's color + + to_chat(summoner, "[my_message]") + var/list/guardians = summoner.get_all_linked_holoparasites() + for(var/guardian in guardians) + to_chat(guardian, "[my_message]") + for(var/dead_mob in GLOB.dead_mob_list) + var/link = FOLLOW_LINK(dead_mob, src) + to_chat(dead_mob, "[link] [my_message]") + + src.log_talk(input, LOG_SAY, tag="guardian") + + +/// Speak with your guardian(s) at a distance. +/datum/action/cooldown/mob_cooldown/guardian_comms + name = "Guardian Communication" + desc = "Communicate telepathically with your guardian." + button_icon = 'icons/hud/guardian.dmi' + button_icon_state = "communicate" + background_icon = 'icons/hud/guardian.dmi' + background_icon_state = "base" + click_to_activate = FALSE + cooldown_time = 0 SECONDS + melee_cooldown_time = 0 + shared_cooldown = NONE + +/datum/action/cooldown/mob_cooldown/guardian_comms/Activate(atom/target) + StartCooldown(360 SECONDS) + var/input = tgui_input_text(owner, "Enter a message to tell your guardian", "Message") + StartCooldown() + if (!input) + return FALSE + + var/preliminary_message = span_boldholoparasite("[input]") //apply basic color/bolding + var/my_message = span_boldholoparasite("[owner]: [preliminary_message]") //add source, color source with default grey... + + to_chat(owner, "[my_message]") + var/mob/living/living_owner = owner + var/list/guardians = living_owner.get_all_linked_holoparasites() + for(var/mob/living/basic/guardian/guardian as anything in guardians) + to_chat(guardian, "[span_bolditalic(owner.real_name)]: [preliminary_message]" ) + for(var/dead_mob in GLOB.dead_mob_list) + var/link = FOLLOW_LINK(dead_mob, owner) + to_chat(dead_mob, "[link] [my_message]") + owner.log_talk(input, LOG_SAY, tag="guardian") + + return TRUE + + +/// Tell your slacking or distracted guardian to come home. +/datum/action/cooldown/mob_cooldown/recall_guardian + name = "Recall Guardian" + desc = "Forcibly recall your guardian." + button_icon = 'icons/hud/guardian.dmi' + button_icon_state = "recall" + background_icon = 'icons/hud/guardian.dmi' + background_icon_state = "base" + click_to_activate = FALSE + cooldown_time = 0 SECONDS + melee_cooldown_time = 0 + shared_cooldown = NONE + +/datum/action/cooldown/mob_cooldown/recall_guardian/Activate(atom/target) + var/mob/living/living_owner = owner + var/list/guardians = living_owner.get_all_linked_holoparasites() + for(var/mob/living/basic/guardian/guardian in guardians) + guardian.recall() + StartCooldown() + return TRUE + +/// Replace an annoying griefer you were paired up to with a different but probably no less annoying player. +/datum/action/cooldown/mob_cooldown/replace_guardian + name = "Reset Guardian Consciousness" + desc = "Replaces the mind of your guardian with that of a different ghost." + button_icon = 'icons/mob/simple/mob.dmi' + button_icon_state = "ghost" + background_icon = 'icons/hud/guardian.dmi' + background_icon_state = "base" + click_to_activate = FALSE + cooldown_time = 5 SECONDS + melee_cooldown_time = 0 + shared_cooldown = NONE + +/datum/action/cooldown/mob_cooldown/replace_guardian/Activate(atom/target) + StartCooldown(5 MINUTES) + + var/mob/living/living_owner = owner + var/list/guardians = living_owner.get_all_linked_holoparasites() + for(var/mob/living/basic/guardian/resetting_guardian as anything in guardians) + if (!COOLDOWN_FINISHED(resetting_guardian, resetting_cooldown)) + guardians -= resetting_guardian //clear out guardians that are already reset + + if (!length(guardians)) + to_chat(owner, span_holoparasite("You cannot reset [length(guardians) > 1 ? "any of your guardians":"your guardian"] yet.")) + StartCooldown() + return FALSE + + var/mob/living/basic/guardian/chosen_guardian = tgui_input_list(owner, "Pick the guardian you wish to reset", "Guardian Reset", sort_names(guardians)) + if (isnull(chosen_guardian)) + to_chat(owner, span_holoparasite("You decide not to reset [length(guardians) > 1 ? "any of your guardians":"your guardian"].")) + StartCooldown() + return FALSE + + to_chat(owner, span_holoparasite("You attempt to reset [span_bold(chosen_guardian.real_name)]'s personality...")) + var/list/mob/dead/observer/ghost_candidates = poll_ghost_candidates("Do you want to play as [owner.real_name]'s [chosen_guardian.theme.name]?", ROLE_PAI, FALSE, 100) + if (!LAZYLEN(ghost_candidates)) + to_chat(owner, span_holoparasite("Your attempt to reset the personality of \ + [span_bold(chosen_guardian.real_name)] appears to have failed... \ + Looks like you're stuck with it for now.")) + StartCooldown() + return FALSE + + var/mob/dead/observer/candidate = pick(ghost_candidates) + to_chat(chosen_guardian, span_holoparasite("Your user reset you, and your body was taken over by a ghost. Looks like they weren't happy with your performance.")) + to_chat(owner, span_boldholoparasite("The personality of [chosen_guardian.theme.name] has been successfully reset.")) + message_admins("[key_name_admin(candidate)] has taken control of ([ADMIN_LOOKUPFLW(chosen_guardian)])") + chosen_guardian.ghostize(FALSE) + chosen_guardian.key = candidate.key + COOLDOWN_START(chosen_guardian, resetting_cooldown, 5 MINUTES) + chosen_guardian.guardian_rename() //give it a new color and name, to show it's a new person + chosen_guardian.guardian_recolour() + StartCooldown() + return TRUE diff --git a/code/modules/mob/living/basic/health_adjustment.dm b/code/modules/mob/living/basic/health_adjustment.dm index 9644a1a629905..43352c689c471 100644 --- a/code/modules/mob/living/basic/health_adjustment.dm +++ b/code/modules/mob/living/basic/health_adjustment.dm @@ -17,6 +17,12 @@ updatehealth() return . - bruteloss +/mob/living/basic/get_damage_mod(damage_type) + var/modifier = ..() + if (damage_type in damage_coeff) + return modifier * damage_coeff[damage_type] + return modifier + /mob/living/basic/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype) if(!can_adjust_brute_loss(amount, forced, required_bodytype)) return 0 diff --git a/code/modules/mob/living/basic/heretic/flesh_stalker.dm b/code/modules/mob/living/basic/heretic/flesh_stalker.dm index f6a051334d22a..c8a3342141ff5 100644 --- a/code/modules/mob/living/basic/heretic/flesh_stalker.dm +++ b/code/modules/mob/living/basic/heretic/flesh_stalker.dm @@ -27,7 +27,7 @@ /datum/ai_controller/basic_controller/stalker ai_traits = CAN_ACT_IN_STASIS blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/heretic/raw_prophet.dm b/code/modules/mob/living/basic/heretic/raw_prophet.dm index f3bb1efa7e91f..f4ed7229a005e 100644 --- a/code/modules/mob/living/basic/heretic/raw_prophet.dm +++ b/code/modules/mob/living/basic/heretic/raw_prophet.dm @@ -48,7 +48,7 @@ /// Returns a list of abilities that we should add. /mob/living/basic/heretic_summon/raw_prophet/proc/get_innate_abilities() var/list/returnable_list = innate_abilities.Copy() - returnable_list += list(/datum/action/cooldown/spell/pointed/blind/eldritch = BB_TARGETTED_ACTION) + returnable_list += list(/datum/action/cooldown/spell/pointed/blind/eldritch = BB_TARGETED_ACTION) return returnable_list /* @@ -79,13 +79,13 @@ /mob/living/basic/heretic_summon/raw_prophet/ruins/get_innate_abilities() var/list/returnable_list = innate_abilities.Copy() - returnable_list += list(/datum/action/cooldown/mob_cooldown/watcher_gaze = BB_TARGETTED_ACTION) + returnable_list += list(/datum/action/cooldown/mob_cooldown/watcher_gaze = BB_TARGETED_ACTION) return returnable_list /// Walk and attack people, blind them when we can /datum/ai_controller/basic_controller/raw_prophet blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/heretic/rust_walker.dm b/code/modules/mob/living/basic/heretic/rust_walker.dm index 9dff3c01e311b..ff56c311f7346 100644 --- a/code/modules/mob/living/basic/heretic/rust_walker.dm +++ b/code/modules/mob/living/basic/heretic/rust_walker.dm @@ -20,7 +20,7 @@ var/static/list/grantable_spells = list( /datum/action/cooldown/spell/aoe/rust_conversion/small = BB_GENERIC_ACTION, - /datum/action/cooldown/spell/basic_projectile/rust_wave/short = BB_TARGETTED_ACTION, + /datum/action/cooldown/spell/basic_projectile/rust_wave/short = BB_TARGETED_ACTION, ) grant_actions_by_list(grantable_spells) @@ -50,7 +50,7 @@ /// Converts unconverted terrain, sprays pocket sand around /datum/ai_controller/basic_controller/rust_walker blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/heretic/star_gazer.dm b/code/modules/mob/living/basic/heretic/star_gazer.dm index a8af89a7f7177..f7ab925440d57 100644 --- a/code/modules/mob/living/basic/heretic/star_gazer.dm +++ b/code/modules/mob/living/basic/heretic/star_gazer.dm @@ -66,7 +66,7 @@ target.apply_status_effect(/datum/status_effect/star_mark) target.apply_damage(damage = 5, damagetype = CLONE) - var/datum/targetting_datum/target_confirmer = ai_controller.blackboard[BB_TARGETTING_DATUM] + var/datum/targeting_strategy/target_confirmer = GET_TARGETING_STRATEGY(ai_controller.blackboard[BB_TARGETING_STRATEGY]) for(var/mob/living/nearby_mob in range(1, src)) if(target == nearby_mob || !target_confirmer?.can_attack(src, nearby_mob)) continue @@ -78,9 +78,9 @@ /datum/ai_controller/basic_controller/star_gazer blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends/attack_closed_turfs, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends/attack_closed_turfs, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -104,7 +104,7 @@ can_attack_turfs = TRUE can_attack_dense_objects = TRUE -/datum/pet_command/point_targetting/attack/star_gazer +/datum/pet_command/point_targeting/attack/star_gazer speech_commands = list("attack", "sic", "kill", "slash them") command_feedback = "stares!" pointed_reaction = "stares intensely!" diff --git a/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm index 3f197860618a7..20bcd8a69a130 100644 --- a/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm +++ b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/ice_demon blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_LIST_SCARY_ITEMS = list( /obj/item/weldingtool, /obj/item/flashlight/flare, diff --git a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm index 2d9715caf3752..725dcc09b5ec9 100644 --- a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm +++ b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm @@ -1,7 +1,7 @@ #define ENRAGE_ADDITION 25 /datum/ai_controller/basic_controller/ice_whelp blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items, BB_TARGET_MINIMUM_STAT = HARD_CRIT, BB_WHELP_ENRAGED = 0, ) diff --git a/code/modules/mob/living/basic/jungle/leaper/leaper.dm b/code/modules/mob/living/basic/jungle/leaper/leaper.dm index 6c866a6a955dc..f3213897f9bdb 100644 --- a/code/modules/mob/living/basic/jungle/leaper/leaper.dm +++ b/code/modules/mob/living/basic/jungle/leaper/leaper.dm @@ -42,11 +42,11 @@ /datum/pet_command/idle, /datum/pet_command/free, /datum/pet_command/follow, - /datum/pet_command/untargetted_ability/blood_rain, - /datum/pet_command/untargetted_ability/summon_toad, - /datum/pet_command/point_targetting/attack, - /datum/pet_command/point_targetting/use_ability/flop, - /datum/pet_command/point_targetting/use_ability/bubble, + /datum/pet_command/untargeted_ability/blood_rain, + /datum/pet_command/untargeted_ability/summon_toad, + /datum/pet_command/point_targeting/attack, + /datum/pet_command/point_targeting/use_ability/flop, + /datum/pet_command/point_targeting/use_ability/bubble, ) /mob/living/basic/leaper/Initialize(mapload) diff --git a/code/modules/mob/living/basic/jungle/leaper/leaper_ai.dm b/code/modules/mob/living/basic/jungle/leaper/leaper_ai.dm index 63e32f069ed40..e776117a3a596 100644 --- a/code/modules/mob/living/basic/jungle/leaper/leaper_ai.dm +++ b/code/modules/mob/living/basic/jungle/leaper/leaper_ai.dm @@ -1,7 +1,7 @@ /datum/ai_controller/basic_controller/leaper blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -39,7 +39,7 @@ ability_key = BB_LEAPER_SUMMON finish_planning = FALSE -/datum/pet_command/point_targetting/use_ability/flop +/datum/pet_command/point_targeting/use_ability/flop command_name = "Flop" command_desc = "Command your pet to belly flop your target!" radial_icon = 'icons/mob/actions/actions_items.dmi' @@ -47,7 +47,7 @@ speech_commands = list("flop", "crush") pet_ability_key = BB_LEAPER_FLOP -/datum/pet_command/point_targetting/use_ability/bubble +/datum/pet_command/point_targeting/use_ability/bubble command_name = "Poison Bubble" command_desc = "Launch poisonous bubbles at your target!" radial_icon = 'icons/obj/weapons/guns/projectiles.dmi' @@ -55,7 +55,7 @@ speech_commands = list("bubble", "shoot") pet_ability_key = BB_LEAPER_BUBBLE -/datum/pet_command/untargetted_ability/blood_rain +/datum/pet_command/untargeted_ability/blood_rain command_name = "Blood Rain" command_desc = "Let it rain poisonous blood!" radial_icon = 'icons/effects/effects.dmi' @@ -64,7 +64,7 @@ ability_key = BB_LEAPER_VOLLEY -/datum/pet_command/untargetted_ability/summon_toad +/datum/pet_command/untargeted_ability/summon_toad command_name = "Summon Toads" command_desc = "Summon crazy suicide frogs!" radial_icon = 'icons/mob/simple/animal.dmi' diff --git a/code/modules/mob/living/basic/jungle/mega_arachnid/mega_arachnid_ai.dm b/code/modules/mob/living/basic/jungle/mega_arachnid/mega_arachnid_ai.dm index 8964ebf837ec1..fa2a86787d861 100644 --- a/code/modules/mob/living/basic/jungle/mega_arachnid/mega_arachnid_ai.dm +++ b/code/modules/mob/living/basic/jungle/mega_arachnid/mega_arachnid_ai.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/mega_arachnid blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_BASIC_MOB_FLEE_DISTANCE = 5, ) diff --git a/code/modules/mob/living/basic/jungle/seedling/seedling.dm b/code/modules/mob/living/basic/jungle/seedling/seedling.dm index 46c67ffa0e4d8..5a958d3ca7c18 100644 --- a/code/modules/mob/living/basic/jungle/seedling/seedling.dm +++ b/code/modules/mob/living/basic/jungle/seedling/seedling.dm @@ -212,9 +212,9 @@ /datum/pet_command/idle, /datum/pet_command/free, /datum/pet_command/follow, - /datum/pet_command/point_targetting/attack, - /datum/pet_command/point_targetting/use_ability/solarbeam, - /datum/pet_command/point_targetting/use_ability/rapidseeds, + /datum/pet_command/point_targeting/attack, + /datum/pet_command/point_targeting/use_ability/solarbeam, + /datum/pet_command/point_targeting/use_ability/rapidseeds, ) //abilities diff --git a/code/modules/mob/living/basic/jungle/seedling/seedling_ai.dm b/code/modules/mob/living/basic/jungle/seedling/seedling_ai.dm index e3f9fe083a63a..2ed4811e46f25 100644 --- a/code/modules/mob/living/basic/jungle/seedling/seedling_ai.dm +++ b/code/modules/mob/living/basic/jungle/seedling/seedling_ai.dm @@ -1,7 +1,7 @@ /datum/ai_controller/basic_controller/seedling blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, BB_WEEDLEVEL_THRESHOLD = 3, BB_WATERLEVEL_THRESHOLD = 90, ) @@ -141,8 +141,8 @@ /datum/ai_controller/basic_controller/seedling/meanie blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, ) planning_subtrees = list( /datum/ai_planning_subtree/pet_planning, @@ -161,7 +161,7 @@ finish_planning = FALSE ///pet commands -/datum/pet_command/point_targetting/use_ability/solarbeam +/datum/pet_command/point_targeting/use_ability/solarbeam command_name = "Launch solarbeam" command_desc = "Command your pet to launch a solarbeam at your target!" radial_icon = 'icons/effects/beam.dmi' @@ -169,7 +169,7 @@ speech_commands = list("beam", "solar") pet_ability_key = BB_SOLARBEAM_ABILITY -/datum/pet_command/point_targetting/use_ability/rapidseeds +/datum/pet_command/point_targeting/use_ability/rapidseeds command_name = "Rapid seeds" command_desc = "Command your pet to launch a volley of seeds at your target!" radial_icon = 'icons/obj/weapons/guns/projectiles.dmi' diff --git a/code/modules/mob/living/basic/jungle/venus_human_trap.dm b/code/modules/mob/living/basic/jungle/venus_human_trap.dm index bfe7c1e849735..b59ec233bd068 100644 --- a/code/modules/mob/living/basic/jungle/venus_human_trap.dm +++ b/code/modules/mob/living/basic/jungle/venus_human_trap.dm @@ -165,7 +165,7 @@ melee_attack_cooldown = 1.2 SECONDS ai_controller = /datum/ai_controller/basic_controller/human_trap ///how much damage we take out of weeds - var/no_weed_damage = 20 + var/no_weed_damage = 12.5 ///how much do we heal in weeds var/weed_heal = 10 ///if the balloon alert was shown atleast once, reset after healing in weeds @@ -175,14 +175,14 @@ . = ..() AddElement(/datum/element/lifesteal, 5) var/static/list/innate_actions = list( - /datum/action/cooldown/vine_tangle = BB_TARGETTED_ACTION, + /datum/action/cooldown/vine_tangle = BB_TARGETED_ACTION, ) grant_actions_by_list(innate_actions) /mob/living/basic/venus_human_trap/RangedAttack(atom/victim) if(!combat_mode) return - var/datum/action/cooldown/mob_cooldown/tangle_ability = ai_controller.blackboard[BB_TARGETTED_ACTION] + var/datum/action/cooldown/mob_cooldown/tangle_ability = ai_controller.blackboard[BB_TARGETED_ACTION] if(!istype(tangle_ability)) return tangle_ability.Trigger(target = victim) @@ -255,7 +255,7 @@ /datum/ai_controller/basic_controller/human_trap blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/lavaland/basilisk/basilisk.dm b/code/modules/mob/living/basic/lavaland/basilisk/basilisk.dm index d4fef239bf84f..90b99a533f9f9 100644 --- a/code/modules/mob/living/basic/lavaland/basilisk/basilisk.dm +++ b/code/modules/mob/living/basic/lavaland/basilisk/basilisk.dm @@ -77,7 +77,7 @@ /datum/ai_controller/basic_controller/basilisk blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_AGGRO_RANGE = 5, ) diff --git a/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm b/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm index d2e04b60d26a7..b66e5eff8a5c6 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm @@ -56,3 +56,4 @@ /datum/action/cooldown/mob_cooldown/devour = BB_BILEWORM_DEVOUR, /datum/action/cooldown/mob_cooldown/resurface = BB_BILEWORM_RESURFACE, ) + grant_actions_by_list(other_innate_actions) diff --git a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm index 0093e69220c17..ea979febff3e3 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/bileworm blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/bileworm(), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/bileworm, ) planning_subtrees = list( @@ -9,7 +9,7 @@ /datum/ai_planning_subtree/bileworm_execute, ) -/datum/targetting_datum/basic/bileworm +/datum/targeting_strategy/basic/bileworm ignore_sight = TRUE /datum/ai_planning_subtree/bileworm_attack diff --git a/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm b/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm index b8e2bb68c69ea..21169ffd36889 100644 --- a/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm +++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm @@ -66,9 +66,10 @@ break if(blocked) break - var/atom/new_brimbeam = new /obj/effect/brimbeam(affected_turf) + var/obj/effect/brimbeam/new_brimbeam = new(affected_turf) new_brimbeam.dir = owner.dir beam_parts += new_brimbeam + new_brimbeam.assign_creator(owner) for(var/mob/living/hit_mob in affected_turf.contents) hit_mob.apply_damage(damage = 25, damagetype = BURN) to_chat(hit_mob, span_userdanger("You're blasted by [owner]'s brimbeam!")) @@ -101,6 +102,8 @@ light_color = LIGHT_COLOR_BLOOD_MAGIC light_power = 3 light_range = 2 + /// Who made us? + var/datum/weakref/creator /obj/effect/brimbeam/Initialize(mapload) . = ..() @@ -111,7 +114,10 @@ return ..() /obj/effect/brimbeam/process() + var/atom/ignore = creator?.resolve() for(var/mob/living/hit_mob in get_turf(src)) + if(hit_mob == ignore) + continue damage(hit_mob) /// Hurt the passed mob @@ -119,6 +125,10 @@ hit_mob.apply_damage(damage = 5, damagetype = BURN) to_chat(hit_mob, span_danger("You're damaged by [src]!")) +/// Ignore damage dealt to this mob +/obj/effect/brimbeam/proc/assign_creator(mob/living/maker) + creator = WEAKREF(maker) + /// Disappear /obj/effect/brimbeam/proc/disperse() animate(src, time = 0.5 SECONDS, alpha = 0) diff --git a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon.dm b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon.dm index dbd017837a913..9a88c636cf511 100644 --- a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon.dm +++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon.dm @@ -41,7 +41,7 @@ AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW) beam = new(src) beam.Grant(src) - ai_controller.set_blackboard_key(BB_TARGETTED_ACTION, beam) + ai_controller.set_blackboard_key(BB_TARGETED_ACTION, beam) /mob/living/basic/mining/brimdemon/RangedAttack(atom/target, modifiers) beam.Trigger(target = target) diff --git a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm index 18f614359c066..fe209387e008b 100644 --- a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm +++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm @@ -3,7 +3,7 @@ */ /datum/ai_controller/basic_controller/brimdemon blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) @@ -28,7 +28,7 @@ if (!succeeded) return var/mob/living/target = controller.blackboard[target_key] - var/datum/action/cooldown/ability = controller.blackboard[BB_TARGETTED_ACTION] + var/datum/action/cooldown/ability = controller.blackboard[BB_TARGETED_ACTION] if(!ability?.IsAvailable()) return ability.InterceptClickOn(caller = controller.pawn, target = target) diff --git a/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub.dm b/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub.dm index 28a76cb2d9733..495ef341b3459 100644 --- a/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub.dm +++ b/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub.dm @@ -36,7 +36,7 @@ /datum/pet_command/free, /datum/pet_command/grub_spit, /datum/pet_command/follow, - /datum/pet_command/point_targetting/fetch, + /datum/pet_command/point_targeting/fetch, ) /mob/living/basic/mining/goldgrub/Initialize(mapload) @@ -52,7 +52,7 @@ /datum/action/cooldown/mob_cooldown/burrow = BB_BURROW_ABILITY, ) grant_actions_by_list(innate_actions) - + AddElement(/datum/element/ore_collecting) AddElement(/datum/element/wall_tearer, allow_reinforced = FALSE) AddComponent(/datum/component/ai_listen_to_weather) AddComponent(\ @@ -67,17 +67,6 @@ RegisterSignal(src, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(block_bullets)) -/mob/living/basic/mining/goldgrub/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) - . = ..() - if(!.) - return - - if(!proximity_flag) - return - - if(istype(attack_target, /obj/item/stack/ore)) - consume_ore(attack_target) - /mob/living/basic/mining/goldgrub/proc/block_bullets(datum/source, obj/projectile/hitting_projectile) SIGNAL_HANDLER @@ -135,12 +124,14 @@ max_eggs_held = 1,\ ) -/mob/living/basic/mining/goldgrub/proc/consume_ore(obj/item/target_ore) +/mob/living/basic/mining/goldgrub/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) + . = ..() + if(!istype(arrived, /obj/item/stack/ore)) + return playsound(src,'sound/items/eatfood.ogg', rand(10,50), TRUE) - target_ore.forceMove(src) if(!can_lay_eggs) return - if(!istype(target_ore, /obj/item/stack/ore/bluespace_crystal) || prob(60)) + if(!istype(arrived, /obj/item/stack/ore/bluespace_crystal) || prob(60)) return new /obj/item/food/egg/green/grub_egg(get_turf(src)) diff --git a/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub_ai.dm b/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub_ai.dm index 7e7a72ec41206..53054052e58af 100644 --- a/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub_ai.dm +++ b/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub_ai.dm @@ -1,7 +1,7 @@ /datum/ai_controller/basic_controller/goldgrub blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, BB_ORE_IGNORE_TYPES = list(/obj/item/stack/ore/iron, /obj/item/stack/ore/glass), BB_STORM_APPROACHING = FALSE, ) @@ -20,7 +20,7 @@ /datum/ai_controller/basic_controller/babygrub blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_ORE_IGNORE_TYPES = list(/obj/item/stack/ore/glass), BB_FIND_MOM_TYPES = list(/mob/living/basic/mining/goldgrub), BB_IGNORE_MOM_TYPES = list(/mob/living/basic/mining/goldgrub/baby), diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath.dm index 20beac22176bb..6d197d8853a76 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath.dm @@ -80,14 +80,14 @@ tentacles.Grant(src) melee_tentacles = new(src) melee_tentacles.Grant(src) - AddComponent(/datum/component/revenge_ability, melee_tentacles, targetting = ai_controller.blackboard[BB_TARGETTING_DATUM], max_range = 1, target_self = TRUE) + AddComponent(/datum/component/revenge_ability, melee_tentacles, targeting = GET_TARGETING_STRATEGY(ai_controller.blackboard[BB_TARGETING_STRATEGY]), max_range = 1, target_self = TRUE) tentacle_line = new (src) tentacle_line.Grant(src) - AddComponent(/datum/component/revenge_ability, tentacle_line, targetting = ai_controller.blackboard[BB_TARGETTING_DATUM], min_range = 2, max_range = 9) + AddComponent(/datum/component/revenge_ability, tentacle_line, targeting = GET_TARGETING_STRATEGY(ai_controller.blackboard[BB_TARGETING_STRATEGY]), min_range = 2, max_range = 9) tentacles_ready() RegisterSignal(src, COMSIG_MOB_ABILITY_FINISHED, PROC_REF(used_ability)) - ai_controller.set_blackboard_key(BB_BASIC_FOODS, goliath_foods) + ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(goliath_foods)) ai_controller.set_blackboard_key(BB_GOLIATH_TENTACLES, tentacles) /mob/living/basic/mining/goliath/examine(mob/user) diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath_actions.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath_actions.dm index b484afa0cea36..31eecc0362906 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath_actions.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath_actions.dm @@ -1,7 +1,7 @@ /// Place some grappling tentacles underfoot /datum/action/cooldown/mob_cooldown/goliath_tentacles name = "Unleash Tentacles" - desc = "Unleash burrowed tentacles at a targetted location, grappling targets after a delay." + desc = "Unleash burrowed tentacles at a targeted location, grappling targets after a delay." button_icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' button_icon_state = "goliath_tentacle_wiggle" background_icon_state = "bg_demon" @@ -59,7 +59,7 @@ /// Summon a line of tentacles towards the target /datum/action/cooldown/mob_cooldown/tentacle_grasp name = "Tentacle Grasp" - desc = "Unleash burrowed tentacles in a line towards a targetted location, grappling targets after a delay." + desc = "Unleash burrowed tentacles in a line towards a targeted location, grappling targets after a delay." button_icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' button_icon_state = "goliath_tentacle_wiggle" background_icon_state = "bg_demon" diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm index 48f0e213e73fb..76c230520df34 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm @@ -3,7 +3,7 @@ /datum/ai_controller/basic_controller/goliath blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items, BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) @@ -27,7 +27,7 @@ /// Go for the tentacles if they're available /datum/ai_behavior/basic_melee_attack/goliath -/datum/ai_behavior/basic_melee_attack/goliath/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key, health_ratio_key) +/datum/ai_behavior/basic_melee_attack/goliath/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key, health_ratio_key) var/time_on_target = controller.blackboard[BB_BASIC_MOB_HAS_TARGET_TIME] || 0 if (time_on_target < MIN_TIME_TO_TENTACLE) return ..() diff --git a/code/modules/mob/living/basic/lavaland/gutlunchers/gutluncher_foodtrough.dm b/code/modules/mob/living/basic/lavaland/gutlunchers/gutluncher_foodtrough.dm new file mode 100644 index 0000000000000..16139da00becb --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/gutlunchers/gutluncher_foodtrough.dm @@ -0,0 +1,40 @@ +/obj/structure/ore_container/gutlunch_trough + name = "gutlunch trough" + desc = "The gutlunches will eat out of it!" + icon = 'icons/obj/structures.dmi' + icon_state = "gutlunch_trough" + density = TRUE + anchored = TRUE + ///list of materials in the trough + var/list/list_of_materials = list() + +/obj/structure/ore_container/gutlunch_trough/Entered(atom/movable/mover) + if(!istype(mover, /obj/item/stack/ore)) + return ..() + if(list_of_materials[mover.type]) + return ..() + list_of_materials[mover.type] = list("pixel_x" = rand(-5, 8), "pixel_y" = rand(-2, -7)) + return ..() + +/obj/structure/ore_container/gutlunch_trough/Exited(atom/movable/mover) + if(!istype(mover, /obj/item/stack/ore) || !isnull(locate(mover.type) in contents)) + return ..() + list_of_materials -= mover.type + return ..() + +/obj/structure/ore_container/gutlunch_trough/deconstruct(disassembled = TRUE) + if(flags_1 & NODECONSTRUCT_1) + return + new /obj/item/stack/sheet/mineral/wood(drop_location(), 5) + qdel(src) + +/obj/structure/ore_container/gutlunch_trough/update_overlays() + . = ..() + for(var/ore_entry in list_of_materials) + var/obj/item/ore_item = ore_entry + var/image/ore_icon = image(icon = initial(ore_item.icon), icon_state = initial(ore_item.icon_state), layer = LOW_ITEM_LAYER) + var/list/pixel_positions = list_of_materials[ore_entry] + ore_icon.transform = ore_icon.transform.Scale(0.4, 0.4) + ore_icon.pixel_x = pixel_positions["pixel_x"] + ore_icon.pixel_y = pixel_positions["pixel_y"] + . += ore_icon diff --git a/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers.dm b/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers.dm new file mode 100644 index 0000000000000..df9dc3cb3ecc0 --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers.dm @@ -0,0 +1,167 @@ +#define MAX_ATTACK_DIFFERENCE 3 +#define MAX_LOWER_ATTACK 15 +#define MINIMUM_POSSIBLE_SPEED 1 +#define MAX_POSSIBLE_HEALTH 100 + +/mob/living/basic/mining/gutlunch + name = "gutlunch" + desc = "A scavenger that eats raw ores, often found alongside ash walkers. Produces a thick, nutritious milk." + icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' + icon_state = "gutlunch" + combat_mode = FALSE + icon_living = "gutlunch" + icon_dead = "gutlunch" + mob_biotypes = MOB_ORGANIC|MOB_BEAST + basic_mob_flags = DEL_ON_DEATH + speak_emote = list("warbles", "quavers") + faction = list(FACTION_MINING, FACTION_ASHWALKER) + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "squishes" + response_harm_simple = "squish" + friendly_verb_continuous = "pinches" + friendly_verb_simple = "pinch" + gold_core_spawnable = FRIENDLY_SPAWN + death_message = "is pulped into bugmash." + greyscale_config = /datum/greyscale_config/gutlunch + ///possible colors we can have + var/list/possible_colors = list(COLOR_WHITE) + ///can we breed? + var/can_breed = TRUE + +/mob/living/basic/mining/gutlunch/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(pre_attack)) + if(greyscale_config) + set_greyscale(colors = list(pick(possible_colors))) + AddElement(/datum/element/ai_retaliate) + if(!can_breed) + return + AddComponent(\ + /datum/component/breed,\ + can_breed_with = typecacheof(list(/mob/living/basic/mining/gutlunch)),\ + baby_path = /mob/living/basic/mining/gutlunch/grub,\ + post_birth = CALLBACK(src, PROC_REF(after_birth)),\ + breed_timer = 3 MINUTES,\ + ) + +/mob/living/basic/mining/gutlunch/proc/pre_attack(mob/living/puncher, atom/target) + SIGNAL_HANDLER + + if(!istype(target, /obj/structure/ore_container/gutlunch_trough)) + return + + var/obj/ore_food = locate(/obj/item/stack/ore) in target + + if(isnull(ore_food)) + balloon_alert(src, "no food!") + else + melee_attack(ore_food) + return COMPONENT_HOSTILE_NO_ATTACK + +/mob/living/basic/mining/gutlunch/proc/after_birth(mob/living/basic/mining/gutlunch/grub/baby, mob/living/partner) + var/our_color = LAZYACCESS(atom_colours, FIXED_COLOUR_PRIORITY) || COLOR_GRAY + var/partner_color = LAZYACCESS(partner.atom_colours, FIXED_COLOUR_PRIORITY) || COLOR_GRAY + baby.add_atom_colour(BlendRGB(our_color, partner_color, 1), FIXED_COLOUR_PRIORITY) + var/atom/male_parent = (gender == MALE) ? src : partner + baby.inherited_stats = new(male_parent) + +/mob/living/basic/mining/gutlunch/proc/roll_stats(input_attack, input_speed, input_health) + melee_damage_lower = rand(input_attack, min(MAX_LOWER_ATTACK, input_attack + MAX_ATTACK_DIFFERENCE)) + melee_damage_upper = melee_damage_lower + MAX_ATTACK_DIFFERENCE + speed = rand(MINIMUM_POSSIBLE_SPEED, input_speed) + maxHealth = rand(input_health, MAX_POSSIBLE_HEALTH) + health = maxHealth + +/mob/living/basic/mining/gutlunch/milk + name = "gubbuck" + gender = FEMALE + possible_colors = list("#E39FBB","#817178","#9d667d") + ai_controller = /datum/ai_controller/basic_controller/gutlunch/gutlunch_milk + ///overlay we display when our udder is full! + var/mutable_appearance/full_udder + +/mob/living/basic/mining/gutlunch/milk/Initialize(mapload) + . = ..() + var/datum/callback/milking_callback = CALLBACK(src, TYPE_PROC_REF(/atom/movable, update_overlays)) + AddComponent(\ + /datum/component/udder,\ + udder_type = /obj/item/udder/gutlunch,\ + on_milk_callback = milking_callback,\ + on_generate_callback = milking_callback,\ + ) + full_udder = mutable_appearance(icon, "gl_full") + full_udder.color = LAZYACCESS(atom_colours, FIXED_COLOUR_PRIORITY) || COLOR_GRAY + +/mob/living/basic/mining/gutlunch/warrior + name = "gunther" + gender = MALE + melee_damage_lower = 8 + melee_damage_upper = 13 + speed = 5 + maxHealth = 70 + health = 70 + ai_controller = /datum/ai_controller/basic_controller/gutlunch/gutlunch_warrior + possible_colors = list("#6d77ff","#8578e4","#97b6f6") + //pet commands when we tame the gutluncher + var/static/list/pet_commands = list( + /datum/pet_command/idle, + /datum/pet_command/free, + /datum/pet_command/point_targeting/attack, + /datum/pet_command/point_targeting/breed, + /datum/pet_command/follow, + /datum/pet_command/point_targeting/fetch, + /datum/pet_command/mine_walls, + ) + +/mob/living/basic/mining/gutlunch/warrior/Initialize(mapload) + . = ..() + roll_stats(melee_damage_lower, speed, maxHealth) + AddComponent(/datum/component/obeys_commands, pet_commands) + AddElement(/datum/element/wall_tearer, allow_reinforced = FALSE) + +/mob/living/basic/mining/gutlunch/milk/update_overlays(new_udder_volume, max_udder_volume) + . = ..() + if(new_udder_volume != max_udder_volume) + return + . += full_udder + +/mob/living/basic/mining/gutlunch/grub + name = "grublunch" + possible_colors = list("#cc9797", "#b74c4c") + can_breed = FALSE + gender = NEUTER + ai_controller = /datum/ai_controller/basic_controller/gutlunch/gutlunch_baby + ///list of stats we inherited + var/datum/gutlunch_inherited_stats/inherited_stats + +/mob/living/basic/mining/gutlunch/grub/Initialize(mapload) + . = ..() + transform = transform.Scale(0.6, 0.6) + AddComponent(\ + /datum/component/growth_and_differentiation,\ + growth_time = 3 MINUTES,\ + growth_probability = 100,\ + lower_growth_value = 0.5,\ + upper_growth_value = 1,\ + signals_to_kill_on = list(COMSIG_MOB_CLIENT_LOGIN),\ + optional_checks = CALLBACK(src, PROC_REF(ready_to_grow)),\ + optional_grow_behavior = CALLBACK(src, PROC_REF(determine_growth_path)),\ + ) + +/mob/living/basic/mining/gutlunch/grub/proc/ready_to_grow() + return (stat == CONSCIOUS) + +/mob/living/basic/mining/gutlunch/grub/proc/determine_growth_path() + var/final_type = prob(50) ? /mob/living/basic/mining/gutlunch/warrior : /mob/living/basic/mining/gutlunch/milk + var/mob/living/basic/mining/gutlunch/grown_mob = new final_type(get_turf(src)) + if(grown_mob.gender == MALE && inherited_stats) + grown_mob.roll_stats(inherited_stats.attack, inherited_stats.speed, inherited_stats.health) + qdel(src) + +#undef MAX_ATTACK_DIFFERENCE +#undef MAX_LOWER_ATTACK +#undef MINIMUM_POSSIBLE_SPEED +#undef MAX_POSSIBLE_HEALTH diff --git a/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm b/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm new file mode 100644 index 0000000000000..8a6379febe031 --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_ai.dm @@ -0,0 +1,119 @@ +/datum/ai_controller/basic_controller/gutlunch + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + +/datum/ai_controller/basic_controller/gutlunch/gutlunch_warrior + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, + BB_BABIES_PARTNER_TYPES = list(/mob/living/basic/mining/gutlunch/milk), + BB_BABIES_CHILD_TYPES = list(/mob/living/basic/mining/gutlunch/grub), + BB_MAX_CHILDREN = 5, + ) + planning_subtrees = list( + /datum/ai_planning_subtree/target_retaliate/check_faction, + /datum/ai_planning_subtree/pet_planning, + /datum/ai_planning_subtree/make_babies, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + /datum/ai_planning_subtree/befriend_ashwalkers, + ) + +///find ashwalkers and add them to the list of masters +/datum/ai_planning_subtree/befriend_ashwalkers + +/datum/ai_planning_subtree/befriend_ashwalkers/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + controller.queue_behavior(/datum/ai_behavior/befriend_ashwalkers) + +/datum/ai_behavior/befriend_ashwalkers + action_cooldown = 5 SECONDS + behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + +/datum/ai_behavior/befriend_ashwalkers/perform(seconds_per_tick, datum/ai_controller/controller, target_key) + var/mob/living/living_pawn = controller.pawn + + for(var/mob/living/potential_friend in oview(9, living_pawn)) + if(!isashwalker(potential_friend)) + continue + if((living_pawn.faction.Find(REF(potential_friend)))) + continue + living_pawn.befriend(potential_friend) + to_chat(potential_friend, span_nicegreen("[living_pawn] looks at you with endearing eyes!")) + finish_action(controller, TRUE) + return + + finish_action(controller, FALSE) + return + + + +/datum/ai_controller/basic_controller/gutlunch/gutlunch_baby + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_FIND_MOM_TYPES = list(/mob/living/basic/mining/gutlunch/milk), + ) + planning_subtrees = list( + /datum/ai_planning_subtree/target_retaliate, + /datum/ai_planning_subtree/flee_target, + /datum/ai_planning_subtree/look_for_adult, + ) + +/datum/ai_controller/basic_controller/gutlunch/gutlunch_milk + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + ) + planning_subtrees = list( + /datum/ai_planning_subtree/target_retaliate, + /datum/ai_planning_subtree/flee_target, + /datum/ai_planning_subtree/find_and_hunt_target/food_trough + ) + +///consume food! +/datum/ai_planning_subtree/find_and_hunt_target/food_trough + target_key = BB_TROUGH_TARGET + hunting_behavior = /datum/ai_behavior/hunt_target/unarmed_attack_target/food_trough + finding_behavior = /datum/ai_behavior/find_hunt_target/food_trough + hunt_targets = list(/obj/structure/ore_container/gutlunch_trough) + hunt_chance = 75 + hunt_range = 9 + + +/datum/ai_planning_subtree/find_and_hunt_target/food_trough/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + if(!controller.blackboard[BB_CHECK_HUNGRY]) + return + return ..() + +/datum/ai_behavior/find_hunt_target/food_trough + +/datum/ai_behavior/find_hunt_target/food_trough/valid_dinner(mob/living/basic/source, obj/target, radius) + if(isnull(target)) + return FALSE + + if(isnull(locate(/obj/item/stack/ore) in target)) + return FALSE + + return can_see(source, target, radius) + +/datum/ai_behavior/hunt_target/unarmed_attack_target/food_trough + always_reset_target = TRUE + switch_combat_mode = TRUE + +/datum/pet_command/mine_walls + command_name = "Mine" + command_desc = "Command your pet to mine down walls." + speech_commands = list("mine", "smash") + +/datum/pet_command/mine_walls/try_activate_command(mob/living/commander) + var/mob/living/parent = weak_parent.resolve() + if(isnull(parent)) + return + //no walls for us to mine + var/target_in_vicinity = locate(/turf/closed/mineral) in oview(9, parent) + if(isnull(target_in_vicinity)) + return + return ..() + +/datum/pet_command/mine_walls/execute_action(datum/ai_controller/controller) + if(controller.blackboard_key_exists(BB_CURRENT_PET_TARGET)) + controller.queue_behavior(/datum/ai_behavior/mine_wall, BB_CURRENT_PET_TARGET) + return SUBTREE_RETURN_FINISH_PLANNING + controller.queue_behavior(/datum/ai_behavior/find_mineral_wall, BB_CURRENT_PET_TARGET) diff --git a/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_inherit_datum.dm b/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_inherit_datum.dm new file mode 100644 index 0000000000000..7051dfc2f4b21 --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/gutlunchers/gutlunchers_inherit_datum.dm @@ -0,0 +1,14 @@ +///stats we inherit from the parent +/datum/gutlunch_inherited_stats + ///attack we inherited + var/attack + ///speed we inherited + var/speed + ///health we inherited + var/health + +/datum/gutlunch_inherited_stats/New(mob/living/basic/parent) + . = ..() + attack = parent.melee_damage_lower + speed = parent.speed + health = parent.maxHealth diff --git a/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm b/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm index 11043e58d11ea..7b1e461991ce7 100644 --- a/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm +++ b/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm @@ -36,7 +36,7 @@ AddComponent(/datum/component/appearance_on_aggro, aggro_state = "hivelord_alert") spawn_brood = new(src) spawn_brood.Grant(src) - ai_controller.set_blackboard_key(BB_TARGETTED_ACTION, spawn_brood) + ai_controller.set_blackboard_key(BB_TARGETED_ACTION, spawn_brood) /mob/living/basic/mining/hivelord/Destroy() QDEL_NULL(spawn_brood) diff --git a/code/modules/mob/living/basic/lavaland/hivelord/hivelord_ai.dm b/code/modules/mob/living/basic/lavaland/hivelord/hivelord_ai.dm index fd7983de3977c..1fb05cd7a012b 100644 --- a/code/modules/mob/living/basic/lavaland/hivelord/hivelord_ai.dm +++ b/code/modules/mob/living/basic/lavaland/hivelord/hivelord_ai.dm @@ -1,7 +1,7 @@ /// Basically just keep away and shit out worms /datum/ai_controller/basic_controller/hivelord blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_AGGRO_RANGE = 5, // Only get mad at people nearby ) diff --git a/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm b/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm index 63a66d4c4e326..7d50806e63a0c 100644 --- a/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm +++ b/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm @@ -10,7 +10,7 @@ cooldown_time = 2 SECONDS melee_cooldown_time = 0 shared_cooldown = NONE - /// If a mob is not clicked directly, inherit targetting data from this blackboard key and setting it upon this target key + /// If a mob is not clicked directly, inherit targeting data from this blackboard key and setting it upon this target key var/ai_target_key = BB_BASIC_MOB_CURRENT_TARGET /// What are we actually spawning? var/spawn_type = /mob/living/basic/hivelord_brood diff --git a/code/modules/mob/living/basic/lavaland/legion/legion.dm b/code/modules/mob/living/basic/lavaland/legion/legion.dm index 5ed501b452dc6..b64c3b257a01e 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion.dm @@ -41,7 +41,7 @@ var/datum/action/cooldown/mob_cooldown/skull_launcher/skull_launcher = new(src) skull_launcher.Grant(src) skull_launcher.spawn_type = brood_type - ai_controller.set_blackboard_key(BB_TARGETTED_ACTION, skull_launcher) + ai_controller.set_blackboard_key(BB_TARGETED_ACTION, skull_launcher) /// Create what we want to drop on death, in proc form so we can always return a static list /mob/living/basic/mining/legion/proc/get_loot_list() diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm index 9167846b6853e..1bae1b3035379 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm @@ -1,7 +1,7 @@ /// Keep away and launch skulls at every opportunity, prioritising injured allies /datum/ai_controller/basic_controller/legion blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/legion, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/legion, BB_TARGET_MINIMUM_STAT = HARD_CRIT, BB_AGGRO_RANGE = 5, // Unobservant BB_BASIC_MOB_FLEE_DISTANCE = 6, @@ -16,10 +16,10 @@ /datum/ai_planning_subtree/flee_target/legion, ) -/// Chase and attack whatever we are targetting, if it's friendly we will heal them +/// Chase and attack whatever we are targeting, if it's friendly we will heal them /datum/ai_controller/basic_controller/legion_brood blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/legion, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/legion, BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) @@ -31,9 +31,9 @@ ) /// Target nearby friendlies if they are hurt (and are not themselves Legions) -/datum/targetting_datum/basic/legion +/datum/targeting_strategy/basic/legion -/datum/targetting_datum/basic/legion/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) +/datum/targeting_strategy/basic/legion/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) if (!living_mob.faction_check_atom(the_target, exact_match = check_factions_exactly)) return FALSE if (istype(the_target, living_mob.type)) diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm b/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm index ff5bfff52573e..91edf40615cf0 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm @@ -57,7 +57,7 @@ return return ..() -/// Turn the targetted mob into one of us +/// Turn the targeted mob into one of us /mob/living/basic/legion_brood/proc/infest(mob/living/target) visible_message(span_warning("[name] burrows into the flesh of [target]!")) var/spawn_type = get_legion_type(target) diff --git a/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm b/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm index f68c5f7fafe03..bd9b2c2aff99f 100644 --- a/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm +++ b/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm @@ -10,7 +10,7 @@ cooldown_time = 2 SECONDS melee_cooldown_time = 0 shared_cooldown = NONE - /// If a mob is not clicked directly, inherit targetting data from this blackboard key and setting it upon this target key + /// If a mob is not clicked directly, inherit targeting data from this blackboard key and setting it upon this target key var/ai_target_key = BB_BASIC_MOB_CURRENT_TARGET /// What are we actually spawning? var/spawn_type = /mob/living/basic/legion_brood diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm index bfd25a7c09b30..64facb5cfa353 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm @@ -43,7 +43,7 @@ ) charge = new(src) charge.Grant(src) - ai_controller.set_blackboard_key(BB_TARGETTED_ACTION, charge) + ai_controller.set_blackboard_key(BB_TARGETED_ACTION, charge) /mob/living/basic/mining/lobstrosity/Destroy() QDEL_NULL(charge) @@ -68,7 +68,7 @@ /datum/action/cooldown/mob_cooldown/charge/basic_charge/lobster/hit_target(atom/movable/source, atom/target, damage_dealt) . = ..() - if(!isliving(target) || !isbasicmob(source)) + if(!isbasicmob(source)) return var/mob/living/basic/basic_source = source var/mob/living/living_target = target diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm index c89cc3b9c07b7..b80d5d6b9f79a 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/lobstrosity blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, BB_LOBSTROSITY_EXPLOIT_TRAITS = list(TRAIT_INCAPACITATED, TRAIT_FLOORED, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT), BB_LOBSTROSITY_FINGER_LUST = 0 @@ -34,7 +34,7 @@ /datum/ai_behavior/basic_melee_attack/lobster -/datum/ai_behavior/basic_melee_attack/lobster/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/basic_melee_attack/lobster/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) var/mob/living/target = controller.blackboard[target_key] if (isnull(target)) return ..() @@ -55,7 +55,7 @@ flee_behaviour = /datum/ai_behavior/run_away_from_target/lobster /datum/ai_planning_subtree/flee_target/lobster/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - var/datum/action/cooldown/using_action = controller.blackboard[BB_TARGETTED_ACTION] + var/datum/action/cooldown/using_action = controller.blackboard[BB_TARGETED_ACTION] if (using_action?.IsAvailable()) return return ..() diff --git a/code/modules/mob/living/basic/lavaland/mook/mook.dm b/code/modules/mob/living/basic/lavaland/mook/mook.dm index 463c9d5de792e..6ecf54bc26482 100644 --- a/code/modules/mob/living/basic/lavaland/mook/mook.dm +++ b/code/modules/mob/living/basic/lavaland/mook/mook.dm @@ -41,8 +41,8 @@ var/list/pet_commands = list( /datum/pet_command/idle, /datum/pet_command/free, - /datum/pet_command/point_targetting/attack, - /datum/pet_command/point_targetting/fetch, + /datum/pet_command/point_targeting/attack, + /datum/pet_command/point_targeting/fetch, ) /mob/living/basic/mining/mook/Initialize(mapload) @@ -107,7 +107,7 @@ ore_target.forceMove(src) return COMPONENT_HOSTILE_NO_ATTACK - if(istype(target, /obj/structure/material_stand)) + if(istype(target, /obj/structure/ore_container/material_stand)) if(held_ore) held_ore.forceMove(target) return COMPONENT_HOSTILE_NO_ATTACK diff --git a/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm b/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm index 0fc2873531e07..cf79eb06aa605 100644 --- a/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm +++ b/code/modules/mob/living/basic/lavaland/mook/mook_ai.dm @@ -1,12 +1,12 @@ ///commands the chief can pick from GLOBAL_LIST_INIT(mook_commands, list( - new /datum/pet_command/point_targetting/attack, - new /datum/pet_command/point_targetting/fetch, + new /datum/pet_command/point_targeting/attack, + new /datum/pet_command/point_targeting/fetch, )) /datum/ai_controller/basic_controller/mook blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/mook, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/mook, BB_BLACKLIST_MINERAL_TURFS = list(/turf/closed/mineral/gibtonite, /turf/closed/mineral/strong), BB_MAXIMUM_DISTANCE_TO_VILLAGE = 7, BB_STORM_APPROACHING = FALSE, @@ -28,7 +28,7 @@ GLOBAL_LIST_INIT(mook_commands, list( ) ///check for faction if not a ash walker, otherwise just attack -/datum/targetting_datum/basic/mook/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) +/datum/targeting_strategy/basic/mook/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) if(FACTION_ASHWALKER in living_mob.faction) return FALSE @@ -71,7 +71,7 @@ GLOBAL_LIST_INIT(mook_commands, list( target_key = BB_MATERIAL_STAND_TARGET hunting_behavior = /datum/ai_behavior/hunt_target/unarmed_attack_target/material_stand finding_behavior = /datum/ai_behavior/find_hunt_target - hunt_targets = list(/obj/structure/material_stand) + hunt_targets = list(/obj/structure/ore_container/material_stand) hunt_range = 9 /datum/ai_planning_subtree/find_and_hunt_target/material_stand/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) @@ -83,6 +83,7 @@ GLOBAL_LIST_INIT(mook_commands, list( /datum/ai_behavior/hunt_target/unarmed_attack_target/material_stand required_distance = 0 always_reset_target = TRUE + switch_combat_mode = TRUE behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT ///try to face the counter when depositing ores @@ -212,7 +213,7 @@ GLOBAL_LIST_INIT(mook_commands, list( ///bard mook plays nice music for the village /datum/ai_controller/basic_controller/mook/bard blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/mook, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/mook, BB_MAXIMUM_DISTANCE_TO_VILLAGE = 10, BB_STORM_APPROACHING = FALSE, BB_SONG_LINES = MOOK_SONG, @@ -264,10 +265,10 @@ GLOBAL_LIST_INIT(mook_commands, list( ///healer mooks guard the village from intruders and heal the miner mooks when they come home /datum/ai_controller/basic_controller/mook/support blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/mook, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/mook, BB_MAXIMUM_DISTANCE_TO_VILLAGE = 10, BB_STORM_APPROACHING = FALSE, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, ) idle_behavior = /datum/idle_behavior/walk_near_target/mook_village planning_subtrees = list( @@ -324,7 +325,7 @@ GLOBAL_LIST_INIT(mook_commands, list( ///the chief would rather command his mooks to attack people than attack them himself /datum/ai_controller/basic_controller/mook/tribal_chief blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/mook, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/mook, BB_STORM_APPROACHING = FALSE, ) idle_behavior = /datum/idle_behavior/walk_near_target/mook_village @@ -349,7 +350,7 @@ GLOBAL_LIST_INIT(mook_commands, list( if(!locate(/mob/living/basic/mining/mook) in oview(command_distance, controller.pawn)) return if(controller.blackboard_key_exists(BB_BASIC_MOB_CURRENT_TARGET)) - controller.queue_behavior(/datum/ai_behavior/issue_commands, BB_BASIC_MOB_CURRENT_TARGET, /datum/pet_command/point_targetting/attack) + controller.queue_behavior(/datum/ai_behavior/issue_commands, BB_BASIC_MOB_CURRENT_TARGET, /datum/pet_command/point_targeting/attack) return var/atom/ore_target = controller.blackboard[BB_ORE_TARGET] @@ -359,7 +360,7 @@ GLOBAL_LIST_INIT(mook_commands, list( if(get_dist(ore_target, living_pawn) <= 1) return - controller.queue_behavior(/datum/ai_behavior/issue_commands, BB_ORE_TARGET, /datum/pet_command/point_targetting/fetch) + controller.queue_behavior(/datum/ai_behavior/issue_commands, BB_ORE_TARGET, /datum/pet_command/point_targeting/fetch) /datum/ai_behavior/issue_commands action_cooldown = 5 SECONDS diff --git a/code/modules/mob/living/basic/lavaland/mook/mook_village.dm b/code/modules/mob/living/basic/lavaland/mook/mook_village.dm index e3a091f6f0e49..ca2719ed7c67f 100644 --- a/code/modules/mob/living/basic/lavaland/mook/mook_village.dm +++ b/code/modules/mob/living/basic/lavaland/mook/mook_village.dm @@ -1,5 +1,5 @@ ///unique items that spawn at the mook village -/obj/structure/material_stand +/obj/structure/ore_container/material_stand name = "material stand" desc = "Is everyone free to use this thing?" icon = 'icons/mob/simple/jungle/mook.dmi' @@ -10,22 +10,8 @@ bound_width = 64 bound_height = 64 -/obj/structure/material_stand/attackby(obj/item/ore, mob/living/carbon/human/user, list/modifiers) - if(istype(ore, /obj/item/stack/ore)) - ore.forceMove(src) - return - return ..() - -/obj/structure/material_stand/Entered(atom/movable/mover) - . = ..() - update_appearance(UPDATE_OVERLAYS) - -/obj/structure/material_stand/Exited(atom/movable/mover) - . = ..() - update_appearance(UPDATE_OVERLAYS) - ///put ore icons on the counter! -/obj/structure/material_stand/update_overlays() +/obj/structure/ore_container/material_stand/update_overlays() . = ..() for(var/obj/item/stack/ore/ore_item in contents) var/image/ore_icon = image(icon = initial(ore_item.icon), icon_state = initial(ore_item.icon_state), layer = LOW_ITEM_LAYER) @@ -34,52 +20,6 @@ ore_icon.pixel_y = rand(2, 4) . += ore_icon -/obj/structure/material_stand/ui_interact(mob/user, datum/tgui/ui) - . = ..() - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "MaterialStand") - ui.open() - -/obj/structure/material_stand/ui_data(mob/user) - var/list/data = list() - data["ores"] = list() - for(var/obj/item/stack/ore/ore_item in contents) - data["ores"] += list(list( - "id" = REF(ore_item), - "name" = ore_item.name, - "amount" = ore_item.amount, - )) - return data - -/obj/structure/material_stand/ui_static_data(mob/user) - var/list/data = list() - data["ore_images"] = list() - for(var/obj/item/stack/ore_item as anything in subtypesof(/obj/item/stack/ore)) - data["ore_images"] += list(list( - "name" = initial(ore_item.name), - "icon" = icon2base64(getFlatIcon(image(icon = initial(ore_item.icon), icon_state = initial(ore_item.icon_state)), no_anim=TRUE)) - )) - return data - -/obj/structure/material_stand/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) - . = ..() - - if(. || !isliving(usr)) - return TRUE - - var/mob/living/customer = usr - var/obj/item/stack_to_move - switch(action) - if("withdraw") - if(isnull(params["reference"])) - return TRUE - stack_to_move = locate(params["reference"]) in contents - if(isnull(stack_to_move)) - return TRUE - stack_to_move.forceMove(get_turf(customer)) - return TRUE - /obj/effect/landmark/mook_village name = "mook village landmark" icon_state = "x" diff --git a/code/modules/mob/living/basic/lavaland/watcher/watcher.dm b/code/modules/mob/living/basic/lavaland/watcher/watcher.dm index 28ed712d06127..c3c30526dff74 100644 --- a/code/modules/mob/living/basic/lavaland/watcher/watcher.dm +++ b/code/modules/mob/living/basic/lavaland/watcher/watcher.dm @@ -62,7 +62,7 @@ var/datum/action/cooldown/mob_cooldown/watcher_gaze/gaze = new gaze_attack(src) gaze.Grant(src) ai_controller.set_blackboard_key(BB_GENERIC_ACTION, gaze) - AddComponent(/datum/component/revenge_ability, gaze, targetting = ai_controller.blackboard[BB_TARGETTING_DATUM]) + AddComponent(/datum/component/revenge_ability, gaze, targeting = GET_TARGETING_STRATEGY(ai_controller.blackboard[BB_TARGETING_STRATEGY])) /mob/living/basic/mining/watcher/update_overlays() . = ..() diff --git a/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm b/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm index 348bbcfcaa7d0..c962ca50c12a4 100644 --- a/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm +++ b/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/watcher blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = PAUSE_DURING_DO_AFTER diff --git a/code/modules/mob/living/basic/minebots/minebot.dm b/code/modules/mob/living/basic/minebots/minebot.dm index ad03da1e697de..6bc0202aed58b 100644 --- a/code/modules/mob/living/basic/minebots/minebot.dm +++ b/code/modules/mob/living/basic/minebots/minebot.dm @@ -40,7 +40,7 @@ /datum/pet_command/automate_mining, /datum/pet_command/free/minebot, /datum/pet_command/follow, - /datum/pet_command/point_targetting/attack/minebot, + /datum/pet_command/point_targeting/attack/minebot, ) /mob/living/basic/mining_drone/Initialize(mapload) diff --git a/code/modules/mob/living/basic/minebots/minebot_ai.dm b/code/modules/mob/living/basic/minebots/minebot_ai.dm index f4a2adda9e1fd..4aba93c426501 100644 --- a/code/modules/mob/living/basic/minebots/minebot_ai.dm +++ b/code/modules/mob/living/basic/minebots/minebot_ai.dm @@ -1,7 +1,7 @@ /datum/ai_controller/basic_controller/minebot blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, BB_BLACKLIST_MINERAL_TURFS = list(/turf/closed/mineral/gibtonite), BB_AUTOMATED_MINING = FALSE, ) @@ -201,10 +201,10 @@ radial_icon_state = "mech_eject" ability_key = BB_MINEBOT_DUMP_ABILITY -/datum/pet_command/point_targetting/attack/minebot +/datum/pet_command/point_targeting/attack/minebot attack_behaviour = /datum/ai_behavior/basic_ranged_attack/minebot -/datum/pet_command/point_targetting/attack/minebot/execute_action(datum/ai_controller/controller) +/datum/pet_command/point_targeting/attack/minebot/execute_action(datum/ai_controller/controller) controller.set_blackboard_key(BB_AUTOMATED_MINING, FALSE) var/mob/living/living_pawn = controller.pawn if(!living_pawn.combat_mode) diff --git a/code/modules/mob/living/basic/pets/dog/_dog.dm b/code/modules/mob/living/basic/pets/dog/_dog.dm index dd3b3b3a4634c..f835d7c5e1758 100644 --- a/code/modules/mob/living/basic/pets/dog/_dog.dm +++ b/code/modules/mob/living/basic/pets/dog/_dog.dm @@ -7,10 +7,10 @@ speech_commands = list("good dog") // Set correct attack behaviour -/datum/pet_command/point_targetting/attack/dog +/datum/pet_command/point_targeting/attack/dog attack_behaviour = /datum/ai_behavior/basic_melee_attack/dog -/datum/pet_command/point_targetting/attack/dog/set_command_active(mob/living/parent, mob/living/commander) +/datum/pet_command/point_targeting/attack/dog/set_command_active(mob/living/parent, mob/living/commander) . = ..() parent.ai_controller.set_blackboard_key(BB_DOG_HARASS_HARM, TRUE) @@ -40,8 +40,8 @@ /datum/pet_command/free, /datum/pet_command/good_boy/dog, /datum/pet_command/follow/dog, - /datum/pet_command/point_targetting/attack/dog, - /datum/pet_command/point_targetting/fetch, + /datum/pet_command/point_targeting/attack/dog, + /datum/pet_command/point_targeting/fetch, /datum/pet_command/play_dead, ) diff --git a/code/modules/mob/living/basic/pets/dog/corgi.dm b/code/modules/mob/living/basic/pets/dog/corgi.dm index 9e120c4e8c038..61c18ab535459 100644 --- a/code/modules/mob/living/basic/pets/dog/corgi.dm +++ b/code/modules/mob/living/basic/pets/dog/corgi.dm @@ -26,6 +26,8 @@ var/is_slow = FALSE ///Item slots that are available for this corgi to equip stuff into var/list/strippable_inventory_slots = list() + ///can this mob breed? + var/can_breed = TRUE /mob/living/basic/pet/dog/corgi/Initialize(mapload) . = ..() @@ -34,6 +36,13 @@ AddElement(/datum/element/swabable, CELL_LINE_TABLE_CORGI, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) RegisterSignal(src, COMSIG_MOB_TRIED_ACCESS, PROC_REF(on_tried_access)) RegisterSignals(src, list(COMSIG_BASICMOB_LOOK_ALIVE, COMSIG_BASICMOB_LOOK_DEAD), PROC_REF(on_appearance_change)) + if(!can_breed) + return + AddComponent(\ + /datum/component/breed,\ + can_breed_with = typecacheof(list(/mob/living/basic/pet/dog/corgi)),\ + baby_path = /mob/living/basic/pet/dog/corgi/puppy,\ + ) /mob/living/basic/pet/dog/corgi/Destroy() QDEL_NULL(inventory_head) @@ -532,9 +541,11 @@ icon_dead = "puppy_dead" density = FALSE pass_flags = PASSMOB + ai_controller = /datum/ai_controller/basic_controller/dog/puppy mob_size = MOB_SIZE_SMALL collar_icon_state = "puppy" strippable_inventory_slots = list(/datum/strippable_item/pet_collar, /datum/strippable_item/corgi_id) //puppies are too small to handle hats and back slot items + can_breed = FALSE //PUPPY IAN! SQUEEEEEEEEE~ /mob/living/basic/pet/dog/corgi/puppy/ian diff --git a/code/modules/mob/living/basic/pets/fox.dm b/code/modules/mob/living/basic/pets/fox.dm index 150abdc676bc7..7d74a6a36e410 100644 --- a/code/modules/mob/living/basic/pets/fox.dm +++ b/code/modules/mob/living/basic/pets/fox.dm @@ -39,8 +39,8 @@ /datum/ai_controller/basic_controller/fox blackboard = list( BB_ALWAYS_IGNORE_FACTION = TRUE, - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/ours_or_smaller, - BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/of_size/ours_or_smaller, + BB_FLEE_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/pets/penguin.dm b/code/modules/mob/living/basic/pets/penguin.dm index 35abc784e3792..671c2cf30c130 100644 --- a/code/modules/mob/living/basic/pets/penguin.dm +++ b/code/modules/mob/living/basic/pets/penguin.dm @@ -84,7 +84,7 @@ /datum/ai_controller/basic_controller/penguin blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED @@ -178,7 +178,7 @@ /datum/ai_controller/basic_controller/penguin/baby blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_FIND_MOM_TYPES = list(/mob/living/basic/pet/penguin), BB_IGNORE_MOM_TYPES = list(/mob/living/basic/pet/penguin/baby), ) diff --git a/code/modules/mob/living/basic/pets/sloth.dm b/code/modules/mob/living/basic/pets/sloth.dm index aaeeb218b2c0c..0b1546ccf93dd 100644 --- a/code/modules/mob/living/basic/pets/sloth.dm +++ b/code/modules/mob/living/basic/pets/sloth.dm @@ -75,8 +75,8 @@ GLOBAL_DATUM(cargo_sloth, /mob/living/basic/sloth) /// They're really passive in game, so they just wanna get away if you start smacking them. No trees in space from them to use for clawing your eyes out, but they will try if desperate. /datum/ai_controller/basic_controller/sloth blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_FLEE_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/ruin_defender/flesh.dm b/code/modules/mob/living/basic/ruin_defender/flesh.dm index 7d13c7e66217f..85f48a8f67266 100644 --- a/code/modules/mob/living/basic/ruin_defender/flesh.dm +++ b/code/modules/mob/living/basic/ruin_defender/flesh.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/living_limb_flesh blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) @@ -78,13 +78,13 @@ return step(victim, pick(GLOB.cardinals)) to_chat(victim, span_warning("Your [current_bodypart] moves on its own!")) - + /mob/living/basic/living_limb_flesh/melee_attack(mob/living/carbon/human/target, list/modifiers, ignore_cooldown) . = ..() if (!ishuman(target) || target.stat == DEAD || HAS_TRAIT(target, TRAIT_NODISMEMBER)) return - + var/list/zone_candidates = target.get_missing_limbs() for(var/obj/item/bodypart/bodypart in target.bodyparts) if(bodypart.body_zone == BODY_ZONE_HEAD || bodypart.body_zone == BODY_ZONE_CHEST) @@ -96,10 +96,10 @@ if(bodypart.brute_dam < 20) continue zone_candidates += bodypart.body_zone - + if(!length(zone_candidates)) return - + var/target_zone = pick(zone_candidates) var/obj/item/bodypart/target_part = target.get_bodypart(target_zone) if(isnull(target_part)) @@ -117,7 +117,7 @@ part_type = /obj/item/bodypart/leg/left/flesh if(BODY_ZONE_R_LEG) part_type = /obj/item/bodypart/leg/right/flesh - + target.visible_message(span_danger("[src] [target_part ? "tears off and attaches itself" : "attaches itself"] to where [target][target.p_s()] limb used to be!")) current_bodypart = new part_type(TRUE) //dont_spawn_flesh, we cant use named arguments here current_bodypart.replace_limb(target, TRUE) diff --git a/code/modules/mob/living/basic/ruin_defender/living_floor.dm b/code/modules/mob/living/basic/ruin_defender/living_floor.dm index f7e8cefa12e89..851a0873657a0 100644 --- a/code/modules/mob/living/basic/ruin_defender/living_floor.dm +++ b/code/modules/mob/living/basic/ruin_defender/living_floor.dm @@ -9,7 +9,7 @@ /datum/ai_controller/basic_controller/living_floor max_target_distance = 2 blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) @@ -46,7 +46,7 @@ attack_verb_simple = "bite" ai_controller = /datum/ai_controller/basic_controller/living_floor melee_attack_cooldown = 0.5 SECONDS // get real - + var/icon_aggro = "floor-hostile" var/desc_aggro = "This flooring is alive and filled with teeth, better not step on that. Being covered in plating, it is immune to damage. Seems vulnerable to prying though." @@ -61,8 +61,8 @@ if(!istype(victim) || istype(victim, /mob/living/basic/living_floor) || victim.stat == DEAD) return if(victim.loc == loc) //guaranteed bite - var/datum/targetting_datum/basic/targetting = ai_controller.blackboard[BB_TARGETTING_DATUM] - if(targetting.can_attack(src, victim)) + var/datum/targeting_strategy/basic/targeting = GET_TARGETING_STRATEGY(ai_controller.blackboard[BB_TARGETING_STRATEGY]) + if(targeting.can_attack(src, victim)) melee_attack(victim) icon_state = icon_aggro desc = desc_aggro diff --git a/code/modules/mob/living/basic/ruin_defender/skeleton.dm b/code/modules/mob/living/basic/ruin_defender/skeleton.dm index 125787319b094..17262f6495da1 100644 --- a/code/modules/mob/living/basic/ruin_defender/skeleton.dm +++ b/code/modules/mob/living/basic/ruin_defender/skeleton.dm @@ -51,7 +51,8 @@ AddElement(/datum/element/basic_eating, heal_amt = 50, drinking = TRUE, food_types = good_drinks) AddElement(/datum/element/basic_eating, heal_amt = 0, damage_amount = 25, damage_type = BURN, drinking = TRUE, food_types = bad_drinks) ADD_TRAIT(src, TRAIT_SNOWSTORM_IMMUNE, INNATE_TRAIT) - ai_controller?.set_blackboard_key(BB_BASIC_FOODS, good_drinks + bad_drinks) + var/list/foods_list = good_drinks + bad_drinks + ai_controller?.set_blackboard_key(BB_BASIC_FOODS, typecacheof(foods_list)) /mob/living/basic/skeleton/settler name = "undead settler" @@ -161,7 +162,7 @@ /// Skeletons mostly just beat people to death, but they'll also find and drink milk. /datum/ai_controller/basic_controller/skeleton blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items, BB_TARGET_MINIMUM_STAT = HARD_CRIT, BB_EMOTE_KEY = "rattles", BB_EMOTE_CHANCE = 20, diff --git a/code/modules/mob/living/basic/ruin_defender/stickman.dm b/code/modules/mob/living/basic/ruin_defender/stickman.dm index 107973135c78c..588a75c634643 100644 --- a/code/modules/mob/living/basic/ruin_defender/stickman.dm +++ b/code/modules/mob/living/basic/ruin_defender/stickman.dm @@ -33,7 +33,7 @@ /datum/ai_controller/basic_controller/stickman blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic() + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/ruin_defender/wizard/wizard_ai.dm b/code/modules/mob/living/basic/ruin_defender/wizard/wizard_ai.dm index ad3fd51b0f977..4430b1339a74e 100644 --- a/code/modules/mob/living/basic/ruin_defender/wizard/wizard_ai.dm +++ b/code/modules/mob/living/basic/ruin_defender/wizard/wizard_ai.dm @@ -5,7 +5,7 @@ */ /datum/ai_controller/basic_controller/wizard blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) diff --git a/code/modules/mob/living/basic/space_fauna/ant.dm b/code/modules/mob/living/basic/space_fauna/ant.dm index 7748d9120d76d..26a904340b7c5 100644 --- a/code/modules/mob/living/basic/space_fauna/ant.dm +++ b/code/modules/mob/living/basic/space_fauna/ant.dm @@ -45,7 +45,7 @@ /datum/ai_controller/basic_controller/ant blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/bear/bear_ai_subtree.dm b/code/modules/mob/living/basic/space_fauna/bear/bear_ai_subtree.dm index 851c0bb80290b..335e7257e504e 100644 --- a/code/modules/mob/living/basic/space_fauna/bear/bear_ai_subtree.dm +++ b/code/modules/mob/living/basic/space_fauna/bear/bear_ai_subtree.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/bear blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp.dm b/code/modules/mob/living/basic/space_fauna/carp/carp.dm index 75be113f651a0..ebb6f1d23f7fa 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp.dm @@ -58,7 +58,7 @@ /datum/pet_command/idle, /datum/pet_command/free, /datum/pet_command/follow, - /datum/pet_command/point_targetting/attack + /datum/pet_command/point_targeting/attack ) /// Carp want to eat raw meat var/static/list/desired_food = list(/obj/item/food/meat/slab, /obj/item/food/meat/rawcutlet) @@ -103,13 +103,14 @@ teleport = new(src) teleport.Grant(src) ai_controller.set_blackboard_key(BB_CARP_RIFT, teleport) - ai_controller.set_blackboard_key(BB_OBSTACLE_TARGETTING_WHITELIST, allowed_obstacle_targets) + ai_controller.set_blackboard_key(BB_OBSTACLE_TARGETING_WHITELIST, allowed_obstacle_targets) /// Tell the elements and the blackboard what food we want to eat /mob/living/basic/carp/proc/setup_eating() AddElement(/datum/element/basic_eating, food_types = desired_food) AddElement(/datum/element/basic_eating, heal_amt = 0, damage_amount = 10, damage_type = BRUTE, food_types = desired_trash) // We are killing our planet - ai_controller.set_blackboard_key(BB_BASIC_FOODS, desired_food + desired_trash) + var/list/foods_list = desired_food + desired_trash + ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(foods_list)) /// Set a random colour on the carp, override to do something else /mob/living/basic/carp/proc/apply_colour() diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm index b1343a7aeedbf..9e767bab3af1f 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm @@ -1,6 +1,6 @@ #define MAGICARP_SPELL_TARGET_SEEK_RANGE 4 -/datum/pet_command/point_targetting/use_ability/magicarp +/datum/pet_command/point_targeting/use_ability/magicarp pet_ability_key = BB_MAGICARP_SPELL /datum/ai_planning_subtree/attack_obstacle_in_path/carp @@ -16,18 +16,18 @@ /// Interrupt your attack chain if: you have a spell, it's not on cooldown, and it has a target /datum/ai_behavior/basic_melee_attack/magicarp -/datum/ai_behavior/basic_melee_attack/magicarp/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key, health_ratio_key) +/datum/ai_behavior/basic_melee_attack/magicarp/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key, health_ratio_key) var/datum/action/cooldown/using_action = controller.blackboard[BB_MAGICARP_SPELL] if (QDELETED(using_action)) return ..() - if (!controller.blackboard[BB_MAGICARP_SPELL_SPECIAL_TARGETTING] && using_action.IsAvailable()) + if (!controller.blackboard[BB_MAGICARP_SPELL_SPECIAL_TARGETING] && using_action.IsAvailable()) finish_action(controller, succeeded = FALSE) return return ..() /** * Find a target for the magicarp's spell - * This gets weird because different spells want different targetting + * This gets weird because different spells want different targeting * but I didn't want a new ai controller for every different spell */ /datum/ai_planning_subtree/find_nearest_magicarp_spell_target @@ -37,12 +37,12 @@ if (!using_action?.IsAvailable()) return - var/spell_targetting = controller.blackboard[BB_MAGICARP_SPELL_SPECIAL_TARGETTING] - if (!spell_targetting) - controller.queue_behavior(/datum/ai_behavior/find_potential_targets/nearest/magicarp, BB_MAGICARP_SPELL_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + var/spell_targeting = controller.blackboard[BB_MAGICARP_SPELL_SPECIAL_TARGETING] + if (!spell_targeting) + controller.queue_behavior(/datum/ai_behavior/find_potential_targets/nearest/magicarp, BB_MAGICARP_SPELL_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) return - switch(spell_targetting) + switch(spell_targeting) if (MAGICARP_SPELL_CORPSES) controller.queue_behavior(/datum/ai_behavior/find_and_set/friendly_corpses, BB_MAGICARP_SPELL_TARGET, MAGICARP_SPELL_TARGET_SEEK_RANGE) return diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm index 5bf664d168784..0befb20987c01 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm @@ -10,8 +10,8 @@ /datum/ai_controller/basic_controller/carp blackboard = list( BB_BASIC_MOB_STOP_FLEEING = TRUE, - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -37,8 +37,8 @@ /datum/ai_controller/basic_controller/carp/pet blackboard = list( BB_BASIC_MOB_STOP_FLEEING = TRUE, - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, ) ai_traits = STOP_MOVING_WHEN_PULLED planning_subtrees = list( @@ -81,8 +81,8 @@ /datum/ai_controller/basic_controller/carp/passive blackboard = list( BB_BASIC_MOB_STOP_FLEEING = TRUE, - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, ) ai_traits = STOP_MOVING_WHEN_PULLED planning_subtrees = list( diff --git a/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm b/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm index 32f02b880dba4..65d16cfb490dd 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm @@ -56,8 +56,8 @@ GLOBAL_LIST_INIT(magicarp_spell_colours, list( /datum/pet_command/idle, /datum/pet_command/free, /datum/pet_command/follow, - /datum/pet_command/point_targetting/attack, - /datum/pet_command/point_targetting/use_ability/magicarp, + /datum/pet_command/point_targeting/attack, + /datum/pet_command/point_targeting/use_ability/magicarp, ) /// List of all projectiles we can fire. /// Non-static, because subtypes can have their own lists. @@ -91,15 +91,15 @@ GLOBAL_LIST_INIT(magicarp_spell_colours, list( ai_controller.set_blackboard_key(BB_MAGICARP_SPELL, spell) assign_spell_ai(spell_type) -/// If you have certain spells, use a different targetting datum +/// If you have certain spells, use a different targeting strategy /mob/living/basic/carp/magic/proc/assign_spell_ai(spell_type) - var/static/list/spell_special_targetting = list( + var/static/list/spell_special_targeting = list( /obj/projectile/magic/animate = MAGICARP_SPELL_OBJECTS, /obj/projectile/magic/door = MAGICARP_SPELL_WALLS, /obj/projectile/magic/resurrection = MAGICARP_SPELL_CORPSES, ) - ai_controller.set_blackboard_key(BB_MAGICARP_SPELL_SPECIAL_TARGETTING, spell_special_targetting[spell_type]) + ai_controller.set_blackboard_key(BB_MAGICARP_SPELL_SPECIAL_TARGETING, spell_special_targeting[spell_type]) /// Shoot when you click away from you /mob/living/basic/carp/magic/RangedAttack(atom/atom_target, modifiers) diff --git a/code/modules/mob/living/basic/space_fauna/cat_surgeon.dm b/code/modules/mob/living/basic/space_fauna/cat_surgeon.dm index 487727fb53cc1..02faf7c2cc9f2 100644 --- a/code/modules/mob/living/basic/space_fauna/cat_surgeon.dm +++ b/code/modules/mob/living/basic/space_fauna/cat_surgeon.dm @@ -64,7 +64,7 @@ /datum/ai_controller/basic_controller/cat_butcherer blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_subtree.dm b/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_subtree.dm index b3033b27a4bd3..29ea1dfc352ea 100644 --- a/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_subtree.dm +++ b/code/modules/mob/living/basic/space_fauna/eyeball/eyeball_ai_subtree.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/eyeball blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/eyeball, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/eyeball, BB_EYE_DAMAGE_THRESHOLD = 10, ) @@ -22,7 +22,7 @@ return SUBTREE_RETURN_FINISH_PLANNING controller.queue_behavior(/datum/ai_behavior/find_the_blind, BB_BLIND_TARGET, BB_EYE_DAMAGE_THRESHOLD) -/datum/targetting_datum/basic/eyeball/can_attack(mob/living/owner, atom/target, vision_range) +/datum/targeting_strategy/basic/eyeball/can_attack(mob/living/owner, atom/target, vision_range) . = ..() if(!.) return FALSE diff --git a/code/modules/mob/living/basic/space_fauna/faithless.dm b/code/modules/mob/living/basic/space_fauna/faithless.dm index 5cfdd4b47b6e2..39f5652d1a0a4 100644 --- a/code/modules/mob/living/basic/space_fauna/faithless.dm +++ b/code/modules/mob/living/basic/space_fauna/faithless.dm @@ -55,7 +55,7 @@ /datum/ai_controller/basic_controller/faithless blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = UNCONSCIOUS, BB_LOW_PRIORITY_HUNTING_TARGET = null, // lights ) diff --git a/code/modules/mob/living/basic/space_fauna/garden_gnome.dm b/code/modules/mob/living/basic/space_fauna/garden_gnome.dm index d9dfc3c534328..40debc7622bc4 100644 --- a/code/modules/mob/living/basic/space_fauna/garden_gnome.dm +++ b/code/modules/mob/living/basic/space_fauna/garden_gnome.dm @@ -125,7 +125,7 @@ /datum/ai_controller/basic_controller/garden_gnome blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/ghost.dm b/code/modules/mob/living/basic/space_fauna/ghost.dm index ad79fefc3e6bc..981357d1a130c 100644 --- a/code/modules/mob/living/basic/space_fauna/ghost.dm +++ b/code/modules/mob/living/basic/space_fauna/ghost.dm @@ -94,7 +94,7 @@ /datum/ai_controller/basic_controller/ghost blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_subtree.dm b/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_subtree.dm index 5bd957a760972..067b0a03c13cc 100644 --- a/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_subtree.dm +++ b/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_subtree.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/hivebot blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/killer_tomato.dm b/code/modules/mob/living/basic/space_fauna/killer_tomato.dm index a3fd64eb79860..c859289b56d7d 100644 --- a/code/modules/mob/living/basic/space_fauna/killer_tomato.dm +++ b/code/modules/mob/living/basic/space_fauna/killer_tomato.dm @@ -42,7 +42,7 @@ /datum/ai_controller/basic_controller/killer_tomato blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/lightgeist.dm b/code/modules/mob/living/basic/space_fauna/lightgeist.dm index 9ab6ffe677855..5847b2b6d771c 100644 --- a/code/modules/mob/living/basic/space_fauna/lightgeist.dm +++ b/code/modules/mob/living/basic/space_fauna/lightgeist.dm @@ -78,7 +78,7 @@ /datum/ai_controller/basic_controller/lightgeist blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/lightgeist, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/lightgeist, ) ai_traits = STOP_MOVING_WHEN_PULLED @@ -91,13 +91,13 @@ ) /// Attack only mobs who have damage that we can heal, I think this is specific enough not to be a generic type -/datum/targetting_datum/lightgeist +/datum/targeting_strategy/lightgeist /// Types of mobs we can heal, not in a blackboard key because there is no point changing this at runtime because the component will already exist var/heal_biotypes = MOB_ORGANIC | MOB_MINERAL /// Type of limb we can heal var/required_bodytype = BODYTYPE_ORGANIC -/datum/targetting_datum/lightgeist/can_attack(mob/living/living_mob, mob/living/target, vision_range) +/datum/targeting_strategy/lightgeist/can_attack(mob/living/living_mob, mob/living/target, vision_range) if (!isliving(target) || target.stat == DEAD) return FALSE if (!(heal_biotypes & target.mob_biotypes)) diff --git a/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart_ai.dm b/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart_ai.dm index 7684011bd667c..09659956c5813 100644 --- a/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart_ai.dm +++ b/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart_ai.dm @@ -1,7 +1,7 @@ /// A spellcasting AI which does not move /datum/ai_controller/basic_controller/meteor_heart blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGETLESS_TIME = 0, ) diff --git a/code/modules/mob/living/basic/space_fauna/morph.dm b/code/modules/mob/living/basic/space_fauna/morph.dm index 32115d0560255..22cce322b13a7 100644 --- a/code/modules/mob/living/basic/space_fauna/morph.dm +++ b/code/modules/mob/living/basic/space_fauna/morph.dm @@ -200,7 +200,7 @@ /// Only real human-powered intelligence is capable of playing prop hunt in SS13 (until further notice). /datum/ai_controller/basic_controller/morph blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/mushroom.dm b/code/modules/mob/living/basic/space_fauna/mushroom.dm index 056a4558081ed..b45c2714d4ab4 100644 --- a/code/modules/mob/living/basic/space_fauna/mushroom.dm +++ b/code/modules/mob/living/basic/space_fauna/mushroom.dm @@ -57,7 +57,7 @@ /datum/ai_controller/basic_controller/mushroom blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/mushroom, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/mushroom, BB_TARGET_MINIMUM_STAT = DEAD, ) @@ -70,10 +70,10 @@ ) -/datum/targetting_datum/basic/mushroom +/datum/targeting_strategy/basic/mushroom ///we only attacked another mushrooms -/datum/targetting_datum/basic/mushroom/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) +/datum/targeting_strategy/basic/mushroom/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) return !living_mob.faction_check_atom(the_target, exact_match = check_factions_exactly) /datum/ai_planning_subtree/find_and_hunt_target/mushroom_food diff --git a/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_wizard.dm b/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_wizard.dm index c4ea41cad37a7..720e0c031c0a3 100644 --- a/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_wizard.dm +++ b/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_wizard.dm @@ -48,7 +48,7 @@ /datum/ai_controller/basic_controller/paper_wizard blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_WRITING_LIST = list( "I can turn the paper into gold and ink into diamonds!", "Your fate is written and sealed!", diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm index 43108c67ef377..6999894801985 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm @@ -71,6 +71,12 @@ grant_actions_by_list(innate_actions) +/mob/living/basic/regal_rat/death(gibbed) + var/datum/component/potential_component = GetComponent(/datum/component/ghost_direct_control) + if(!QDELETED(potential_component)) + qdel(potential_component) + return ..() + /mob/living/basic/regal_rat/examine(mob/user) . = ..() if(user == src) diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm index e617ae0a670af..1ab7bd36594c6 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm @@ -56,7 +56,7 @@ /datum/pet_command/free, /datum/pet_command/protect_owner, /datum/pet_command/follow, - /datum/pet_command/point_targetting/attack/mouse + /datum/pet_command/point_targeting/attack/mouse ) /// Commands you can give to glockroaches var/static/list/glockroach_commands = list( @@ -64,7 +64,7 @@ /datum/pet_command/free, /datum/pet_command/protect_owner/glockroach, /datum/pet_command/follow, - /datum/pet_command/point_targetting/attack/glockroach + /datum/pet_command/point_targeting/attack/glockroach ) /datum/action/cooldown/mob_cooldown/riot/Activate(atom/target) @@ -193,7 +193,7 @@ return TRUE // Command you can give to a mouse to make it kill someone -/datum/pet_command/point_targetting/attack/mouse +/datum/pet_command/point_targeting/attack/mouse speech_commands = list("attack", "sic", "kill", "cheese em") command_feedback = "squeak!" // Frogs and roaches can squeak too it's fine pointed_reaction = "and squeaks aggressively" @@ -201,7 +201,7 @@ attack_behaviour = /datum/ai_behavior/basic_melee_attack // Command you can give to a mouse to make it kill someone -/datum/pet_command/point_targetting/attack/glockroach +/datum/pet_command/point_targeting/attack/glockroach speech_commands = list("attack", "sic", "kill", "cheese em") command_feedback = "squeak!" pointed_reaction = "and cocks its gun" diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_ai.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_ai.dm index 8a7013b962373..073029bef3c26 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_ai.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_ai.dm @@ -1,7 +1,7 @@ /datum/ai_controller/basic_controller/regal_rat blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_FLEE_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/snake/snake.dm b/code/modules/mob/living/basic/space_fauna/snake/snake.dm index 164752e277d97..7a30d713a4d98 100644 --- a/code/modules/mob/living/basic/space_fauna/snake/snake.dm +++ b/code/modules/mob/living/basic/space_fauna/snake/snake.dm @@ -50,7 +50,7 @@ AddElement(/datum/element/swabable, CELL_LINE_TABLE_SNAKE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) AddElement(/datum/element/basic_eating, heal_amt = 2, food_types = edibles) - ai_controller.set_blackboard_key(BB_BASIC_FOODS, edibles) + ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(edibles)) AddComponent(\ /datum/component/tameable,\ @@ -71,7 +71,7 @@ /// Snakes are primarily concerned with getting those tasty, tasty mice, but aren't afraid to strike back at those who attack them /datum/ai_controller/basic_controller/snake blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends/allow_items, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends/allow_items, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/space_fauna/spaceman.dm b/code/modules/mob/living/basic/space_fauna/spaceman.dm index 5851bfa531b37..8a9ba36287ae3 100644 --- a/code/modules/mob/living/basic/space_fauna/spaceman.dm +++ b/code/modules/mob/living/basic/space_fauna/spaceman.dm @@ -32,7 +32,7 @@ /datum/ai_controller/basic_controller/spaceman blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_ai.dm b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_ai.dm index 7dd61b72070df..ae971fd2558e5 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_ai.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_ai.dm @@ -1,7 +1,7 @@ /// Attacks people it can see, spins webs if it can't see anything to attack. /datum/ai_controller/basic_controller/giant_spider blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED | PAUSE_DURING_DO_AFTER @@ -30,7 +30,7 @@ /// Used by Araneus, who only attacks those who attack first. He is house-trained and will not web up the HoS office. /datum/ai_controller/basic_controller/giant_spider/retaliate blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) planning_subtrees = list( @@ -43,8 +43,8 @@ /// Retaliates, hunts other maintenance creatures, runs away from larger attackers, and spins webs. /datum/ai_controller/basic_controller/giant_spider/pest blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/ours_or_smaller(), // Hunt mobs our size - BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/larger(), // Run away from mobs bigger than we are + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/of_size/ours_or_smaller, // Hunt mobs our size + BB_FLEE_TARGETING_STRATEGY = /datum/targeting_strategy/basic/of_size/larger, // Run away from mobs bigger than we are ) idle_behavior = /datum/idle_behavior/idle_random_walk diff --git a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spiders.dm b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spiders.dm index c79731bcdd1a8..99e4b2b03cc06 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spiders.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spiders.dm @@ -225,7 +225,7 @@ heal_brute = 15,\ heal_burn = 15,\ heal_time = 3 SECONDS,\ - self_targetting = HEALING_TOUCH_SELF_ONLY,\ + self_targeting = HEALING_TOUCH_SELF_ONLY,\ interaction_key = DOAFTER_SOURCE_SPIDER,\ valid_targets_typecache = typecacheof(list(/mob/living/basic/spider/growing/young/tangle, /mob/living/basic/spider/giant/tangle)),\ extra_checks = CALLBACK(src, PROC_REF(can_mend)),\ @@ -275,7 +275,7 @@ heal_brute = 50,\ heal_burn = 50,\ heal_time = 5 SECONDS,\ - self_targetting = HEALING_TOUCH_SELF_ONLY,\ + self_targeting = HEALING_TOUCH_SELF_ONLY,\ interaction_key = DOAFTER_SOURCE_SPIDER,\ valid_targets_typecache = typecacheof(list(/mob/living/basic/spider/growing/young/tank, /mob/living/basic/spider/giant/tank)),\ extra_checks = CALLBACK(src, PROC_REF(can_mend)),\ diff --git a/code/modules/mob/living/basic/space_fauna/spider/spiderlings/spiderling.dm b/code/modules/mob/living/basic/space_fauna/spider/spiderlings/spiderling.dm index f36b1bc46ba35..2bce05b1a61ba 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/spiderlings/spiderling.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/spiderlings/spiderling.dm @@ -61,7 +61,7 @@ /// Opportunistically hops in and out of vents, if it can find one. We aren't interested in attacking due to how weak we are, we gotta be quick and hidey. /datum/ai_controller/basic_controller/spiderling blackboard = list( - BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/larger, // Run away from mobs bigger than we are + BB_FLEE_TARGETING_STRATEGY = /datum/targeting_strategy/basic/of_size/larger, // Run away from mobs bigger than we are BB_VENTCRAWL_COOLDOWN = 20 SECONDS, // enough time to get splatted while we're out in the open. BB_TIME_TO_GIVE_UP_ON_VENT_PATHING = 30 SECONDS, ) diff --git a/code/modules/mob/living/basic/space_fauna/spider/young_spider/young_spider.dm b/code/modules/mob/living/basic/space_fauna/spider/young_spider/young_spider.dm index bdaf7d03faa6e..8c17833c0c7e8 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/young_spider/young_spider.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/young_spider/young_spider.dm @@ -29,7 +29,7 @@ /// Used by all young spiders if they ever appear. /datum/ai_controller/basic_controller/young_spider blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_BASIC_MOB_FLEE_DISTANCE = 6, ) diff --git a/code/modules/mob/living/basic/space_fauna/spider/young_spider/young_spider_subtypes.dm b/code/modules/mob/living/basic/space_fauna/spider/young_spider/young_spider_subtypes.dm index 809755e355514..3a9bad4e75f98 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/young_spider/young_spider_subtypes.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/young_spider/young_spider_subtypes.dm @@ -135,7 +135,7 @@ heal_brute = 10,\ heal_burn = 10,\ heal_time = 3 SECONDS,\ - self_targetting = HEALING_TOUCH_SELF_ONLY,\ + self_targeting = HEALING_TOUCH_SELF_ONLY,\ interaction_key = DOAFTER_SOURCE_SPIDER,\ valid_targets_typecache = typecacheof(list(/mob/living/basic/spider/growing/young/tangle, /mob/living/basic/spider/giant/tangle)),\ extra_checks = CALLBACK(src, PROC_REF(can_mend)),\ @@ -174,7 +174,7 @@ heal_brute = 5,\ heal_burn = 5,\ heal_time = 2 SECONDS,\ - self_targetting = HEALING_TOUCH_SELF_ONLY,\ + self_targeting = HEALING_TOUCH_SELF_ONLY,\ interaction_key = DOAFTER_SOURCE_SPIDER,\ valid_targets_typecache = typecacheof(list(/mob/living/basic/spider/growing/young/tank, /mob/living/basic/spider/giant/tank)),\ extra_checks = CALLBACK(src, PROC_REF(can_mend)),\ diff --git a/code/modules/mob/living/basic/space_fauna/statue/statue.dm b/code/modules/mob/living/basic/space_fauna/statue/statue.dm index c525c03bda017..801aa271d91f7 100644 --- a/code/modules/mob/living/basic/space_fauna/statue/statue.dm +++ b/code/modules/mob/living/basic/space_fauna/statue/statue.dm @@ -141,7 +141,7 @@ /datum/ai_controller/basic_controller/statue blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_LOW_PRIORITY_HUNTING_TARGET = null, // lights ) diff --git a/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm b/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm index 2a3ba326eaca9..02fd9ed1bcf1e 100644 --- a/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm +++ b/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm @@ -82,7 +82,7 @@ /datum/ai_controller/basic_controller/supermatter_spider blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm index 3dbb4a743ccf6..98daeb6d8c232 100644 --- a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm +++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm @@ -15,7 +15,7 @@ if(fugu_blacklist) return fugu_blacklist = typecacheof(list( - /mob/living/simple_animal/hostile/guardian, + /mob/living/basic/guardian, )) /obj/item/fugu_gland/afterattack(atom/target, mob/user, proximity_flag) diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_ai.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_ai.dm index e405ee3755abf..1b4e2cdd62019 100644 --- a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_ai.dm +++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_ai.dm @@ -1,7 +1,7 @@ /// Cowardly when small, aggressive when big. Tries to transform whenever possible. /datum/ai_controller/basic_controller/wumborian_fugu blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/trader/trader_ai.dm b/code/modules/mob/living/basic/trader/trader_ai.dm index d6cf0095c7d83..5f447ab3229af 100644 --- a/code/modules/mob/living/basic/trader/trader_ai.dm +++ b/code/modules/mob/living/basic/trader/trader_ai.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/trader blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/tree.dm b/code/modules/mob/living/basic/tree.dm index 2a0806b105c98..3f3894f190b5e 100644 --- a/code/modules/mob/living/basic/tree.dm +++ b/code/modules/mob/living/basic/tree.dm @@ -56,7 +56,7 @@ . = ..() AddComponent(/datum/component/seethrough_mob) AddElement(/datum/element/swabable, CELL_LINE_TABLE_PINE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) - var/static/list/death_loot = list(/obj/item/stack/sheet/mineral/wood) + var/list/death_loot = string_list(list(/obj/item/stack/sheet/mineral/wood)) AddElement(/datum/element/death_drops, death_loot) AddComponent(/datum/component/aggro_emote, emote_list = string_list(list("growls")), emote_chance = 20) @@ -100,7 +100,7 @@ /datum/ai_controller/basic_controller/tree blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/trooper/nanotrasen.dm b/code/modules/mob/living/basic/trooper/nanotrasen.dm index 7dfab5298c208..6da3d2d9fb21b 100644 --- a/code/modules/mob/living/basic/trooper/nanotrasen.dm +++ b/code/modules/mob/living/basic/trooper/nanotrasen.dm @@ -34,6 +34,8 @@ cooldown_time = ranged_cooldown,\ burst_shots = burst_shots,\ ) + if (ranged_cooldown <= 1 SECONDS) + AddComponent(/datum/component/ranged_mob_full_auto) /mob/living/basic/trooper/nanotrasen/ranged/smg ai_controller = /datum/ai_controller/basic_controller/trooper/ranged/burst diff --git a/code/modules/mob/living/basic/trooper/syndicate.dm b/code/modules/mob/living/basic/trooper/syndicate.dm index 7075e293add78..76ad808ceb38c 100644 --- a/code/modules/mob/living/basic/trooper/syndicate.dm +++ b/code/modules/mob/living/basic/trooper/syndicate.dm @@ -121,6 +121,8 @@ cooldown_time = ranged_cooldown,\ burst_shots = burst_shots,\ ) + if (ranged_cooldown <= 1 SECONDS) + AddComponent(/datum/component/ranged_mob_full_auto) /mob/living/basic/trooper/syndicate/ranged/infiltrator //shuttle loan event projectilesound = 'sound/weapons/gun/smg/shot_suppressed.ogg' diff --git a/code/modules/mob/living/basic/trooper/trooper_ai.dm b/code/modules/mob/living/basic/trooper/trooper_ai.dm index 3b89807ea62c2..cf71b38f45b53 100644 --- a/code/modules/mob/living/basic/trooper/trooper_ai.dm +++ b/code/modules/mob/living/basic/trooper/trooper_ai.dm @@ -1,6 +1,6 @@ /datum/ai_controller/basic_controller/trooper blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_TARGET_MINIMUM_STAT = HARD_CRIT, BB_REINFORCEMENTS_SAY = "411 in progress, requesting backup!" ) @@ -90,10 +90,10 @@ /datum/ai_behavior/basic_ranged_attack/trooper_shotgun action_cooldown = 3 SECONDS - required_distance = 1 + required_distance = 3 avoid_friendly_fire = TRUE /datum/ai_controller/basic_controller/trooper/viscerator blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) diff --git a/code/modules/mob/living/basic/vermin/cockroach.dm b/code/modules/mob/living/basic/vermin/cockroach.dm index 639a9720dbce3..595ef0b37d7f3 100644 --- a/code/modules/mob/living/basic/vermin/cockroach.dm +++ b/code/modules/mob/living/basic/vermin/cockroach.dm @@ -60,8 +60,8 @@ /datum/ai_controller/basic_controller/cockroach blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, ) ai_traits = STOP_MOVING_WHEN_PULLED @@ -106,6 +106,8 @@ burst_shots = burst_shots,\ cooldown_time = ranged_cooldown,\ ) + if (ranged_cooldown <= 1 SECONDS) + AddComponent(/datum/component/ranged_mob_full_auto) /datum/ai_controller/basic_controller/cockroach/glockroach planning_subtrees = list( diff --git a/code/modules/mob/living/basic/vermin/crab.dm b/code/modules/mob/living/basic/vermin/crab.dm index 276ed86d4de62..3dd3d0db0fea1 100644 --- a/code/modules/mob/living/basic/vermin/crab.dm +++ b/code/modules/mob/living/basic/vermin/crab.dm @@ -78,8 +78,8 @@ /datum/ai_controller/basic_controller/crab blackboard = list( BB_ALWAYS_IGNORE_FACTION = TRUE, - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/ours_or_smaller, - BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/of_size/ours_or_smaller, + BB_FLEE_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/vermin/frog.dm b/code/modules/mob/living/basic/vermin/frog.dm index 1ffe12e063ba5..6bf034219e947 100644 --- a/code/modules/mob/living/basic/vermin/frog.dm +++ b/code/modules/mob/living/basic/vermin/frog.dm @@ -94,8 +94,8 @@ /datum/ai_controller/basic_controller/frog blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/vermin/lizard.dm b/code/modules/mob/living/basic/vermin/lizard.dm index d1a30826f4ac4..da68087d70ffa 100644 --- a/code/modules/mob/living/basic/vermin/lizard.dm +++ b/code/modules/mob/living/basic/vermin/lizard.dm @@ -51,11 +51,11 @@ ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT) AddElement(/datum/element/pet_bonus, "sticks its tongue out contentedly!") AddElement(/datum/element/basic_eating, heal_amt = 5, food_types = edibles) - ai_controller.set_blackboard_key(BB_BASIC_FOODS, edibles) + ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(edibles)) /datum/ai_controller/basic_controller/lizard blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items(), + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index 2929085fb939f..c1ba3c12e364b 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -379,7 +379,7 @@ blackboard = list( // Always cowardly BB_CURRENT_HUNTING_TARGET = null, // cheese BB_LOW_PRIORITY_HUNTING_TARGET = null, // cable - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), // Use this to find people to run away from + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, // Use this to find people to run away from BB_BASIC_MOB_FLEE_DISTANCE = 3, ) @@ -411,8 +411,8 @@ /// AI controller for rats, slightly more complex than mice becuase they attack people /datum/ai_controller/basic_controller/mouse/rat blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, BB_BASIC_MOB_CURRENT_TARGET = null, // heathen BB_CURRENT_HUNTING_TARGET = null, // cheese BB_LOW_PRIORITY_HUNTING_TARGET = null, // cable diff --git a/code/modules/mob/living/basic/vermin/space_bat.dm b/code/modules/mob/living/basic/vermin/space_bat.dm index 232febf0f97d2..24718c8481acd 100644 --- a/code/modules/mob/living/basic/vermin/space_bat.dm +++ b/code/modules/mob/living/basic/vermin/space_bat.dm @@ -42,7 +42,7 @@ ///Controller for space bats, has nothing unique, just retaliation. /datum/ai_controller/basic_controller/space_bat blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/brain/brain_cybernetic.dm b/code/modules/mob/living/brain/brain_cybernetic.dm new file mode 100644 index 0000000000000..d87b6d902837c --- /dev/null +++ b/code/modules/mob/living/brain/brain_cybernetic.dm @@ -0,0 +1,59 @@ +/obj/item/organ/internal/brain/cybernetic + name = "cybernetic brain" + desc = "A mechanical brain found inside of androids. Not to be confused with a positronic brain." + icon_state = "brain-c" + organ_flags = ORGAN_ROBOTIC | ORGAN_VITAL + failing_desc = "seems to be broken, and will not work without repairs." + +/obj/item/organ/internal/brain/cybernetic/brain_damage_examine() + if(suicided) + return span_info("Its circuitry is smoking slightly. They must not have been able to handle the stress of it all.") + if(brainmob && (decoy_override || brainmob.client || brainmob.get_ghost())) + if(organ_flags & ORGAN_FAILING) + return span_info("It seems to still have a bit of energy within it, but it's rather damaged... You may be able to repair it with a multitool.") + else if(damage >= BRAIN_DAMAGE_DEATH*0.5) + return span_info("You can feel the small spark of life still left in this one, but it's got some dents. You may be able to restore it with a multitool.") + else + return span_info("You can feel the small spark of life still left in this one.") + else + return span_info("This one is completely devoid of life.") + +/obj/item/organ/internal/brain/cybernetic/check_for_repair(obj/item/item, mob/user) + if (item.tool_behaviour == TOOL_MULTITOOL) //attempt to repair the brain + if (brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing + to_chat(user, span_warning("[src] is far too damaged, there's nothing else we can do for it!")) + return TRUE + + if (DOING_INTERACTION(user, src)) + to_chat(user, span_warning("you're already repairing [src]!")) + return TRUE + + user.visible_message(span_notice("[user] slowly starts to repair [src] with [item]."), span_notice("You slowly start to repair [src] with [item].")) + var/did_repair = FALSE + while(damage > 0) + if(item.use_tool(src, user, 3 SECONDS, volume = 50)) + did_repair = TRUE + set_organ_damage(max(0, damage - 20)) + else + break + + if (did_repair) + if (damage > 0) + user.visible_message(span_notice("[user] partially repairs [src] with [item]."), span_notice("You partially repair [src] with [item].")) + else + user.visible_message(span_notice("[user] fully repairs [src] with [item], causing its warning light to stop flashing."), span_notice("You fully repair [src] with [item], causing its warning light to stop flashing.")) + else + to_chat(user, span_warning("You failed to repair [src] with [item]!")) + + return TRUE + return FALSE + +/obj/item/organ/internal/brain/cybernetic/emp_act(severity) + . = ..() + if(. & EMP_PROTECT_SELF) + return + switch(severity) // Hard cap on brain damage from EMP + if (EMP_HEAVY) + apply_organ_damage(20, BRAIN_DAMAGE_SEVERE) + if (EMP_LIGHT) + apply_organ_damage(10, BRAIN_DAMAGE_MILD) diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 9918a21b4f6d4..b8caff51fdeb9 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -47,13 +47,6 @@ // Brain size logic transform = transform.Scale(brain_size) -/obj/item/organ/internal/brain/examine() - . = ..() - if(brain_size < 1) - . += span_notice("It is a bit on the smaller side...") - if(brain_size > 1) - . += span_notice("It is bigger than average...") - /obj/item/organ/internal/brain/Insert(mob/living/carbon/brain_owner, special = FALSE, drop_if_replaced = TRUE, no_id_transfer = FALSE) . = ..() if(!.) @@ -177,32 +170,17 @@ L.mind.transfer_to(brainmob) to_chat(brainmob, span_notice("You feel slightly disoriented. That's normal when you're just a brain.")) -/obj/item/organ/internal/brain/attackby(obj/item/O, mob/user, params) +/obj/item/organ/internal/brain/attackby(obj/item/item, mob/user, params) user.changeNext_move(CLICK_CD_MELEE) - if(istype(O, /obj/item/borg/apparatus/organ_storage)) + if(istype(item, /obj/item/borg/apparatus/organ_storage)) return //Borg organ bags shouldn't be killing brains - if(damage && O.is_drainable() && O.reagents.has_reagent(/datum/reagent/medicine/mannitol)) //attempt to heal the brain - . = TRUE //don't do attack animation. - if(brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing - to_chat(user, span_warning("[src] is far too damaged, there's nothing else we can do for it!")) - return - - user.visible_message(span_notice("[user] starts to slowly pour the contents of [O] onto [src]."), span_notice("You start to slowly pour the contents of [O] onto [src].")) - if(!do_after(user, 3 SECONDS, src)) - to_chat(user, span_warning("You failed to pour the contents of [O] onto [src]!")) - return - - user.visible_message(span_notice("[user] pours the contents of [O] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink."), span_notice("You pour the contents of [O] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink.")) - var/amount = O.reagents.get_reagent_amount(/datum/reagent/medicine/mannitol) - var/healto = max(0, damage - amount * 2) - O.reagents.remove_all(ROUND_UP(O.reagents.total_volume / amount * (damage - healto) * 0.5)) //only removes however much solution is needed while also taking into account how much of the solution is mannitol - set_organ_damage(healto) //heals 2 damage per unit of mannitol, and by using "set_organ_damage", we clear the failing variable if that was up - return + if (check_for_repair(item, user)) + return TRUE // Cutting out skill chips. - if(length(skillchips) && O.get_sharpness() == SHARP_EDGED) + if(length(skillchips) && item.get_sharpness() == SHARP_EDGED) to_chat(user,span_notice("You begin to excise skillchips from [src].")) if(do_after(user, 15 SECONDS, target = src)) for(var/chip in skillchips) @@ -225,31 +203,57 @@ return if(brainmob) //if we aren't trying to heal the brain, pass the attack onto the brainmob. - O.attack(brainmob, user) //Oh noooeeeee + item.attack(brainmob, user) //Oh noooeeeee - if(O.force != 0 && !(O.item_flags & NOBLUDGEON)) + if(item.force != 0 && !(item.item_flags & NOBLUDGEON)) user.do_attack_animation(src) playsound(loc, 'sound/effects/meatslap.ogg', 50) set_organ_damage(maxHealth) //fails the brain as the brain was attacked, they're pretty fragile. - visible_message(span_danger("[user] hits [src] with [O]!")) - to_chat(user, span_danger("You hit [src] with [O]!")) + visible_message(span_danger("[user] hits [src] with [item]!")) + to_chat(user, span_danger("You hit [src] with [item]!")) + +/obj/item/organ/internal/brain/proc/check_for_repair(obj/item/item, mob/user) + if(damage && item.is_drainable() && item.reagents.has_reagent(/datum/reagent/medicine/mannitol) && (organ_flags & ORGAN_ORGANIC)) //attempt to heal the brain + if(brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing + to_chat(user, span_warning("[src] is far too damaged, there's nothing else we can do for it!")) + return TRUE + + user.visible_message(span_notice("[user] starts to slowly pour the contents of [item] onto [src]."), span_notice("You start to slowly pour the contents of [item] onto [src].")) + if(!do_after(user, 3 SECONDS, src)) + to_chat(user, span_warning("You failed to pour the contents of [item] onto [src]!")) + return TRUE + + user.visible_message(span_notice("[user] pours the contents of [item] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink."), span_notice("You pour the contents of [item] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink.")) + var/amount = item.reagents.get_reagent_amount(/datum/reagent/medicine/mannitol) + var/healto = max(0, damage - amount * 2) + item.reagents.remove_all(ROUND_UP(item.reagents.total_volume / amount * (damage - healto) * 0.5)) //only removes however much solution is needed while also taking into account how much of the solution is mannitol + set_organ_damage(healto) //heals 2 damage per unit of mannitol, and by using "set_organ_damage", we clear the failing variable if that was up + return TRUE + return FALSE /obj/item/organ/internal/brain/examine(mob/user) . = ..() if(length(skillchips)) . += span_info("It has a skillchip embedded in it.") + . += brain_damage_examine() + if(brain_size < 1) + . += span_notice("It is a bit on the smaller side...") + if(brain_size > 1) + . += span_notice("It is bigger than average...") + +/// Needed so subtypes can override examine text while still calling parent +/obj/item/organ/internal/brain/proc/brain_damage_examine() if(suicided) - . += span_info("It's started turning slightly grey. They must not have been able to handle the stress of it all.") - return + return span_info("It's started turning slightly grey. They must not have been able to handle the stress of it all.") if(brainmob && (decoy_override || brainmob.client || brainmob.get_ghost())) if(organ_flags & ORGAN_FAILING) - . += span_info("It seems to still have a bit of energy within it, but it's rather damaged... You may be able to restore it with some mannitol.") + return span_info("It seems to still have a bit of energy within it, but it's rather damaged... You may be able to restore it with some mannitol.") else if(damage >= BRAIN_DAMAGE_DEATH*0.5) - . += span_info("You can feel the small spark of life still left in this one, but it's got some bruises. You may be able to restore it with some mannitol.") + return span_info("You can feel the small spark of life still left in this one, but it's got some bruises. You may be able to restore it with some mannitol.") else - . += span_info("You can feel the small spark of life still left in this one.") + return span_info("You can feel the small spark of life still left in this one.") else - . += span_info("This one is completely devoid of life.") + return span_info("This one is completely devoid of life.") /obj/item/organ/internal/brain/attack(mob/living/carbon/C, mob/user) if(!istype(C)) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index eb72b273453a4..83e0a375479ab 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -220,16 +220,7 @@ buckled.user_unbuckle_mob(src,src) /mob/living/carbon/resist_fire() - adjust_fire_stacks(-5) - Paralyze(60, ignore_canstun = TRUE) - spin(32,2) - visible_message(span_danger("[src] rolls on the floor, trying to put [p_them()]self out!"), \ - span_notice("You stop, drop, and roll!")) - sleep(3 SECONDS) - if(fire_stacks <= 0 && !QDELETED(src)) - visible_message(span_danger("[src] successfully extinguishes [p_them()]self!"), \ - span_notice("You extinguish yourself.")) - return + return !!apply_status_effect(/datum/status_effect/stop_drop_roll) /mob/living/carbon/resist_restraints() var/obj/item/I = null @@ -251,6 +242,8 @@ /mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 1 MINUTES, cuff_break = 0) + if((cuff_break != INSTANT_CUFFBREAK) && (SEND_SIGNAL(src, COMSIG_MOB_REMOVING_CUFFS, I) & COMSIG_MOB_BLOCK_CUFF_REMOVAL)) + return //The blocking object should sent a fluff-appropriate to_chat about cuff removal being blocked if(I.item_flags & BEING_REMOVED) to_chat(src, span_warning("You're already attempting to remove [I]!")) return diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index cb77b0fc86066..4845d55bf134d 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -356,6 +356,7 @@ if(!target.has_movespeed_modifier(/datum/movespeed_modifier/shove)) target.add_movespeed_modifier(/datum/movespeed_modifier/shove) + target.emote("sway") if(target_held_item) append_message = "loosening [target.p_their()] grip on [target_held_item]" target.visible_message(span_danger("[target.name]'s grip on \the [target_held_item] loosens!"), //He's already out what are you doing diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index 6ecc62b04981d..e8a9f5bd46728 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -28,6 +28,12 @@ return . +/mob/living/carbon/human/get_damage_mod(damage_type) + if (!dna?.species?.damage_modifier) + return ..() + var/species_mod = (100 - dna.species.damage_modifier) / 100 + return ..() * species_mod + /mob/living/carbon/human/apply_damage( damage = 0, damagetype = BRUTE, diff --git a/code/modules/mob/living/carbon/emote.dm b/code/modules/mob/living/carbon/emote.dm index bc9384de23b68..9ba533a33b5d2 100644 --- a/code/modules/mob/living/carbon/emote.dm +++ b/code/modules/mob/living/carbon/emote.dm @@ -13,6 +13,7 @@ /datum/emote/living/carbon/blink_r key = "blink_r" + name = "blink (Rapid)" message = "blinks rapidly." /datum/emote/living/carbon/clap diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index f4789613064fb..2f05304ca27a7 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -1160,16 +1160,29 @@ GLOBAL_LIST_EMPTY(features_by_species) return FALSE user.do_attack_animation(target, atk_effect) + //has our target been shoved recently? If so, they're off-balance and we get an easy hit. + var/off_balance = FALSE + + //Someone in a grapple is much more vulnerable to being harmed by punches. + var/grappled = FALSE + + if(target.has_movespeed_modifier(/datum/movespeed_modifier/shove)) + off_balance = TRUE + + if(target.pulledby && target.pulledby.grab_state >= GRAB_AGGRESSIVE) + grappled = TRUE + var/damage = rand(attacking_bodypart.unarmed_damage_low, attacking_bodypart.unarmed_damage_high) + var/limb_accuracy = attacking_bodypart.unarmed_effectiveness var/obj/item/bodypart/affecting = target.get_bodypart(target.get_random_valid_zone(user.zone_selected)) var/miss_chance = 100//calculate the odds that a punch misses entirely. considers stamina and brute damage of the puncher. punches miss by default to prevent weird cases if(attacking_bodypart.unarmed_damage_low) - if((target.body_position == LYING_DOWN) || HAS_TRAIT(user, TRAIT_PERFECT_ATTACKER)) //kicks never miss (provided your species deals more than 0 damage) + if((target.body_position == LYING_DOWN) || HAS_TRAIT(user, TRAIT_PERFECT_ATTACKER) || off_balance) //kicks and attacks against off-balance targets never miss (provided your species deals more than 0 damage) miss_chance = 0 else - miss_chance = min((attacking_bodypart.unarmed_damage_high/attacking_bodypart.unarmed_damage_low) + user.getStaminaLoss() + (user.getBruteLoss()*0.5), 100) //old base chance for a miss + various damage. capped at 100 to prevent weirdness in prob() + miss_chance = clamp(UNARMED_MISS_CHANCE_BASE - limb_accuracy + user.getStaminaLoss() + (user.getBruteLoss()*0.5), 0, UNARMED_MISS_CHANCE_MAX) //Limb miss chance + various damage. capped at 80 so there is at least a chance to land a hit. if(!damage || !affecting || prob(miss_chance))//future-proofing for species that have 0 damage/weird cases where no zone is targeted playsound(target.loc, attacking_bodypart.unarmed_miss_sound, 25, TRUE, -1) @@ -1195,23 +1208,25 @@ GLOBAL_LIST_EMPTY(features_by_species) var/attack_direction = get_dir(user, target) var/attack_type = attacking_bodypart.attack_type - if(atk_effect == ATTACK_EFFECT_KICK)//kicks deal 1.5x raw damage + if(atk_effect == ATTACK_EFFECT_KICK || grappled) //kicks and punches when grappling bypass armor slightly. if(damage >= 9) target.force_say() - log_combat(user, target, "kicked") - target.apply_damage(damage, attack_type, affecting, armor_block, attack_direction = attack_direction) - else//other attacks deal full raw damage + 1.5x in stamina damage + log_combat(user, target, grappled ? "grapple punched" : "kicked") + target.apply_damage(damage, attack_type, affecting, armor_block - limb_accuracy, attack_direction = attack_direction) + target.apply_damage(damage*1.5, STAMINA, affecting, armor_block - limb_accuracy) + else // Normal attacks do not gain the benefit of armor penetration. target.apply_damage(damage, attack_type, affecting, armor_block, attack_direction = attack_direction) target.apply_damage(damage*1.5, STAMINA, affecting, armor_block) if(damage >= 9) target.force_say() log_combat(user, target, "punched") - if((target.stat != DEAD) && damage >= attacking_bodypart.unarmed_stun_threshold) + //If we rolled a punch high enough to hit our stun threshold, or our target is off-balance and they have at least 40 damage+stamina loss, we knock them down + if((target.stat != DEAD) && prob(limb_accuracy) || (target.stat != DEAD) && off_balance && (target.getStaminaLoss() + user.getBruteLoss()) >= 40) target.visible_message(span_danger("[user] knocks [target] down!"), \ span_userdanger("You're knocked down by [user]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, user) to_chat(user, span_danger("You knock [target] down!")) - var/knockdown_duration = 40 + (target.getStaminaLoss() + (target.getBruteLoss()*0.5))*0.8 //50 total damage = 40 base stun + 40 stun modifier = 80 stun duration, which is the old base duration + var/knockdown_duration = 4 SECONDS + (target.getStaminaLoss() + (target.getBruteLoss()*0.5))*0.8 //50 total damage = 4 second base stun + 4 second stun modifier = 8 second knockdown duration target.apply_effect(knockdown_duration, EFFECT_KNOCKDOWN, armor_block) log_combat(user, target, "got a stun punch with their previous punch") diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index f8cee3b4851f8..6f647e7a3bc3a 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -21,9 +21,8 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift) if(stat == DEAD) return stop_sound_channel(CHANNEL_HEARTBEAT) - var/obj/item/organ/internal/heart/H = get_organ_slot(ORGAN_SLOT_HEART) - if(H) - H.beat = BEAT_NONE + var/obj/item/organ/internal/heart/human_heart = get_organ_slot(ORGAN_SLOT_HEART) + human_heart?.beat = BEAT_NONE . = ..() diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 6a6714b084441..3141783033d89 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -10,7 +10,7 @@ var/obj/item/bodypart/affecting = get_bodypart(check_zone(def_zone)) if(affecting) return check_armor(affecting, type) - //If a specific bodypart is targetted, check how that bodypart is protected and return the value. + //If a specific bodypart is targeted, check how that bodypart is protected and return the value. //If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values for(var/X in bodyparts) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 818ca1cf860a4..b637abf125672 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -234,7 +234,7 @@ var/t_his = p_their() var/t_is = p_are() //This checks to see if the body is revivable - if(key || !get_organ_by_type(/obj/item/organ/internal/brain) || ghost?.can_reenter_corpse || HAS_TRAIT(src, TRAIT_MIND_TEMPORARILY_GONE)) + if(get_organ_by_type(/obj/item/organ/internal/brain) && (client || HAS_TRAIT(src, TRAIT_MIND_TEMPORARILY_GONE) || (ghost?.can_reenter_corpse && ghost?.client))) return span_deadsay("[t_He] [t_is] limp and unresponsive; there are no signs of life...") else return span_deadsay("[t_He] [t_is] limp and unresponsive; there are no signs of life and [t_his] soul has departed...") diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm index c1afc0c026611..b8c783779ea6c 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -26,6 +26,7 @@ inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID meat = null + mutantbrain = /obj/item/organ/internal/brain/cybernetic mutanttongue = /obj/item/organ/internal/tongue/robot mutantstomach = null mutantappendix = null diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 66948253d9e35..616541bffe7c6 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -27,11 +27,9 @@ if(stat == DEAD) stop_sound_channel(CHANNEL_HEARTBEAT) else - if(getStaminaLoss() > 0 && stam_regen_start_time <= world.time) adjustStaminaLoss(-INFINITY) - - handle_bodyparts(seconds_per_tick, times_fired) + handle_bodyparts(seconds_per_tick, times_fired) if(. && mind) //. == not dead for(var/key in mind.addiction_points) @@ -769,12 +767,19 @@ */ /mob/living/carbon/proc/undergoing_cardiac_arrest() var/obj/item/organ/internal/heart/heart = get_organ_slot(ORGAN_SLOT_HEART) - if(istype(heart) && heart.beating) + if(istype(heart) && heart.is_beating()) return FALSE else if(!needs_heart()) return FALSE return TRUE +/** + * Causes the mob to either start or stop having a heart attack. + * + * status - Pass TRUE to start a heart attack, or FALSE to stop one. + * + * Returns TRUE if heart status was changed (heart attack -> no heart attack, or visa versa) + */ /mob/living/carbon/proc/set_heartattack(status) if(!can_heartattack()) return FALSE @@ -783,5 +788,7 @@ if(!istype(heart)) return FALSE - heart.beating = !status - return TRUE + if(status) + return heart.Stop() + + return heart.Restart() diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index d5114bdcc654a..963ca36e6d7e2 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -260,6 +260,17 @@ return TRUE +/// Returns a multiplier to apply to a specific kind of damage +/mob/living/proc/get_damage_mod(damage_type) + switch(damage_type) + if (OXY) + return HAS_TRAIT(src, TRAIT_NOBREATH) ? 0 : 1 + if (TOX) + if (HAS_TRAIT(src, TRAIT_TOXINLOVER)) + return -1 + return HAS_TRAIT(src, TRAIT_TOXIMMUNE) ? 0 : 1 + return 1 + /mob/living/proc/getBruteLoss() return bruteloss diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 09478e995a130..9faf70427bcfd 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -163,6 +163,7 @@ /datum/emote/living/flap/aflap key = "aflap" key_third_person = "aflaps" + name = "flap (Angry)" message = "flaps their wings ANGRILY!" hands_use_check = TRUE wing_time = 10 @@ -190,6 +191,7 @@ /datum/emote/living/gasp_shock key = "gaspshock" key_third_person = "gaspsshock" + name = "gasp (Shock)" message = "gasps in shock!" message_mime = "gasps in silent shock!" emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE @@ -506,6 +508,7 @@ /datum/emote/living/twitch_s key = "twitch_s" + name = "twitch (Slight)" message = "twitches." /datum/emote/living/twitch_s/run_emote(mob/living/user, params, type_override, intentional) @@ -530,6 +533,7 @@ /datum/emote/living/wsmile key = "wsmile" key_third_person = "wsmiles" + name = "smile (Weak)" message = "smiles weakly." /// The base chance for your yawn to propagate to someone else if they're on the same tile as you diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 71a818706b581..5d4eea36d7567 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -89,6 +89,9 @@ if(move_intent == MOVE_INTENT_WALK) return TRUE + if(SEND_SIGNAL(M, COMSIG_LIVING_PRE_MOB_BUMP, src) & COMPONENT_LIVING_BLOCK_PRE_MOB_BUMP) + return TRUE + SEND_SIGNAL(src, COMSIG_LIVING_MOB_BUMP, M) //Even if we don't push/swap places, we "touched" them, so spread fire spreadFire(M) @@ -768,6 +771,9 @@ * */ /mob/living/proc/revive(full_heal_flags = NONE, excess_healing = 0, force_grab_ghost = FALSE) + if(QDELETED(src)) + // Bro just like, don't ok + return FALSE if(excess_healing) adjustOxyLoss(-excess_healing, updating_health = FALSE) adjustToxLoss(-excess_healing, updating_health = FALSE, forced = TRUE) //slime friendly @@ -1110,7 +1116,8 @@ /mob/living/resist_grab(moving_resist) . = TRUE - if(pulledby.grab_state || body_position == LYING_DOWN || HAS_TRAIT(src, TRAIT_GRABWEAKNESS)) + //If we're in an aggressive grab or higher, we're lying down, we're vulnerable to grabs, or we've been shoved and we have some amount of stamina loss, we must resist + if(pulledby.grab_state || body_position == LYING_DOWN || HAS_TRAIT(src, TRAIT_GRABWEAKNESS) || has_movespeed_modifier(/datum/movespeed_modifier/shove) && getStaminaLoss() >= 30) var/altered_grab_state = pulledby.grab_state if((body_position == LYING_DOWN || HAS_TRAIT(src, TRAIT_GRABWEAKNESS)) && pulledby.grab_state < GRAB_KILL) //If prone, resisting out of a grab is equivalent to 1 grab state higher. won't make the grab state exceed the normal max, however altered_grab_state++ @@ -1138,7 +1145,7 @@ buckled.user_unbuckle_mob(src,src) /mob/living/proc/resist_fire() - return + return FALSE /mob/living/proc/resist_restraints() return @@ -2484,7 +2491,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) /mob/living/proc/compare_sentience_type(compare_type) return FALSE -/// Proc called when targetted by a lazarus injector +/// Proc called when TARGETED by a lazarus injector /mob/living/proc/lazarus_revive(mob/living/reviver, malfunctioning) revive(HEAL_ALL) befriend(reviver) @@ -2498,7 +2505,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) lazarus_policy = get_policy(ROLE_LAZARUS_BAD) || "You have been revived by a malfunctioning lazarus injector! You are now enslaved by whoever revived you." to_chat(src, span_boldnotice(lazarus_policy)) -/// Proc for giving a mob a new 'friend', generally used for AI control and targetting. Returns false if already friends. +/// Proc for giving a mob a new 'friend', generally used for AI control and targeting. Returns false if already friends. /mob/living/proc/befriend(mob/living/new_friend) SHOULD_CALL_PARENT(TRUE) var/friend_ref = REF(new_friend) @@ -2558,14 +2565,10 @@ GLOBAL_LIST_EMPTY(fire_appearances) return var/del_mob = FALSE var/mob/old_mob - var/ai_control = FALSE - var/list/possible_players = list("None", "Poll Ghosts") + sort_list(GLOB.clients) + var/list/possible_players = list("Poll Ghosts") + sort_list(GLOB.clients) var/client/guardian_client = tgui_input_list(admin, "Pick the player to put in control.", "Guardian Controller", possible_players) - if(!guardian_client) + if(isnull(guardian_client)) return - else if(guardian_client == "None") - guardian_client = null - ai_control = (tgui_alert(admin, "Do you want to give the spirit AI control?", "Guardian Controller", list("Yes", "No")) == "Yes") else if(guardian_client == "Poll Ghosts") var/list/candidates = poll_ghost_candidates("Do you want to play as an admin created Guardian Spirit of [real_name]?", ROLE_PAI, FALSE, 100, POLL_IGNORE_HOLOPARASITE) if(LAZYLEN(candidates)) @@ -2578,7 +2581,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) old_mob = guardian_client.mob if(isobserver(old_mob) || tgui_alert(admin, "Do you want to delete [guardian_client]'s old mob?", "Guardian Controller", list("Yes"," No")) == "Yes") del_mob = TRUE - var/picked_type = tgui_input_list(admin, "Pick the guardian type.", "Guardian Controller", subtypesof(/mob/living/simple_animal/hostile/guardian)) + var/picked_type = tgui_input_list(admin, "Pick the guardian type.", "Guardian Controller", subtypesof(/mob/living/basic/guardian)) var/picked_theme = tgui_input_list(admin, "Pick the guardian theme.", "Guardian Controller", list(GUARDIAN_THEME_TECH, GUARDIAN_THEME_MAGIC, GUARDIAN_THEME_CARP, GUARDIAN_THEME_MINER, "Random")) if(picked_theme == "Random") picked_theme = null //holopara code handles not having a theme by giving a random one @@ -2586,20 +2589,16 @@ GLOBAL_LIST_EMPTY(fire_appearances) var/picked_color = input(admin, "Set the guardian's color, cancel to let player set it.", "Guardian Controller", "#ffffff") as color|null if(tgui_alert(admin, "Confirm creation.", "Guardian Controller", list("Yes", "No")) != "Yes") return - var/mob/living/simple_animal/hostile/guardian/summoned_guardian = new picked_type(src, picked_theme) + var/mob/living/basic/guardian/summoned_guardian = new picked_type(src, picked_theme) summoned_guardian.set_summoner(src, different_person = TRUE) if(picked_name) summoned_guardian.fully_replace_character_name(null, picked_name) if(picked_color) - summoned_guardian.set_guardian_color(picked_color) + summoned_guardian.set_guardian_colour(picked_color) summoned_guardian.key = guardian_client?.key guardian_client?.init_verbs() if(del_mob) qdel(old_mob) - if(ai_control) - summoned_guardian.can_have_ai = TRUE - summoned_guardian.toggle_ai(AI_ON) - summoned_guardian.manifest() message_admins(span_adminnotice("[key_name_admin(admin)] gave a guardian spirit controlled by [guardian_client || "AI"] to [src].")) log_admin("[key_name(admin)] gave a guardian spirit controlled by [guardian_client] to [src].") SSblackbox.record_feedback("tally", "admin_verb", 1, "Give Guardian Spirit") diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index 6ce7907abbb10..1cd72a3cc4046 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -185,11 +185,10 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( last_say_args_ref = REF(args) #endif - if(!HAS_TRAIT(src, TRAIT_SIGN_LANG)) // if using sign language skip sending the say signal - // Make sure the arglist is passed exactly - don't pass a copy of it. Say signal handlers will modify some of the parameters. - var/sigreturn = SEND_SIGNAL(src, COMSIG_MOB_SAY, args) - if(sigreturn & COMPONENT_UPPERCASE_SPEECH) - message = uppertext(message) + // Make sure the arglist is passed exactly - don't pass a copy of it. Say signal handlers will modify some of the parameters. + var/sigreturn = SEND_SIGNAL(src, COMSIG_MOB_SAY, args) + if(sigreturn & COMPONENT_UPPERCASE_SPEECH) + message = uppertext(message) var/list/message_data = treat_message(message) // unfortunately we still need this message = message_data["message"] diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 182aeb870a98c..ed9cbe09352c3 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -998,6 +998,9 @@ if(.) var/mob/living/silicon/ai/old_ai = . old_ai.connected_robots -= src + // if the borg has a malf AI zeroth law and has been unsynced from the malf AI, then remove the law + if(isnull(connected_ai) && IS_MALF_AI(old_ai) && !isnull(laws?.zeroth)) + clear_zeroth_law(FALSE, TRUE) lamp_doom = FALSE if(connected_ai) connected_ai.connected_robots |= src diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index b9d3304ef8de7..e5117317cbd94 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -95,8 +95,12 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real if(shell) //AI shells always have the laws of the AI to_chat(user, span_warning("[src] is controlled remotely! You cannot upload new laws this way!")) return - if(emagged || (connected_ai && lawupdate)) //Can't be sure which, metagamers - emote("buzz-[user.name]") + if(connected_ai && lawupdate) + to_chat(user, span_warning("[src] is receiving laws remotely from a synced AI!")) + return + if(emagged) + to_chat(user, span_warning("The law interface glitches out!")) + emote("buzz") return if(!mind) //A player mind is required for law procs to run antag checks. to_chat(user, span_warning("[src] is entirely unresponsive!")) diff --git a/code/modules/mob/living/simple_animal/bot/firebot.dm b/code/modules/mob/living/simple_animal/bot/firebot.dm index 59d08fe7339e0..98d34fc2f711e 100644 --- a/code/modules/mob/living/simple_animal/bot/firebot.dm +++ b/code/modules/mob/living/simple_animal/bot/firebot.dm @@ -119,7 +119,7 @@ if(!(bot_cover_flags & BOT_COVER_EMAGGED)) return - to_chat(user, span_warning("You enable the very ironically named \"fighting with fire\" mode, and disable the targetting safeties.")) // heheehe. funny + to_chat(user, span_warning("You enable the very ironically named \"fighting with fire\" mode, and disable the targeting safeties.")) // heheehe. funny audible_message(span_danger("[src] buzzes oddly!")) playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) diff --git a/code/modules/mob/living/simple_animal/damage_procs.dm b/code/modules/mob/living/simple_animal/damage_procs.dm index 9640dbb9de440..d92478907a1c0 100644 --- a/code/modules/mob/living/simple_animal/damage_procs.dm +++ b/code/modules/mob/living/simple_animal/damage_procs.dm @@ -18,6 +18,12 @@ if(AIStatus == AI_IDLE) toggle_ai(AI_ON) +/mob/living/simple_animal/get_damage_mod(damage_type) + var/modifier = ..() + if (damage_type in damage_coeff) + return modifier * damage_coeff[damage_type] + return modifier + /mob/living/simple_animal/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype) if(!can_adjust_brute_loss(amount, forced, required_bodytype)) return 0 diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm deleted file mode 100644 index 212867877554c..0000000000000 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ /dev/null @@ -1,616 +0,0 @@ -GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians - -/mob/living/simple_animal/hostile/guardian - name = "Guardian Spirit" - real_name = "Guardian Spirit" - desc = "A mysterious being that stands by its charge, ever vigilant." - speak_emote = list("hisses") - gender = NEUTER - mob_biotypes = MOB_SPECIAL - sentience_type = SENTIENCE_HUMANOID - bubble_icon = "guardian" - response_help_continuous = "passes through" - response_help_simple = "pass through" - response_disarm_continuous = "flails at" - response_disarm_simple = "flail at" - response_harm_continuous = "punches" - response_harm_simple = "punch" - icon = 'icons/mob/nonhuman-player/guardian.dmi' - icon_state = "magicbase" - icon_living = "magicbase" - icon_dead = "magicbase" - speed = 0 - combat_mode = TRUE - stop_automated_movement = 1 - attack_sound = 'sound/weapons/punch1.ogg' - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - maxbodytemp = INFINITY - attack_verb_continuous = "punches" - attack_verb_simple = "punch" - maxHealth = INFINITY //The spirit itself is invincible - health = INFINITY - mob_biotypes = MOB_BEAST - damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) //how much damage from each damage type we transfer to the owner - environment_smash = ENVIRONMENT_SMASH_STRUCTURES - obj_damage = 40 - melee_damage_lower = 15 - melee_damage_upper = 15 - del_on_death = TRUE - loot = list(/obj/effect/temp_visual/guardian/phase/out) - AIStatus = AI_OFF - can_have_ai = FALSE - light_system = MOVABLE_LIGHT - light_range = 3 - light_on = FALSE - hud_type = /datum/hud/guardian - faction = list() - - /// The guardian's color, used for their sprite, chat, and some effects made by it. - var/guardian_color - /// List of overlays we use. - var/list/guardian_overlays[GUARDIAN_TOTAL_LAYERS] - - /// The summoner of the guardian, the one it's intended to guard! - var/mob/living/summoner - /// How far from the summoner the guardian can be. - var/range = 10 - - /// Which toggle button the HUD uses. - var/toggle_button_type = /atom/movable/screen/guardian/toggle_mode/inactive - /// Name used by the guardian creator. - var/creator_name = "Error" - /// Description used by the guardian creator. - var/creator_desc = "This shouldn't be here! Report it on GitHub!" - /// Icon used by the guardian creator. - var/creator_icon = "fuck" - - /// A string explaining to the guardian what they can do. - var/playstyle_string = span_boldholoparasite("You are a Guardian without any type. You shouldn't exist!") - /// The fluff string we actually use. - var/used_fluff_string - /// Fluff string from tarot cards. - var/magic_fluff_string = span_holoparasite("You draw the Coder, symbolizing bugs and errors. This shouldn't happen! Submit a bug report!") - /// Fluff string from holoparasite injectors. - var/tech_fluff_string = span_holoparasite("BOOT SEQUENCE COMPLETE. ERROR MODULE LOADED. THIS SHOULDN'T HAPPEN. Submit a bug report!") - /// Fluff string from holocarp fishsticks. - var/carp_fluff_string = span_holoparasite("CARP CARP CARP SOME SORT OF HORRIFIC BUG BLAME THE CODERS CARP CARP CARP") - /// Fluff string from the dusty shard. - var/miner_fluff_string = span_holoparasite("You encounter... Mythril, it shouldn't exist... Submit a bug report!") - - /// Are we forced to not be able to manifest/recall? - var/locked = FALSE - /// Cooldown between manifests/recalls. - COOLDOWN_DECLARE(manifest_cooldown) - /// Cooldown between the summoner resetting the guardian's client. - COOLDOWN_DECLARE(resetting_cooldown) - -/mob/living/simple_animal/hostile/guardian/Initialize(mapload, theme) - . = ..() - GLOB.parasites += src - update_theme(theme) - AddElement(/datum/element/simple_flying) - AddComponent(/datum/component/basic_inhands) - manifest_effects() - -/mob/living/simple_animal/hostile/guardian/Destroy() //if deleted by admins or something random, cut from the summoner - if(is_deployed()) - recall_effects() - if(!QDELETED(summoner)) - cut_summoner(different_person = TRUE) - return ..() - -/// Setter for our summoner mob. -/mob/living/simple_animal/hostile/guardian/proc/set_summoner(mob/living/to_who, different_person = FALSE) - if(QDELETED(to_who)) - qdel(src) //no gettin off scot-free pal......... - return - if(summoner) - cut_summoner(different_person) - summoner = to_who - update_health_hud() - med_hud_set_health() - med_hud_set_status() - add_verb(to_who, list( - /mob/living/proc/guardian_comm, - /mob/living/proc/guardian_recall, - /mob/living/proc/guardian_reset, - )) - if(different_person) - if(mind) - mind.enslave_mind_to_creator(to_who) - else //mindless guardian, manually give them factions - faction += summoner.faction - summoner.faction += "[REF(src)]" - remove_all_languages(LANGUAGE_MASTER) - copy_languages(to_who, LANGUAGE_MASTER) // make sure holoparasites speak same language as master - RegisterSignal(to_who, COMSIG_MOVABLE_MOVED, PROC_REF(check_distance)) - RegisterSignal(to_who, COMSIG_QDELETING, PROC_REF(on_summoner_deletion)) - RegisterSignal(to_who, COMSIG_LIVING_DEATH, PROC_REF(on_summoner_death)) - RegisterSignal(to_who, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(on_summoner_health_update)) - RegisterSignal(to_who, COMSIG_LIVING_ON_WABBAJACKED, PROC_REF(on_summoner_wabbajacked)) - RegisterSignal(to_who, COMSIG_LIVING_SHAPESHIFTED, PROC_REF(on_summoner_shapeshifted)) - RegisterSignal(to_who, COMSIG_LIVING_UNSHAPESHIFTED, PROC_REF(on_summoner_unshapeshifted)) - recall(forced = TRUE) - if(to_who.stat == DEAD) - on_summoner_death(to_who) - -/mob/living/simple_animal/hostile/guardian/proc/cut_summoner(different_person = FALSE) - if(is_deployed()) - recall_effects() - var/summoner_turf = get_turf(src) - if (!isnull(summoner_turf)) - forceMove(summoner_turf) - UnregisterSignal(summoner, list(COMSIG_MOVABLE_MOVED, COMSIG_QDELETING, COMSIG_LIVING_DEATH, COMSIG_LIVING_HEALTH_UPDATE, COMSIG_LIVING_ON_WABBAJACKED, COMSIG_LIVING_SHAPESHIFTED, COMSIG_LIVING_UNSHAPESHIFTED)) - if(different_person) - summoner.faction -= "[REF(src)]" - faction -= summoner.faction - mind?.remove_all_antag_datums() - if(!length(summoner.get_all_linked_holoparasites() - src)) - remove_verb(summoner, list( - /mob/living/proc/guardian_comm, - /mob/living/proc/guardian_recall, - /mob/living/proc/guardian_reset, - )) - summoner = null - -/// Signal proc for [COMSIG_LIVING_ON_WABBAJACKED], when our summoner is wabbajacked we should be alerted. -/mob/living/simple_animal/hostile/guardian/proc/on_summoner_wabbajacked(mob/living/source, mob/living/new_mob) - SIGNAL_HANDLER - - set_summoner(new_mob) - to_chat(src, span_holoparasite("Your summoner has changed form!")) - -/// Signal proc for [COMSIG_LIVING_SHAPESHIFTED], when our summoner is shapeshifted we should change to the new mob -/mob/living/simple_animal/hostile/guardian/proc/on_summoner_shapeshifted(mob/living/source, mob/living/new_shape) - SIGNAL_HANDLER - - set_summoner(new_shape) - to_chat(src, span_holoparasite("Your summoner has shapeshifted into that of a [new_shape]!")) - -/// Signal proc for [COMSIG_LIVING_UNSHAPESHIFTED], when our summoner unshapeshifts go back to that mob -/mob/living/simple_animal/hostile/guardian/proc/on_summoner_unshapeshifted(mob/living/source, mob/living/old_summoner) - SIGNAL_HANDLER - - set_summoner(old_summoner) - to_chat(src, span_holoparasite("Your summoner has shapeshifted back into their normal form!")) - -// Ha, no -/mob/living/simple_animal/hostile/guardian/wabbajack(what_to_randomize, change_flags = WABBAJACK) - visible_message(span_warning("[src] resists the polymorph!")) - -/mob/living/simple_animal/hostile/guardian/proc/on_summoner_health_update(mob/living/source) - SIGNAL_HANDLER - - update_health_hud() - med_hud_set_health() - med_hud_set_status() - -/mob/living/simple_animal/hostile/guardian/med_hud_set_health() - var/image/holder = hud_list?[HEALTH_HUD] - if(isnull(holder)) - return - holder.icon_state = "hud[RoundHealth(summoner || src)]" - var/icon/size_check = icon(icon, icon_state, dir) - holder.pixel_y = size_check.Height() - world.icon_size - -/mob/living/simple_animal/hostile/guardian/med_hud_set_status() - var/image/holder = hud_list?[STATUS_HUD] - if(isnull(holder)) - return - var/icon/size_check = icon(icon, icon_state, dir) - holder.pixel_y = size_check.Height() - world.icon_size - var/mob/living/checking_mob = summoner || src - if(checking_mob.stat == DEAD || HAS_TRAIT(checking_mob, TRAIT_FAKEDEATH)) - holder.icon_state = "huddead" - else - holder.icon_state = "hudhealthy" - -/mob/living/simple_animal/hostile/guardian/Destroy() - GLOB.parasites -= src - return ..() - -/mob/living/simple_animal/hostile/guardian/proc/update_theme(theme) //update the guardian's theme - if(!theme) - theme = pick(GUARDIAN_THEME_MAGIC, GUARDIAN_THEME_TECH, GUARDIAN_THEME_CARP, GUARDIAN_THEME_MINER) - switch(theme)//should make it easier to create new stand designs in the future if anyone likes that - if(GUARDIAN_THEME_MAGIC) - name = "Guardian Spirit" - real_name = "Guardian Spirit" - bubble_icon = "guardian" - icon_state = "magicbase" - icon_living = "magicbase" - icon_dead = "magicbase" - used_fluff_string = magic_fluff_string - if(GUARDIAN_THEME_TECH) - name = "Holoparasite" - real_name = "Holoparasite" - bubble_icon = "holo" - icon_state = "techbase" - icon_living = "techbase" - icon_dead = "techbase" - used_fluff_string = tech_fluff_string - if(GUARDIAN_THEME_MINER) - name = "Power Miner" - real_name = "Power Miner" - bubble_icon = "guardian" - icon_state = "minerbase" - icon_living = "minerbase" - icon_dead = "minerbase" - used_fluff_string = miner_fluff_string - if(GUARDIAN_THEME_CARP) - name = "Holocarp" - real_name = "Holocarp" - bubble_icon = "holo" - icon_state = null //entirely handled by overlays - icon_living = null - icon_dead = null - speak_emote = string_list(list("gnashes")) - desc = "A mysterious fish that stands by its charge, ever vigilant." - attack_verb_continuous = "bites" - attack_verb_simple = "bite" - attack_sound = 'sound/weapons/bite.ogg' - attack_vis_effect = ATTACK_EFFECT_BITE - used_fluff_string = carp_fluff_string - guardian_overlays[GUARDIAN_COLOR_LAYER] = mutable_appearance(icon, theme) - apply_overlay(GUARDIAN_COLOR_LAYER) - -/mob/living/simple_animal/hostile/guardian/Login() //if we have a mind, set its name to ours when it logs in - . = ..() - if(!. || !client) - return FALSE - if(!summoner) - to_chat(src, span_boldholoparasite("For some reason, somehow, you have no summoner. Please report this bug immediately.")) - else - to_chat(src, span_holoparasite("You are a [real_name], bound to serve [summoner.real_name].")) - to_chat(src, span_holoparasite("You are capable of manifesting or recalling to your master with the buttons on your HUD. You will also find a button to communicate with [summoner.p_them()] privately there.")) - to_chat(src, span_holoparasite("While personally invincible, you will die if [summoner.real_name] does, and any damage dealt to you will have a portion passed on to [summoner.p_them()] as you feed upon [summoner.p_them()] to sustain yourself.")) - to_chat(src, playstyle_string) - if(!guardian_color) - locked = TRUE - guardian_rename() - guardian_recolor() - locked = FALSE - -/mob/living/simple_animal/hostile/guardian/mind_initialize() - . = ..() - if(!summoner) - to_chat(src, span_boldholoparasite("For some reason, somehow, you have no summoner. Please report this bug immediately.")) - return - mind.enslave_mind_to_creator(summoner) //once our mind is created, we become enslaved to our summoner. cant be done in the first run of set_summoner, because by then we dont have a mind yet. - -/mob/living/simple_animal/hostile/guardian/proc/guardian_recolor() - if(!client) - return - var/chosen_guardian_color = input(src, "What would you like your color to be?","Choose Your Color","#ffffff") as color|null - if(!chosen_guardian_color) //redo proc until we get a color - to_chat(src, span_warning("Not a valid color, please try again.")) - guardian_recolor() - return - set_guardian_color(chosen_guardian_color) - -/mob/living/simple_animal/hostile/guardian/proc/set_guardian_color(colour) - guardian_color = colour - set_light_color(guardian_color) - var/mutable_appearance/guardian_color_overlay = guardian_overlays[GUARDIAN_COLOR_LAYER] - remove_overlay(GUARDIAN_COLOR_LAYER) - guardian_color_overlay.color = guardian_color - guardian_overlays[GUARDIAN_COLOR_LAYER] = guardian_color_overlay - apply_overlay(GUARDIAN_COLOR_LAYER) - -/mob/living/simple_animal/hostile/guardian/proc/guardian_rename() - if(!client) - return - var/new_name = sanitize_name(reject_bad_text(tgui_input_text(src, "What would you like your name to be?", "Choose Your Name", real_name, MAX_NAME_LEN))) - if(!new_name) //redo proc until we get a good name - to_chat(src, span_warning("Not a valid name, please try again.")) - guardian_rename() - return - to_chat(src, span_notice("Your new name [span_name("[new_name]")] anchors itself in your mind.")) - fully_replace_character_name(null, new_name) - -/mob/living/simple_animal/hostile/guardian/proc/on_summoner_death(mob/living/source) - SIGNAL_HANDLER - - cut_summoner() - if (!isnull(source.loc)) - forceMove(source.loc) - to_chat(src, span_danger("Your summoner has died!")) - visible_message(span_bolddanger("\The [src] dies along with its user!")) - source.visible_message(span_bolddanger("[source]'s body is completely consumed by the strain of sustaining [src]!")) - source.dust(drop_items = TRUE) - death(TRUE) - -/mob/living/simple_animal/hostile/guardian/proc/on_summoner_deletion(mob/living/source) - SIGNAL_HANDLER - - cut_summoner() - to_chat(src, span_danger("Your summoner is gone!")) - qdel(src) - -/mob/living/simple_animal/hostile/guardian/get_status_tab_items() - . += ..() - if(summoner) - var/healthpercent = health_percentage(summoner) - . += "Summoner Health: [round(healthpercent, 0.5)]%" - if(!COOLDOWN_FINISHED(src, manifest_cooldown)) - . += "Manifest/Recall Cooldown Remaining: [DisplayTimeText(COOLDOWN_TIMELEFT(src, manifest_cooldown))]" - -/mob/living/simple_animal/hostile/guardian/Move() //Returns to summoner if they move out of range - . = ..() - check_distance() - -/mob/living/simple_animal/hostile/guardian/proc/check_distance() - SIGNAL_HANDLER - - if(!summoner) - return - if(get_dist(get_turf(summoner), get_turf(src)) <= range) - return - to_chat(src, span_holoparasite("You moved out of range, and were pulled back! You can only move [range] meters from [summoner.real_name]!")) - visible_message(span_danger("\The [src] jumps back to its user.")) - new /obj/effect/temp_visual/guardian/phase/out(loc) - if(istype(summoner.loc, /obj/effect) || isnull(summoner.loc)) - recall(forced = TRUE) - return - forceMove(summoner.loc) - new /obj/effect/temp_visual/guardian/phase(loc) - -/mob/living/simple_animal/hostile/guardian/can_suicide() - return FALSE - -/mob/living/simple_animal/hostile/guardian/proc/is_deployed() - return loc != summoner || !summoner - -/mob/living/simple_animal/hostile/guardian/AttackingTarget(atom/attacked_target) - if(!is_deployed()) - to_chat(src, span_bolddanger("You must be manifested to attack!")) - return FALSE - else - return ..() - -/mob/living/simple_animal/hostile/guardian/death(gibbed) - if(!QDELETED(summoner)) - to_chat(summoner, span_bolddanger("Your [name] died somehow!")) - summoner.dust() - return ..() - -/mob/living/simple_animal/hostile/guardian/update_health_hud() - var/severity = 0 - var/healthpercent = health_percentage(summoner || src) - switch(healthpercent) - if(100 to INFINITY) - severity = 0 - if(85 to 100) - severity = 1 - if(70 to 85) - severity = 2 - if(55 to 70) - severity = 3 - if(40 to 55) - severity = 4 - if(25 to 40) - severity = 5 - else - severity = 6 - if(severity > 0) - overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity) - else - clear_fullscreen("brute") - if(hud_used?.healths) - hud_used.healths.maptext = MAPTEXT("
[round(healthpercent, 0.5)]%
") - -/mob/living/simple_animal/hostile/guardian/adjustHealth(amount, updating_health = TRUE, forced = FALSE) //The spirit is invincible, but passes on damage to the summoner - . = amount - if(!summoner) - return ..() - if(!is_deployed()) - return FALSE - summoner.adjustBruteLoss(amount) - if(amount < 0 || QDELETED(summoner)) - return - to_chat(summoner, span_bolddanger("Your [name] is under attack! You take damage!")) - summoner.visible_message(span_bolddanger("Blood sprays from [summoner] as [src] takes damage!")) - if(summoner.stat == UNCONSCIOUS || summoner.stat == HARD_CRIT) - to_chat(summoner, span_bolddanger("Your head pounds, you can't take the strain of sustaining [src] in this condition!")) - summoner.adjustOrganLoss(ORGAN_SLOT_BRAIN, amount * 0.5) - -/mob/living/simple_animal/hostile/guardian/ex_act(severity, target) - switch(severity) - if(EXPLODE_DEVASTATE) - investigate_log("has been gibbed by an explosion.", INVESTIGATE_DEATHS) - gib() - return TRUE - if(EXPLODE_HEAVY) - adjustBruteLoss(60) - if(EXPLODE_LIGHT) - adjustBruteLoss(30) - - return TRUE - -/mob/living/simple_animal/hostile/guardian/gib() - death(TRUE) - -/mob/living/simple_animal/hostile/guardian/dust(just_ash, drop_items, force) - death(TRUE) - -//HAND HANDLING - -/mob/living/simple_animal/hostile/guardian/equip_to_slot(obj/item/equipping, slot, initial = FALSE, redraw_mob = FALSE, indirect_action = FALSE) - if(!slot) - return FALSE - if(!istype(equipping)) - return FALSE - - . = TRUE - var/index = get_held_index_of_item(equipping) - if(index) - held_items[index] = null - update_held_items() - - if(equipping.pulledby) - equipping.pulledby.stop_pulling() - - equipping.screen_loc = null // will get moved if inventory is visible - equipping.forceMove(src) - SET_PLANE_EXPLICIT(equipping, ABOVE_HUD_PLANE, src) - equipping.on_equipped(src, slot) - -/mob/living/simple_animal/hostile/guardian/proc/apply_overlay(cache_index) - if((. = guardian_overlays[cache_index])) - add_overlay(.) - -/mob/living/simple_animal/hostile/guardian/proc/remove_overlay(cache_index) - var/overlay = guardian_overlays[cache_index] - if(overlay) - cut_overlay(overlay) - guardian_overlays[cache_index] = null - -/mob/living/simple_animal/hostile/guardian/regenerate_icons() - update_held_items() - -//MANIFEST, RECALL, TOGGLE MODE/LIGHT, SHOW TYPE - -/mob/living/simple_animal/hostile/guardian/proc/manifest(forced) - if(is_deployed() || isnull(summoner.loc) || istype(summoner.loc, /obj/effect) || (!COOLDOWN_FINISHED(src, manifest_cooldown) && !forced) || locked) - return FALSE - forceMove(summoner.loc) - new /obj/effect/temp_visual/guardian/phase(loc) - COOLDOWN_START(src, manifest_cooldown, 1 SECONDS) - reset_perspective() - manifest_effects() - return TRUE - -/mob/living/simple_animal/hostile/guardian/proc/recall(forced) - if(!is_deployed() || !summoner || (!COOLDOWN_FINISHED(src, manifest_cooldown) && !forced) || locked) - return FALSE - new /obj/effect/temp_visual/guardian/phase/out(loc) - forceMove(summoner) - COOLDOWN_START(src, manifest_cooldown, 1 SECONDS) - recall_effects() - return TRUE - -/mob/living/simple_animal/hostile/guardian/proc/manifest_effects() - return - -/mob/living/simple_animal/hostile/guardian/proc/recall_effects() - return - -/mob/living/simple_animal/hostile/guardian/proc/toggle_modes() - to_chat(src, span_bolddanger("You don't have another mode!")) - -/mob/living/simple_animal/hostile/guardian/proc/toggle_light() - if(!light_on) - to_chat(src, span_notice("You activate your light.")) - set_light_on(TRUE) - else - to_chat(src, span_notice("You deactivate your light.")) - set_light_on(FALSE) - - -/mob/living/simple_animal/hostile/guardian/verb/check_type() - set name = "Check Guardian Type" - set category = "Guardian" - set desc = "Check what type you are." - to_chat(src, playstyle_string) - -//COMMUNICATION - -/mob/living/simple_animal/hostile/guardian/proc/communicate() - if(!summoner) - return - var/sender_key = key - var/input = tgui_input_text(src, "Enter a message to tell your summoner", "Guardian") - if(sender_key != key || !input) //guardian got reset, or did not enter anything - return - - var/preliminary_message = span_boldholoparasite("[input]") //apply basic color/bolding - var/my_message = "[src]: [preliminary_message]" //add source, color source with the guardian's color - - to_chat(summoner, "[my_message]") - var/list/guardians = summoner.get_all_linked_holoparasites() - for(var/guardian in guardians) - to_chat(guardian, "[my_message]") - for(var/dead_mob in GLOB.dead_mob_list) - var/link = FOLLOW_LINK(dead_mob, src) - to_chat(dead_mob, "[link] [my_message]") - - src.log_talk(input, LOG_SAY, tag="guardian") - -/mob/living/proc/guardian_comm() - set name = "Communicate" - set category = "Guardian" - set desc = "Communicate telepathically with your guardian." - var/input = tgui_input_text(src, "Enter a message to tell your guardian", "Message") - if(!input) - return - - var/preliminary_message = span_boldholoparasite("[input]") //apply basic color/bolding - var/my_message = span_boldholoparasite("[src]: [preliminary_message]") //add source, color source with default grey... - - to_chat(src, "[my_message]") - var/list/guardians = get_all_linked_holoparasites() - for(var/mob/living/simple_animal/hostile/guardian/guardian as anything in guardians) - to_chat(guardian, "[src]: [preliminary_message]" ) - for(var/dead_mob in GLOB.dead_mob_list) - var/link = FOLLOW_LINK(dead_mob, src) - to_chat(dead_mob, "[link] [my_message]") - - src.log_talk(input, LOG_SAY, tag="guardian") - -//FORCE RECALL/RESET - -/mob/living/proc/guardian_recall() - set name = "Recall Guardian" - set category = "Guardian" - set desc = "Forcibly recall your guardian." - var/list/guardians = get_all_linked_holoparasites() - for(var/mob/living/simple_animal/hostile/guardian/guardian in guardians) - guardian.recall() - -/mob/living/proc/guardian_reset() - set name = "Reset Guardian Player (5 Minute Cooldown)" - set category = "Guardian" - set desc = "Re-rolls which ghost will control your Guardian. Can be used once per 5 minutes." - - var/list/guardians = get_all_linked_holoparasites() - for(var/mob/living/simple_animal/hostile/guardian/resetting_guardian as anything in guardians) - if(!COOLDOWN_FINISHED(resetting_guardian, resetting_cooldown)) - guardians -= resetting_guardian //clear out guardians that are already reset - - var/mob/living/simple_animal/hostile/guardian/chosen_guardian = tgui_input_list(src, "Pick the guardian you wish to reset", "Guardian Reset", sort_names(guardians)) - if(isnull(chosen_guardian)) - to_chat(src, span_holoparasite("You decide not to reset [length(guardians) > 1 ? "any of your guardians":"your guardian"].")) - return - - to_chat(src, span_holoparasite("You attempt to reset [chosen_guardian.real_name]'s personality...")) - var/list/mob/dead/observer/ghost_candidates = poll_ghost_candidates("Do you want to play as [src.real_name]'s Guardian Spirit?", ROLE_PAI, FALSE, 100) - if(!LAZYLEN(ghost_candidates)) - to_chat(src, span_holoparasite("There were no ghosts willing to take control of [chosen_guardian.real_name]. Looks like you're stuck with it for now.")) - return - - var/mob/dead/observer/candidate = pick(ghost_candidates) - to_chat(chosen_guardian, span_holoparasite("Your user reset you, and your body was taken over by a ghost. Looks like they weren't happy with your performance.")) - to_chat(src, span_boldholoparasite("Your [chosen_guardian.real_name] has been successfully reset.")) - message_admins("[key_name_admin(candidate)] has taken control of ([ADMIN_LOOKUPFLW(chosen_guardian)])") - chosen_guardian.ghostize(FALSE) - chosen_guardian.key = candidate.key - COOLDOWN_START(chosen_guardian, resetting_cooldown, 5 MINUTES) - chosen_guardian.guardian_rename() //give it a new color and name, to show it's a new person - chosen_guardian.guardian_recolor() - -////////parasite tracking/finding procs - -/// Returns a list of all holoparasites that has this mob as a summoner. -/mob/living/proc/get_all_linked_holoparasites() - RETURN_TYPE(/list) - var/list/all_parasites = list() - for(var/mob/living/simple_animal/hostile/guardian/stand as anything in GLOB.parasites) - if(stand.summoner != src) - continue - all_parasites += stand - return all_parasites - -/// Returns true if this holoparasite has the same summoner as the passed holoparasite. -/mob/living/simple_animal/hostile/guardian/proc/hasmatchingsummoner(mob/living/simple_animal/hostile/guardian/other_guardian) - return istype(other_guardian) && other_guardian.summoner == summoner diff --git a/code/modules/mob/living/simple_animal/guardian/types/assassin.dm b/code/modules/mob/living/simple_animal/guardian/types/assassin.dm deleted file mode 100644 index 340e92a5b4236..0000000000000 --- a/code/modules/mob/living/simple_animal/guardian/types/assassin.dm +++ /dev/null @@ -1,107 +0,0 @@ -//Assassin -/mob/living/simple_animal/hostile/guardian/assassin - melee_damage_lower = 15 - melee_damage_upper = 15 - attack_verb_continuous = "slashes" - attack_verb_simple = "slash" - attack_sound = 'sound/weapons/bladeslice.ogg' - attack_vis_effect = ATTACK_EFFECT_SLASH - sharpness = SHARP_POINTY - damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) - playstyle_string = span_holoparasite("As an assassin type you do medium damage and have no damage resistance, but can enter stealth, massively increasing the damage of your next attack and causing it to ignore armor. Stealth is broken when you attack or take damage.") - magic_fluff_string = span_holoparasite("..And draw the Space Ninja, a lethal, invisible assassin.") - tech_fluff_string = span_holoparasite("Boot sequence complete. Assassin modules loaded. Holoparasite swarm online.") - carp_fluff_string = span_holoparasite("CARP CARP CARP! Caught one! It's an assassin carp! Just when you thought it was safe to go back to the water... which is unhelpful, because we're in space.") - miner_fluff_string = span_holoparasite("You encounter... Glass, a sharp, fragile attacker.") - creator_name = "Assassin" - creator_desc = "Does medium damage and takes full damage, but can enter stealth, causing its next attack to do massive damage and ignore armor. However, it becomes briefly unable to recall after attacking from stealth." - creator_icon = "assassin" - toggle_button_type = /atom/movable/screen/guardian/toggle_mode/assassin - /// Is it in stealth mode? - var/toggle = FALSE - /// Time between going in stealth. - var/stealth_cooldown_time = 16 SECONDS - /// Damage added in stealth mode. - var/damage_bonus = 35 - /// Our wound bonus when in stealth mode. - var/stealth_wound_bonus = -20 //from -100, you can now wound! - /// Screen alert given when we are able to stealth. - var/atom/movable/screen/alert/canstealthalert - /// Screen alert given when we are in stealth. - var/atom/movable/screen/alert/instealthalert - /// Cooldown for the stealth toggle. - COOLDOWN_DECLARE(stealth_cooldown) - -/mob/living/simple_animal/hostile/guardian/assassin/get_status_tab_items() - . = ..() - if(!COOLDOWN_FINISHED(src, stealth_cooldown)) - . += "Stealth Cooldown Remaining: [DisplayTimeText(COOLDOWN_TIMELEFT(src, stealth_cooldown))]" - -/mob/living/simple_animal/hostile/guardian/assassin/AttackingTarget(atom/attacked_target) - . = ..() - if(.) - if(toggle && (isliving(target) || istype(target, /obj/structure/window) || istype(target, /obj/structure/grille))) - toggle_modes(forced = TRUE) - -/mob/living/simple_animal/hostile/guardian/assassin/adjustHealth(amount, updating_health = TRUE, forced = FALSE) - . = ..() - if(. > 0 && toggle) - toggle_modes(forced = TRUE) - -/mob/living/simple_animal/hostile/guardian/assassin/recall_effects() - if(toggle) - toggle_modes(forced = TRUE) - -/mob/living/simple_animal/hostile/guardian/assassin/toggle_modes(forced = FALSE) - if(toggle) - melee_damage_lower -= damage_bonus - melee_damage_upper -= damage_bonus - armour_penetration = initial(armour_penetration) - wound_bonus = initial(wound_bonus) - obj_damage = initial(obj_damage) - environment_smash = initial(environment_smash) - alpha = initial(alpha) - if(!forced) - to_chat(src, span_bolddanger("You exit stealth.")) - else - visible_message(span_danger("\The [src] suddenly appears!")) - COOLDOWN_START(src, stealth_cooldown, stealth_cooldown_time) //we were forced out of stealth and go on cooldown - addtimer(CALLBACK(src, PROC_REF(updatestealthalert)), stealth_cooldown_time) - COOLDOWN_START(src, manifest_cooldown, 4 SECONDS) //can't recall for 4 seconds - updatestealthalert() - toggle = FALSE - else if(COOLDOWN_FINISHED(src, stealth_cooldown)) - if(!is_deployed()) - to_chat(src, span_bolddanger("You have to be manifested to enter stealth!")) - return - melee_damage_lower += damage_bonus - melee_damage_upper += damage_bonus - armour_penetration = 100 - wound_bonus = stealth_wound_bonus - obj_damage = 0 - environment_smash = ENVIRONMENT_SMASH_NONE - new /obj/effect/temp_visual/guardian/phase/out(get_turf(src)) - alpha = 15 - if(!forced) - to_chat(src, span_bolddanger("You enter stealth, empowering your next attack.")) - updatestealthalert() - toggle = TRUE - else if(!forced) - to_chat(src, span_bolddanger("You cannot yet enter stealth, wait another [DisplayTimeText(COOLDOWN_TIMELEFT(src, stealth_cooldown))]!")) - -/mob/living/simple_animal/hostile/guardian/assassin/proc/updatestealthalert() - if(!COOLDOWN_FINISHED(src, stealth_cooldown)) - clear_alert("instealth") - instealthalert = null - clear_alert("canstealth") - canstealthalert = null - return - if(toggle && !instealthalert) - instealthalert = throw_alert("instealth", /atom/movable/screen/alert/instealth) - clear_alert("canstealth") - canstealthalert = null - else if(!toggle && !canstealthalert) - canstealthalert = throw_alert("canstealth", /atom/movable/screen/alert/canstealth) - clear_alert("instealth") - instealthalert = null - diff --git a/code/modules/mob/living/simple_animal/guardian/types/charger.dm b/code/modules/mob/living/simple_animal/guardian/types/charger.dm deleted file mode 100644 index e1e0de66b00a8..0000000000000 --- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm +++ /dev/null @@ -1,74 +0,0 @@ -//Charger -/mob/living/simple_animal/hostile/guardian/charger - melee_damage_lower = 15 - melee_damage_upper = 15 - ranged = TRUE //technically - ranged_message = "charges" - ranged_cooldown_time = 4 SECONDS - speed = -0.5 - damage_coeff = list(BRUTE = 0.75, BURN = 0.75, TOX = 0.75, CLONE = 0.75, STAMINA = 0, OXY = 0.75) - playstyle_string = span_holoparasite("As a charger type you do medium damage, have light damage resistance, move very fast, can be ridden, and can charge at a location, damaging any target hit and forcing them to drop any items they are holding.") - magic_fluff_string = span_holoparasite("..And draw the Hunter, an alien master of rapid assault.") - tech_fluff_string = span_holoparasite("Boot sequence complete. Charge modules loaded. Holoparasite swarm online.") - carp_fluff_string = span_holoparasite("CARP CARP CARP! Caught one! It's a charger carp, that likes running at people. But it doesn't have any legs...") - miner_fluff_string = span_holoparasite("You encounter... Titanium, a lightweight, agile fighter.") - creator_name = "Charger" - creator_desc = "Moves very fast, does medium damage on attack, can be ridden and can charge at targets, damaging the first target hit and forcing them to drop any items they are holding." - creator_icon = "charger" - /// Is it currently charging at something? - var/charging = FALSE - /// How much damage it does while charging. - var/charge_damage = 20 - -/mob/living/simple_animal/hostile/guardian/charger/Initialize(mapload, theme) - . = ..() - AddElement(/datum/element/ridable, /datum/component/riding/creature/guardian) - -/mob/living/simple_animal/hostile/guardian/charger/get_status_tab_items() - . = ..() - if(!COOLDOWN_FINISHED(src, ranged_cooldown)) - . += "Charge Cooldown Remaining: [DisplayTimeText(COOLDOWN_TIMELEFT(src, ranged_cooldown))]" - -/mob/living/simple_animal/hostile/guardian/charger/OpenFire(atom/target) - if(charging) - return - visible_message(span_danger("[src] [ranged_message] at [target]!")) - COOLDOWN_START(src, ranged_cooldown, ranged_cooldown_time) - clear_alert(ALERT_CHARGE) - addtimer(CALLBACK(src, PROC_REF(throw_alert), ALERT_CHARGE, /atom/movable/screen/alert/cancharge), ranged_cooldown_time) - Shoot(target) - -/mob/living/simple_animal/hostile/guardian/charger/Shoot(atom/targeted_atom) - charging = TRUE - playsound(src, 'sound/items/modsuit/loader_launch.ogg', 75, TRUE) - throw_at(targeted_atom, range, speed = 1.5, thrower = src, spin = FALSE, diagonals_first = TRUE, callback = CALLBACK(src, PROC_REF(charging_end))) - -/mob/living/simple_animal/hostile/guardian/charger/proc/charging_end() - charging = FALSE - -/mob/living/simple_animal/hostile/guardian/charger/Move() - if(charging) - new /obj/effect/temp_visual/decoy/fading(loc, src) - return ..() - -/mob/living/simple_animal/hostile/guardian/charger/check_distance() - if(!charging) - ..() - -/mob/living/simple_animal/hostile/guardian/charger/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) - if(!charging) - return ..() - if(!isliving(hit_atom) || hit_atom == summoner || hasmatchingsummoner(hit_atom)) - return - var/mob/living/hit_mob = hit_atom - if(ishuman(hit_mob)) - var/mob/living/carbon/human/hit_human = hit_mob - if(hit_human.check_shields(src, charge_damage, name, attack_type = THROWN_PROJECTILE_ATTACK)) - return - hit_mob.drop_all_held_items() - hit_mob.visible_message(span_danger("[src] slams into [hit_mob]!"), span_userdanger("[src] slams into you!")) - hit_mob.apply_damage(charge_damage, BRUTE) - playsound(hit_mob, 'sound/effects/meteorimpact.ogg', 100, TRUE) - shake_camera(hit_mob, 4, 3) - shake_camera(src, 2, 3) - diff --git a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm deleted file mode 100644 index d2fbfc33c877d..0000000000000 --- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm +++ /dev/null @@ -1,90 +0,0 @@ -//Dextrous -/mob/living/simple_animal/hostile/guardian/dextrous - melee_damage_lower = 10 - melee_damage_upper = 10 - damage_coeff = list(BRUTE = 0.75, BURN = 0.75, TOX = 0.75, CLONE = 0.75, STAMINA = 0, OXY = 0.75) - playstyle_string = span_holoparasite("As a dextrous type you can hold items, store an item within yourself, and have medium damage resistance, but do low damage on attacks. Recalling and leashing will force you to drop unstored items!") - magic_fluff_string = span_holoparasite("..And draw the Drone, a dextrous master of construction and repair.") - tech_fluff_string = span_holoparasite("Boot sequence complete. Dextrous combat modules loaded. Holoparasite swarm online.") - carp_fluff_string = span_holoparasite("CARP CARP CARP! You caught one! It can hold stuff in its fins, sort of.") - miner_fluff_string = span_holoparasite("You encounter... Gold, a malleable constructor.") - creator_name = "Dextrous" - creator_desc = "Does low damage on attack, but is capable of holding items and storing a single item within it. It will drop items held in its hands when it recalls, but it will retain the stored item." - creator_icon = "dextrous" - dextrous = TRUE - hud_type = /datum/hud/dextrous/guardian - held_items = list(null, null) - var/obj/item/internal_storage //what we're storing within ourself - -/mob/living/simple_animal/hostile/guardian/dextrous/death(gibbed) - . = ..() - if(internal_storage) - dropItemToGround(internal_storage) - -/mob/living/simple_animal/hostile/guardian/dextrous/examine(mob/user) - . = ..() - if(internal_storage && !(internal_storage.item_flags & ABSTRACT)) - . += span_info("It is holding [internal_storage.get_examine_string(user)] in its internal storage.") - -/mob/living/simple_animal/hostile/guardian/dextrous/recall_effects() - drop_all_held_items() - -/mob/living/simple_animal/hostile/guardian/dextrous/check_distance() - if(!summoner || get_dist(get_turf(summoner), get_turf(src)) <= range) - return - drop_all_held_items() - ..() //lose items, then return - -//SLOT HANDLING BULLSHIT FOR INTERNAL STORAGE -/mob/living/simple_animal/hostile/guardian/dextrous/doUnEquip(obj/item/equipped_item, force, newloc, no_move, invdrop = TRUE, silent = FALSE) - if(..()) - update_held_items() - if(equipped_item == internal_storage) - internal_storage = null - update_inv_internal_storage() - return TRUE - return FALSE - -/mob/living/simple_animal/hostile/guardian/dextrous/can_equip(obj/item/equipped_item, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, ignore_equipped = FALSE) - switch(slot) - if(ITEM_SLOT_DEX_STORAGE) - if(internal_storage) - return FALSE - return TRUE - ..() - -/mob/living/simple_animal/hostile/guardian/dextrous/get_item_by_slot(slot_id) - if(slot_id == ITEM_SLOT_DEX_STORAGE) - return internal_storage - return ..() - -/mob/living/simple_animal/hostile/guardian/dextrous/get_slot_by_item(obj/item/looking_for) - if(internal_storage == looking_for) - return ITEM_SLOT_DEX_STORAGE - return ..() - -/mob/living/simple_animal/hostile/guardian/dextrous/equip_to_slot(obj/item/equipping, slot, initial = FALSE, redraw_mob = FALSE, indirect_action = FALSE) - if(!..()) - return - - switch(slot) - if(ITEM_SLOT_DEX_STORAGE) - internal_storage = equipping - update_inv_internal_storage() - else - to_chat(src, span_danger("You are trying to equip this item to an unsupported inventory slot. Report this to a coder!")) - -/mob/living/simple_animal/hostile/guardian/dextrous/getBackSlot() - return ITEM_SLOT_DEX_STORAGE - -/mob/living/simple_animal/hostile/guardian/dextrous/getBeltSlot() - return ITEM_SLOT_DEX_STORAGE - -/mob/living/simple_animal/hostile/guardian/dextrous/proc/update_inv_internal_storage() - if(internal_storage && client && hud_used?.hud_shown) - internal_storage.screen_loc = ui_id - client.screen += internal_storage - -/mob/living/simple_animal/hostile/guardian/dextrous/regenerate_icons() - ..() - update_inv_internal_storage() diff --git a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm deleted file mode 100644 index 6fbc61ee45886..0000000000000 --- a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm +++ /dev/null @@ -1,72 +0,0 @@ -#define UNREGISTER_BOMB_SIGNALS(A) \ - do { \ - UnregisterSignal(A, boom_signals); \ - UnregisterSignal(A, COMSIG_ATOM_EXAMINE); \ - } while (0) - -//Explosive -/mob/living/simple_animal/hostile/guardian/explosive - melee_damage_lower = 15 - melee_damage_upper = 15 - damage_coeff = list(BRUTE = 0.6, BURN = 0.6, TOX = 0.6, CLONE = 0.6, STAMINA = 0, OXY = 0.6) - range = 13 - playstyle_string = span_holoparasite("As an explosive type, you have moderate close combat abilities and are capable of converting nearby items and objects into disguised bombs via right-click.") - magic_fluff_string = span_holoparasite("..And draw the Scientist, master of explosive death.") - tech_fluff_string = span_holoparasite("Boot sequence complete. Explosive modules active. Holoparasite swarm online.") - carp_fluff_string = span_holoparasite("CARP CARP CARP! Caught one! It's an explosive carp! Boom goes the fishy.") - miner_fluff_string = span_holoparasite("You encounter... Gibtonite, an explosive fighter.") - creator_name = "Explosive" - creator_desc = "High damage resist and medium power attack. Can turn any object, including objects too large to pick up, into a bomb, dealing explosive damage to the next person to touch it. The object will return to normal after the trap is triggered or after a delay." - creator_icon = "explosive" - /// Static list of signals that activate the boom. - var/static/list/boom_signals = list(COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_BUMPED, COMSIG_ATOM_ATTACK_HAND) - /// After this amount of time passses, boom deactivates. - var/decay_time = 1 MINUTES - /// Time between bombs. - var/bomb_cooldown_time = 20 SECONDS - /// The cooldown timer between bombs. - COOLDOWN_DECLARE(bomb_cooldown) - -/mob/living/simple_animal/hostile/guardian/explosive/get_status_tab_items() - . = ..() - if(!COOLDOWN_FINISHED(src, bomb_cooldown)) - . += "Bomb Cooldown Remaining: [DisplayTimeText(COOLDOWN_TIMELEFT(src, bomb_cooldown))]" - -/mob/living/simple_animal/hostile/guardian/explosive/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) - if(LAZYACCESS(modifiers, RIGHT_CLICK) && proximity_flag && isobj(attack_target)) - plant_bomb(attack_target) - return - return ..() - -/mob/living/simple_animal/hostile/guardian/explosive/proc/plant_bomb(obj/planting_on) - if(!COOLDOWN_FINISHED(src, bomb_cooldown)) - to_chat(src, span_bolddanger("Your powers are on cooldown! You must wait [DisplayTimeText(COOLDOWN_TIMELEFT(src, bomb_cooldown))] between bombs.")) - return - to_chat(src, span_bolddanger("Success! Bomb armed!")) - COOLDOWN_START(src, bomb_cooldown, bomb_cooldown_time) - RegisterSignal(planting_on, COMSIG_ATOM_EXAMINE, PROC_REF(display_examine)) - RegisterSignals(planting_on, boom_signals, PROC_REF(kaboom)) - addtimer(CALLBACK(src, PROC_REF(disable), planting_on), decay_time, TIMER_UNIQUE|TIMER_OVERRIDE) - -/mob/living/simple_animal/hostile/guardian/explosive/proc/kaboom(atom/source, mob/living/explodee) - SIGNAL_HANDLER - if(!istype(explodee)) - return - if(explodee == src || explodee == summoner || hasmatchingsummoner(explodee)) - return - to_chat(explodee, span_bolddanger("[source] was boobytrapped!")) - to_chat(src, span_bolddanger("Success! Your trap caught [explodee]")) - playsound(source, 'sound/effects/explosion2.ogg', 200, TRUE) - new /obj/effect/temp_visual/explosion(get_turf(source)) - EX_ACT(explodee, EXPLODE_HEAVY) - UNREGISTER_BOMB_SIGNALS(source) - -/mob/living/simple_animal/hostile/guardian/explosive/proc/disable(obj/rigged_obj) - to_chat(src, span_bolddanger("Failure! Your trap didn't catch anyone this time.")) - UNREGISTER_BOMB_SIGNALS(rigged_obj) - -/mob/living/simple_animal/hostile/guardian/explosive/proc/display_examine(datum/source, mob/user, text) - SIGNAL_HANDLER - text += span_holoparasite("It glows with a strange light!") - -#undef UNREGISTER_BOMB_SIGNALS diff --git a/code/modules/mob/living/simple_animal/guardian/types/gaseous.dm b/code/modules/mob/living/simple_animal/guardian/types/gaseous.dm deleted file mode 100644 index 7808f8a6b482b..0000000000000 --- a/code/modules/mob/living/simple_animal/guardian/types/gaseous.dm +++ /dev/null @@ -1,103 +0,0 @@ -//Gaseous -/mob/living/simple_animal/hostile/guardian/gaseous - melee_damage_lower = 10 - melee_damage_upper = 10 - damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 0) - range = 7 - playstyle_string = span_holoparasite("As a gaseous type, you have only light damage resistance, but you can expel gas in an area. In addition, your punches cause sparks, and you make your summoner inflammable.") - magic_fluff_string = span_holoparasite("..And draw the Atmospheric Technician, flooding the area with gas!") - tech_fluff_string = span_holoparasite("Boot sequence complete. Atmospheric modules activated. Holoparasite swarm online.") - carp_fluff_string = span_holoparasite("CARP CARP CARP! You caught one! OH GOD, EVERYTHING'S ON FIRE. Except you and the fish.") - miner_fluff_string = span_holoparasite("You encounter... Plasma, the bringer of fire.") - creator_name = "Gaseous" - creator_desc = "Creates sparks on touch and continuously expels a gas of its choice. Automatically extinguishes the user if they catch on fire." - creator_icon = "gaseous" - toggle_button_type = /atom/movable/screen/guardian/toggle_mode/gases - /// Gas being expelled. - var/expelled_gas = null - /// Rate of temperature stabilization per second. - var/temp_stabilization_rate = 0.1 - /// Possible gases to expel, with how much moles they create. - var/static/list/possible_gases = list( - /datum/gas/oxygen = 50, - /datum/gas/nitrogen = 750, //overpressurizing is hard!. - /datum/gas/water_vapor = 1, //you need incredibly little water vapor for the effects to kick in - /datum/gas/nitrous_oxide = 15, - /datum/gas/carbon_dioxide = 50, - /datum/gas/plasma = 3, - /datum/gas/bz = 10, - ) - /// Gas colors, used for the particles. - var/static/list/gas_colors = list( - /datum/gas/oxygen = "#63BFDD", //color of frozen oxygen - /datum/gas/nitrogen = "#777777", //grey (grey) - /datum/gas/water_vapor = "#96ADCF", //water is slightly blue - /datum/gas/nitrous_oxide = "#FEFEFE", //white like the sprite - /datum/gas/carbon_dioxide = "#222222", //black like coal - /datum/gas/plasma = "#B233CC", //color of the plasma sprite - /datum/gas/bz = "#FAFF00", //color of the bz metabolites reagent - ) - -/mob/living/simple_animal/hostile/guardian/gaseous/Initialize(mapload, theme) - . = ..() - RegisterSignal(src, COMSIG_ATOM_PRE_PRESSURE_PUSH, PROC_REF(stop_pressure)) - -/mob/living/simple_animal/hostile/guardian/gaseous/AttackingTarget(atom/attacked_target) - . = ..() - if(!isliving(target)) - return - do_sparks(1, TRUE, target) - -/mob/living/simple_animal/hostile/guardian/gaseous/recall(forced) - expelled_gas = null - QDEL_NULL(particles) //need to delete before putting in another object - . = ..() - if(. && summoner) - UnregisterSignal(summoner, COMSIG_ATOM_PRE_PRESSURE_PUSH) - -/mob/living/simple_animal/hostile/guardian/gaseous/manifest(forced) - . = ..() - if(. && summoner) - RegisterSignal(summoner, COMSIG_ATOM_PRE_PRESSURE_PUSH, PROC_REF(stop_pressure)) - -/mob/living/simple_animal/hostile/guardian/gaseous/Life(seconds_per_tick, times_fired) - . = ..() - if(summoner) - summoner.extinguish_mob() - summoner.set_fire_stacks(0, remove_wet_stacks = FALSE) - summoner.adjust_bodytemperature(get_temp_change_amount((summoner.get_body_temp_normal() - summoner.bodytemperature), temp_stabilization_rate * seconds_per_tick)) - if(!expelled_gas) - return - var/datum/gas_mixture/mix_to_spawn = new() - mix_to_spawn.add_gas(expelled_gas) - mix_to_spawn.gases[expelled_gas][MOLES] = possible_gases[expelled_gas] * seconds_per_tick - mix_to_spawn.temperature = T20C - var/turf/open/our_turf = get_turf(src) - our_turf.assume_air(mix_to_spawn) - -/mob/living/simple_animal/hostile/guardian/gaseous/toggle_modes() - var/list/gases = list("None") - for(var/datum/gas/gas as anything in possible_gases) - gases[initial(gas.name)] = gas - var/picked_gas = tgui_input_list(src, "Select a gas to expel.", "Gas Producer", gases) - if(picked_gas == "None") - expelled_gas = null - QDEL_NULL(particles) - to_chat(src, span_notice("You stopped expelling gas.")) - return - var/gas_type = gases[picked_gas] - if(!picked_gas || !gas_type) - return - to_chat(src, span_bolddanger("You are now expelling [picked_gas].")) - investigate_log("set their gas type to [picked_gas].", INVESTIGATE_ATMOS) - expelled_gas = gas_type - if(!particles) - particles = new /particles/smoke/steam() - particles.position = list(-1, 8, 0) - particles.fadein = 5 - particles.height = 200 - particles.color = gas_colors[gas_type] - -/mob/living/simple_animal/hostile/guardian/gaseous/proc/stop_pressure(datum/source) - SIGNAL_HANDLER - return COMSIG_ATOM_BLOCKS_PRESSURE diff --git a/code/modules/mob/living/simple_animal/guardian/types/gravitokinetic.dm b/code/modules/mob/living/simple_animal/guardian/types/gravitokinetic.dm deleted file mode 100644 index fe6a0ec58563d..0000000000000 --- a/code/modules/mob/living/simple_animal/guardian/types/gravitokinetic.dm +++ /dev/null @@ -1,91 +0,0 @@ -//gravitokinetic -/mob/living/simple_animal/hostile/guardian/gravitokinetic - melee_damage_lower = 15 - melee_damage_upper = 15 - damage_coeff = list(BRUTE = 0.75, BURN = 0.75, TOX = 0.75, CLONE = 0.75, STAMINA = 0, OXY = 0.75) - playstyle_string = span_holoparasite("As a gravitokinetic type, you can right-click to make the gravity on the ground stronger, and punching applies this effect to a target.") - magic_fluff_string = span_holoparasite("..And draw the Singularity, an anomalous force of terror.") - tech_fluff_string = span_holoparasite("Boot sequence complete. Gravitokinetic modules loaded. Holoparasite swarm online.") - carp_fluff_string = span_holoparasite("CARP CARP CARP! Caught one! It's a gravitokinetic carp! Now do you understand the gravity of the situation?") - miner_fluff_string = span_holoparasite("You encounter... Bananium, a master of gravity business.") - creator_name = "Gravitokinetic" - creator_desc = "Attacks will apply crushing gravity to the target. Can target the ground as well to slow targets advancing on you, but this will affect the user." - creator_icon = "gravitokinetic" - /// Targets we have applied our effects on. - var/list/gravity_targets = list() - /// Distance in which our ability works - var/gravity_power_range = 10 - /// Gravity added on punches. - var/punch_gravity = 5 - /// Gravity added to turfs. - var/turf_gravity = 3 - -/mob/living/simple_animal/hostile/guardian/gravitokinetic/Initialize(mapload, theme) - . = ..() - AddElement(/datum/element/forced_gravity, 1) - -/mob/living/simple_animal/hostile/guardian/gravitokinetic/set_summoner(mob/to_who, different_person) - . = ..() - to_who.AddElement(/datum/element/forced_gravity, 1) - -/mob/living/simple_animal/hostile/guardian/gravitokinetic/cut_summoner(different_person) - summoner.RemoveElement(/datum/element/forced_gravity, 1) - return ..() - -///Removes gravity from affected mobs upon guardian death to prevent permanent effects -/mob/living/simple_animal/hostile/guardian/gravitokinetic/death() - . = ..() - for(var/gravity_target in gravity_targets) - remove_gravity(gravity_target) - -/mob/living/simple_animal/hostile/guardian/gravitokinetic/AttackingTarget(atom/attacked_target) - . = ..() - if(isliving(target) && !hasmatchingsummoner(attacked_target) && target != src && target != summoner && !gravity_targets[target]) - to_chat(src, span_bolddanger("Your punch has applied heavy gravity to [target]!")) - add_gravity(target, punch_gravity) - to_chat(target, span_userdanger("Everything feels really heavy!")) - -/mob/living/simple_animal/hostile/guardian/gravitokinetic/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) - if(LAZYACCESS(modifiers, RIGHT_CLICK) && proximity_flag && !gravity_targets[target]) - slam_turf(attack_target) - return - return ..() - -/mob/living/simple_animal/hostile/guardian/gravitokinetic/proc/slam_turf(turf/open/slammed) - if(!isopenturf(slammed) || isgroundlessturf(slammed)) - to_chat(src, span_warning("You cannot add gravity to this!")) - return - visible_message(span_danger("[src] slams their fist into the [slammed]!"), span_notice("You modify the gravity of the [slammed].")) - do_attack_animation(slammed) - add_gravity(slammed, turf_gravity) - -/mob/living/simple_animal/hostile/guardian/gravitokinetic/recall_effects() - to_chat(src, span_bolddanger("You have released your gravitokinetic powers!")) - for(var/gravity_target in gravity_targets) - remove_gravity(gravity_target) - -/mob/living/simple_animal/hostile/guardian/gravitokinetic/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) - . = ..() - for(var/gravity_target in gravity_targets) - if(get_dist(src, gravity_target) > gravity_power_range) - remove_gravity(gravity_target) - -/mob/living/simple_animal/hostile/guardian/gravitokinetic/proc/add_gravity(atom/target, new_gravity = 3) - if(gravity_targets[target]) - return - target.AddElement(/datum/element/forced_gravity, new_gravity) - gravity_targets[target] = new_gravity - RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(distance_check)) - playsound(src, 'sound/effects/gravhit.ogg', 100, TRUE) - -/mob/living/simple_animal/hostile/guardian/gravitokinetic/proc/remove_gravity(atom/target) - if(isnull(gravity_targets[target])) - return - UnregisterSignal(target, COMSIG_MOVABLE_MOVED) - target.RemoveElement(/datum/element/forced_gravity, gravity_targets[target]) - gravity_targets -= target - -/mob/living/simple_animal/hostile/guardian/gravitokinetic/proc/distance_check(atom/movable/moving_target, old_loc, dir, forced) - SIGNAL_HANDLER - if(get_dist(src, moving_target) > gravity_power_range) - remove_gravity(moving_target) diff --git a/code/modules/mob/living/simple_animal/guardian/types/lightning.dm b/code/modules/mob/living/simple_animal/guardian/types/lightning.dm deleted file mode 100644 index 9739445f7c9c7..0000000000000 --- a/code/modules/mob/living/simple_animal/guardian/types/lightning.dm +++ /dev/null @@ -1,111 +0,0 @@ -/obj/effect/ebeam/chain - name = "lightning chain" - layer = LYING_MOB_LAYER - plane = GAME_PLANE_FOV_HIDDEN - -//Lightning -/mob/living/simple_animal/hostile/guardian/lightning - melee_damage_lower = 7 - melee_damage_upper = 7 - attack_verb_continuous = "shocks" - attack_verb_simple = "shock" - melee_damage_type = BURN - attack_sound = 'sound/machines/defib_zap.ogg' - damage_coeff = list(BRUTE = 0.7, BURN = 0.7, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7) - range = 7 - playstyle_string = span_holoparasite("As a lightning type, you will apply lightning chains to targets on attack and have a lightning chain to your summoner. Lightning chains will shock anyone near them.") - magic_fluff_string = span_holoparasite("..And draw the Tesla, a shocking, lethal source of power.") - tech_fluff_string = span_holoparasite("Boot sequence complete. Lightning modules active. Holoparasite swarm online.") - carp_fluff_string = span_holoparasite("CARP CARP CARP! Caught one! It's a lightning carp! Everyone else goes zap zap.") - miner_fluff_string = span_holoparasite("You encounter... Iron, a conductive master of lightning.") - creator_name = "Lightning" - creator_desc = "Attacks apply lightning chains to targets. Has a lightning chain to the user. Lightning chains shock everything near them, doing constant damage." - creator_icon = "lightning" - /// Beam datum of our lightning chain to the summoner. - var/datum/beam/summonerchain - /// List of all lightning chains attached to enemies. - var/list/enemychains = list() - /// Amount of shocks we've given through the chain to the summoner. - var/successfulshocks = 0 - /// Cooldown between shocks. - COOLDOWN_DECLARE(shock_cooldown) - -/mob/living/simple_animal/hostile/guardian/lightning/AttackingTarget(atom/attacked_target) - . = ..() - if(!. || !isliving(target) || target == summoner || hasmatchingsummoner(target)) - return - cleardeletedchains() - for(var/datum/beam/chain as anything in enemychains) - if(chain.target == target) - return //oh this guy already HAS a chain, let's not chain again - if(length(enemychains) > 2) - var/datum/beam/enemy_chain = pick(enemychains) - qdel(enemy_chain) - enemychains -= enemy_chain - enemychains += Beam(target, "lightning[rand(1,12)]", maxdistance=7, beam_type=/obj/effect/ebeam/chain) - -/mob/living/simple_animal/hostile/guardian/lightning/manifest_effects() - START_PROCESSING(SSfastprocess, src) - if(summoner) - summonerchain = Beam(summoner, "lightning[rand(1,12)]", beam_type=/obj/effect/ebeam/chain) - -/mob/living/simple_animal/hostile/guardian/lightning/recall_effects() - STOP_PROCESSING(SSfastprocess, src) - removechains() - -/mob/living/simple_animal/hostile/guardian/lightning/process(seconds_per_tick) - if(!COOLDOWN_FINISHED(src, shock_cooldown)) - return - if(successfulshocks > 5) - successfulshocks = 0 - if(shockallchains()) - successfulshocks++ - COOLDOWN_START(src, shock_cooldown, 0.3 SECONDS) - -/mob/living/simple_animal/hostile/guardian/lightning/proc/cleardeletedchains() - if(summonerchain && QDELETED(summonerchain)) - summonerchain = null - for(var/datum/chain as anything in enemychains) - if(QDELETED(chain)) - enemychains -= chain - -/mob/living/simple_animal/hostile/guardian/lightning/proc/shockallchains() - . = 0 - cleardeletedchains() - if(summonerchain) - . += chainshock(summonerchain) - for(var/chain in enemychains) - . += chainshock(chain) - -/mob/living/simple_animal/hostile/guardian/lightning/proc/removechains() - QDEL_NULL(summonerchain) - for(var/chain in enemychains) - qdel(chain) - enemychains = list() - -/mob/living/simple_animal/hostile/guardian/lightning/proc/chainshock(datum/beam/B) //fuck you, fuck this - . = 0 - var/list/turfs = list() - for(var/E in B.elements) - var/obj/effect/ebeam/chainpart = E - if(chainpart && chainpart.x && chainpart.y && chainpart.z) - var/turf/T = get_turf_pixel(chainpart) - turfs |= T - if(T != get_turf(B.origin) && T != get_turf(B.target)) - for(var/turf/TU in circle_range(T, 1)) - turfs |= TU - for(var/turf in turfs) - var/turf/T = turf - for(var/mob/living/L in T) - if(L.stat != DEAD && L != src && L != summoner) - if(hasmatchingsummoner(L)) //if the summoner matches don't hurt them - continue - if(successfulshocks > 4) - L.electrocute_act(0) - L.visible_message( - span_danger("[L] was shocked by the lightning chain!"), \ - span_userdanger("You are shocked by the lightning chain!"), \ - span_hear("You hear a heavy electrical crack.") \ - ) - L.adjustFireLoss(1.2) //adds up very rapidly - . = 1 diff --git a/code/modules/mob/living/simple_animal/guardian/types/protector.dm b/code/modules/mob/living/simple_animal/guardian/types/protector.dm deleted file mode 100644 index 4809c3dc1c6bb..0000000000000 --- a/code/modules/mob/living/simple_animal/guardian/types/protector.dm +++ /dev/null @@ -1,78 +0,0 @@ -//Protector -/mob/living/simple_animal/hostile/guardian/protector - melee_damage_lower = 15 - melee_damage_upper = 15 - range = 15 //worse for it due to how it leashes - damage_coeff = list(BRUTE = 0.4, BURN = 0.4, TOX = 0.4, CLONE = 0.4, STAMINA = 0, OXY = 0.4) - playstyle_string = span_holoparasite("As a protector type you cause your summoner to leash to you instead of you leashing to them and have two modes; Combat Mode, where you do and take medium damage, and Protection Mode, where you do and take almost no damage, but move slightly slower.") - magic_fluff_string = span_holoparasite("..And draw the Guardian, a stalwart protector that never leaves the side of its charge.") - tech_fluff_string = span_holoparasite("Boot sequence complete. Protector modules loaded. Holoparasite swarm online.") - carp_fluff_string = span_holoparasite("CARP CARP CARP! You caught one! Wait, no... it caught you! The fisher has become the fishy.") - miner_fluff_string = span_holoparasite("You encounter... Uranium, a very resistant guardian.") - creator_name = "Protector" - creator_desc = "Causes you to teleport to it when out of range, unlike other parasites. Has two modes; Combat, where it does and takes medium damage, and Protection, where it does and takes almost no damage but moves slightly slower." - creator_icon = "protector" - toggle_button_type = /atom/movable/screen/guardian/toggle_mode - /// Damage removed in protecting mode. - var/damage_penalty = 13 - /// Is it in protecting mode? - var/toggle = FALSE - /// Overlay of our protection shield. - var/mutable_appearance/shield_overlay - -/mob/living/simple_animal/hostile/guardian/protector/ex_act(severity) - if(severity >= EXPLODE_DEVASTATE) - adjustBruteLoss(400) //if in protector mode, will do 20 damage and not actually necessarily kill the summoner - else - . = ..() - if(QDELETED(src)) - return FALSE - if(toggle) - visible_message(span_danger("The explosion glances off [src]'s energy shielding!")) - - return TRUE - -/mob/living/simple_animal/hostile/guardian/protector/adjustHealth(amount, updating_health = TRUE, forced = FALSE) - . = ..() - if(. > 0 && toggle) - var/image/flash_overlay = new('icons/effects/effects.dmi', src, "shield-flash", dir = pick(GLOB.cardinals)) - flash_overlay.color = guardian_color - flick_overlay_view(flash_overlay, 0.5 SECONDS) - -/mob/living/simple_animal/hostile/guardian/protector/toggle_modes() - if(COOLDOWN_FINISHED(src, manifest_cooldown)) - return - COOLDOWN_START(src, manifest_cooldown, 1 SECONDS) - if(toggle) - cut_overlay(shield_overlay) - melee_damage_lower += damage_penalty - melee_damage_upper += damage_penalty - speed = initial(speed) - damage_coeff = list(BRUTE = 0.4, BURN = 0.4, TOX = 0.4, CLONE = 0.4, STAMINA = 0, OXY = 0.4) - to_chat(src, span_bolddanger("You switch to combat mode.")) - toggle = FALSE - else - if(!shield_overlay) - shield_overlay = mutable_appearance('icons/effects/effects.dmi', "shield-grey") - shield_overlay.color = guardian_color - add_overlay(shield_overlay) - melee_damage_lower -= damage_penalty - melee_damage_upper -= damage_penalty - speed = 1 - damage_coeff = list(BRUTE = 0.05, BURN = 0.05, TOX = 0.05, CLONE = 0.05, STAMINA = 0, OXY = 0.05) //damage? what's damage? - to_chat(src, span_bolddanger("You switch to protection mode.")) - toggle = TRUE - -/mob/living/simple_animal/hostile/guardian/protector/check_distance() //snap to what? snap to the guardian! - if(!summoner || get_dist(summoner, src) <= range) - return - if(istype(summoner.loc, /obj/effect)) - to_chat(src, span_holoparasite("You moved out of range, and were pulled back! You can only move [range] meters from [summoner.real_name]!")) - visible_message(span_danger("\The [src] jumps back to its user.")) - recall(forced = TRUE) - return - to_chat(summoner, span_holoparasite("You moved out of range, and were pulled back! You can only move [range] meters from [real_name]!")) - summoner.visible_message(span_danger("\The [summoner] jumps back to [summoner.p_their()] protector.")) - new /obj/effect/temp_visual/guardian/phase/out(get_turf(summoner)) - summoner.forceMove(get_turf(src)) - new /obj/effect/temp_visual/guardian/phase(get_turf(summoner)) diff --git a/code/modules/mob/living/simple_animal/guardian/types/ranged.dm b/code/modules/mob/living/simple_animal/guardian/types/ranged.dm deleted file mode 100644 index 0cb7303e26a56..0000000000000 --- a/code/modules/mob/living/simple_animal/guardian/types/ranged.dm +++ /dev/null @@ -1,182 +0,0 @@ -//Ranged -/obj/projectile/guardian - name = "crystal spray" - icon_state = "guardian" - damage = 5 - damage_type = BRUTE - armour_penetration = 100 - -/mob/living/simple_animal/hostile/guardian/ranged - combat_mode = FALSE - friendly_verb_continuous = "quietly assesses" - friendly_verb_simple = "quietly assess" - melee_damage_lower = 10 - melee_damage_upper = 10 - damage_coeff = list(BRUTE = 0.9, BURN = 0.9, TOX = 0.9, CLONE = 0.9, STAMINA = 0, OXY = 0.9) - projectiletype = /obj/projectile/guardian - ranged_cooldown_time = 1 //fast! - projectilesound = 'sound/effects/hit_on_shattered_glass.ogg' - ranged = 1 - range = 13 - playstyle_string = span_holoparasite("As a ranged type, you have only light damage resistance, but are capable of spraying shards of crystal at incredibly high speed. You can also deploy surveillance snares to monitor enemy movement. Finally, you can switch to scout mode, in which you can't attack, but can move without limit.") - magic_fluff_string = span_holoparasite("..And draw the Sentinel, an alien master of ranged combat.") - tech_fluff_string = span_holoparasite("Boot sequence complete. Ranged combat modules active. Holoparasite swarm online.") - carp_fluff_string = span_holoparasite("CARP CARP CARP! Caught one, it's a ranged carp. This fishy can watch people pee in the ocean.") - miner_fluff_string = span_holoparasite("You encounter... Diamond, a powerful projectile thrower.") - creator_name = "Ranged" - creator_desc = "Has two modes. Ranged; which fires a constant stream of weak, armor-ignoring projectiles. Scout; where it cannot attack, but can move through walls and is quite hard to see. Can lay surveillance snares, which alert it when crossed, in either mode." - creator_icon = "ranged" - see_invisible = SEE_INVISIBLE_LIVING - toggle_button_type = /atom/movable/screen/guardian/toggle_mode - /// List of all deployed snares. - var/list/snares = list() - /// Is it in scouting mode? - var/toggle = FALSE - /// Maximum snares deployed at once. - var/max_snares = 6 - /// Lower damage before scouting. - var/previous_lower_damage = 0 - /// Upper damage before scouting. - var/previous_upper_damage = 0 - -/mob/living/simple_animal/hostile/guardian/ranged/toggle_modes() - if(is_deployed() && summoner) - to_chat(src, span_bolddanger("You have to be recalled to toggle modes!")) - return - if(toggle) - ranged = initial(ranged) - melee_damage_lower = previous_lower_damage - melee_damage_upper = previous_upper_damage - previous_lower_damage = 0 - previous_upper_damage = 0 - obj_damage = initial(obj_damage) - environment_smash = initial(environment_smash) - alpha = 255 - range = initial(range) - to_chat(src, span_bolddanger("You switch to combat mode.")) - toggle = FALSE - else - ranged = 0 - previous_lower_damage = melee_damage_lower - melee_damage_lower = 0 - previous_upper_damage = melee_damage_upper - melee_damage_upper = 0 - obj_damage = 0 - environment_smash = ENVIRONMENT_SMASH_NONE - alpha = 45 - range = 255 - to_chat(src, span_bolddanger("You switch to scout mode.")) - toggle = TRUE - - -/mob/living/simple_animal/hostile/guardian/ranged/Shoot(atom/targeted_atom) - . = ..() - if(!istype(., /obj/projectile)) - return - var/obj/projectile/shot_projectile = . - shot_projectile.color = guardian_color - -/mob/living/simple_animal/hostile/guardian/ranged/toggle_light() - var/msg - switch(lighting_cutoff) - if (LIGHTING_CUTOFF_VISIBLE) - lighting_cutoff_red = 10 - lighting_cutoff_green = 10 - lighting_cutoff_blue = 15 - msg = "You activate your night vision." - if (LIGHTING_CUTOFF_MEDIUM) - lighting_cutoff_red = 25 - lighting_cutoff_green = 25 - lighting_cutoff_blue = 35 - msg = "You increase your night vision." - if (LIGHTING_CUTOFF_HIGH) - lighting_cutoff_red = 35 - lighting_cutoff_green = 35 - lighting_cutoff_blue = 50 - msg = "You maximize your night vision." - else - lighting_cutoff_red = 0 - lighting_cutoff_green = 0 - lighting_cutoff_blue = 0 - msg = "You deactivate your night vision." - sync_lighting_plane_cutoff() - to_chat(src, span_notice(msg)) - - -/mob/living/simple_animal/hostile/guardian/ranged/verb/Snare() - set name = "Set Surveillance Snare" - set category = "Guardian" - set desc = "Set an invisible snare that will alert you when living creatures walk over it. Max of 5" - if(length(snares) < max_snares) - var/turf/snare_loc = get_turf(src) - var/obj/effect/snare/new_snare = new /obj/effect/snare(snare_loc, src) - new_snare.name = "[get_area(snare_loc)] snare ([rand(1, 1000)])" - snares += new_snare - to_chat(src, span_bolddanger("Surveillance snare deployed!")) - else - to_chat(src, span_bolddanger("You have too many snares deployed. Remove some first.")) - -/mob/living/simple_animal/hostile/guardian/ranged/verb/DisarmSnare() - set name = "Remove Surveillance Snare" - set category = "Guardian" - set desc = "Disarm unwanted surveillance snares." - var/picked_snare = tgui_input_list(src, "Pick which snare to remove.", "Remove Snare", sort_names(snares)) - if(isnull(picked_snare)) - return - qdel(picked_snare) - to_chat(src, span_bolddanger("Snare disarmed.")) - -/obj/effect/snare - name = "snare" - desc = "You shouldn't be seeing this!" - invisibility = INVISIBILITY_ABSTRACT - var/datum/weakref/guardian_ref - -/obj/effect/snare/Initialize(mapload, spawning_guardian) - . = ..() - guardian_ref = WEAKREF(spawning_guardian) - var/static/list/loc_connections = list( - COMSIG_ATOM_ENTERED = PROC_REF(on_entered), - ) - AddElement(/datum/element/connect_loc, loc_connections) - -/obj/effect/snare/Destroy(force) - var/mob/living/simple_animal/hostile/guardian/ranged/spawning_guardian = guardian_ref?.resolve() - if(spawning_guardian) - spawning_guardian.snares -= src - return ..() - -/obj/effect/snare/proc/on_entered(datum/source, crossed_object) - SIGNAL_HANDLER - var/mob/living/simple_animal/hostile/guardian/ranged/spawning_guardian = guardian_ref?.resolve() - if(!spawning_guardian) - qdel(src) - return - if(!isliving(crossed_object) || crossed_object == spawning_guardian || spawning_guardian.hasmatchingsummoner(crossed_object)) - return - send_message(spawning_guardian.summoner || spawning_guardian, crossed_object) - -/obj/effect/snare/proc/send_message(mob/living/recipient, crossed_object) - to_chat(recipient, span_bolddanger("[crossed_object] has crossed [name].")) - var/list/guardians = recipient.get_all_linked_holoparasites() - for(var/guardian in guardians) - send_message(guardian, crossed_object) - -/obj/effect/snare/singularity_act() - return - -/obj/effect/snare/singularity_pull() - return - -/mob/living/simple_animal/hostile/guardian/ranged/manifest_effects() - if(toggle) - incorporeal_move = INCORPOREAL_MOVE_BASIC - -/mob/living/simple_animal/hostile/guardian/ranged/recall_effects() - // To stop scout mode from moving when recalled - incorporeal_move = FALSE - -/mob/living/simple_animal/hostile/guardian/ranged/AttackingTarget(atom/attacked_target) - if(toggle) - return - return ..() diff --git a/code/modules/mob/living/simple_animal/guardian/types/standard.dm b/code/modules/mob/living/simple_animal/guardian/types/standard.dm deleted file mode 100644 index 89f671d3ffa19..0000000000000 --- a/code/modules/mob/living/simple_animal/guardian/types/standard.dm +++ /dev/null @@ -1,41 +0,0 @@ -//Standard -/mob/living/simple_animal/hostile/guardian/standard - damage_coeff = list(BRUTE = 0.5, BURN = 0.5, TOX = 0.5, CLONE = 0.5, STAMINA = 0, OXY = 0.5) - melee_damage_lower = 20 - melee_damage_upper = 20 - wound_bonus = -5 //you can wound! - obj_damage = 80 - next_move_modifier = 0.8 //attacks 20% faster - environment_smash = ENVIRONMENT_SMASH_WALLS - playstyle_string = span_holoparasite("As a standard type you have no special abilities, but have a high damage resistance and a powerful attack capable of smashing through walls.") - magic_fluff_string = span_holoparasite("..And draw the Assistant, faceless and generic, but never to be underestimated.") - tech_fluff_string = span_holoparasite("Boot sequence complete. Standard combat modules loaded. Holoparasite swarm online.") - carp_fluff_string = span_holoparasite("CARP CARP CARP! You caught one! It's really boring and standard. Better punch some walls to ease the tension.") - miner_fluff_string = span_holoparasite("You encounter... Adamantine, a powerful attacker.") - creator_name = "Standard" - creator_desc = "Devastating close combat attacks and high damage resistance. Can smash through weak walls." - creator_icon = "standard" - /// The text we shout when attacking. - var/battlecry = "AT" - -/mob/living/simple_animal/hostile/guardian/standard/verb/Battlecry() - set name = "Set Battlecry" - set category = "Guardian" - set desc = "Choose what you shout as you punch people." - var/input = tgui_input_text(src, "What do you want your battlecry to be?", "Battle Cry", max_length = 6) - if(input) - battlecry = input - -/mob/living/simple_animal/hostile/guardian/standard/AttackingTarget(atom/attacked_target) - . = ..() - if(!isliving(target) || attacked_target == src) - return - var/msg = "" - for(var/i in 1 to 9) - msg += battlecry - say("[msg]!!", ignore_spam = TRUE) - for(var/j in 1 to 4) - addtimer(CALLBACK(src, PROC_REF(do_attack_sound), target.loc), j) - -/mob/living/simple_animal/hostile/guardian/standard/proc/do_attack_sound(atom/playing_from) - playsound(playing_from, attack_sound, 50, TRUE, TRUE) diff --git a/code/modules/mob/living/simple_animal/guardian/types/support.dm b/code/modules/mob/living/simple_animal/guardian/types/support.dm deleted file mode 100644 index 9afdf231ce7c4..0000000000000 --- a/code/modules/mob/living/simple_animal/guardian/types/support.dm +++ /dev/null @@ -1,141 +0,0 @@ -//Support -/mob/living/simple_animal/hostile/guardian/support - speed = 0 - damage_coeff = list(BRUTE = 0.7, BURN = 0.7, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7) - melee_damage_lower = 15 - melee_damage_upper = 15 - playstyle_string = span_holoparasite("As a support type, you may right-click to heal targets. In addition, alt-clicking on an adjacent object or mob will warp them to your bluespace beacon after a short delay.") - magic_fluff_string = span_holoparasite("..And draw the Chief Medical Officer, a potent force of life... and death.") - carp_fluff_string = span_holoparasite("CARP CARP CARP! You caught a support carp. It's a kleptocarp!") - tech_fluff_string = span_holoparasite("Boot sequence complete. Support modules active. Holoparasite swarm online.") - miner_fluff_string = span_holoparasite("You encounter... Bluespace, the master of support.") - creator_name = "Support" - creator_desc = "Does medium damage, but can heal its targets and create beacons to teleport people and things to." - creator_icon = "support" - /// Is it in healing mode? - var/toggle = FALSE - /// How much we heal per hit. - var/healing_amount = 5 - /// Our teleportation beacon. - var/obj/structure/receiving_pad/beacon - /// Time it takes to teleport. - var/teleporting_time = 6 SECONDS - /// Time between creating beacons. - var/beacon_cooldown_time = 5 MINUTES - /// Cooldown between creating beacons. - COOLDOWN_DECLARE(beacon_cooldown) - -/mob/living/simple_animal/hostile/guardian/support/Initialize(mapload) - . = ..() - var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] - medsensor.show_to(src) - -/mob/living/simple_animal/hostile/guardian/support/get_status_tab_items() - . = ..() - if(!COOLDOWN_FINISHED(src, beacon_cooldown)) - . += "Beacon Cooldown Remaining: [DisplayTimeText(COOLDOWN_TIMELEFT(src, beacon_cooldown))]" - -/mob/living/simple_animal/hostile/guardian/support/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) - if(LAZYACCESS(modifiers, RIGHT_CLICK) && proximity_flag && isliving(attack_target)) - heal_target(attack_target) - return - return ..() - -/mob/living/simple_animal/hostile/guardian/support/proc/heal_target(mob/living/target) - do_attack_animation(target, ATTACK_EFFECT_PUNCH) - target.visible_message(span_notice("[src] heals [target]!"),\ - span_userdanger("[src] heals you!"), null, COMBAT_MESSAGE_RANGE, src) - to_chat(src, span_notice("You heal [target]!")) - playsound(target, attack_sound, 50, TRUE, TRUE, frequency = -1) //play punch in REVERSE - var/need_mob_update - need_mob_update = target.adjustBruteLoss(-healing_amount, updating_health = FALSE) - need_mob_update += target.adjustFireLoss(-healing_amount, updating_health = FALSE) - need_mob_update += target.adjustOxyLoss(-healing_amount, updating_health = FALSE) - need_mob_update += target.adjustToxLoss(-healing_amount, updating_health = FALSE, forced = TRUE) - if(need_mob_update) - target.updatehealth() - var/obj/effect/temp_visual/heal/heal_effect = new /obj/effect/temp_visual/heal(get_turf(target)) - heal_effect.color = guardian_color - -/mob/living/simple_animal/hostile/guardian/support/verb/Beacon() - set name = "Place Bluespace Beacon" - set category = "Guardian" - set desc = "Mark a floor as your beacon point, allowing you to warp targets to it. Your beacon will not work at extreme distances." - - if(!COOLDOWN_FINISHED(src, beacon_cooldown)) - to_chat(src, span_bolddanger("Your power is on cooldown. You must wait five minutes between placing beacons.")) - return - - var/turf/beacon_loc = get_turf(src.loc) - if(!isfloorturf(beacon_loc)) - return - - if(beacon) - beacon.disappear() - beacon = null - - beacon = new(beacon_loc, src) - - to_chat(src, span_bolddanger("Beacon placed! You may now warp targets and objects to it, including your user, via Alt+Click.")) - - COOLDOWN_START(src, beacon_cooldown, beacon_cooldown_time) - -/obj/structure/receiving_pad - name = "bluespace receiving pad" - icon = 'icons/turf/floors.dmi' - desc = "A receiving zone for bluespace teleportations." - icon_state = "light_on-8" - light_range = MINIMUM_USEFUL_LIGHT_RANGE - density = FALSE - anchored = TRUE - plane = FLOOR_PLANE - layer = ABOVE_OPEN_TURF_LAYER - -/obj/structure/receiving_pad/New(loc, mob/living/simple_animal/hostile/guardian/spawning_guardian) - . = ..() - add_atom_colour(spawning_guardian?.guardian_color, FIXED_COLOUR_PRIORITY) - -/obj/structure/receiving_pad/proc/disappear() - visible_message(span_notice("[src] vanishes!")) - qdel(src) - -/mob/living/simple_animal/hostile/guardian/support/AltClickOn(atom/movable/target) - teleport_to_beacon(target) - -/mob/living/simple_animal/hostile/guardian/support/proc/teleport_to_beacon(atom/movable/teleport_target) - if(!istype(teleport_target)) - return - if(!beacon) - to_chat(src, span_bolddanger("You need a beacon placed to warp things!")) - return - if(!is_deployed()) - to_chat(src, span_bolddanger("You must be manifested to warp a target!")) - return - if(!Adjacent(teleport_target)) - to_chat(src, span_bolddanger("You must be adjacent to your target!")) - return - if(teleport_target.anchored) - to_chat(src, span_bolddanger("Your target is anchored!")) - return - var/turf/target_turf = get_turf(teleport_target) - if(beacon.z != target_turf.z) - to_chat(src, span_bolddanger("The beacon is too far away to warp to!")) - return - to_chat(src, span_bolddanger("You begin to warp [teleport_target].")) - teleport_target.visible_message(span_danger("[teleport_target] starts to glow faintly!"), \ - span_userdanger("You start to faintly glow, and you feel strangely weightless!")) - do_attack_animation(teleport_target) - playsound(teleport_target, attack_sound, 50, TRUE, TRUE, frequency = -1) //play punch in REVERSE - if(!do_after(src, teleporting_time, teleport_target)) //now start the channel - to_chat(src, span_bolddanger("You need to hold still!")) - return - new /obj/effect/temp_visual/guardian/phase/out(target_turf) - if(isliving(teleport_target)) - var/mob/living/living_target = teleport_target - living_target.flash_act() - teleport_target.visible_message( - span_danger("[teleport_target] disappears in a flash of light!"), \ - span_userdanger("Your vision is obscured by a flash of light!"), \ - ) - do_teleport(teleport_target, beacon, 0, channel = TELEPORT_CHANNEL_BLUESPACE) - new /obj/effect/temp_visual/guardian/phase(get_turf(teleport_target)) diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 45f75b229b138..331d3097fac4a 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -172,7 +172,7 @@ Goto(P.starting, move_to_delay, 3) return ..() -//////////////HOSTILE MOB TARGETTING AND AGGRESSION//////////// +//////////////HOSTILE MOB TARGETING AND AGGRESSION//////////// /mob/living/simple_animal/hostile/proc/ListTargets() //Step 1, find out what we can see var/atom/target_from = GET_TARGETS_FROM(src) @@ -196,7 +196,7 @@ possible_targets = ListTargets() for(var/atom/pos_targ as anything in possible_targets) - if(Found(pos_targ)) //Just in case people want to override targetting + if(Found(pos_targ)) //Just in case people want to override targeting all_potential_targets = list(pos_targ) break @@ -421,7 +421,7 @@ SSmove_manager.stop_looping(src) LoseAggro() -//////////////END HOSTILE MOB TARGETTING AND AGGRESSION//////////// +//////////////END HOSTILE MOB TARGETING AND AGGRESSION//////////// /mob/living/simple_animal/hostile/death(gibbed) LoseTarget() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm deleted file mode 100644 index 7a3451e4ef86e..0000000000000 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm +++ /dev/null @@ -1,128 +0,0 @@ -//Gutlunches, passive mods that devour blood and gibs -/mob/living/simple_animal/hostile/asteroid/gutlunch - name = "gutlunch" - desc = "A scavenger that eats raw meat, often found alongside ash walkers. Produces a thick, nutritious milk." - icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' - icon_state = "gutlunch" - icon_living = "gutlunch" - icon_dead = "gutlunch" - mob_biotypes = MOB_ORGANIC|MOB_BEAST - speak_emote = list("warbles", "quavers") - emote_hear = list("trills.") - emote_see = list("sniffs.", "burps.") - weather_immunities = list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE) - faction = list(FACTION_MINING, FACTION_ASHWALKER) - density = FALSE - speak_chance = 1 - turns_per_move = 8 - obj_damage = 0 - environment_smash = ENVIRONMENT_SMASH_NONE - move_to_delay = 15 - response_help_continuous = "pets" - response_help_simple = "pet" - response_disarm_continuous = "gently pushes aside" - response_disarm_simple = "gently push aside" - response_harm_continuous = "squishes" - response_harm_simple = "squish" - friendly_verb_continuous = "pinches" - friendly_verb_simple = "pinch" - combat_mode = FALSE - gold_core_spawnable = FRIENDLY_SPAWN - stat_attack = HARD_CRIT - gender = NEUTER - stop_automated_movement = FALSE - stop_automated_movement_when_pulled = TRUE - stat_exclusive = TRUE - robust_searching = TRUE - search_objects = 3 //Ancient simplemob AI shitcode. This makes them ignore all other mobs. - del_on_death = TRUE - loot = list(/obj/effect/decal/cleanable/blood/gibs) - death_message = "is pulped into bugmash." - - animal_species = /mob/living/simple_animal/hostile/asteroid/gutlunch - childtype = list(/mob/living/simple_animal/hostile/asteroid/gutlunch/grublunch = 100) - - wanted_objects = list(/obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/blood/gibs/, /obj/item/organ) - -/mob/living/simple_animal/hostile/asteroid/gutlunch/Initialize(mapload) - . = ..() - if(wanted_objects.len) - AddComponent(/datum/component/udder, /obj/item/udder/gutlunch, CALLBACK(src, PROC_REF(regenerate_icons)), CALLBACK(src, PROC_REF(regenerate_icons))) - ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT) - -/mob/living/simple_animal/hostile/asteroid/gutlunch/CanAttack(atom/the_target) // Gutlunch-specific version of CanAttack to handle stupid stat_exclusive = true crap so we don't have to do it for literally every single simple_animal/hostile except the two that spawn in lavaland - if(!the_target || !isturf(the_target.loc)) // bail out on invalids - return FALSE - - if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it - return FALSE - - if(isliving(the_target)) - var/mob/living/L = the_target - - if(faction_check_atom(L) && !attack_same) - return FALSE - if(L.stat > stat_attack || L.stat != stat_attack && stat_exclusive) - return FALSE - - return TRUE - - if(isobj(the_target) && is_type_in_typecache(the_target, wanted_objects)) - return TRUE - - return FALSE - -/mob/living/simple_animal/hostile/asteroid/gutlunch/regenerate_icons(new_udder_volume, max_udder_volume) - cut_overlays() - var/static/gutlunch_full_overlay - if(isnull(gutlunch_full_overlay)) - gutlunch_full_overlay = iconstate2appearance(icon, "gl_full") - if(new_udder_volume == max_udder_volume) - add_overlay(gutlunch_full_overlay) - ..() - -//Male gutlunch. They're smaller and more colorful! -/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck - name = "gubbuck" - gender = MALE - -/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck/Initialize(mapload) - . = ..() - add_atom_colour(pick("#E39FBB", "#D97D64", "#CF8C4A"), FIXED_COLOUR_PRIORITY) - update_transform(0.85) - -//Lady gutlunch. They make the babby. -/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen - name = "guthen" - gender = FEMALE - -/mob/living/simple_animal/hostile/asteroid/gutlunch/grublunch - name = "grublunch" - wanted_objects = list() //They don't eat. - gold_core_spawnable = NO_SPAWN - var/growth = 0 - -//Baby gutlunch -/mob/living/simple_animal/hostile/asteroid/gutlunch/grublunch/Initialize(mapload) - . = ..() - add_atom_colour("#9E9E9E", FIXED_COLOUR_PRIORITY) //Somewhat hidden - update_transform(0.45) - -/mob/living/simple_animal/hostile/asteroid/gutlunch/grublunch/Life(seconds_per_tick = SSMOBS_DT, times_fired) - ..() - growth++ - if(growth > 50) //originally used a timer for this but it was more of a problem than it was worth. - growUp() - -/mob/living/simple_animal/hostile/asteroid/gutlunch/grublunch/proc/growUp() - var/mob/living/L - if(prob(45)) - L = new /mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck(loc) - else - L = new /mob/living/simple_animal/hostile/asteroid/gutlunch/guthen(loc) - mind?.transfer_to(L) - L.faction = faction - L.setDir(dir) - L.Stun(20, ignore_canstun = TRUE) - visible_message(span_notice("[src] grows up into [L].")) - qdel(src) diff --git a/code/modules/mob/living/simple_animal/hostile/ooze.dm b/code/modules/mob/living/simple_animal/hostile/ooze.dm index 2e1db456b5b28..f024247356b04 100644 --- a/code/modules/mob/living/simple_animal/hostile/ooze.dm +++ b/code/modules/mob/living/simple_animal/hostile/ooze.dm @@ -298,7 +298,7 @@ /mob/living/simple_animal/hostile/ooze/grapes/add_cell_sample() AddElement(/datum/element/swabable, CELL_LINE_TABLE_GRAPE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) -///Ability that allows the owner to fire healing globules at mobs, targetting specific limbs. +///Ability that allows the owner to fire healing globules at mobs, targeting specific limbs. /datum/action/cooldown/globules name = "Fire Mending globule" desc = "Fires a mending globule at someone, healing a specific limb of theirs." diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 4c382a59b2f64..ed304e276b0fd 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -133,9 +133,6 @@ ///Played when someone punches the creature. var/attacked_sound = SFX_PUNCH - ///If the creature has, and can use, hands. - var/dextrous = FALSE - ///The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever), AI_Z_OFF (Temporarily off due to nonpresence of players). var/AIStatus = AI_ON ///once we have become sentient, we can never go back. @@ -176,10 +173,6 @@ if(!loc) stack_trace("Simple animal being instantiated in nullspace") update_simplemob_varspeed() - if(dextrous) - AddElement(/datum/element/dextrous, hud_type = hud_type) - AddComponent(/datum/component/personal_crafting) - add_traits(list(TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP), ROUNDSTART_TRAIT) ADD_TRAIT(src, TRAIT_NOFIRE_SPREAD, ROUNDSTART_TRAIT) if(length(weather_immunities)) add_traits(weather_immunities, ROUNDSTART_TRAIT) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 6808728a833b7..2c2f8519e2515 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -20,7 +20,7 @@ // we never want to hide a turf because it's not lit // We can rely on the lighting plane to handle that for us see_in_dark = 1e6 - // A list of factions that this mob is currently in, for hostile mob targetting, amongst other things + // A list of factions that this mob is currently in, for hostile mob targeting, amongst other things faction = list(FACTION_NEUTRAL) /// The current client inhabiting this mob. Managed by login/logout /// This exists so we can do cleanup in logout for occasions where a client was transfere rather then destroyed diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 6b89495887682..d9bfef8f72b80 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -308,7 +308,7 @@ toast.add_overlay(alert_overlay) toast.desc = "[message] -- Click to [action]." toast.name = header - toast.target = source + toast.target_ref = WEAKREF(source) /// Heals a robotic limb on a mob /proc/item_heal_robotic(mob/living/carbon/human/human, mob/user, brute_heal, burn_heal) diff --git a/code/modules/mod/modules/modules_ninja.dm b/code/modules/mod/modules/modules_ninja.dm index 427226071994f..5ed1e44b70987 100644 --- a/code/modules/mod/modules/modules_ninja.dm +++ b/code/modules/mod/modules/modules_ninja.dm @@ -463,7 +463,7 @@ if(reagents.has_reagent(reagent_required, reagent_required_amount)) balloon_alert(mod.wearer, "already charged!") return FALSE - if(!attacking_item.reagents.trans_id_to(src, reagent_required, reagent_required_amount)) + if(!attacking_item.reagents.trans_to(src, reagent_required_amount, target_id = reagent_required)) return FALSE balloon_alert(mod.wearer, "charge [reagents.has_reagent(reagent_required, reagent_required_amount) ? "fully" : "partially"] reloaded") return TRUE diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index 8761606568281..b0a75108d569c 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -324,11 +324,14 @@ return FALSE . = ..() + if(!forced) + add_log("manual overriding of permissions and modification of device firmware detected. Reboot and reinstall required.") obj_flags |= EMAGGED device_theme = PDA_THEME_SYNDICATE - balloon_alert(user, "syndieOS loaded") - if (emag_card) - to_chat(user, span_notice("You swipe \the [src] with [emag_card]. A console window momentarily fills the screen, with white text rapidly scrolling past.")) + if(user) + balloon_alert(user, "syndieOS loaded") + if (emag_card) + to_chat(user, span_notice("You swipe \the [src] with [emag_card]. A console window momentarily fills the screen, with white text rapidly scrolling past.")) return TRUE /obj/item/modular_computer/examine(mob/user) diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm index 1b87a014f185b..c98284fbf6629 100644 --- a/code/modules/modular_computers/computers/item/computer_ui.dm +++ b/code/modules/modular_computers/computers/item/computer_ui.dm @@ -96,6 +96,7 @@ ) data["proposed_login"] = list( + IDInserted = computer_id_slot ? TRUE : FALSE, IDName = computer_id_slot?.registered_name, IDJob = computer_id_slot?.assignment, ) diff --git a/code/modules/modular_computers/documentation.md b/code/modules/modular_computers/documentation.md index 7e0cd7dbca18e..925f2f5668b0f 100644 --- a/code/modules/modular_computers/documentation.md +++ b/code/modules/modular_computers/documentation.md @@ -31,13 +31,12 @@ This is how the base program is setup. the rest is mostly tgui stuff. I'll use t /// programs. requires_ntnet = 1 - /// This is access required to run the program itself. ONLY SET THIS FOR - /// SUPER SECURE SHIT. This also acts as transfer_access as well. - required_access = access_network + /// This is access required to run the program itself. + run_access = access_network /// This is the access needed to download from ntnet or host on the ptp /// program. This is what you want to use most of the time. - transfer_access = access_change_ids + download_access = access_change_ids /// If it's available to download on ntnet. pretty self explanatory. available_on_ntnet = 1 diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index 8cb741d376ed9..d050bd804b327 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -9,10 +9,11 @@ ///How much power running this program costs. var/power_cell_use = PROGRAM_BASIC_CELL_USE - /// List of required accesses to *run* the program. Any match will do. - var/list/required_access = list() - /// List of required access to download or file host the program. Any match will do. - var/list/transfer_access = list() + ///List of required accesses to *run* the program. Any match will do. + ///This also acts as download_access if that is not set, making this more draconic and restrictive. + var/list/run_access = list() + ///List of required access to download or file host the program. Any match will do. + var/list/download_access = list() /// User-friendly name of this program. var/filedesc = "Unknown Program" /// Short description of this program's function. @@ -52,7 +53,7 @@ /datum/computer_file/program/clone() var/datum/computer_file/program/temp = ..() - temp.required_access = required_access + temp.run_access = run_access temp.filedesc = filedesc temp.program_icon_state = program_icon_state temp.requires_ntnet = requires_ntnet @@ -83,9 +84,9 @@ ///Attempts to generate an Ntnet log, returns the log on success, FALSE otherwise. /datum/computer_file/program/proc/generate_network_log(text) - if(computer) - return computer.add_log(text) - return FALSE + if(!computer || computer.obj_flags & EMAGGED) + return FALSE + return computer.add_log(text) /** *Runs when the device is used to attack an atom in non-combat mode using right click (secondary). @@ -115,33 +116,32 @@ return TRUE /** - *Check if the user can run program. Only humans and silicons can operate computer. Automatically called in on_start() - *ID must be inserted into a card slot to be read. If the program is not currently installed (as is the case when - *NT Software Hub is checking available software), a list can be given to be used instead. - *Arguments: - *user is a ref of the mob using the device. - *loud is a bool deciding if this proc should use to_chats - *access_to_check is an access level that will be checked against the ID - *transfer, if TRUE and access_to_check is null, will tell this proc to use the program's transfer_access in place of access_to_check - *access can contain a list of access numbers to check against. If access is not empty, it will be used istead of checking any inserted ID. -*/ -/datum/computer_file/program/proc/can_run(mob/user, loud = FALSE, access_to_check, transfer = FALSE, list/access) + * Checks if the user can run program. Only humans and silicons can operate computer. Automatically called in on_start() + * ID must be inserted into a card slot to be read. If the program is not currently installed (as is the case when + * NT Software Hub is checking available software), a list can be given to be used instead. + * Args: + * user is a ref of the mob using the device. + * loud is a bool deciding if this proc should use to_chats + * access_to_check is an access level that will be checked against the ID + * downloading: Boolean on whether it's downloading the app or not. If it is, it will check download_access instead of run_access. + * access can contain a list of access numbers to check against. If access is not empty, it will be used istead of checking any inserted ID. + */ +/datum/computer_file/program/proc/can_run(mob/user, loud = FALSE, access_to_check, downloading = FALSE, list/access) if(issilicon(user) && !ispAI(user)) return TRUE if(isAdminGhostAI(user)) return TRUE - if(computer && (computer.obj_flags & EMAGGED) && (available_on_syndinet || !transfer)) //emagged can run anything on syndinet, and can bypass execution locks, but not download. + if(computer && (computer.obj_flags & EMAGGED) && (available_on_syndinet || !downloading)) //emagged can run anything on syndinet, and can bypass execution locks, but not download. return TRUE - // Defaults to required_access if(!access_to_check) - if(transfer && length(transfer_access)) - access_to_check = transfer_access + if(downloading && length(download_access)) + access_to_check = download_access else - access_to_check = required_access - if(!length(access_to_check)) // No required_access, allow it. + access_to_check = run_access + if(!length(access_to_check)) // No access requirements, allow it. return TRUE if(!length(access)) diff --git a/code/modules/modular_computers/file_system/programs/airestorer.dm b/code/modules/modular_computers/file_system/programs/airestorer.dm index 4f24b2c61d872..ee3f983cbd554 100644 --- a/code/modules/modular_computers/file_system/programs/airestorer.dm +++ b/code/modules/modular_computers/file_system/programs/airestorer.dm @@ -7,7 +7,7 @@ size = 12 requires_ntnet = FALSE usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP - transfer_access = list(ACCESS_RD) + download_access = list(ACCESS_RD) available_on_ntnet = TRUE tgui_id = "NtosAiRestorer" program_icon = "laptop-code" diff --git a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm index 856cc9b6b02b3..be15e90faea16 100644 --- a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm +++ b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm @@ -42,7 +42,7 @@ /datum/computer_file/program/ntnet_dos/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) switch(action) if("PRG_target_relay") - for(var/obj/machinery/ntnet_relay/relays as anything in GLOB.ntnet_relays) + for(var/obj/machinery/ntnet_relay/relays as anything in SSmachines.get_machines_by_type(/obj/machinery/ntnet_relay)) if(relays.uid == params["targid"]) target = relays break @@ -76,7 +76,7 @@ else data["target"] = FALSE data["relays"] = list() - for(var/obj/machinery/ntnet_relay/relays as anything in GLOB.ntnet_relays) + for(var/obj/machinery/ntnet_relay/relays as anything in SSmachines.get_machines_by_type(/obj/machinery/ntnet_relay)) data["relays"] += list(list("id" = relays.uid)) data["focus"] = target ? target.uid : null diff --git a/code/modules/modular_computers/file_system/programs/borg_monitor.dm b/code/modules/modular_computers/file_system/programs/borg_monitor.dm index 2a2e494c1eca8..fae48fbff2f9e 100644 --- a/code/modules/modular_computers/file_system/programs/borg_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/borg_monitor.dm @@ -6,7 +6,7 @@ program_icon_state = "generic" extended_desc = "This program allows for remote monitoring of station cyborgs." requires_ntnet = TRUE - transfer_access = list(ACCESS_ROBOTICS) + download_access = list(ACCESS_ROBOTICS) size = 5 tgui_id = "NtosCyborgRemoteMonitor" program_icon = "project-diagram" @@ -155,7 +155,7 @@ requires_ntnet = FALSE available_on_ntnet = FALSE available_on_syndinet = TRUE - transfer_access = list() + download_access = list() /datum/computer_file/program/borg_monitor/syndicate/evaluate_borg(mob/living/silicon/robot/R) if(!is_valid_z_level(get_turf(computer), get_turf(R))) diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm index 529cf813d1bb9..05ac394b7bd73 100644 --- a/code/modules/modular_computers/file_system/programs/card.dm +++ b/code/modules/modular_computers/file_system/programs/card.dm @@ -4,7 +4,7 @@ category = PROGRAM_CATEGORY_CREW program_icon_state = "id" extended_desc = "Program for programming employee ID cards to access parts of the station." - transfer_access = list(ACCESS_COMMAND) + download_access = list(ACCESS_COMMAND) requires_ntnet = 0 size = 8 tgui_id = "NtosCard" diff --git a/code/modules/modular_computers/file_system/programs/crewmanifest.dm b/code/modules/modular_computers/file_system/programs/crewmanifest.dm index cdd05d6b4c64f..85f9a4c5ffed3 100644 --- a/code/modules/modular_computers/file_system/programs/crewmanifest.dm +++ b/code/modules/modular_computers/file_system/programs/crewmanifest.dm @@ -4,7 +4,7 @@ category = PROGRAM_CATEGORY_CREW program_icon_state = "id" extended_desc = "Program for viewing and printing the current crew manifest" - transfer_access = list(ACCESS_SECURITY, ACCESS_COMMAND) + download_access = list(ACCESS_SECURITY, ACCESS_COMMAND) requires_ntnet = TRUE size = 4 tgui_id = "NtosCrewManifest" diff --git a/code/modules/modular_computers/file_system/programs/frontier.dm b/code/modules/modular_computers/file_system/programs/frontier.dm index 9c6e33bcde971..3b001e9f39d23 100644 --- a/code/modules/modular_computers/file_system/programs/frontier.dm +++ b/code/modules/modular_computers/file_system/programs/frontier.dm @@ -8,7 +8,7 @@ program_icon_state = "research" tgui_id = "NtosScipaper" program_icon = "paper-plane" - transfer_access = list(ACCESS_ORDNANCE) + download_access = list(ACCESS_ORDNANCE) var/datum/techweb/linked_techweb /// Unpublished, temporary paper datum. @@ -65,9 +65,9 @@ singular_partner["path"] = partner.type singular_partner["boostedNodes"] = list() singular_partner["acceptedExperiments"] = list() - for (var/node_id in partner.boosted_nodes) + for (var/node_id in partner.boostable_nodes) var/datum/techweb_node/node = SSresearch.techweb_node_by_id(node_id) - singular_partner["boostedNodes"] += list(list("name" = node.display_name, "discount" = partner.boosted_nodes[node_id], "id"=node_id)) + singular_partner["boostedNodes"] += list(list("name" = node.display_name, "discount" = partner.boostable_nodes[node_id], "id" = node_id)) for (var/datum/experiment/ordnance/ordnance_experiment as anything in partner.accepted_experiments) singular_partner["acceptedExperiments"] += initial(ordnance_experiment.name) parsed_partners += list(singular_partner) @@ -154,7 +154,7 @@ data["purchaseableBoosts"][partner.type] = list() for(var/node_id in linked_techweb.get_available_nodes()) // Not from our partner - if(!(node_id in partner.boosted_nodes)) + if(!(node_id in partner.boostable_nodes)) continue if(!partner.allowed_to_boost(linked_techweb, node_id)) continue diff --git a/code/modules/modular_computers/file_system/programs/jobmanagement.dm b/code/modules/modular_computers/file_system/programs/jobmanagement.dm index b394b0a2ad9f9..c90fcf21f0328 100644 --- a/code/modules/modular_computers/file_system/programs/jobmanagement.dm +++ b/code/modules/modular_computers/file_system/programs/jobmanagement.dm @@ -7,7 +7,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) category = PROGRAM_CATEGORY_CREW program_icon_state = "id" extended_desc = "Program for viewing and changing job slot availability." - transfer_access = list(ACCESS_COMMAND) + download_access = list(ACCESS_COMMAND) requires_ntnet = TRUE size = 4 tgui_id = "NtosJobManager" diff --git a/code/modules/modular_computers/file_system/programs/newscasterapp.dm b/code/modules/modular_computers/file_system/programs/newscasterapp.dm index 47e4f65d48f01..27aafee3a41fa 100644 --- a/code/modules/modular_computers/file_system/programs/newscasterapp.dm +++ b/code/modules/modular_computers/file_system/programs/newscasterapp.dm @@ -1,7 +1,7 @@ /datum/computer_file/program/newscaster filename = "newscasterapp" filedesc = "Newscaster" - transfer_access = list(ACCESS_LIBRARY) + download_access = list(ACCESS_LIBRARY) category = PROGRAM_CATEGORY_CREW program_icon_state = "bountyboard" extended_desc = "This program allows any user to access the Newscaster network from anywhere." diff --git a/code/modules/modular_computers/file_system/programs/ntdownloader.dm b/code/modules/modular_computers/file_system/programs/ntdownloader.dm index c9723d905b5f1..a5aaee6dca48f 100644 --- a/code/modules/modular_computers/file_system/programs/ntdownloader.dm +++ b/code/modules/modular_computers/file_system/programs/ntdownloader.dm @@ -143,7 +143,7 @@ "installed" = !!computer.find_file_by_name(programs.filename), "compatible" = check_compatibility(programs), "size" = programs.size, - "access" = programs.can_run(user, transfer = TRUE, access = access), + "access" = programs.can_run(user, downloading = TRUE, access = access), "verifiedsource" = programs.available_on_ntnet, )) diff --git a/code/modules/modular_computers/file_system/programs/portrait_printer.dm b/code/modules/modular_computers/file_system/programs/portrait_printer.dm index 68c94e87e8d32..cdfa24be1b108 100644 --- a/code/modules/modular_computers/file_system/programs/portrait_printer.dm +++ b/code/modules/modular_computers/file_system/programs/portrait_printer.dm @@ -15,7 +15,7 @@ category = PROGRAM_CATEGORY_CREW program_icon_state = "dummy" extended_desc = "This program connects to a Spinward Sector community art site for viewing and printing art." - transfer_access = list(ACCESS_LIBRARY) + download_access = list(ACCESS_LIBRARY) usage_flags = PROGRAM_CONSOLE requires_ntnet = TRUE size = 9 diff --git a/code/modules/modular_computers/file_system/programs/powermonitor.dm b/code/modules/modular_computers/file_system/programs/powermonitor.dm index e82821d75e4f2..9a8026ccd6cba 100644 --- a/code/modules/modular_computers/file_system/programs/powermonitor.dm +++ b/code/modules/modular_computers/file_system/programs/powermonitor.dm @@ -7,7 +7,7 @@ program_icon_state = "power_monitor" extended_desc = "This program connects to sensors around the station to provide information about electrical systems" ui_header = "power_norm.gif" - transfer_access = list(ACCESS_ENGINEERING) + download_access = list(ACCESS_ENGINEERING) usage_flags = PROGRAM_CONSOLE requires_ntnet = FALSE size = 8 diff --git a/code/modules/modular_computers/file_system/programs/radar.dm b/code/modules/modular_computers/file_system/programs/radar.dm index c230614339d49..704be0dc25514 100644 --- a/code/modules/modular_computers/file_system/programs/radar.dm +++ b/code/modules/modular_computers/file_system/programs/radar.dm @@ -220,7 +220,7 @@ filedesc = "Lifeline" extended_desc = "This program allows for tracking of crew members via their suit sensors." requires_ntnet = TRUE - transfer_access = list(ACCESS_MEDICAL) + download_access = list(ACCESS_MEDICAL) available_on_ntnet = TRUE program_icon = "heartbeat" @@ -260,7 +260,7 @@ filedesc = "Custodial Locator" extended_desc = "This program allows for tracking of custodial equipment." requires_ntnet = TRUE - transfer_access = list(ACCESS_JANITOR) + download_access = list(ACCESS_JANITOR) available_on_ntnet = TRUE program_icon = "broom" size = 2 diff --git a/code/modules/modular_computers/file_system/programs/records.dm b/code/modules/modular_computers/file_system/programs/records.dm index 9b5617364c0aa..12c682f562664 100644 --- a/code/modules/modular_computers/file_system/programs/records.dm +++ b/code/modules/modular_computers/file_system/programs/records.dm @@ -18,7 +18,7 @@ filename = "medrecords" program_icon = "book-medical" extended_desc = "Allows the user to view several basic medical records from the crew." - transfer_access = list(ACCESS_MEDICAL, ACCESS_FLAG_COMMAND) + download_access = list(ACCESS_MEDICAL, ACCESS_FLAG_COMMAND) available_on_ntnet = TRUE mode = "medical" @@ -26,7 +26,7 @@ filedesc = "Security Records" filename = "secrecords" extended_desc = "Allows the user to view several basic security records from the crew." - transfer_access = list(ACCESS_SECURITY, ACCESS_FLAG_COMMAND) + download_access = list(ACCESS_SECURITY, ACCESS_FLAG_COMMAND) available_on_ntnet = TRUE mode = "security" diff --git a/code/modules/modular_computers/file_system/programs/secureye.dm b/code/modules/modular_computers/file_system/programs/secureye.dm index 6e3e69cdccfc5..bb31d74f9ab78 100644 --- a/code/modules/modular_computers/file_system/programs/secureye.dm +++ b/code/modules/modular_computers/file_system/programs/secureye.dm @@ -8,7 +8,7 @@ program_icon_state = "generic" extended_desc = "This program allows access to standard security camera networks." requires_ntnet = TRUE - transfer_access = list(ACCESS_SECURITY) + download_access = list(ACCESS_SECURITY) usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP size = 5 tgui_id = "NtosSecurEye" @@ -39,7 +39,7 @@ filename = "syndeye" filedesc = "SyndEye" extended_desc = "This program allows for illegal access to security camera networks." - transfer_access = list() + download_access = list() available_on_ntnet = FALSE available_on_syndinet = TRUE requires_ntnet = FALSE diff --git a/code/modules/modular_computers/file_system/programs/sm_monitor.dm b/code/modules/modular_computers/file_system/programs/sm_monitor.dm index 0ba8a72140779..e310d402e9ed1 100644 --- a/code/modules/modular_computers/file_system/programs/sm_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/sm_monitor.dm @@ -6,7 +6,7 @@ program_icon_state = "smmon_0" extended_desc = "Crystal Integrity Monitoring System, connects to specially calibrated supermatter sensors to provide information on the status of supermatter-based engines." requires_ntnet = TRUE - transfer_access = list(ACCESS_CONSTRUCTION) + download_access = list(ACCESS_CONSTRUCTION) size = 5 tgui_id = "NtosSupermatter" program_icon = "radiation" diff --git a/code/modules/modular_computers/file_system/programs/techweb.dm b/code/modules/modular_computers/file_system/programs/techweb.dm index 77d0a0900e4a5..ad503422b47ff 100644 --- a/code/modules/modular_computers/file_system/programs/techweb.dm +++ b/code/modules/modular_computers/file_system/programs/techweb.dm @@ -8,8 +8,8 @@ size = 10 tgui_id = "NtosTechweb" program_icon = "atom" - required_access = list(ACCESS_COMMAND, ACCESS_RESEARCH) - transfer_access = list(ACCESS_RESEARCH) + run_access = list(ACCESS_COMMAND, ACCESS_RESEARCH) + download_access = list(ACCESS_RESEARCH) /// Reference to global science techweb var/datum/techweb/stored_research /// Access needed to lock/unlock the console diff --git a/code/modules/modular_computers/file_system/programs/wirecarp.dm b/code/modules/modular_computers/file_system/programs/wirecarp.dm index 712d1e92cdafe..ed83f2ca334e1 100644 --- a/code/modules/modular_computers/file_system/programs/wirecarp.dm +++ b/code/modules/modular_computers/file_system/programs/wirecarp.dm @@ -6,7 +6,7 @@ extended_desc = "This program monitors stationwide NTNet network, provides access to logging systems, and allows for configuration changes" size = 12 requires_ntnet = TRUE - required_access = list(ACCESS_NETWORK) //NETWORK CONTROL IS A MORE SECURE PROGRAM. + run_access = list(ACCESS_NETWORK) //NETWORK CONTROL IS A MORE SECURE PROGRAM. available_on_ntnet = TRUE tgui_id = "NtosNetMonitor" program_icon = "network-wired" @@ -20,7 +20,7 @@ SSmodular_computers.intrusion_detection_enabled = !SSmodular_computers.intrusion_detection_enabled return TRUE if("toggle_relay") - var/obj/machinery/ntnet_relay/target_relay = locate(params["ref"]) in GLOB.ntnet_relays + var/obj/machinery/ntnet_relay/target_relay = locate(params["ref"]) in SSmachines.get_machines_by_type(/obj/machinery/ntnet_relay) if(!istype(target_relay)) return target_relay.set_relay_enabled(!target_relay.relay_enabled) @@ -39,7 +39,7 @@ var/list/data = list() data["ntnetrelays"] = list() - for(var/obj/machinery/ntnet_relay/relays as anything in GLOB.ntnet_relays) + for(var/obj/machinery/ntnet_relay/relays as anything in SSmachines.get_machines_by_type(/obj/machinery/ntnet_relay)) var/list/relay_data = list() relay_data["is_operational"] = !!relays.is_operational relay_data["name"] = relays.name diff --git a/code/modules/movespeed/modifiers/status_effects.dm b/code/modules/movespeed/modifiers/status_effects.dm index 65245880ef42b..4768f66a544f4 100644 --- a/code/modules/movespeed/modifiers/status_effects.dm +++ b/code/modules/movespeed/modifiers/status_effects.dm @@ -53,3 +53,6 @@ /datum/movespeed_modifier/status_effect/midas_blight/gold multiplicative_slowdown = 2 + +/datum/movespeed_modifier/status_effect/guardian_shield + multiplicative_slowdown = 1 diff --git a/code/modules/pai/card.dm b/code/modules/pai/card.dm index 086e188b4319c..2fc3d2d0ca4c7 100644 --- a/code/modules/pai/card.dm +++ b/code/modules/pai/card.dm @@ -26,7 +26,6 @@ if(!pai.encrypt_mod) to_chat(user, span_alert("Encryption Key ports not configured.")) return - user.set_machine(src) pai.radio.attackby(used, user, params) to_chat(user, span_notice("You insert [used] into the [src].")) return @@ -35,7 +34,6 @@ /obj/item/pai_card/attack_self(mob/user) if(!in_range(src, user)) return - user.set_machine(src) ui_interact(user) /obj/item/pai_card/Destroy() diff --git a/code/modules/paperwork/fax.dm b/code/modules/paperwork/fax.dm index a03c79f44d066..29eeffb7e75b7 100644 --- a/code/modules/paperwork/fax.dm +++ b/code/modules/paperwork/fax.dm @@ -174,7 +174,7 @@ GLOBAL_VAR_INIT(nt_fax_department, pick("NT HR Department", "NT Legal Department var/obj/item/reagent_containers/spray/clean_spray = item if(!clean_spray.reagents.has_reagent(/datum/reagent/space_cleaner, clean_spray.amount_per_transfer_from_this)) return FALSE - clean_spray.reagents.remove_reagent(/datum/reagent/space_cleaner, clean_spray.amount_per_transfer_from_this, 1) + clean_spray.reagents.remove_reagent(/datum/reagent/space_cleaner, clean_spray.amount_per_transfer_from_this) playsound(loc, 'sound/effects/spray3.ogg', 50, TRUE, MEDIUM_RANGE_SOUND_EXTRARANGE) user.visible_message(span_notice("[user] cleans \the [src]."), span_notice("You clean \the [src].")) jammed = FALSE diff --git a/code/modules/plumbing/plumbers/bottler.dm b/code/modules/plumbing/plumbers/bottler.dm index eab1811ec6c5c..8e0158b61da78 100644 --- a/code/modules/plumbing/plumbers/bottler.dm +++ b/code/modules/plumbing/plumbers/bottler.dm @@ -91,13 +91,13 @@ var/obj/item/B = AM ///see if it would overflow else inject if((B.reagents.total_volume + wanted_amount) <= B.reagents.maximum_volume) - reagents.trans_to(B, wanted_amount, transferred_by = src) + reagents.trans_to(B, wanted_amount) B.forceMove(goodspot) return ///glass was full so we move it away AM.forceMove(badspot) else if(istype(AM, /obj/item/slime_extract)) ///slime extracts need inject AM.forceMove(goodspot) - reagents.trans_to(AM, wanted_amount, transferred_by = src, methods = INJECT) + reagents.trans_to(AM, wanted_amount, methods = INJECT) else if(istype(AM, /obj/item/slimecross/industrial)) ///no need to move slimecross industrial things - reagents.trans_to(AM, wanted_amount, transferred_by = src, methods = INJECT) + reagents.trans_to(AM, wanted_amount, methods = INJECT) diff --git a/code/modules/plumbing/plumbers/filter.dm b/code/modules/plumbing/plumbers/filter.dm index 4e4a282bd1dcd..633f70830f016 100644 --- a/code/modules/plumbing/plumbers/filter.dm +++ b/code/modules/plumbing/plumbers/filter.dm @@ -38,11 +38,12 @@ switch(action) if("add") var/which = params["which"] - var/selected_reagent = tgui_input_list(usr, "Select [which] reagent", "Reagent", GLOB.chemical_name_list) + + var/selected_reagent = tgui_input_list(usr, "Select [which] reagent", "Reagent", GLOB.name2reagent) if(!selected_reagent) return TRUE - var/chem_id = get_chem_id(selected_reagent) + var/datum/reagent/chem_id = GLOB.name2reagent[selected_reagent] if(!chem_id) return TRUE diff --git a/code/modules/plumbing/plumbers/reaction_chamber.dm b/code/modules/plumbing/plumbers/reaction_chamber.dm index 01a6b4a0b82fd..965b428acbdfd 100644 --- a/code/modules/plumbing/plumbers/reaction_chamber.dm +++ b/code/modules/plumbing/plumbers/reaction_chamber.dm @@ -3,9 +3,6 @@ /// coefficient to convert temperature to joules. same lvl as acclimator #define HEATER_COEFFICIENT 0.05 -/// maximum number of attempts the reaction chamber will make to balance the ph(More means better results but higher tick usage) -#define MAX_PH_ADJUSTMENTS 5 - /obj/machinery/plumbing/reaction_chamber name = "mixing chamber" desc = "Keeps chemicals separated until given conditions are met." @@ -107,32 +104,34 @@ switch(action) if("add") - var/selected_reagent = tgui_input_list(ui.user, "Select reagent", "Reagent", GLOB.chemical_name_list) + var/selected_reagent = tgui_input_list(ui.user, "Select reagent", "Reagent", GLOB.name2reagent) if(!selected_reagent) - return TRUE + return FALSE - var/input_reagent = get_chem_id(selected_reagent) + var/datum/reagent/input_reagent = GLOB.name2reagent[selected_reagent] if(!input_reagent) - return TRUE + return FALSE if(!required_reagents.Find(input_reagent)) var/input_amount = text2num(params["amount"]) - if(input_amount) + if(!isnull(input_amount)) required_reagents[input_reagent] = input_amount - - return TRUE + return TRUE + return FALSE if("remove") var/reagent = get_chem_id(params["chem"]) if(reagent) required_reagents.Remove(reagent) - return TRUE + return TRUE + return FALSE if("temperature") var/target = text2num(params["target"]) - if(target != null) + if(!isnull(target)) target_temperature = clamp(target, 0, 1000) - return TRUE + return TRUE + return FALSE var/result = handle_ui_act(action, params, ui, state) if(isnull(result)) @@ -173,8 +172,7 @@ return ..() /obj/machinery/plumbing/reaction_chamber/chem/handle_reagents(seconds_per_tick) - var/ph_balance_attempts = 0 - while(ph_balance_attempts < MAX_PH_ADJUSTMENTS && (reagents.ph < acidic_limit || reagents.ph > alkaline_limit)) + if(reagents.ph < acidic_limit || reagents.ph > alkaline_limit) //no power if(machine_stat & NOPOWER) return @@ -194,14 +192,13 @@ return //transfer buffer and handle reactions - var/ph_change = (reagents.ph > alkaline_limit ? (reagents.ph - alkaline_limit) : (acidic_limit - reagents.ph)) - var/buffer_amount = ((ph_change * reagents.total_volume) / (BUFFER_IONIZING_STRENGTH * num_of_reagents)) - if(!buffer.trans_to(reagents, buffer_amount * seconds_per_tick)) + var/ph_change = max((reagents.ph > alkaline_limit ? (reagents.ph - alkaline_limit) : (acidic_limit - reagents.ph)), 0.25) + var/buffer_amount = ((ph_change * reagents.total_volume) / (BUFFER_IONIZING_STRENGTH * num_of_reagents)) * seconds_per_tick + if(!buffer.trans_to(reagents, buffer_amount)) return //some power for accurate ph balancing & keep track of attempts made - use_power(active_power_usage * 0.03 * buffer_amount * seconds_per_tick) - ph_balance_attempts += 1 + use_power(active_power_usage * 0.03 * buffer_amount) /obj/machinery/plumbing/reaction_chamber/chem/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -227,4 +224,3 @@ return FALSE #undef HEATER_COEFFICIENT -#undef MAX_PH_ADJUSTMENTS diff --git a/code/modules/plumbing/plumbers/synthesizer.dm b/code/modules/plumbing/plumbers/synthesizer.dm index 3dddd648e6165..0e9cb0c1b1125 100644 --- a/code/modules/plumbing/plumbers/synthesizer.dm +++ b/code/modules/plumbing/plumbers/synthesizer.dm @@ -2,7 +2,6 @@ /obj/machinery/plumbing/synthesizer name = "chemical synthesizer" desc = "Produces a single chemical at a given volume. Must be plumbed. Most effective when working in unison with other chemical synthesizers, heaters and filters." - icon_state = "synthesizer" icon = 'icons/obj/pipes_n_cables/hydrochem/plumbers.dmi' active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 @@ -52,10 +51,13 @@ /obj/machinery/plumbing/synthesizer/process(seconds_per_tick) if(machine_stat & NOPOWER || !reagent_id || !amount) return - if(reagents.total_volume >= amount*seconds_per_tick*0.5) //otherwise we get leftovers, and we need this to be precise + + //otherwise we get leftovers, and we need this to be precise + if(reagents.total_volume >= amount) return - reagents.add_reagent(reagent_id, amount*seconds_per_tick*0.5) - use_power(active_power_usage * amount * seconds_per_tick * 0.5) + reagents.add_reagent(reagent_id, amount) + + use_power(active_power_usage) /obj/machinery/plumbing/synthesizer/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -63,8 +65,13 @@ ui = new(user, src, "ChemSynthesizer", name) ui.open() +/obj/machinery/plumbing/synthesizer/ui_static_data(mob/user) + . = ..() + .["possible_amounts"] = possible_amounts + /obj/machinery/plumbing/synthesizer/ui_data(mob/user) - var/list/data = list() + . = list() + .["amount"] = amount var/is_hallucinating = FALSE if(isliving(user)) @@ -72,36 +79,35 @@ is_hallucinating = !!living_user.has_status_effect(/datum/status_effect/hallucination) var/list/chemicals = list() - for(var/A in dispensable_reagents) - var/datum/reagent/R = GLOB.chemical_reagents_list[A] - if(R) - var/chemname = R.name + for(var/reagentID in dispensable_reagents) + var/datum/reagent/reagent = GLOB.chemical_reagents_list[reagentID] + if(reagent) + var/chemname = reagent.name if(is_hallucinating && prob(5)) chemname = "[pick_list_replacements("hallucination.json", "chemicals")]" - chemicals.Add(list(list("title" = chemname, "id" = ckey(R.name)))) - data["chemicals"] = chemicals - data["amount"] = amount - data["possible_amounts"] = possible_amounts + chemicals += list(list("title" = chemname, "id" = reagent.name)) + .["chemicals"] = chemicals - data["current_reagent"] = ckey(initial(reagent_id.name)) - return data + .["current_reagent"] = initial(reagent_id.name) /obj/machinery/plumbing/synthesizer/ui_act(action, params) . = ..() if(.) return - . = TRUE + switch(action) if("amount") var/new_amount = text2num(params["target"]) if(new_amount in possible_amounts) amount = new_amount . = TRUE + if("select") var/new_reagent = GLOB.name2reagent[params["reagent"]] if(new_reagent in dispensable_reagents) reagent_id = new_reagent . = TRUE + update_appearance() reagents.clear_reagents() diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm index 747010fc6c006..67efe69f1e7ed 100644 --- a/code/modules/power/lighting/light.dm +++ b/code/modules/power/lighting/light.dm @@ -101,7 +101,7 @@ qdel(on_turf) if(!mapload) //sync up nightshift lighting for player made lights - var/area/our_area = get_room_area(src) + var/area/our_area = get_room_area() var/obj/machinery/power/apc/temp_apc = our_area.apc nightshift_enabled = temp_apc?.nightshift_lights @@ -131,7 +131,7 @@ update(trigger = FALSE) /obj/machinery/light/Destroy() - var/area/local_area = get_room_area(src) + var/area/local_area = get_room_area() if(local_area) on = FALSE QDEL_NULL(cell) @@ -154,7 +154,7 @@ /obj/machinery/light/update_icon_state() switch(status) // set icon_states if(LIGHT_OK) - var/area/local_area =get_room_area(src) + var/area/local_area = get_room_area() if(low_power_mode || major_emergency || (local_area?.fire)) icon_state = "[base_state]_emergency" else @@ -174,7 +174,7 @@ . += emissive_appearance(overlay_icon, "[base_state]", src, alpha = src.alpha) - var/area/local_area = get_room_area(src) + var/area/local_area = get_room_area() if(low_power_mode || major_emergency || (local_area?.fire)) . += mutable_appearance(overlay_icon, "[base_state]_emergency") @@ -190,7 +190,7 @@ . = ..() if(!.) return - var/area/our_area = get_room_area(src) + var/area/our_area = get_room_area() RegisterSignal(our_area, COMSIG_AREA_FIRE_CHANGED, PROC_REF(handle_fire)) /obj/machinery/light/on_enter_area(datum/source, area/area_to_register) @@ -220,7 +220,7 @@ color_set = color if(reagents) START_PROCESSING(SSmachines, src) - var/area/local_area =get_room_area(src) + var/area/local_area = get_room_area() if (local_area?.fire) color_set = fire_colour brightness_set = fire_brightness @@ -262,7 +262,7 @@ static_power_used = 0 else if(on) //Light is on, just recalculate usage var/static_power_used_new = 0 - var/area/local_area = get_room_area(src) + var/area/local_area = get_room_area() if (nightshift_enabled && !local_area?.fire) static_power_used_new = nightshift_brightness * nightshift_light_power * power_consumption_rate else @@ -447,13 +447,13 @@ // returns if the light has power /but/ is manually turned off // if a light is turned off, it won't activate emergency power /obj/machinery/light/proc/turned_off() - var/area/local_area = get_room_area(src) + var/area/local_area = get_room_area() return !local_area.lightswitch && local_area.power_light || flickering // returns whether this light has power // true if area has power and lightswitch is on /obj/machinery/light/proc/has_power() - var/area/local_area =get_room_area(src) + var/area/local_area = get_room_area() return local_area.lightswitch && local_area.power_light // returns whether this light has emergency power @@ -655,7 +655,7 @@ // called when area power state changes /obj/machinery/light/power_change() SHOULD_CALL_PARENT(FALSE) - var/area/local_area =get_room_area(src) + var/area/local_area = get_room_area() set_on(local_area.lightswitch && local_area.power_light) // called when heated diff --git a/code/modules/power/turbine/turbine_parts.dm b/code/modules/power/turbine/turbine_parts.dm index d53d92190e1a5..4215fccf39fe0 100644 --- a/code/modules/power/turbine/turbine_parts.dm +++ b/code/modules/power/turbine/turbine_parts.dm @@ -64,7 +64,7 @@ if(!istype(attacking_item, second_tier_material)) return var/obj/item/stack/sheet/second_tier = attacking_item - if(second_tier.use(second_tier_material_amount) && do_after(user, 1 SECONDS, src)) + if(do_after(user, 1 SECONDS, src) && second_tier.use(second_tier_material_amount)) current_tier = 2 part_efficiency += part_efficiency_increase_amount max_rpm *= max_rpm_tier_multiplier @@ -74,7 +74,7 @@ if(!istype(attacking_item, third_tier_material)) return var/obj/item/stack/sheet/third_tier = attacking_item - if(third_tier.use(third_tier_material_amount) && do_after(user, 2 SECONDS, src)) + if(do_after(user, 2 SECONDS, src) && third_tier.use(third_tier_material_amount)) current_tier = 3 part_efficiency += part_efficiency_increase_amount max_rpm *= max_rpm_tier_multiplier @@ -84,7 +84,7 @@ if(!istype(attacking_item, fourth_tier_material)) return var/obj/item/stack/sheet/fourth_tier = attacking_item - if(fourth_tier.use(fourth_tier_material_amount) && do_after(user, 3 SECONDS, src)) + if(do_after(user, 3 SECONDS, src) && fourth_tier.use(fourth_tier_material_amount)) current_tier = 4 part_efficiency += part_efficiency_increase_amount max_rpm *= max_rpm_tier_multiplier diff --git a/code/modules/projectiles/ammunition/ballistic/rifle.dm b/code/modules/projectiles/ammunition/ballistic/rifle.dm index 3e545dc106077..8e06a0e10b5af 100644 --- a/code/modules/projectiles/ammunition/ballistic/rifle.dm +++ b/code/modules/projectiles/ammunition/ballistic/rifle.dm @@ -49,3 +49,27 @@ name = "40mm rubber shell" desc = "A cased rubber slug. The big brother of the beanbag slug, this thing will knock someone out in one. Doesn't do so great against anyone in armor." projectile_type = /obj/projectile/bullet/shotgun_beanbag/a40mm + +/obj/item/ammo_casing/rebar + name = "sharpened iron rod" + desc = "A Sharpened Iron rod. It's Pointy!" + caliber = CALIBER_REBAR + icon_state = "rod_sharp" + base_icon_state = "rod_sharp" + projectile_type = /obj/projectile/bullet/rebar + +/obj/item/ammo_casing/rebar/Initialize(mapload) + . = ..() + AddElement(/datum/element/caseless, TRUE) + +/obj/item/ammo_casing/rebar/update_icon_state() + . = ..() + icon_state = "[base_icon_state]" + +/obj/item/ammo_casing/rebar/syndie + name = "Jagged iron rod" + desc = "An Iron rod, with notches cut into it. You really dont want this stuck in you." + caliber = CALIBER_REBAR_SYNDIE + icon_state = "rod_jagged" + base_icon_state = "rod_jagged" + projectile_type = /obj/projectile/bullet/rebarsyndie diff --git a/code/modules/projectiles/boxes_magazines/internal/rifle.dm b/code/modules/projectiles/boxes_magazines/internal/rifle.dm index 83133186c9ddc..5fdc182ccff98 100644 --- a/code/modules/projectiles/boxes_magazines/internal/rifle.dm +++ b/code/modules/projectiles/boxes_magazines/internal/rifle.dm @@ -28,3 +28,24 @@ max_ammo = 1 caliber = CALIBER_HARPOON ammo_type = /obj/item/ammo_casing/harpoon + +/obj/item/ammo_box/magazine/internal/boltaction/rebarxbow/normal + name = "single round magazine" + max_ammo = 1 + caliber = CALIBER_REBAR + ammo_type = /obj/item/ammo_casing/rebar + +/obj/item/ammo_box/magazine/internal/boltaction/rebarxbow/force + name = "two round magazine" + max_ammo = 2 + caliber = CALIBER_REBAR_FORCED + ammo_type = /obj/item/ammo_casing/rebar + +/obj/item/ammo_box/magazine/internal/boltaction/rebarxbow/syndie + max_ammo = 3 + caliber = CALIBER_REBAR_SYNDIE + ammo_type = /obj/item/ammo_casing/rebar/syndie + +/obj/item/ammo_box/magazine/internal/boltaction/rebarxbow/syndie/normal + caliber = CALIBER_REBAR_SYNDIE_NORMAL + ammo_type = /obj/item/ammo_casing/rebar diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index 2b943a5f6db63..9a80b605d0ee7 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -60,9 +60,9 @@ set category = "Object" set desc = "Click to spin your revolver's chamber." - var/mob/M = usr + var/mob/user = usr - if(M.stat || !in_range(M,src)) + if(user.stat || !in_range(user, src)) return if (recent_spin > world.time) @@ -71,7 +71,8 @@ if(do_spin()) playsound(usr, SFX_REVOLVER_SPIN, 30, FALSE) - usr.visible_message(span_notice("[usr] spins [src]'s chamber."), span_notice("You spin [src]'s chamber.")) + visible_message(span_notice("[user] spins [src]'s chamber."), span_notice("You spin [src]'s chamber.")) + balloon_alert(user, "chamber spun") else verbs -= /obj/item/gun/ballistic/revolver/verb/spin @@ -212,10 +213,13 @@ /obj/item/gun/ballistic/revolver/russian/fire_gun(atom/target, mob/living/user, flag, params) . = ..(null, user, flag, params) + var/tk_controlled = FALSE if(flag) if(!(target in user.contents) && ismob(target)) if(user.combat_mode) // Flogging action return + else if (HAS_TRAIT_FROM_ONLY(src, TRAIT_TELEKINESIS_CONTROLLED, REF(user))) // if we're far away, you can still fire it at yourself if you have TK. + tk_controlled = TRUE if(isliving(user)) if(!can_trigger_gun(user)) @@ -223,8 +227,9 @@ if(target != user) playsound(src, dry_fire_sound, 30, TRUE) user.visible_message( - span_danger("[user.name] tries to fire \the [src] at the same time, but only succeeds at looking like an idiot."), \ - span_danger("\The [src]'s anti-combat mechanism prevents you from firing it at anyone but yourself!")) + span_danger("[user.name] tries to fire \the [src] at the same time, but only succeeds at looking like an idiot."), + span_danger("\The [src]'s anti-combat mechanism prevents you from firing it at anyone but yourself!"), + ) return if(ishuman(user)) @@ -246,7 +251,8 @@ antagonist = src, \ rounds_loaded = loaded_rounds, \ aimed_at = affecting.name, \ - result = (chambered ? "lost" : "won")) + result = (chambered ? "lost" : "won"), \ + ) if(chambered) if(HAS_TRAIT(user, TRAIT_CURSED)) // I cannot live, I cannot die, trapped in myself, body my holding cell. @@ -257,6 +263,9 @@ playsound(user, fire_sound, fire_sound_volume, vary_fire_sound) if(is_target_face) shoot_self(user, affecting) + else if(tk_controlled) // the consequence of you doing the telekinesis stuff + to_chat(user, span_userdanger("As your mind concentrates on the revolver, you realize that it's pointing towards your head a little too late!")) + shoot_self(user, BODY_ZONE_HEAD) else user.visible_message(span_danger("[user.name] cowardly fires [src] at [user.p_their()] [affecting.name]!"), span_userdanger("You cowardly fire [src] at your [affecting.name]!"), span_hear("You hear a gunshot!")) chambered = null diff --git a/code/modules/projectiles/guns/ballistic/rifle.dm b/code/modules/projectiles/guns/ballistic/rifle.dm index 67c70352ff306..a7a1206db1f7b 100644 --- a/code/modules/projectiles/guns/ballistic/rifle.dm +++ b/code/modules/projectiles/guns/ballistic/rifle.dm @@ -25,6 +25,7 @@ return drop_bolt(user) + /obj/item/gun/ballistic/rifle/can_shoot() if (bolt_locked) return FALSE @@ -169,6 +170,91 @@ if(.) name = "\improper Obrez Moderna" // wear it loud and proud +/obj/item/gun/ballistic/rifle/rebarxbow + name = "Heated Rebar Crossbow" + desc = "Made from an inducer, iron rods, and some wire, this crossbow fires sharpened iron rods, made from the plentiful iron rods found stationwide. \ + Only holds one rod in the magazine - you can craft the crossbow with a crowbar to try and force a second rod in, but risks a misfire, or worse..." + icon = 'icons/obj/weapons/guns/ballistic.dmi' + icon_state = "rebarxbow" + inhand_icon_state = "rebarxbow" + worn_icon_state = "rebarxbow" + rack_sound = 'sound/weapons/gun/sniper/rack.ogg' + must_hold_to_load = TRUE + mag_display = FALSE + empty_indicator = TRUE + bolt_type = BOLT_TYPE_LOCKING + semi_auto = FALSE + internal_magazine = TRUE + can_modify_ammo = FALSE + slot_flags = ITEM_SLOT_BACK|ITEM_SLOT_SUITSTORE + bolt_wording = "bowstring" + magazine_wording = "rod" + cartridge_wording = "rod" + misfire_probability = 25 + weapon_weight = WEAPON_HEAVY + initial_caliber = CALIBER_REBAR + accepted_magazine_type = /obj/item/ammo_box/magazine/internal/boltaction/rebarxbow/normal + fire_sound = 'sound/items/syringeproj.ogg' + can_be_sawn_off = FALSE + tac_reloads = FALSE + var/draw_time = 3 SECONDS + SET_BASE_PIXEL(0, 0) + +/obj/item/gun/ballistic/rifle/rebarxbow/rack(mob/user = null) + if (bolt_locked) + drop_bolt(user) + return + balloon_alert(user, "bowstring loosened") + playsound(src, rack_sound, rack_sound_volume, rack_sound_vary) + handle_chamber(empty_chamber = FALSE, from_firing = FALSE, chamber_next_round = FALSE) + bolt_locked = TRUE + update_appearance() + +/obj/item/gun/ballistic/rifle/rebarxbow/drop_bolt(mob/user = null) + if(!do_after(user, draw_time, target = src)) + return + playsound(src, bolt_drop_sound, bolt_drop_sound_volume, FALSE) + balloon_alert(user, "bowstring drawn") + chamber_round() + bolt_locked = FALSE + update_appearance() + +/obj/item/gun/ballistic/rifle/rebarxbow/can_shoot() + if (bolt_locked) + return FALSE + return ..() + +/obj/item/gun/ballistic/rifle/rebarxbow/examine(mob/user) + . = ..() + . += "The crossbow is [bolt_locked ? "not ready" : "ready"] to fire." + +/obj/item/gun/ballistic/rifle/rebarxbow/forced + name = "Stressed Rebar Crossbow" + desc = "Some idiot decided that they would risk shooting themselves in the face if it meant they could have a bit more ammo in this crossbow. Hopefully, it was worth it." + // Feel free to add a recipe to allow you to change it back if you would like, I just wasn't sure if you could have two recipes for the same thing. + can_misfire = TRUE + misfire_probability = 25 + accepted_magazine_type = /obj/item/ammo_box/magazine/internal/boltaction/rebarxbow/force + +/obj/item/gun/ballistic/rifle/rebarxbow/syndie + name = "Syndicate Rebar Crossbow" + desc = "The syndicate liked the bootleg rebar crossbow NT engineers made, so they showed what it could be if properly developed. \ + Holds three shots without a chance of exploding, and features a built in scope. Normally uses special syndicate jagged iron bars, but can be wrenched to shoot inferior normal ones." + icon_state = "rebarxbowsyndie" + inhand_icon_state = "rebarxbowsyndie" + worn_icon_state = "rebarxbowsyndie" + w_class = WEIGHT_CLASS_NORMAL + can_modify_ammo = TRUE + initial_caliber = CALIBER_REBAR_SYNDIE + alternative_caliber = CALIBER_REBAR_SYNDIE_NORMAL + alternative_ammo_misfires = FALSE + draw_time = 1 + accepted_magazine_type = /obj/item/ammo_box/magazine/internal/boltaction/rebarxbow/syndie + +/obj/item/gun/ballistic/rifle/rebarxbow/syndie/Initialize(mapload) + . = ..() + AddComponent(/datum/component/scope, range_modifier = 2) //enough range to at least be useful for stealth + /obj/item/gun/ballistic/rifle/boltaction/pipegun name = "pipegun" desc = "An excellent weapon for flushing out tunnel rats and enemy assistants, but its rifling leaves much to be desired." diff --git a/code/modules/projectiles/guns/special/hand_of_midas.dm b/code/modules/projectiles/guns/special/hand_of_midas.dm index 69d3430cf9e73..d515c252bafb0 100644 --- a/code/modules/projectiles/guns/special/hand_of_midas.dm +++ b/code/modules/projectiles/guns/special/hand_of_midas.dm @@ -45,7 +45,9 @@ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN if(!victim.reagents) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(!victim.reagents.has_reagent(/datum/reagent/gold, check_subtypes = TRUE)) + + var/gold_amount = victim.reagents.get_reagent_amount(/datum/reagent/gold, include_subtypes = TRUE) + if(!gold_amount) balloon_alert(user, "no gold in bloodstream") return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN var/gold_beam = user.Beam(victim, icon_state="drain_gold") @@ -53,8 +55,8 @@ qdel(gold_beam) balloon_alert(user, "link broken") return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - handle_gold_charges(user, victim.reagents.get_reagent_amount(/datum/reagent/gold, include_subtypes = TRUE)) - victim.reagents.remove_all_type(/datum/reagent/gold, victim.reagents.get_reagent_amount(/datum/reagent/gold, include_subtypes = TRUE)) + handle_gold_charges(user, gold_amount) + victim.reagents.remove_reagent(/datum/reagent/gold, gold_amount, include_subtypes = TRUE) victim.remove_status_effect(/datum/status_effect/midas_blight) qdel(gold_beam) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN diff --git a/code/modules/projectiles/pins.dm b/code/modules/projectiles/pins.dm index 45763feff043b..5437a7096da5b 100644 --- a/code/modules/projectiles/pins.dm +++ b/code/modules/projectiles/pins.dm @@ -30,19 +30,19 @@ if(proximity_flag) if(isgun(target)) . |= AFTERATTACK_PROCESSED_ITEM - var/obj/item/gun/targetted_gun = target - var/obj/item/firing_pin/old_pin = targetted_gun.pin + var/obj/item/gun/targeted_gun = target + var/obj/item/firing_pin/old_pin = targeted_gun.pin if(old_pin?.pin_removable && (force_replace || old_pin.pin_hot_swappable)) if(Adjacent(user)) user.put_in_hands(old_pin) else - old_pin.forceMove(targetted_gun.drop_location()) + old_pin.forceMove(targeted_gun.drop_location()) old_pin.gun_remove(user) - if(!targetted_gun.pin) + if(!targeted_gun.pin) if(!user.temporarilyRemoveItemFromInventory(src)) return . - if(gun_insert(user, targetted_gun)) + if(gun_insert(user, targeted_gun)) if(old_pin) balloon_alert(user, "swapped firing pin") else diff --git a/code/modules/projectiles/projectile/bullets/rifle.dm b/code/modules/projectiles/projectile/bullets/rifle.dm index 4cb7bd543b481..de7e59facc3cf 100644 --- a/code/modules/projectiles/projectile/bullets/rifle.dm +++ b/code/modules/projectiles/projectile/bullets/rifle.dm @@ -47,3 +47,32 @@ embedding = list(embed_chance=100, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10) wound_falloff_tile = -5 shrapnel_type = /obj/item/ammo_casing/harpoon + +// Rebar (Rebar Crossbow) +/obj/projectile/bullet/rebar + name = "rebar" + icon_state = "rebar" + damage = 30 + speed = 0.4 + dismemberment = 1 //because a 1 in 100 chance to just blow someones arm off is enough to be cool but also not enough to be reliable + armour_penetration = 10 + wound_bonus = -20 + bare_wound_bonus = 20 + embedding = list(embed_chance=60, fall_chance=2, jostle_chance=2, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=3, jostle_pain_mult=2, rip_time=10) + embed_falloff_tile = -5 + wound_falloff_tile = -2 + shrapnel_type = /obj/item/stack/rods + +/obj/projectile/bullet/rebarsyndie + name = "rebar" + icon_state = "rebar" + damage = 35 + speed = 0.4 + dismemberment = 2 //It's a budget sniper rifle. + armour_penetration = 20 //A bit better versus armor. Gets past anti laser armor or a vest, but doesnt wound proc on sec armor. + wound_bonus = 10 + bare_wound_bonus = 10 + embedding = list(embed_chance=80, fall_chance=1, jostle_chance=3, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=3, jostle_pain_mult=2, rip_time=14) + embed_falloff_tile = -3 + shrapnel_type = /obj/item/stack/rods + diff --git a/code/modules/reagents/chem_splash.dm b/code/modules/reagents/chem_splash.dm index 50d5ed37b474a..ebc02c308964d 100644 --- a/code/modules/reagents/chem_splash.dm +++ b/code/modules/reagents/chem_splash.dm @@ -50,7 +50,7 @@ holder.multiply_reagents(threatscale) for(var/datum/reagents/reactant as anything in reactants) - reactant.trans_to(holder, reactant.total_volume, threatscale, preserve_data = TRUE, no_react = TRUE) + reactant.trans_to(holder, reactant.total_volume, threatscale, no_react = TRUE) holder.chem_temp += extra_heat // Average temperature of reagents + extra heat. holder.handle_reactions() // React them now. diff --git a/code/modules/reagents/chemistry/equilibrium.dm b/code/modules/reagents/chemistry/equilibrium.dm index 073eaf69e5ae1..bcca8eb67da4a 100644 --- a/code/modules/reagents/chemistry/equilibrium.dm +++ b/code/modules/reagents/chemistry/equilibrium.dm @@ -332,7 +332,7 @@ //Calculate how much product to make and how much reactant to remove factors.. for(var/reagent in reaction.required_reagents) - holder.remove_reagent(reagent, (delta_chem_factor * reaction.required_reagents[reagent]), safety = TRUE) + holder.remove_reagent(reagent, (delta_chem_factor * reaction.required_reagents[reagent])) //Apply pH changes var/pH_adjust if(reaction.reaction_flags & REACTION_PH_VOL_CONSTANT) @@ -414,4 +414,4 @@ ///Panic stop a reaction - cleanup should be handled by the next timestep /datum/equilibrium/proc/force_clear_reactive_agents() for(var/reagent in reaction.required_reagents) - holder.remove_reagent(reagent, (multiplier * reaction.required_reagents[reagent]), safety = 1) + holder.remove_reagent(reagent, (multiplier * reaction.required_reagents[reagent])) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 41611b19b715f..fe70822348c10 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -106,7 +106,7 @@ var/has_split = FALSE if(!ignore_splitting && (flags & REAGENT_HOLDER_ALIVE)) //Stomachs are a pain - they will constantly call on_mob_add unless we split on addition to stomachs, but we also want to make sure we don't double split var/adjusted_vol = process_mob_reagent_purity(glob_reagent, amount, added_purity) - if(adjusted_vol <= CHEMICAL_QUANTISATION_LEVEL) //If we're inverse or FALSE cancel addition + if(!adjusted_vol) //If we're inverse or FALSE cancel addition return amount /* We return true here because of #63301 The only cases where this will be false or 0 if its an inverse chem, an impure chem of 0 purity (highly unlikely if even possible), or if glob_reagent is null (which shouldn't happen at all as there's a check for that a few lines up), @@ -120,6 +120,8 @@ if(cached_total + amount > maximum_volume) amount = maximum_volume - cached_total //Doesnt fit in. Make it disappear. shouldn't happen. Will happen. amount = round(amount, CHEMICAL_QUANTISATION_LEVEL) + if(amount <= 0) + return FALSE var/cached_temp = chem_temp var/list/cached_reagents = reagent_list @@ -203,8 +205,9 @@ * * [reagent_type][datum/reagent] - the type of reagent * * amount - the volume to remove * * safety - if FALSE will initiate reactions upon removing. used for trans_id_to + * * include_subtypes - if TRUE will remove the specified amount from all subtypes of reagent_type as well */ -/datum/reagents/proc/remove_reagent(datum/reagent/reagent_type, amount, safety = TRUE) +/datum/reagents/proc/remove_reagent(datum/reagent/reagent_type, amount, safety = TRUE, include_subtypes = FALSE) if(!ispath(reagent_type)) stack_trace("invalid reagent passed to remove reagent [reagent_type]") return FALSE @@ -217,23 +220,37 @@ if(amount <= 0) return FALSE + var/total_removed_amount = 0 + var/remove_amount = 0 var/list/cached_reagents = reagent_list for(var/datum/reagent/cached_reagent as anything in cached_reagents) - if(cached_reagent.type == reagent_type) - cached_reagent.volume -= amount + //check for specific type or subtypes + if(!include_subtypes) + if(cached_reagent.type != reagent_type) + continue + else if(!istype(cached_reagent, reagent_type)) + continue - update_total() - if(!safety)//So it does not handle reactions when it need not to - handle_reactions() + remove_amount = min(cached_reagent.volume, amount) + cached_reagent.volume -= remove_amount - SEND_SIGNAL(src, COMSIG_REAGENTS_REM_REAGENT, QDELING(cached_reagent) ? reagent_type : cached_reagent, amount) + update_total() + if(!safety)//So it does not handle reactions when it need not to + handle_reactions() + SEND_SIGNAL(src, COMSIG_REAGENTS_REM_REAGENT, QDELING(cached_reagent) ? reagent_type : cached_reagent, amount) - return TRUE + total_removed_amount += remove_amount - return FALSE + //if we reached here means we have found our specific reagent type so break + if(!include_subtypes) + break + + return total_removed_amount /** - * Removes a reagent at random by the specified amount + * Removes a reagent at random and by a random quantity till the specified amount has been removed. + * Used to create a shower/spray effect for e.g. when you spill a bottle or turn a shower on + * and you want an chaotic effect of whatever coming out * Arguments * * * amount- the volume to remove @@ -296,56 +313,13 @@ var/list/cached_reagents = reagent_list var/part = amount / total_volume - var/remove_amount - var/removed_amount = 0 + var/total_removed_amount = 0 for(var/datum/reagent/reagent as anything in cached_reagents) - remove_amount = reagent.volume * part - remove_reagent(reagent.type, remove_amount) - removed_amount += remove_amount + total_removed_amount += remove_reagent(reagent.type, reagent.volume * part) handle_reactions() - return round(removed_amount, CHEMICAL_VOLUME_ROUNDING) - -/** - * Removes all reagent of X type - * Arguments - * - * * [reagent_type][datum/reagent] - the reagent typepath we are trying to remove - * * amount - the volume of reagent to remove - * * strict - If TRUE will also remove childs of this reagent type - */ -/datum/reagents/proc/remove_all_type(datum/reagent/reagent_type, amount, strict = 0, safety = 1) - if(!ispath(reagent_type)) - stack_trace("invalid reagent path passed to remove all type [reagent_type]") - return FALSE - - if(!IS_FINITE(amount)) - stack_trace("non finite amount passed to remove all type reagent [amount] [reagent_type]") - return FALSE - - amount = round(amount, CHEMICAL_QUANTISATION_LEVEL) - if(amount <= 0) - return FALSE - - var/list/cached_reagents = reagent_list - var/has_removed_reagent = 0 - - for(var/datum/reagent/reagent as anything in cached_reagents) - var/matches = 0 - // Switch between how we check the reagent type - if(strict) - if(reagent.type == reagent_type) - matches = 1 - else - if(istype(reagent, reagent_type)) - matches = 1 - // We found a match, proceed to remove the reagent. Keep looping, we might find other reagents of the same type. - if(matches) - // Have our other proc handle removement - has_removed_reagent = remove_reagent(reagent.type, amount, safety) - - return has_removed_reagent + return round(total_removed_amount, CHEMICAL_VOLUME_ROUNDING) /** * Removes an specific reagent from this holder @@ -485,6 +459,7 @@ * * obj/target - Target to attempt transfer to * * amount - amount of reagent volume to transfer * * multiplier - multiplies each reagent amount by this number well byond their available volume before transfering. used to create reagents from thin air if you ever need to + * * datum/reagent/target_id - transfer only this reagent in this holder leaving others untouched * * preserve_data - if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. * * no_react - passed through to [/datum/reagents/proc/add_reagent] * * mob/transferred_by - used for logging @@ -497,6 +472,7 @@ obj/target, amount = 1, multiplier = 1, + datum/reagent/target_id, preserve_data = TRUE, no_react = FALSE, mob/transferred_by, @@ -506,12 +482,16 @@ ignore_stomach = FALSE ) if(QDELETED(target) || !total_volume) - return + return FALSE if(!IS_FINITE(amount)) stack_trace("non finite amount passed to trans_to [amount] amount of reagents") return FALSE + if(!isnull(target_id) && !ispath(target_id)) + stack_trace("invalid target reagent id [target_id] passed to trans_to") + return FALSE + var/list/cached_reagents = reagent_list var/atom/target_atom @@ -539,8 +519,8 @@ var/cached_amount = amount // Prevents small amount problems, as well as zero and below zero amounts. - amount = FLOOR(min(amount, total_volume, target_holder.maximum_volume - target_holder.total_volume), CHEMICAL_QUANTISATION_LEVEL) - if(amount <= CHEMICAL_QUANTISATION_LEVEL) + amount = round(min(amount, total_volume, target_holder.maximum_volume - target_holder.total_volume), CHEMICAL_QUANTISATION_LEVEL) + if(amount <= 0) return //Set up new reagents to inherit the old ongoing reactions @@ -552,7 +532,7 @@ var/list/r_to_send = list() // Validated list of reagents to be exposed var/list/reagents_to_remove = list() - var/part = amount / total_volume + var/part = isnull(target_id) ? (amount / total_volume) : 1 var/transfer_amount var/transfered_amount var/total_transfered_amount = 0 @@ -561,11 +541,20 @@ for(var/datum/reagent/reagent as anything in cached_reagents) if(remove_blacklisted && !(reagent.chemical_flags & REAGENT_CAN_BE_SYNTHESIZED)) continue + + if(!isnull(target_id)) + if(reagent.type == target_id) + force_stop_reagent_reacting(reagent) + transfer_amount = min(amount, reagent.volume) + else + continue + else + transfer_amount = reagent.volume * part + if(preserve_data) trans_data = copy_data(reagent) if(reagent.intercept_reagents_transfer(target_holder, cached_amount)) continue - transfer_amount = reagent.volume * part transfered_amount = target_holder.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT) //we only handle reaction after every reagent has been transferred. if(!transfered_amount) continue @@ -574,6 +563,9 @@ reagents_to_remove += list(list("R" = reagent, "T" = transfer_amount)) total_transfered_amount += transfered_amount + if(!isnull(target_id)) + break + //expose target to reagent changes target_holder.expose_multiple(r_to_send, isorgan(target_atom) ? target : target_atom, methods, part, show_message) @@ -598,64 +590,6 @@ return round(total_transfered_amount, CHEMICAL_VOLUME_ROUNDING) -/** - * Transfer a specific reagent id to the target object - * Arguments - * - * * [target][obj] - the target to transfer reagents to - * * [reagent_type][datum/reagent] - the type of reagent to transfer to the target - * * amount - volume to transfer - * * preserve_data- if TRUE reagent user data will remain preserved - */ -/datum/reagents/proc/trans_id_to( - obj/target, - datum/reagent/reagent_type, - amount = 1, - preserve_data = 1 -) - if (QDELETED(target) || !total_volume) - return - - if(!IS_FINITE(amount)) - stack_trace("non finite amount passed to trans_id_to [amount] [reagent_type]") - return FALSE - - var/cached_amount = amount - - var/available_volume = get_reagent_amount(reagent_type) - var/datum/reagents/holder - if(istype(target, /datum/reagents)) - holder = target - else if(target.reagents && available_volume) - holder = target.reagents - else - return - - // Prevents small amount problems, as well as zero and below zero amounts. - amount = FLOOR(min(amount, available_volume, holder.maximum_volume - holder.total_volume), CHEMICAL_QUANTISATION_LEVEL) - if(amount <= CHEMICAL_QUANTISATION_LEVEL) - return - - var/list/cached_reagents = reagent_list - - var/trans_data = null - for (var/looping_through_reagents in cached_reagents) - var/datum/reagent/current_reagent = looping_through_reagents - if(current_reagent.type == reagent_type) - if(preserve_data) - trans_data = current_reagent.data - if(current_reagent.intercept_reagents_transfer(holder, cached_amount))//Use input amount instead. - break - force_stop_reagent_reacting(current_reagent) - holder.add_reagent(current_reagent.type, amount, trans_data, chem_temp, current_reagent.purity, current_reagent.ph, no_react = TRUE, ignore_splitting = current_reagent.chemical_flags & REAGENT_DONOTSPLIT) - remove_reagent(current_reagent.type, amount, 1) - break - - update_total() - holder.update_total() - holder.handle_reactions() - return amount - /** * Copies the reagents to the target object * Arguments @@ -688,8 +622,8 @@ target_holder = target.reagents // Prevents small amount problems, as well as zero and below zero amounts. - amount = FLOOR(min(amount, total_volume, target_holder.maximum_volume - target_holder.total_volume), CHEMICAL_QUANTISATION_LEVEL) - if(amount <= CHEMICAL_QUANTISATION_LEVEL) + amount = round(min(amount, total_volume, target_holder.maximum_volume - target_holder.total_volume), CHEMICAL_QUANTISATION_LEVEL) + if(amount <= 0) return var/list/cached_reagents = reagent_list @@ -702,7 +636,7 @@ for(var/datum/reagent/reagent as anything in cached_reagents) transfer_amount = reagent.volume * part * multiplier if(preserve_data) - trans_data = reagent.data + trans_data = copy_data(reagent) transfered_amount = target_holder.add_reagent(reagent.type, transfer_amount, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT) if(!transfered_amount) continue @@ -737,30 +671,6 @@ handle_reactions() -/// Get the name of the reagent there is the most of in this holder -/datum/reagents/proc/get_master_reagent_name() - var/list/cached_reagents = reagent_list - var/name - var/max_volume = 0 - for(var/datum/reagent/reagent as anything in cached_reagents) - if(reagent.volume > max_volume) - max_volume = reagent.volume - name = reagent.name - - return name - -/// Get the id of the reagent there is the most of in this holder -/datum/reagents/proc/get_master_reagent_id() - var/list/cached_reagents = reagent_list - var/max_type - var/max_volume = 0 - for(var/datum/reagent/reagent as anything in cached_reagents) - if(reagent.volume > max_volume) - max_volume = reagent.volume - max_type = reagent.type - - return max_type - /// Get a reference to the reagent there is the most of in this holder /datum/reagents/proc/get_master_reagent() var/list/cached_reagents = reagent_list @@ -1246,7 +1156,7 @@ if (!reagent) continue sum_purity += reagent.purity - remove_reagent(_reagent, (multiplier * cached_required_reagents[_reagent]), safety = 1) + remove_reagent(_reagent, (multiplier * cached_required_reagents[_reagent])) sum_purity /= cached_required_reagents.len for(var/product in selected_reaction.results) @@ -1314,7 +1224,7 @@ . += reagent_volume total_ph += (reagent.ph * reagent_volume) - //reasign floored value + //reasign rounded value reagent.volume = reagent_volume //assign the final values, rounding up can sometimes cause overflow so bring it down diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 44c2b72121c9b..6219e7de83b1d 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -1,16 +1,3 @@ -/proc/translate_legacy_chem_id(id) - switch (id) - if ("sacid") - return "sulfuricacid" - if ("facid") - return "fluorosulfuricacid" - if ("co2") - return "carbondioxide" - if ("mine_salve") - return "minerssalve" - else - return ckey(id) - /obj/machinery/chem_dispenser name = "chem dispenser" desc = "Creates and dispenses chemicals." @@ -23,21 +10,45 @@ circuit = /obj/item/circuitboard/machine/chem_dispenser processing_flags = NONE + /// The cell used to dispense reagents var/obj/item/stock_parts/cell/cell + /// Efficiency used when converting cell power to reagents var/powerefficiency = 0.1 + /// The current amount this machine is dispensing var/amount = 30 + /// The rate at which this machine recharges the power cell var/recharge_amount = 10 + /// Keep track of the intervals made during recharges var/recharge_counter = 0 + /// The temperature reagents are dispensed into the beaker var/dispensed_temperature = DEFAULT_REAGENT_TEMPERATURE - ///If the UI has the pH meter shown + /// If the UI has the pH meter shown var/show_ph = TRUE + /// The overlay used to display the beaker on the machine var/mutable_appearance/beaker_overlay + /// Icon to display when the machine is powered var/working_state = "dispenser_working" + /// Icon to display when the machine is not powered var/nopower_state = "dispenser_nopower" + /// Should we display the open panel overlay when the panel is opened with a screwdriver var/has_panel_overlay = TRUE + /// The actual beaker inserted into this machine var/obj/item/reagent_containers/beaker = null - //dispensable_reagents is copypasted in plumbing synthesizers. Please update accordingly. (I didn't make it global because that would limit custom chem dispensers) - var/list/dispensable_reagents = list( + /// Dispensable_reagents is copypasted in plumbing synthesizers. Please update accordingly. (I didn't make it global because that would limit custom chem dispensers) + var/list/dispensable_reagents = list() + /// These become available once the manipulator has been upgraded to tier 4 (femto) + var/list/upgrade_reagents = list() + /// These become available once the machine has been emaged + var/list/emagged_reagents = list() + /// Starting purity of the created reagents + var/base_reagent_purity = 1 + /// Records the reagents dispensed by the user if this list is not null + var/list/recording_recipe + /// Saves all the recipes recorded by the machine + var/list/saved_recipes = list() + + /// The default list of dispensable_reagents + var/static/list/default_dispensable_reagents = list( /datum/reagent/aluminium, /datum/reagent/bromine, /datum/reagent/carbon, @@ -64,8 +75,8 @@ /datum/reagent/water, /datum/reagent/fuel ) - //these become available once the manipulator has been upgraded to tier 4 (femto) - var/list/upgrade_reagents = list( + /// The default list of reagents upgrade_reagents + var/static/list/default_upgrade_reagents = list( /datum/reagent/acetone, /datum/reagent/ammonia, /datum/reagent/ash, @@ -73,34 +84,38 @@ /datum/reagent/fuel/oil, /datum/reagent/saltpetre ) - var/list/emagged_reagents = list( + /// The default list of reagents emagged_reagents + var/static/list/default_emagged_reagents = list( /datum/reagent/toxin/carpotoxin, /datum/reagent/medicine/mine_salve, /datum/reagent/medicine/morphine, /datum/reagent/drug/space_drugs, /datum/reagent/toxin ) - /// Starting purity of the created reagents - var/base_reagent_purity = 1 - - var/list/recording_recipe - - var/list/saved_recipes = list() - /obj/machinery/chem_dispenser/Initialize(mapload) . = ..() - dispensable_reagents = sort_list(dispensable_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) - if(emagged_reagents) - emagged_reagents = sort_list(emagged_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) + if(dispensable_reagents != null && !dispensable_reagents.len) + dispensable_reagents = default_dispensable_reagents + if(dispensable_reagents) + dispensable_reagents = sort_list(dispensable_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) + + if(upgrade_reagents != null && !upgrade_reagents.len) + upgrade_reagents = default_upgrade_reagents if(upgrade_reagents) upgrade_reagents = sort_list(upgrade_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) + + if(emagged_reagents != null && !emagged_reagents.len) + emagged_reagents = default_emagged_reagents + if(emagged_reagents) + emagged_reagents = sort_list(emagged_reagents, GLOBAL_PROC_REF(cmp_reagents_asc)) + if(is_operational) begin_processing() update_appearance() /obj/machinery/chem_dispenser/Destroy() + cell = null QDEL_NULL(beaker) - QDEL_NULL(cell) return ..() /obj/machinery/chem_dispenser/examine(mob/user) @@ -110,17 +125,15 @@ if(in_range(user, src) || isobserver(user)) . += "The status display reads:\n\ Recharging [recharge_amount] power units per interval.\n\ - Power efficiency increased by [round((powerefficiency*1000)-100, 1)]%." + Power efficiency increased by [round((powerefficiency * 1000) -100, 1)]%.
" . += span_notice("Use RMB to eject a stored beaker.") - /obj/machinery/chem_dispenser/on_set_is_operational(old_value) if(old_value) //Turned off end_processing() else //Turned on begin_processing() - /obj/machinery/chem_dispenser/process(seconds_per_tick) if (recharge_counter >= 8) var/usedpower = cell.give(recharge_amount) @@ -153,7 +166,6 @@ beaker_overlay = display_beaker() . += beaker_overlay - /obj/machinery/chem_dispenser/emag_act(mob/user, obj/item/card/emag/emag_card) if(obj_flags & EMAGGED) balloon_alert(user, "already emagged!") @@ -164,12 +176,10 @@ return TRUE /obj/machinery/chem_dispenser/ex_act(severity, target) - if(severity <= EXPLODE_LIGHT) - return FALSE - return ..() + return severity <= EXPLODE_LIGHT ? FALSE : ..() /obj/machinery/chem_dispenser/contents_explosion(severity, target) - ..() + . = ..() if(!beaker) return @@ -191,45 +201,25 @@ ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "ChemDispenser", name) + ui.open() - var/is_hallucinating = FALSE - if(isliving(user)) - var/mob/living/living_user = user - is_hallucinating = !!living_user.has_status_effect(/datum/status_effect/hallucination) - - if(is_hallucinating) - ui.set_autoupdate(FALSE) //to not ruin the immersion by constantly changing the fake chemicals + var/is_hallucinating = FALSE + if(isliving(user)) + var/mob/living/living_user = user + is_hallucinating = !!living_user.has_status_effect(/datum/status_effect/hallucination) + ui.set_autoupdate(!is_hallucinating) //to not ruin the immersion by constantly changing the fake chemicals - ui.open() +/obj/machinery/chem_dispenser/ui_static_data(mob/user) + . = ..() + .["showpH"] = show_ph /obj/machinery/chem_dispenser/ui_data(mob/user) - var/data = list() - data["amount"] = amount - data["energy"] = cell.charge ? cell.charge * powerefficiency : "0" //To prevent NaN in the UI. - data["maxEnergy"] = cell.maxcharge * powerefficiency - data["isBeakerLoaded"] = beaker ? 1 : 0 - data["showpH"] = show_ph - - var/beakerContents[0] - var/beakerCurrentVolume = 0 - if(beaker && beaker.reagents && beaker.reagents.reagent_list.len) - for(var/datum/reagent/R in beaker.reagents.reagent_list) - beakerContents.Add(list(list("name" = R.name, "volume" = round(R.volume, 0.01), "pH" = R.ph, "purity" = R.purity))) // list in a list because Byond merges the first list... - beakerCurrentVolume += R.volume - data["beakerContents"] = beakerContents - - if (beaker) - data["beakerCurrentVolume"] = round(beakerCurrentVolume, 0.01) - data["beakerMaxVolume"] = beaker.volume - data["beakerTransferAmounts"] = beaker.possible_transfer_amounts - data["beakerCurrentpH"] = round(beaker.reagents.ph, 0.01) - else - data["beakerCurrentVolume"] = null - data["beakerMaxVolume"] = null - data["beakerTransferAmounts"] = null - data["beakerCurrentpH"] = null + . = list() + .["amount"] = amount + .["energy"] = cell.charge ? cell.charge * powerefficiency : 0 //To prevent NaN in the UI. + .["maxEnergy"] = cell.maxcharge * powerefficiency - var/chemicals[0] + var/list/chemicals = list() var/is_hallucinating = FALSE if(isliving(user)) var/mob/living/living_user = user @@ -241,23 +231,37 @@ var/chemname = temp.name if(is_hallucinating && prob(5)) chemname = "[pick_list_replacements("hallucination.json", "chemicals")]" - chemicals.Add(list(list("title" = chemname, "id" = ckey(temp.name), "pH" = temp.ph, "pHCol" = convert_ph_to_readable_color(temp.ph)))) - data["chemicals"] = chemicals - data["recipes"] = saved_recipes + chemicals += list(list("title" = chemname, "id" = temp.name, "pH" = temp.ph, "pHCol" = convert_ph_to_readable_color(temp.ph))) + .["chemicals"] = chemicals + .["recipes"] = saved_recipes - data["recordingRecipe"] = recording_recipe - data["recipeReagents"] = list() + .["recordingRecipe"] = recording_recipe + .["recipeReagents"] = list() if(beaker?.reagents.ui_reaction_id) var/datum/chemical_reaction/reaction = get_chemical_reaction(beaker.reagents.ui_reaction_id) for(var/_reagent in reaction.required_reagents) var/datum/reagent/reagent = find_reagent_object_from_type(_reagent) - data["recipeReagents"] += ckey(reagent.name) - return data - -/obj/machinery/chem_dispenser/ui_act(action, params) + .["recipeReagents"] += reagent.name + + var/list/beaker_data = null + if(!QDELETED(beaker)) + beaker_data = list() + beaker_data["maxVolume"] = beaker.volume + beaker_data["transferAmounts"] = beaker.possible_transfer_amounts + beaker_data["pH"] = round(beaker.reagents.ph, 0.01) + beaker_data["currentVolume"] = round(beaker.reagents.total_volume, 0.01) + var/list/beakerContents = list() + if(beaker && beaker.reagents && beaker.reagents.reagent_list.len) + for(var/datum/reagent/reagent in beaker.reagents.reagent_list) + beakerContents += list(list("name" = reagent.name, "volume" = round(reagent.volume, 0.01))) // list in a list because Byond merges the first list... + beaker_data["contents"] = beakerContents + .["beaker"] = beaker_data + +/obj/machinery/chem_dispenser/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) return + switch(action) if("amount") if(!is_operational || QDELETED(beaker)) @@ -266,7 +270,8 @@ if(target in beaker.possible_transfer_amounts) amount = target work_animation() - . = TRUE + return TRUE + if("dispense") if(!is_operational || QDELETED(cell)) return @@ -277,7 +282,7 @@ var/datum/reagents/holder = beaker.reagents var/to_dispense = max(0, min(amount, holder.maximum_volume - holder.total_volume)) - if(!cell?.use(to_dispense / powerefficiency)) + if(!cell.use(to_dispense / powerefficiency)) say("Not enough energy to complete operation!") return holder.add_reagent(reagent, to_dispense, reagtemp = dispensed_temperature, added_purity = base_reagent_purity) @@ -285,7 +290,8 @@ work_animation() else recording_recipe[reagent_name] += amount - . = TRUE + return TRUE + if("remove") if(!is_operational || recording_recipe) return @@ -293,10 +299,12 @@ if(beaker && (amount in beaker.possible_transfer_amounts)) beaker.reagents.remove_all(amount) work_animation() - . = TRUE + return TRUE + if("eject") - replace_beaker(usr) - . = TRUE + replace_beaker(ui.user) + return TRUE + if("dispense_recipe") if(!is_operational || QDELETED(cell)) return @@ -305,7 +313,7 @@ if(!LAZYLEN(chemicals_to_dispense)) return for(var/key in chemicals_to_dispense) - var/reagent = GLOB.name2reagent[translate_legacy_chem_id(key)] + var/reagent = GLOB.name2reagent[key] var/dispense_amount = chemicals_to_dispense[key] if(!dispensable_reagents.Find(reagent)) return @@ -317,65 +325,71 @@ var/to_dispense = max(0, min(dispense_amount, holder.maximum_volume - holder.total_volume)) if(!to_dispense) continue - if(!cell?.use(to_dispense / powerefficiency)) + if(!cell.use(to_dispense / powerefficiency)) say("Not enough energy to complete operation!") return holder.add_reagent(reagent, to_dispense, reagtemp = dispensed_temperature, added_purity = base_reagent_purity) work_animation() else recording_recipe[key] += dispense_amount - . = TRUE + return TRUE + if("clear_recipes") - if(!is_operational) - return - var/yesno = tgui_alert(usr, "Clear all recipes?",, list("Yes","No")) - if(yesno == "Yes") + if(is_operational && tgui_alert(ui.user, "Clear all recipes?", "Clear?", list("Yes", "No")) == "Yes") saved_recipes = list() - . = TRUE + return TRUE + if("record_recipe") - if(!is_operational) - return - recording_recipe = list() - . = TRUE + if(is_operational) + recording_recipe = list() + return TRUE + if("save_recording") if(!is_operational) return - var/name = tgui_input_text(usr, "What do you want to name this recipe?", "Recipe Name", MAX_NAME_LEN) - if(!usr.can_perform_action(src, ALLOW_SILICON_REACH)) + var/name = tgui_input_text(ui.user, "What do you want to name this recipe?", "Recipe Name", MAX_NAME_LEN) + if(!ui.user.can_perform_action(src, ALLOW_SILICON_REACH)) return - if(saved_recipes[name] && tgui_alert(usr, "\"[name]\" already exists, do you want to overwrite it?",, list("Yes", "No")) == "No") + if(saved_recipes[name] && tgui_alert(ui.user, "\"[name]\" already exists, do you want to overwrite it?",, list("Yes", "No")) == "No") return if(name && recording_recipe) for(var/reagent in recording_recipe) - var/reagent_id = GLOB.name2reagent[translate_legacy_chem_id(reagent)] + var/reagent_id = GLOB.name2reagent[reagent] if(!dispensable_reagents.Find(reagent_id)) visible_message(span_warning("[src] buzzes."), span_hear("You hear a faint buzz.")) - to_chat(usr, span_warning("[src] cannot find [reagent]!")) + to_chat(ui.user, span_warning("[src] cannot find [reagent]!")) playsound(src, 'sound/machines/buzz-two.ogg', 50, TRUE) return saved_recipes[name] = recording_recipe recording_recipe = null - . = TRUE + return TRUE + if("cancel_recording") - if(!is_operational) - return - recording_recipe = null - . = TRUE + if(is_operational) + recording_recipe = null + return TRUE + if("reaction_lookup") if(beaker) - beaker.reagents.ui_interact(usr) + beaker.reagents.ui_interact(ui.user) /obj/machinery/chem_dispenser/wrench_act(mob/living/user, obj/item/tool) . = ..() - default_unfasten_wrench(user, tool) - return TOOL_ACT_TOOLTYPE_SUCCESS + if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) + return TOOL_ACT_TOOLTYPE_SUCCESS -/obj/machinery/chem_dispenser/attackby(obj/item/I, mob/living/user, params) - if(default_deconstruction_screwdriver(user, icon_state, icon_state, I)) +/obj/machinery/chem_dispenser/screwdriver_act(mob/living/user, obj/item/tool) + . = ..() + if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool)) update_appearance() - return - if(default_deconstruction_crowbar(I)) - return + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/machinery/chem_dispenser/crowbar_act(mob/living/user, obj/item/tool) + . = ..() + if(default_deconstruction_crowbar(tool)) + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/machinery/chem_dispenser/attackby(obj/item/I, mob/living/user, params) if(is_reagent_container(I) && !(I.item_flags & ABSTRACT) && I.is_open_container()) var/obj/item/reagent_containers/B = I . = TRUE //no afterattack @@ -485,7 +499,8 @@ nopower_state = null pass_flags = PASSTABLE show_ph = FALSE - dispensable_reagents = list( + /// The default list of reagents dispensable by the soda dispenser + var/static/list/drinks_dispensable_reagents = list( /datum/reagent/consumable/coffee, /datum/reagent/consumable/space_cola, /datum/reagent/consumable/cream, @@ -513,7 +528,8 @@ /datum/reagent/water, ) upgrade_reagents = null - emagged_reagents = list( + /// The default list of emagged reagents dispensable by the soda dispenser + var/static/list/drink_emagged_reagents = list( /datum/reagent/consumable/ethanol/thirteenloko, /datum/reagent/consumable/ethanol/whiskey_cola, /datum/reagent/toxin/mindbreaker, @@ -522,6 +538,10 @@ base_reagent_purity = 0.5 /obj/machinery/chem_dispenser/drinks/Initialize(mapload) + if(dispensable_reagents != null && !dispensable_reagents.len) + dispensable_reagents = drinks_dispensable_reagents + if(emagged_reagents != null && !emagged_reagents.len) + emagged_reagents = drink_emagged_reagents . = ..() AddComponent(/datum/component/simple_rotation) @@ -566,7 +586,8 @@ base_icon_state = "booze_dispenser" dispensed_temperature = WATER_MATTERSTATE_CHANGE_TEMP circuit = /obj/item/circuitboard/machine/chem_dispenser/drinks/beer - dispensable_reagents = list( + /// The default list of reagents dispensable by the beer dispenser + var/static/list/beer_dispensable_reagents = list( /datum/reagent/consumable/ethanol/absinthe, /datum/reagent/consumable/ethanol/ale, /datum/reagent/consumable/ethanol/applejack, @@ -594,7 +615,8 @@ /datum/reagent/consumable/ethanol/yuyake, ) upgrade_reagents = null - emagged_reagents = list( + /// The default list of emagged reagents dispensable by the beer dispenser + var/static/list/beer_emagged_reagents = list( /datum/reagent/consumable/ethanol, /datum/reagent/iron, /datum/reagent/consumable/mintextract, @@ -602,6 +624,11 @@ /datum/reagent/consumable/ethanol/fernet ) +/obj/machinery/chem_dispenser/drinks/beer/Initialize(mapload) + dispensable_reagents = beer_dispensable_reagents + emagged_reagents = beer_emagged_reagents + . = ..() + /obj/machinery/chem_dispenser/drinks/beer/fullupgrade //fully ugpraded stock parts, emagged desc = "Contains a large reservoir of the good stuff. This model has had its safeties shorted out." obj_flags = CAN_BE_HIT | EMAGGED @@ -615,19 +642,25 @@ /obj/machinery/chem_dispenser/mutagen name = "mutagen dispenser" desc = "Creates and dispenses mutagen." - dispensable_reagents = list(/datum/reagent/toxin/mutagen) + /// The default list of reagents dispensable by mutagen chem dispenser + var/static/list/mutagen_dispensable_reagents = list(/datum/reagent/toxin/mutagen) upgrade_reagents = null - emagged_reagents = list(/datum/reagent/toxin/plasma) + /// The default list of emagged reagents dispensable by mutagen chem dispenser + var/static/list/mutagen_emagged_reagents = list(/datum/reagent/toxin/plasma) +/obj/machinery/chem_dispenser/mutagen/Initialize(mapload) + dispensable_reagents = mutagen_dispensable_reagents + emagged_reagents = mutagen_emagged_reagents + . = ..() /obj/machinery/chem_dispenser/mutagensaltpeter name = "botanical chemical dispenser" desc = "Creates and dispenses chemicals useful for botany." flags_1 = NODECONSTRUCT_1 - circuit = /obj/item/circuitboard/machine/chem_dispenser/mutagensaltpeter - dispensable_reagents = list( + /// The default list of dispensable reagents available in the mutagensaltpeter chem dispenser + var/static/list/mutagensaltpeter_dispensable_reagents = list( /datum/reagent/toxin/mutagen, /datum/reagent/saltpetre, /datum/reagent/plantnutriment/eznutriment, @@ -643,6 +676,10 @@ /datum/reagent/diethylamine) upgrade_reagents = null +/obj/machinery/chem_dispenser/mutagensaltpeter/Initialize(mapload) + dispensable_reagents = mutagensaltpeter_dispensable_reagents + . = ..() + /obj/machinery/chem_dispenser/fullupgrade //fully ugpraded stock parts, emagged desc = "Creates and dispenses chemicals. This model has had its safeties shorted out." obj_flags = CAN_BE_HIT | EMAGGED @@ -664,7 +701,9 @@ working_state = null nopower_state = null use_power = NO_POWER_USE - dispensable_reagents = list( + + /// The default list of dispensable reagents available in the abductor chem dispenser + var/static/list/abductor_dispensable_reagents = list( /datum/reagent/aluminium, /datum/reagent/bromine, /datum/reagent/carbon, @@ -706,3 +745,7 @@ /datum/reagent/consumable/liquidelectricity/enriched, /datum/reagent/medicine/c2/synthflesh ) + +/obj/machinery/chem_dispenser/abductor/Initialize(mapload) + dispensable_reagents = abductor_dispensable_reagents + . = ..() diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index 3716715a2d6cf..2461f8eb90b3e 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -447,10 +447,10 @@ To continue set your target temperature to 390K."} if(acid_reagent_heater) cur_vol = acid_reagent_heater.volume volume = 100 - cur_vol - beaker.reagents.trans_id_to(src, acid_reagent.type, volume)//negative because we're going backwards + beaker.reagents.trans_to(src, volume, target_id = acid_reagent.type)//negative because we're going backwards return //We must be positive here - reagents.trans_id_to(beaker, /datum/reagent/reaction_agent/acidic_buffer, dispense_volume) + reagents.trans_to(beaker, dispense_volume, target_id = /datum/reagent/reaction_agent/acidic_buffer) return if(buffer_type == "basic") @@ -464,9 +464,9 @@ To continue set your target temperature to 390K."} if(basic_reagent_heater) cur_vol = basic_reagent_heater.volume volume = 100 - cur_vol - beaker.reagents.trans_id_to(src, basic_reagent.type, volume)//negative because we're going backwards + beaker.reagents.trans_to(src, volume, target_id = basic_reagent.type)//negative because we're going backwards return - reagents.trans_id_to(beaker, /datum/reagent/reaction_agent/basic_buffer, dispense_volume) + reagents.trans_to(beaker, dispense_volume, target_id = /datum/reagent/reaction_agent/basic_buffer) return diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 6955cede78de4..dc83ad0b9012e 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -337,10 +337,11 @@ // Generate item name var/item_name_default = initial(container_style.name) + var/datum/reagent/master_reagent = reagents.get_master_reagent() if(selected_container == default_container) // Tubes and bottles gain reagent name - item_name_default = "[reagents.get_master_reagent_name()] [item_name_default]" + item_name_default = "[master_reagent.name] [item_name_default]" if(!(initial(container_style.reagent_flags) & OPENCONTAINER)) // Closed containers get both reagent name and units in the name - item_name_default = "[reagents.get_master_reagent_name()] [item_name_default] ([volume_in_each]u)" + item_name_default = "[master_reagent.name] [item_name_default] ([volume_in_each]u)" var/item_name = tgui_input_text(usr, "Container name", "Name", @@ -392,7 +393,7 @@ if (target == TARGET_BUFFER) if(!check_reactions(reagent, beaker.reagents)) return FALSE - beaker.reagents.trans_id_to(src, reagent.type, amount) + beaker.reagents.trans_to(src, amount, target_id = reagent.type) update_appearance(UPDATE_ICON) return TRUE @@ -403,7 +404,7 @@ if (target == TARGET_BEAKER && transfer_mode == TRANSFER_MODE_MOVE) if(!check_reactions(reagent, reagents)) return FALSE - reagents.trans_id_to(beaker, reagent.type, amount) + reagents.trans_to(beaker, amount, target_id = reagent.type) update_appearance(UPDATE_ICON) return TRUE diff --git a/code/modules/reagents/chemistry/machinery/chem_separator.dm b/code/modules/reagents/chemistry/machinery/chem_separator.dm index 2e5571fd4312b..13be8d6554f3a 100644 --- a/code/modules/reagents/chemistry/machinery/chem_separator.dm +++ b/code/modules/reagents/chemistry/machinery/chem_separator.dm @@ -231,7 +231,7 @@ soundloop.start() var/vapor_amount = distillation_rate * seconds_per_tick // Vapor to condenser - reagents.trans_id_to(condenser, separating_reagent.type, vapor_amount) + reagents.trans_to(condenser, vapor_amount, target_id = separating_reagent.type) // Cool the vapor down condenser.set_temperature(air.temperature) // Condense into container diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm index 7a3dc6ab8fba6..d589420ab695d 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm @@ -147,6 +147,7 @@ name = "Green Beer" description = "An alcoholic beverage brewed since ancient times on Old Earth. This variety is dyed a festive green." color = COLOR_CRAYON_GREEN + overdose_threshold = 55 //More than a glass taste_description = "green piss water" ph = 6 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -159,6 +160,20 @@ /datum/reagent/consumable/ethanol/beer/green/on_mob_end_metabolize(mob/living/drinker) drinker.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, color) +/datum/reagent/consumable/ethanol/beer/green/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired) + . = ..() + metabolization_rate = 1 * REAGENTS_METABOLISM + + if(!ishuman(affected_mob)) + return + + var/mob/living/carbon/human/affected_human = affected_mob + if(HAS_TRAIT(affected_human, TRAIT_USES_SKINTONES)) + affected_human.skin_tone = "green" + else if(HAS_TRAIT(affected_human, TRAIT_MUTANT_COLORS) && !HAS_TRAIT(affected_human, TRAIT_FIXED_MUTANT_COLORS)) //Code stolen from spraytan overdose + affected_human.dna.features["mcolor"] = "#a8e61d" + affected_human.update_body(is_creating = TRUE) + /datum/reagent/consumable/ethanol/kahlua name = "Kahlua" description = "A widely known, Mexican coffee-flavoured liqueur. In production since 1936!" diff --git a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm index 28039f8b5b63a..9a459e41e5b93 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm @@ -225,7 +225,7 @@ if(affected_mob.heal_bodypart_damage(brute = 1 * REM * seconds_per_tick, burn = 0, updating_health = FALSE)) . = UPDATE_MOB_HEALTH if(holder.has_reagent(/datum/reagent/consumable/capsaicin)) - holder.remove_reagent(/datum/reagent/consumable/capsaicin, 1 * seconds_per_tick) + holder.remove_reagent(/datum/reagent/consumable/capsaicin, seconds_per_tick) return ..() || . /datum/reagent/consumable/soymilk diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index 67fb8104efaa9..a013c5acc556c 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -84,7 +84,7 @@ if(SPT_PROB(0.5, seconds_per_tick)) var/smoke_message = pick("You feel relaxed.", "You feel calmed.","You feel alert.","You feel rugged.") to_chat(affected_mob, span_notice("[smoke_message]")) - affected_mob.add_mood_event("smoked", /datum/mood_event/smoked, name) + affected_mob.add_mood_event("smoked", /datum/mood_event/smoked) affected_mob.remove_status_effect(/datum/status_effect/jitter) affected_mob.AdjustStun(-50 * REM * seconds_per_tick) affected_mob.AdjustKnockdown(-50 * REM * seconds_per_tick) @@ -117,7 +117,7 @@ var/high_message = pick("You feel calm.", "You feel collected.", "You feel like you need to relax.") if(SPT_PROB(2.5, seconds_per_tick)) to_chat(affected_mob, span_notice("[high_message]")) - affected_mob.add_mood_event("smacked out", /datum/mood_event/narcotic_heavy, name) + affected_mob.add_mood_event("smacked out", /datum/mood_event/narcotic_heavy) if(current_cycle == 36 && creation_purity <= 0.6) if(!istype(affected_mob.dna.species, /datum/species/human/krokodil_addict)) to_chat(affected_mob, span_userdanger("Your skin falls off easily!")) @@ -175,7 +175,7 @@ var/high_message = pick("You feel hyper.", "You feel like you need to go faster.", "You feel like you can run the world.") if(SPT_PROB(2.5, seconds_per_tick)) to_chat(affected_mob, span_notice("[high_message]")) - affected_mob.add_mood_event("tweaking", /datum/mood_event/stimulant_medium, name) + affected_mob.add_mood_event("tweaking", /datum/mood_event/stimulant_medium) affected_mob.AdjustStun(-40 * REM * seconds_per_tick) affected_mob.AdjustKnockdown(-40 * REM * seconds_per_tick) affected_mob.AdjustUnconscious(-40 * REM * seconds_per_tick) @@ -237,7 +237,7 @@ var/high_message = pick("You feel amped up.", "You feel ready.", "You feel like you can push it to the limit.") if(SPT_PROB(2.5, seconds_per_tick)) to_chat(affected_mob, span_notice("[high_message]")) - affected_mob.add_mood_event("salted", /datum/mood_event/stimulant_heavy, name) + affected_mob.add_mood_event("salted", /datum/mood_event/stimulant_heavy) var/need_mob_update need_mob_update = affected_mob.adjustStaminaLoss(-5 * REM * seconds_per_tick, updating_stamina = FALSE, required_biotype = affected_biotype) need_mob_update += affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 4 * REM * seconds_per_tick, required_organ_flag = affected_organ_flags) @@ -518,7 +518,7 @@ /datum/reagent/drug/mushroomhallucinogen/on_mob_metabolize(mob/living/psychonaut) . = ..() - psychonaut.add_mood_event("tripping", /datum/mood_event/high, name) + psychonaut.add_mood_event("tripping", /datum/mood_event/high) if(!psychonaut.hud_used) return @@ -579,7 +579,7 @@ /datum/reagent/drug/blastoff/on_mob_metabolize(mob/living/dancer) . = ..() - dancer.add_mood_event("vibing", /datum/mood_event/high, name) + dancer.add_mood_event("vibing", /datum/mood_event/high) RegisterSignal(dancer, COMSIG_MOB_EMOTED("flip"), PROC_REF(on_flip)) RegisterSignal(dancer, COMSIG_MOB_EMOTED("spin"), PROC_REF(on_spin)) @@ -819,7 +819,7 @@ /datum/reagent/drug/kronkaine/on_mob_life(mob/living/carbon/kronkaine_fiend, seconds_per_tick, times_fired) . = ..() || TRUE - kronkaine_fiend.add_mood_event("tweaking", /datum/mood_event/stimulant_medium, name) + kronkaine_fiend.add_mood_event("tweaking", /datum/mood_event/stimulant_medium) if(kronkaine_fiend.adjustOrganLoss(ORGAN_SLOT_HEART, 0.4 * REM * seconds_per_tick, required_organ_flag = affected_organ_flags)) . = UPDATE_MOB_HEALTH kronkaine_fiend.set_jitter_if_lower(20 SECONDS * REM * seconds_per_tick) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 68eefcdf0cd44..b5b1f2f89f5fc 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -1148,7 +1148,7 @@ . = ..() for(var/effect in status_effects_to_clear) affected_mob.remove_status_effect(effect) - affected_mob.reagents.remove_all_type(/datum/reagent/consumable/ethanol, 3 * REM * seconds_per_tick * normalise_creation_purity(), FALSE, TRUE) + affected_mob.reagents.remove_reagent(/datum/reagent/consumable/ethanol, 3 * REM * seconds_per_tick * normalise_creation_purity(), include_subtypes = TRUE) if(affected_mob.adjustToxLoss(-0.2 * REM * seconds_per_tick, updating_health = FALSE, required_biotype = affected_biotype)) . = UPDATE_MOB_HEALTH affected_mob.adjust_drunk_effect(-10 * REM * seconds_per_tick * normalise_creation_purity()) @@ -1285,7 +1285,7 @@ /datum/reagent/medicine/syndicate_nanites/overdose_process(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) //wtb flavortext messages that hint that you're vomitting up robots . = ..() if(SPT_PROB(13, seconds_per_tick)) - affected_mob.reagents.remove_reagent(type, metabolization_rate*15) // ~5 units at a rate of 0.4 but i wanted a nice number in code + affected_mob.reagents.remove_reagent(type, metabolization_rate * 15) // ~5 units at a rate of 0.4 but i wanted a nice number in code affected_mob.vomit(vomit_flags = VOMIT_CATEGORY_DEFAULT, vomit_type = /obj/effect/decal/cleanable/vomit/nanites, lost_nutrition = 20) // nanite safety protocols make your body expel them to prevent harmies /datum/reagent/medicine/earthsblood //Created by ambrosia gaia plants diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index e42cfc55107d7..20f77cc696e9c 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -531,7 +531,7 @@ need_mob_update += affected_mob.adjustFireLoss(0.5*seconds_per_tick, updating_health = FALSE) //Hence the other damages... ain't I a bastard? affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2.5*seconds_per_tick, 150) if(holder) - holder.remove_reagent(type, 0.5*seconds_per_tick) + holder.remove_reagent(type, 0.5 * seconds_per_tick) if(need_mob_update) return UPDATE_MOB_HEALTH diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 390c3d7bfd4dd..f281bb3c852b4 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -782,7 +782,7 @@ if(SPT_PROB(1.5, seconds_per_tick)) holder.add_reagent(/datum/reagent/toxin/histamine,rand(1,3)) - holder.remove_reagent(/datum/reagent/toxin/itching_powder,1.2) + holder.remove_reagent(/datum/reagent/toxin/itching_powder, 1.2) return else return ..() || . @@ -963,7 +963,7 @@ affected_mob.vomit(vomit_flags = constructed_flags, distance = rand(0,4)) for(var/datum/reagent/toxin/R in affected_mob.reagents.reagent_list) if(R != src) - affected_mob.reagents.remove_reagent(R.type,1) + affected_mob.reagents.remove_reagent(R.type, 1) /datum/reagent/toxin/spewium/overdose_process(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm index 74e7d40659cbd..83eb6437b1dd1 100644 --- a/code/modules/reagents/chemistry/recipes.dm +++ b/code/modules/reagents/chemistry/recipes.dm @@ -161,7 +161,7 @@ var/cached_purity = reagent.purity if((reaction_flags & REACTION_CLEAR_INVERSE) && reagent.inverse_chem) if(reagent.inverse_chem_val > reagent.purity) - holder.remove_reagent(reagent.type, cached_volume, FALSE) + holder.remove_reagent(reagent.type, cached_volume, safety = FALSE) holder.add_reagent(reagent.inverse_chem, cached_volume, FALSE, added_purity = reagent.get_inverse_purity(cached_purity)) return diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index 05bc622faa70f..f524d92ff8e47 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -17,7 +17,7 @@ if(holder.has_reagent(/datum/reagent/exotic_stabilizer,round(created_volume / 25, CHEMICAL_QUANTISATION_LEVEL))) return - holder.remove_reagent(/datum/reagent/nitroglycerin, created_volume*2) + holder.remove_reagent(/datum/reagent/nitroglycerin, created_volume * 2) ..() /datum/chemical_reaction/reagent_explosion/nitroglycerin_explosion @@ -35,7 +35,7 @@ /datum/chemical_reaction/reagent_explosion/rdx/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) if(holder.has_reagent(/datum/reagent/stabilizing_agent)) return - holder.remove_reagent(/datum/reagent/rdx, created_volume*2) + holder.remove_reagent(/datum/reagent/rdx, created_volume * 2) ..() /datum/chemical_reaction/reagent_explosion/rdx_explosion @@ -242,7 +242,7 @@ /datum/chemical_reaction/sorium/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) if(holder.has_reagent(/datum/reagent/stabilizing_agent)) return - holder.remove_reagent(/datum/reagent/sorium, created_volume*4) + holder.remove_reagent(/datum/reagent/sorium, created_volume * 4) var/turf/T = get_turf(holder.my_atom) var/range = clamp(sqrt(created_volume*4), 1, 6) goonchem_vortex(T, 1, range) @@ -265,7 +265,7 @@ /datum/chemical_reaction/liquid_dark_matter/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) if(holder.has_reagent(/datum/reagent/stabilizing_agent)) return - holder.remove_reagent(/datum/reagent/liquid_dark_matter, created_volume*3) + holder.remove_reagent(/datum/reagent/liquid_dark_matter, created_volume * 3) var/turf/T = get_turf(holder.my_atom) var/range = clamp(sqrt(created_volume*3), 1, 6) goonchem_vortex(T, 0, range) @@ -301,7 +301,7 @@ C.Paralyze(60) else C.Stun(100) - holder.remove_reagent(/datum/reagent/flash_powder, created_volume*3) + holder.remove_reagent(/datum/reagent/flash_powder, created_volume * 3) /datum/chemical_reaction/flash_powder_flash required_reagents = list(/datum/reagent/flash_powder = 1) @@ -331,7 +331,7 @@ /datum/chemical_reaction/smoke_powder/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) if(holder.has_reagent(/datum/reagent/stabilizing_agent)) return - holder.remove_reagent(/datum/reagent/smoke_powder, created_volume*3) + holder.remove_reagent(/datum/reagent/smoke_powder, created_volume * 3) var/location = get_turf(holder.my_atom) var/datum/effect_system/fluid_spread/smoke/chem/S = new S.attach(location) @@ -368,7 +368,7 @@ /datum/chemical_reaction/sonic_powder/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) if(holder.has_reagent(/datum/reagent/stabilizing_agent)) return - holder.remove_reagent(/datum/reagent/sonic_powder, created_volume*3) + holder.remove_reagent(/datum/reagent/sonic_powder, created_volume * 3) var/location = get_turf(holder.my_atom) playsound(location, 'sound/effects/bang.ogg', 25, TRUE) for(var/mob/living/carbon/C in get_hearers_in_view(created_volume/3, location)) @@ -574,7 +574,7 @@ modifier = 1 /datum/chemical_reaction/reagent_explosion/nitrous_oxide/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) - holder.remove_reagent(/datum/reagent/sorium, created_volume*2) + holder.remove_reagent(/datum/reagent/sorium, created_volume * 2) var/turf/turfie = get_turf(holder.my_atom) //generally half as strong as sorium. var/range = clamp(sqrt(created_volume*2), 1, 6) diff --git a/code/modules/reagents/reagent_containers/condiment.dm b/code/modules/reagents/reagent_containers/condiment.dm index 8b8d4470f2fd7..bbd0a84504fac 100644 --- a/code/modules/reagents/reagent_containers/condiment.dm +++ b/code/modules/reagents/reagent_containers/condiment.dm @@ -464,9 +464,12 @@ /// Handles reagents getting added to the condiment pack. /obj/item/reagent_containers/condiment/pack/proc/on_reagent_add(datum/reagents/reagents) SIGNAL_HANDLER - var/main_reagent = reagents.get_master_reagent_id() - if(main_reagent in possible_states) - var/list/temp_list = possible_states[main_reagent] + + var/datum/reagent/main_reagent = reagents.get_master_reagent() + + var/main_reagent_type = main_reagent?.type + if(main_reagent_type in possible_states) + var/list/temp_list = possible_states[main_reagent_type] icon_state = temp_list[1] desc = temp_list[3] else diff --git a/code/modules/reagents/reagent_containers/cups/_cup.dm b/code/modules/reagents/reagent_containers/cups/_cup.dm index 7ccc3209ab0d7..364ba381fdc90 100644 --- a/code/modules/reagents/reagent_containers/cups/_cup.dm +++ b/code/modules/reagents/reagent_containers/cups/_cup.dm @@ -508,6 +508,11 @@ to_chat(user, span_warning("You can't grind this!")) /obj/item/reagent_containers/cup/mortar/proc/grind_item(obj/item/item, mob/living/carbon/human/user) + if(item.flags_1 & HOLOGRAM_1) + to_chat(user, span_notice("You try to grind [item], but it fades away!")) + qdel(item) + return + if(!item.grind(reagents, user)) if(isstack(item)) to_chat(usr, span_notice("[src] attempts to grind as many pieces of [item] as possible.")) @@ -519,6 +524,11 @@ QDEL_NULL(item) /obj/item/reagent_containers/cup/mortar/proc/juice_item(obj/item/item, mob/living/carbon/human/user) + if(item.flags_1 & HOLOGRAM_1) + to_chat(user, span_notice("You try to juice [item], but it fades away!")) + qdel(item) + return + if(!item.juice(reagents, user)) to_chat(user, span_notice("You fail to juice [item].")) return diff --git a/code/modules/reagents/reagent_containers/cups/drinkingglass.dm b/code/modules/reagents/reagent_containers/cups/drinkingglass.dm index c32c83effa96b..d795a5e0dcf34 100644 --- a/code/modules/reagents/reagent_containers/cups/drinkingglass.dm +++ b/code/modules/reagents/reagent_containers/cups/drinkingglass.dm @@ -101,6 +101,10 @@ name = "Nuka Cola" list_reagents = list(/datum/reagent/consumable/nuka_cola = 50) +/obj/item/reagent_containers/cup/glass/drinkingglass/filled/pina_colada + name = "Pina Colada" + list_reagents = list(/datum/reagent/consumable/ethanol/pina_colada = 50) + /obj/item/reagent_containers/cup/glass/drinkingglass/filled/half_full name = "half full glass of water" desc = "It's a glass of water. It seems half full. Or is it half empty? You're pretty sure it's full of shit." diff --git a/code/modules/reagents/reagent_containers/cups/glassbottle.dm b/code/modules/reagents/reagent_containers/cups/glassbottle.dm index e204c6803fb89..1eed3c36b7691 100644 --- a/code/modules/reagents/reagent_containers/cups/glassbottle.dm +++ b/code/modules/reagents/reagent_containers/cups/glassbottle.dm @@ -803,10 +803,10 @@ if(istype(contained_reagent, accelerant_type)) firestarter = 1 break + ..() if(firestarter && active) target.fire_act() new /obj/effect/hotspot(get_turf(target)) - ..() /obj/item/reagent_containers/cup/glass/bottle/molotov/attackby(obj/item/I, mob/user, params) if(I.get_temperature() && !active) diff --git a/code/modules/recycling/disposal/eject.dm b/code/modules/recycling/disposal/eject.dm index febd4f5d604e0..523f034703c10 100644 --- a/code/modules/recycling/disposal/eject.dm +++ b/code/modules/recycling/disposal/eject.dm @@ -2,11 +2,33 @@ * General proc used to expel a holder's contents through src (for bins holder is also the src). */ /obj/proc/pipe_eject(obj/holder, direction, throw_em = TRUE, turf/target, throw_range = 5, throw_speed = 1) - var/turf/src_T = get_turf(src) - for(var/A in holder) - var/atom/movable/AM = A - AM.forceMove(src_T) - SEND_SIGNAL(AM, COMSIG_MOVABLE_PIPE_EJECTING, direction) - if(throw_em && !QDELETED(AM)) - var/turf/T = target || get_offset_target_turf(loc, rand(5)-rand(5), rand(5)-rand(5)) - AM.throw_at(T, throw_range, throw_speed) + var/turf/origin_turf = get_turf(src) + var/turf/target_turf + if(isnull(target)) // done up here as a safety + target_turf = get_offset_target_turf(loc, rand(5) - rand(5), rand(5) - rand(5)) + else + target_turf = target + + if(QDELETED(origin_turf)) + stack_trace("pipe_eject() attempted to operate on a qdeleted turf! In order to avoid sending things to nullspace, we are going to send everything directly to the target turf instead.") + origin_turf = target_turf + + var/list/contents_to_eject = holder.contents + var/list/contents_to_throw = list() + + for(var/atom/movable/thing in contents_to_eject) + thing.forceMove(origin_turf) + SEND_SIGNAL(thing, COMSIG_MOVABLE_PIPE_EJECTING, direction) + if(QDELETED(thing)) + continue + + contents_to_throw += thing + + if(!throw_em) + return + + for(var/atom/movable/throwable as anything in contents_to_throw) + if(isnull(target)) // we want the thrown things to be spread out a bit if we weren't given a target + target_turf = get_offset_target_turf(loc, rand(5) - rand(5), rand(5) - rand(5)) + + throwable.throw_at(target_turf, throw_range, throw_speed) diff --git a/code/modules/recycling/disposal/holder.dm b/code/modules/recycling/disposal/holder.dm index cf9ae8f6b4e10..2d964d0f8fb3f 100644 --- a/code/modules/recycling/disposal/holder.dm +++ b/code/modules/recycling/disposal/holder.dm @@ -42,7 +42,7 @@ if(M.client) M.reset_perspective(src) hasmob = TRUE - RegisterSignal(M, COMSIG_LIVING_RESIST, PROC_REF(struggle_prep), M) + RegisterSignal(M, COMSIG_LIVING_RESIST, PROC_REF(struggle_prep)) //Checks 1 contents level deep. This means that players can be sent through disposals mail... //...but it should require a second person to open the package. (i.e. person inside a wrapped locker) @@ -179,12 +179,12 @@ /// Merge two holder objects, used when a holder meets a stuck holder /obj/structure/disposalholder/proc/merge(obj/structure/disposalholder/other) - for(var/A in other) - var/atom/movable/AM = A - AM.forceMove(src) // move everything in other holder to this one - if(ismob(AM)) - var/mob/M = AM - M.reset_perspective(src) // if a client mob, update eye to follow this holder + for(var/atom/movable/movable as anything in other) + movable.forceMove(src) // move everything in other holder to this one + if(ismob(movable)) + var/mob/mob = movable + mob.reset_perspective(src) // if a client mob, update eye to follow this holder + RegisterSignal(mob, COMSIG_LIVING_RESIST, PROC_REF(struggle_prep)) hasmob = TRUE if(destinationTag == 0 && other.destinationTag != 0) destinationTag = other.destinationTag diff --git a/code/modules/recycling/disposal/outlet.dm b/code/modules/recycling/disposal/outlet.dm index 4327567fb1746..4fa9f1e0aab15 100644 --- a/code/modules/recycling/disposal/outlet.dm +++ b/code/modules/recycling/disposal/outlet.dm @@ -47,6 +47,11 @@ /obj/structure/disposaloutlet/Destroy() if(trunk) + // preemptively expel the contents from the trunk + // in case the outlet is deleted before expel_holder could be called. + var/obj/structure/disposalholder/holder = locate() in trunk + if(holder) + trunk.expel(holder) trunk.linked = null trunk = null QDEL_NULL(stored) @@ -60,15 +65,15 @@ if((start_eject + 30) < world.time) start_eject = world.time playsound(src, 'sound/machines/warning-buzzer.ogg', 50, FALSE, FALSE) - addtimer(CALLBACK(src, PROC_REF(expel_holder), H, TRUE), 20) + addtimer(CALLBACK(src, PROC_REF(expel_holder), H, TRUE), 2 SECONDS) else - addtimer(CALLBACK(src, PROC_REF(expel_holder), H), 20) + addtimer(CALLBACK(src, PROC_REF(expel_holder), H), 2 SECONDS) /obj/structure/disposaloutlet/proc/expel_holder(obj/structure/disposalholder/H, playsound=FALSE) if(playsound) playsound(src, 'sound/machines/hiss.ogg', 50, FALSE, FALSE) - if(!H) + if(QDELETED(H)) return pipe_eject(H, dir, TRUE, target, eject_range, eject_speed) diff --git a/code/modules/religion/religion_sects.dm b/code/modules/religion/religion_sects.dm index 3135fddeace8d..8b96c2105110f 100644 --- a/code/modules/religion/religion_sects.dm +++ b/code/modules/religion/religion_sects.dm @@ -168,7 +168,7 @@ eth_stomach.adjust_charge(60) did_we_charge = TRUE - //if we're not targetting a robot part we stop early + //if we're not targeting a robot part we stop early var/obj/item/bodypart/bodypart = blessed.get_bodypart(chap.zone_selected) if(IS_ORGANIC_LIMB(bodypart)) if(!did_we_charge) diff --git a/code/modules/research/designs/mecha_designs.dm b/code/modules/research/designs/mecha_designs.dm index c495bdc9e47b5..098cac6a3894b 100644 --- a/code/modules/research/designs/mecha_designs.dm +++ b/code/modules/research/designs/mecha_designs.dm @@ -229,6 +229,7 @@ construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -246,6 +247,7 @@ construction_time = 20 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -263,6 +265,7 @@ construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -280,6 +283,7 @@ construction_time = 20 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -297,6 +301,7 @@ construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -314,6 +319,7 @@ construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -331,6 +337,7 @@ construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -348,6 +355,7 @@ construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -365,6 +373,7 @@ construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -382,6 +391,7 @@ construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -399,6 +409,7 @@ construction_time = 20 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -416,6 +427,7 @@ construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -433,6 +445,7 @@ construction_time = 20 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -450,6 +463,7 @@ construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -467,6 +481,7 @@ construction_time = 20 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_WEAPONS, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -486,6 +501,7 @@ RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MISC, RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_ODYSSEUS + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_HONK + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -506,6 +522,7 @@ RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MISC, RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_ODYSSEUS + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_HONK + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -526,6 +543,7 @@ RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MISC, RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_ODYSSEUS + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_HONK + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -566,6 +584,7 @@ RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MISC, RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_ODYSSEUS + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_HONK + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -586,6 +605,7 @@ RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MODULES, RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_ODYSSEUS + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_HONK + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -606,6 +626,7 @@ RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MODULES, RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_ODYSSEUS + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_HONK + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -626,6 +647,7 @@ RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MODULES, RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_ODYSSEUS + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_HONK + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -660,6 +682,7 @@ category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MINING, RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_HONK + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -679,6 +702,7 @@ category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MINING, RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_HONK + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -697,6 +721,7 @@ construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MINING, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, @@ -713,6 +738,7 @@ construction_time = 20 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MINING, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index e9d31c0ba85c2..d287100c951b1 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -775,12 +775,24 @@ materials = list(/datum/material/iron=SHEET_MATERIAL_AMOUNT*5,/datum/material/plasma=SHEET_MATERIAL_AMOUNT*5) construction_time = 100 category = list( - RND_CATEGORY_MECHFAB_EQUIPMENT, - RND_CATEGORY_MECHFAB_RIPLEY + RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MODULES, + RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, + ) + +/datum/design/paddyupgrade + name = "Ripley MK-I to Paddy Conversion Kit" + id = "paddyupgrade" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_equipment/ripleyupgrade/paddy + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 10, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 5, + /datum/material/titanium = SHEET_MATERIAL_AMOUNT *5, ) + construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MODULES, - RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_CHASSIS, ) /datum/design/mech_hydraulic_clamp @@ -791,12 +803,20 @@ materials = list(/datum/material/iron=SHEET_MATERIAL_AMOUNT*5) construction_time = 100 category = list( - RND_CATEGORY_MECHFAB_EQUIPMENT, - RND_CATEGORY_MECHFAB_RIPLEY + RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MISC, + RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, ) + +/datum/design/mech_hydraulic_claw + name = "Hydraulic Claw" + id = "mech_hydraulic_claw" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_equipment/weapon/paddy_claw + materials = list(/datum/material/iron=SHEET_MATERIAL_AMOUNT*5) + construction_time = 100 category = list( RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_MISC, - RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, + RND_CATEGORY_MECHFAB_PADDY + RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT, ) /datum/design/mech_drill diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index a99c5e24217c9..ae8f7e43a4078 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -411,7 +411,7 @@ category = list( RND_CATEGORY_STOCK_PARTS + RND_SUBCATEGORY_STOCK_PARTS_MISC ) - departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_SERVICE /datum/design/oxygen_tank name = "Oxygen Tank" diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm index 2d1e786208cfd..03a6d9934f5f7 100644 --- a/code/modules/research/destructive_analyzer.dm +++ b/code/modules/research/destructive_analyzer.dm @@ -1,225 +1,189 @@ -/* -Destructive Analyzer - -It is used to destroy hand-held objects and advance technological research. Controls are in the linked R&D console. - -Note: Must be placed within 3 tiles of the R&D Console -*/ +///How much power it costs to deconstruct an item. +#define DESTRUCTIVE_ANALYZER_POWER_USAGE (BASE_MACHINE_IDLE_CONSUMPTION * 2.5) +///The 'ID' for deconstructing items for Research points instead of nodes. +#define DESTRUCTIVE_ANALYZER_DESTROY_POINTS "research_points" + +/** + * ## Destructive Analyzer + * It is used to destroy hand-held objects and advance technological research. + */ /obj/machinery/rnd/destructive_analyzer name = "destructive analyzer" desc = "Learn science by destroying things!" icon_state = "d_analyzer" base_icon_state = "d_analyzer" circuit = /obj/item/circuitboard/machine/destructive_analyzer - var/decon_mod = 0 -/obj/machinery/rnd/destructive_analyzer/RefreshParts() +/obj/machinery/rnd/destructive_analyzer/Initialize(mapload) . = ..() - var/T = 0 - for(var/datum/stock_part/stock_part in component_parts) - T += stock_part.tier - decon_mod = T - -/obj/machinery/rnd/destructive_analyzer/proc/ConvertReqString2List(list/source_list) - var/list/temp_list = params2list(source_list) - for(var/O in temp_list) - temp_list[O] = text2num(temp_list[O]) - return temp_list - -/obj/machinery/rnd/destructive_analyzer/Insert_Item(obj/item/O, mob/living/user) - if(!user.combat_mode) - . = 1 - if(!is_insertion_ready(user)) - return - if(!user.transferItemToLoc(O, src)) - to_chat(user, span_warning("\The [O] is stuck to your hand, you cannot put it in the [src.name]!")) - return - busy = TRUE - loaded_item = O - to_chat(user, span_notice("You add the [O.name] to the [src.name]!")) - flick("d_analyzer_la", src) - addtimer(CALLBACK(src, PROC_REF(finish_loading)), 10) - updateUsrDialog() + register_context() + +/obj/machinery/rnd/destructive_analyzer/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) + if(loaded_item) + context[SCREENTIP_CONTEXT_ALT_LMB] = "Remove Item" + else if(!isnull(held_item)) + context[SCREENTIP_CONTEXT_LMB] = "Insert Item" + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/rnd/destructive_analyzer/attackby(obj/item/weapon, mob/living/user, params) + if(user.combat_mode) + return ..() + if(!is_insertion_ready(user)) + return ..() + if(!user.transferItemToLoc(weapon, src)) + to_chat(user, span_warning("\The [weapon] is stuck to your hand, you cannot put it in the [name]!")) + return TRUE + busy = TRUE + loaded_item = weapon + to_chat(user, span_notice("You add the [weapon.name] to the [name]!")) + flick("[base_icon_state]_la", src) + addtimer(CALLBACK(src, PROC_REF(finish_loading)), 1 SECONDS) + return TRUE -/obj/machinery/rnd/destructive_analyzer/proc/finish_loading() - update_appearance() - reset_busy() +/obj/machinery/rnd/destructive_analyzer/AltClick(mob/user) + . = ..() + unload_item() /obj/machinery/rnd/destructive_analyzer/update_icon_state() icon_state = "[base_icon_state][loaded_item ? "_l" : null]" return ..() -/obj/machinery/rnd/destructive_analyzer/proc/destroy_item(obj/item/thing, innermode = FALSE) - if(QDELETED(thing) || QDELETED(src)) - return FALSE - if(!innermode) - flick("d_analyzer_process", src) - busy = TRUE - addtimer(CALLBACK(src, PROC_REF(reset_busy)), 24) - use_power(250) - if(thing == loaded_item) - loaded_item = null - var/list/food = thing.GetDeconstructableContents() - for(var/obj/item/innerthing in food) - destroy_item(innerthing, TRUE) - for(var/mob/living/victim in thing) - if(victim.stat != DEAD) - victim.investigate_log("has been killed by a destructive analyzer.", INVESTIGATE_DEATHS) - victim.death() - - qdel(thing) - loaded_item = null - if (!innermode) - update_appearance() - return TRUE +/obj/machinery/rnd/destructive_analyzer/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "DestructiveAnalyzer") + ui.open() + +/obj/machinery/rnd/destructive_analyzer/ui_data(mob/user) + var/list/data = list() + data["server_connected"] = !!stored_research + data["node_data"] = list() + if(loaded_item) + data["item_icon"] = icon2base64(getFlatIcon(image(icon = loaded_item.icon, icon_state = loaded_item.icon_state), no_anim = TRUE)) + data["indestructible"] = !(loaded_item.resistance_flags & INDESTRUCTIBLE) + data["loaded_item"] = loaded_item + data["already_deconstructed"] = !!stored_research.deconstructed_items[loaded_item.type] + var/list/points = techweb_item_point_check(loaded_item) + data["recoverable_points"] = techweb_point_display_generic(points) + + var/list/boostable_nodes = techweb_item_unlock_check(loaded_item) + for(var/id in boostable_nodes) + var/datum/techweb_node/unlockable_node = SSresearch.techweb_node_by_id(id) + var/list/node_data = list() + node_data["node_name"] = unlockable_node.display_name + node_data["node_id"] = unlockable_node.id + node_data["node_hidden"] = !!stored_research.hidden_nodes[unlockable_node.id] + data["node_data"] += list(node_data) + else + data["loaded_item"] = null + return data -/obj/machinery/rnd/destructive_analyzer/proc/user_try_decon_id(id, mob/user) - if(!istype(loaded_item)) - return FALSE +/obj/machinery/rnd/destructive_analyzer/ui_static_data(mob/user) + var/list/data = list() + data["research_point_id"] = DESTRUCTIVE_ANALYZER_DESTROY_POINTS + return data - if (id && id != RESEARCH_MATERIAL_DESTROY_ID) - var/datum/techweb_node/TN = SSresearch.techweb_node_by_id(id) - if(!istype(TN)) - return FALSE - var/dpath = loaded_item.type - var/list/worths = TN.boost_item_paths[dpath] - var/list/differences = list() - var/list/already_boosted = stored_research.boosted_nodes[TN.id] - for(var/i in worths) - var/used = already_boosted? already_boosted[i] : 0 - var/value = min(worths[i], TN.research_costs[i]) - used - if(value > 0) - differences[i] = value - if(length(worths) && !length(differences)) - return FALSE - var/choice = tgui_alert(user, "Are you sure you want to destroy [loaded_item] to [!length(worths) ? "reveal [TN.display_name]" : "boost [TN.display_name] by [json_encode(differences)] point\s"]?", "Destructive Analyzer", list("Proceed", "Cancel")) - if(choice != "Proceed") - return FALSE - if(QDELETED(loaded_item) || QDELETED(src)) - return FALSE - SSblackbox.record_feedback("nested tally", "item_deconstructed", 1, list("[TN.id]", "[loaded_item.type]")) - if(destroy_item(loaded_item)) - stored_research.boost_with_item(SSresearch.techweb_node_by_id(TN.id), dpath) +/obj/machinery/rnd/destructive_analyzer/ui_act(action, params, datum/tgui/ui) + . = ..() + if(.) + return - else - var/list/point_value = techweb_item_point_check(loaded_item) - if(stored_research.deconstructed_items[loaded_item.type]) - point_value = list() - var/user_mode_string = "" - if(length(point_value)) - user_mode_string = " for [json_encode(point_value)] points" - var/choice = tgui_alert(usr, "Are you sure you want to destroy [loaded_item][user_mode_string]?",, list("Proceed", "Cancel")) - if(choice == "Cancel") - return FALSE - if(QDELETED(loaded_item) || QDELETED(src)) - return FALSE - destroy_item(loaded_item) - return TRUE + var/mob/user = usr + switch(action) + if("eject_item") + if(busy) + balloon_alert(user, "already busy!") + return TRUE + if(loaded_item) + unload_item() + return TRUE + if("deconstruct") + if(!user_try_decon_id(params["deconstruct_id"])) + say("Destructive analysis failed!") + return TRUE + +//This allows people to put syndicate screwdrivers in the machine. Secondary act still passes. +/obj/machinery/rnd/destructive_analyzer/screwdriver_act(mob/living/user, obj/item/tool) + return FALSE +///Drops the loaded item where it can and nulls it. /obj/machinery/rnd/destructive_analyzer/proc/unload_item() if(!loaded_item) return FALSE - loaded_item.forceMove(get_turf(src)) + playsound(loc, 'sound/machines/terminal_insert_disc.ogg', 30, FALSE) + loaded_item.forceMove(drop_location()) loaded_item = null - update_appearance() + update_appearance(UPDATE_ICON) return TRUE -/obj/machinery/rnd/destructive_analyzer/ui_interact(mob/user) - . = ..() - var/datum/browser/popup = new(user, "destructive_analyzer", name, 900, 600) - popup.set_content(ui_deconstruct()) - popup.open() +///Called in a timer callback after loading something into it, this handles resetting the 'busy' state back to its initial state +///So the machine can be used. +/obj/machinery/rnd/destructive_analyzer/proc/finish_loading() + update_appearance(UPDATE_ICON) + reset_busy() -/obj/machinery/rnd/destructive_analyzer/proc/ui_deconstruct() //Legacy code - var/list/l = list() - if(!loaded_item) - l += "
No item loaded. Standing-by...
" - else - l += "
[RDSCREEN_NOBREAK]" - l += "
[icon2html(loaded_item, usr)][loaded_item.name] Eject
[RDSCREEN_NOBREAK]" - l += "Select a node to boost by deconstructing this item. This item can boost:" +/** + * Destroys an item by going through all its contents (including itself) and calling destroy_item_individual + * Args: + * gain_research_points - Whether deconstructing each individual item should check for research points to boost. + */ +/obj/machinery/rnd/destructive_analyzer/proc/destroy_item(gain_research_points = FALSE) + if(QDELETED(loaded_item) || QDELETED(src)) + return FALSE + flick("[base_icon_state]_process", src) + busy = TRUE + addtimer(CALLBACK(src, PROC_REF(reset_busy)), 2.4 SECONDS) + use_power(DESTRUCTIVE_ANALYZER_POWER_USAGE) + var/list/all_contents = loaded_item.get_all_contents() + for(var/innerthing in all_contents) + destroy_item_individual(innerthing, gain_research_points) - var/anything = FALSE - var/list/boostable_nodes = techweb_item_boost_check(loaded_item) - for(var/id in boostable_nodes) - anything = TRUE - var/list/worth = boostable_nodes[id] - var/datum/techweb_node/N = SSresearch.techweb_node_by_id(id) - - l += "
[RDSCREEN_NOBREAK]" - if (stored_research.researched_nodes[N.id]) // already researched - l += "[N.display_name]" - l += "This node has already been researched." - else if(!length(worth)) // reveal only - if (stored_research.hidden_nodes[N.id]) - l += "[N.display_name]" - l += "This node will be revealed." - else - l += "[N.display_name]" - l += "This node has already been revealed." - else // boost by the difference - var/list/differences = list() - var/list/already_boosted = stored_research.boosted_nodes[N.id] - for(var/i in worth) - var/already_boosted_amount = already_boosted? stored_research.boosted_nodes[N.id][i] : 0 - var/amt = min(worth[i], N.research_costs[i]) - already_boosted_amount - if(amt > 0) - differences[i] = amt - if (length(differences)) - l += "[N.display_name]" - l += "This node will be boosted with the following:
[techweb_point_display_generic(differences)]" - else - l += "[N.display_name]" - l += "This node has already been boosted." - l += "
[RDSCREEN_NOBREAK]" - - var/list/point_values = techweb_item_point_check(loaded_item) - if(point_values) - anything = TRUE - l += "
[RDSCREEN_NOBREAK]" - if (stored_research.deconstructed_items[loaded_item.type]) - l += "Point Deconstruction" - l += "This item's points have already been claimed." - else - l += "Point Deconstruction" - l += "This item is worth:
[techweb_point_display_generic(point_values)]!" - l += "
[RDSCREEN_NOBREAK]" - - if(!(loaded_item.resistance_flags & INDESTRUCTIBLE)) - l += "
Destroy Item" - l += "
[RDSCREEN_NOBREAK]" - anything = TRUE - - if (!anything) - l += "Nothing!" - - l += "
" - - for(var/i in 1 to length(l)) - if(!findtextEx(l[i], RDSCREEN_NOBREAK)) - l[i] += "
" - . = l.Join("") - return replacetextEx(., RDSCREEN_NOBREAK, "") - -/obj/machinery/rnd/destructive_analyzer/Topic(raw, ls) - . = ..() - if(.) - return + loaded_item = null + update_appearance(UPDATE_ICON) + return TRUE + +/** + * Destroys the individual provided item + * Args: + * thing - The thing being destroyed. Generally an object, but it can be a mob too, such as intellicards and pAIs. + * gain_research_points - Whether deconstructing this should give research points to the stored techweb, if applicable. + */ +/obj/machinery/rnd/destructive_analyzer/proc/destroy_item_individual(obj/item/thing, gain_research_points = FALSE) + if(isliving(thing)) + var/mob/living/mob_thing = thing + if(mob_thing.stat != DEAD) + mob_thing.investigate_log("has been killed by a destructive analyzer.", INVESTIGATE_DEATHS) + mob_thing.death() + var/list/point_value = techweb_item_point_check(thing) + if(point_value && !stored_research.deconstructed_items[thing.type]) + stored_research.deconstructed_items[thing.type] = TRUE + stored_research.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = point_value)) + qdel(thing) - add_fingerprint(usr) - usr.set_machine(src) +/** + * Attempts to destroy the loaded item using a provided research id. + * Args: + * id - The techweb ID node that we're meant to unlock if applicable. + */ +/obj/machinery/rnd/destructive_analyzer/proc/user_try_decon_id(id) + if(!istype(loaded_item)) + return FALSE + if(isnull(id)) + return FALSE - if(ls["eject_item"]) //Eject the item inside the destructive analyzer. - if(busy) - to_chat(usr, span_danger("The destructive analyzer is busy at the moment.")) - return - if(loaded_item) - unload_item() - if(ls["deconstruct"]) - if(!user_try_decon_id(ls["deconstruct"], usr)) - say("Destructive analysis failed!") + if(id == DESTRUCTIVE_ANALYZER_DESTROY_POINTS) + if(!destroy_item(gain_research_points = TRUE)) + return FALSE + return TRUE - updateUsrDialog() + var/datum/techweb_node/node_to_discover = SSresearch.techweb_node_by_id(id) + if(!istype(node_to_discover)) + return FALSE + SSblackbox.record_feedback("nested tally", "item_deconstructed", 1, list("[node_to_discover.id]", "[loaded_item.type]")) + if(!destroy_item()) + return FALSE + stored_research.unhide_node(SSresearch.techweb_node_by_id(node_to_discover.id)) + return TRUE -/obj/machinery/rnd/destructive_analyzer/screwdriver_act(mob/living/user, obj/item/tool) - return FALSE +#undef DESTRUCTIVE_ANALYZER_DESTROY_POINTS +#undef DESTRUCTIVE_ANALYZER_POWER_USAGE diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index c4983ad6c814f..9d2e200b672da 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -26,6 +26,7 @@ density = TRUE use_power = IDLE_POWER_USE circuit = /obj/item/circuitboard/machine/experimentor + interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN|INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_OPEN_SILICON|INTERACT_MACHINE_SET_MACHINE var/recentlyExperimented = 0 /// Weakref to the first ian we can find at init var/datum/weakref/tracked_ian_ref @@ -41,12 +42,6 @@ var/static/list/valid_items //valid items for special reactions like transforming var/list/critical_items_typecache //items that can cause critical reactions -/obj/machinery/rnd/experimentor/proc/ConvertReqString2List(list/source_list) - var/list/temp_list = params2list(source_list) - for(var/O in temp_list) - temp_list[O] = text2num(temp_list[O]) - return temp_list - /obj/machinery/rnd/experimentor/proc/valid_items() RETURN_TYPE(/list) @@ -130,20 +125,22 @@ return FALSE return TRUE -/obj/machinery/rnd/experimentor/Insert_Item(obj/item/O, mob/living/user) - if(!user.combat_mode) - . = 1 - if(!is_insertion_ready(user)) - return - if(!user.transferItemToLoc(O, src)) - return - loaded_item = O - to_chat(user, span_notice("You add [O] to the machine.")) - flick("h_lathe_load", src) +/obj/machinery/rnd/experimentor/attackby(obj/item/weapon, mob/living/user, params) + if(user.combat_mode) + return ..() + if(!is_insertion_ready(user)) + return ..() + if(!user.transferItemToLoc(weapon, src)) + to_chat(user, span_warning("\The [weapon] is stuck to your hand, you cannot put it in the [name]!")) + return TRUE + loaded_item = weapon + to_chat(user, span_notice("You add [weapon] to the machine.")) + flick("h_lathe_load", src) + return TRUE /obj/machinery/rnd/experimentor/default_deconstruction_crowbar(obj/item/O) ejectItem() - . = ..(O) + return ..(O) /obj/machinery/rnd/experimentor/ui_interact(mob/user) var/list/dat = list("
") @@ -160,22 +157,19 @@ if(istype(loaded_item,/obj/item/relic)) dat += "Discover" dat += "Eject" - var/list/listin = techweb_item_boost_check(src) + var/list/listin = techweb_item_unlock_check(src) if(listin) var/list/output = list("Research Boost Data:") var/list/res = list("Already researched:") - var/list/boosted = list("Already boosted:") for(var/node_id in listin) var/datum/techweb_node/N = SSresearch.techweb_node_by_id(node_id) var/str = "[N.display_name]: [listin[N]] points." var/datum/techweb/science_web = locate(/datum/techweb/science) in SSresearch.techwebs if(science_web.researched_nodes[N.id]) res += str - else if(science_web.boosted_nodes[N.id]) - boosted += str if(science_web.visible_nodes[N.id]) //JOY OF DISCOVERY! output += str - output += boosted + res + output += res dat += output else dat += "Nothing loaded." @@ -217,9 +211,9 @@ experiment(dotype,process) use_power(750) if(dotype != FAIL) - var/list/nodes = techweb_item_boost_check(process) + var/list/nodes = techweb_item_unlock_check(process) var/picked = pick_weight(nodes) //This should work. - stored_research.boost_with_item(SSresearch.techweb_node_by_id(picked), process.type) + stored_research.unhide_node(SSresearch.techweb_node_by_id(picked)) updateUsrDialog() /obj/machinery/rnd/experimentor/proc/matchReaction(matching,reaction) diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm index 4668753f0483f..b71bc1d025f3a 100644 --- a/code/modules/research/machinery/_production.dm +++ b/code/modules/research/machinery/_production.dm @@ -107,10 +107,7 @@ ) /obj/machinery/rnd/production/ui_interact(mob/user, datum/tgui/ui) - user.set_machine(src) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) ui = new(user, src, "Fabricator") ui.open() diff --git a/code/modules/research/ordnance/_scipaper.dm b/code/modules/research/ordnance/_scipaper.dm index 38f35e75a7718..f1d94af76316a 100644 --- a/code/modules/research/ordnance/_scipaper.dm +++ b/code/modules/research/ordnance/_scipaper.dm @@ -287,21 +287,20 @@ /// List of ordnance experiments that our partner is willing to accept. If this list is not filled it means the partner will accept everything. var/list/accepted_experiments = list() /// Associative list of which technology the partner might be able to boost and by how much. - var/list/boosted_nodes = list() - + var/list/boostable_nodes = list() /datum/scientific_partner/proc/purchase_boost(datum/techweb/purchasing_techweb, datum/techweb_node/node) if(!allowed_to_boost(purchasing_techweb, node.id)) return FALSE - purchasing_techweb.boost_techweb_node(node, list(TECHWEB_POINT_TYPE_GENERIC=boosted_nodes[node.id])) - purchasing_techweb.scientific_cooperation[type] -= boosted_nodes[node.id] * SCIENTIFIC_COOPERATION_PURCHASE_MULTIPLIER + purchasing_techweb.boost_techweb_node(node, list(TECHWEB_POINT_TYPE_GENERIC = boostable_nodes[node.id])) + purchasing_techweb.scientific_cooperation[type] -= boostable_nodes[node.id] * SCIENTIFIC_COOPERATION_PURCHASE_MULTIPLIER return TRUE /datum/scientific_partner/proc/allowed_to_boost(datum/techweb/purchasing_techweb, node_id) - if(purchasing_techweb.scientific_cooperation[type] < (boosted_nodes[node_id] * SCIENTIFIC_COOPERATION_PURCHASE_MULTIPLIER)) // Too expensive + if(purchasing_techweb.scientific_cooperation[type] < (boostable_nodes[node_id] * SCIENTIFIC_COOPERATION_PURCHASE_MULTIPLIER)) // Too expensive return FALSE if(!(node_id in purchasing_techweb.get_available_nodes())) // Not currently available return FALSE - if((TECHWEB_POINT_TYPE_GENERIC in purchasing_techweb.boosted_nodes[node_id]) && (purchasing_techweb.boosted_nodes[node_id][TECHWEB_POINT_TYPE_GENERIC] >= boosted_nodes[node_id])) // Already bought or we have a bigger discount + if((TECHWEB_POINT_TYPE_GENERIC in purchasing_techweb.boosted_nodes[node_id]) && (purchasing_techweb.boosted_nodes[node_id][TECHWEB_POINT_TYPE_GENERIC] >= boostable_nodes[node_id])) // Already bought or we have a bigger discount return FALSE return TRUE diff --git a/code/modules/research/ordnance/scipaper_partner.dm b/code/modules/research/ordnance/scipaper_partner.dm index fe302c73bb06c..712ec4b4127e9 100644 --- a/code/modules/research/ordnance/scipaper_partner.dm +++ b/code/modules/research/ordnance/scipaper_partner.dm @@ -3,7 +3,7 @@ flufftext = "A local group of miners are looking for ways to improve their mining output. They are interested in smaller scale explosives." accepted_experiments = list(/datum/experiment/ordnance/explosive/lowyieldbomb) multipliers = list(SCIPAPER_COOPERATION_INDEX = 0.75, SCIPAPER_FUNDING_INDEX = 0.75) - boosted_nodes = list( + boostable_nodes = list( "bluespace_basic" = 2000, "NVGtech" = 1500, "practical_bluespace" = 2500, @@ -16,7 +16,7 @@ name = "Ghost Writing" flufftext = "A nearby research station ran by a very wealthy captain seems to be struggling with their scientific output. They might reward us handsomely if we ghostwrite for them." multipliers = list(SCIPAPER_COOPERATION_INDEX = 0.25, SCIPAPER_FUNDING_INDEX = 2) - boosted_nodes = list( + boostable_nodes = list( "comp_recordkeeping" = 500, "computer_data_disks" = 500, ) @@ -29,7 +29,7 @@ /datum/experiment/ordnance/explosive/pressurebomb, /datum/experiment/ordnance/explosive/hydrogenbomb, ) - boosted_nodes = list( + boostable_nodes = list( "adv_weaponry" = 5000, "weaponry" = 2500, "sec_basic" = 1250, @@ -47,7 +47,7 @@ /datum/experiment/ordnance/gaseous/nitrous_oxide, /datum/experiment/ordnance/gaseous/bz, ) - boosted_nodes = list( + boostable_nodes = list( "cyber_organs" = 750, "cyber_organs_upgraded" = 1000, "genetics" = 500, @@ -63,7 +63,7 @@ /datum/experiment/ordnance/gaseous/noblium, /datum/experiment/ordnance/explosive/nobliumbomb, ) - boosted_nodes = list( + boostable_nodes = list( "engineering" = 5000, "adv_engi" = 5000, "emp_super" = 3000, diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm index 3047c3e1a9ac1..4ab9d73dca7b5 100644 --- a/code/modules/research/rdmachines.dm +++ b/code/modules/research/rdmachines.dm @@ -11,9 +11,10 @@ var/hacked = FALSE var/console_link = TRUE //allow console link. var/disabled = FALSE - var/obj/item/loaded_item = null //the item loaded inside the machine (currently only used by experimentor and destructive analyzer) /// Ref to global science techweb. var/datum/techweb/stored_research + ///The item loaded inside the machine, used by experimentors and destructive analyzers only. + var/obj/item/loaded_item /obj/machinery/rnd/proc/reset_busy() busy = FALSE @@ -59,14 +60,6 @@ else return FALSE -/obj/machinery/rnd/attackby(obj/item/O, mob/user, params) - if(is_refillable() && O.is_drainable()) - return FALSE //inserting reagents into the machine - if(Insert_Item(O, user)) - return TRUE - - return ..() - /obj/machinery/rnd/crowbar_act(mob/living/user, obj/item/tool) return default_deconstruction_crowbar(tool) @@ -103,36 +96,32 @@ wires.interact(user) return TRUE -//proc used to handle inserting items or reagents into rnd machines -/obj/machinery/rnd/proc/Insert_Item(obj/item/I, mob/user) - return - //whether the machine can have an item inserted in its current state. /obj/machinery/rnd/proc/is_insertion_ready(mob/user) if(panel_open) - to_chat(user, span_warning("You can't load [src] while it's opened!")) + balloon_alert(user, "panel open!") return FALSE if(disabled) - to_chat(user, span_warning("The insertion belts of [src] won't engage!")) + balloon_alert(user, "belts disabled!") return FALSE if(busy) - to_chat(user, span_warning("[src] is busy right now.")) + balloon_alert(user, "still busy!") return FALSE if(machine_stat & BROKEN) - to_chat(user, span_warning("[src] is broken.")) + balloon_alert(user, "machine broken!") return FALSE if(machine_stat & NOPOWER) - to_chat(user, span_warning("[src] has no power.")) + balloon_alert(user, "no power!") return FALSE if(loaded_item) - to_chat(user, span_warning("[src] is already loaded.")) + balloon_alert(user, "item already loaded!") return FALSE return TRUE //we eject the loaded item when deconstructing the machine /obj/machinery/rnd/on_deconstruction() if(loaded_item) - loaded_item.forceMove(loc) + loaded_item.forceMove(drop_location()) ..() /obj/machinery/rnd/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted) diff --git a/code/modules/research/techweb/__techweb_helpers.dm b/code/modules/research/techweb/__techweb_helpers.dm index 2b0a294c606f2..469c467bc133b 100644 --- a/code/modules/research/techweb/__techweb_helpers.dm +++ b/code/modules/research/techweb/__techweb_helpers.dm @@ -10,14 +10,15 @@ WARNING("Invalid boost information for node \[[id]\]: [message]") SSresearch.invalid_node_boost[id] = message -///Returns an associative list of techweb node datums with values of the boost it gives. var/list/returned = list() -/proc/techweb_item_boost_check(obj/item/I) - if(SSresearch.techweb_boost_items[I.type]) - return SSresearch.techweb_boost_items[I.type] //It should already be formatted in node datum = list(point type = value) +///Returns an associative list of techweb node datums with values of the nodes it unlocks. +/proc/techweb_item_unlock_check(obj/item/I) + if(SSresearch.techweb_unlock_items[I.type]) + return SSresearch.techweb_unlock_items[I.type] //It should already be formatted in node datum = list(point type = value) /proc/techweb_item_point_check(obj/item/I) if(SSresearch.techweb_point_items[I.type]) return SSresearch.techweb_point_items[I.type] + return FALSE /proc/techweb_point_display_generic(pointlist) var/list/ret = list() diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm index bd1e5cc4a80d8..8aeb63a9f8a7d 100644 --- a/code/modules/research/techweb/_techweb.dm +++ b/code/modules/research/techweb/_techweb.dm @@ -26,7 +26,7 @@ var/list/boosted_nodes = list() /// Hidden nodes. id = TRUE. Used for unhiding nodes when requirements are met by removing the entry of the node. var/list/hidden_nodes = list() - /// Items already deconstructed for a generic point boost, path = list(point_type = points) + /// List of items already deconstructed for research points, preventing infinite research point generation. var/list/deconstructed_items = list() /// Available research points, type = number var/list/research_points = list() @@ -400,17 +400,15 @@ LAZYINITLIST(boosted_nodes[node.id]) for(var/point_type in pointlist) boosted_nodes[node.id][point_type] = max(boosted_nodes[node.id][point_type], pointlist[point_type]) - if(node.autounlock_by_boost) - hidden_nodes -= node.id + unhide_node(node) update_node_status(node) return TRUE -/// Boosts a techweb node by using items. -/datum/techweb/proc/boost_with_item(datum/techweb_node/node, itempath) - if(!istype(node) || !ispath(itempath)) +///Removes a node from the hidden_nodes list, making it viewable and researchable (if no experiments are required). +/datum/techweb/proc/unhide_node(datum/techweb_node/node) + if(!istype(node)) return FALSE - var/list/boost_amount = node.boost_item_paths[itempath] - boost_techweb_node(node, boost_amount) + hidden_nodes -= node.id return TRUE /datum/techweb/proc/update_tiers(datum/techweb_node/base) diff --git a/code/modules/research/techweb/_techweb_node.dm b/code/modules/research/techweb/_techweb_node.dm index f5e1481e62cff..c36eb88627137 100644 --- a/code/modules/research/techweb/_techweb_node.dm +++ b/code/modules/research/techweb/_techweb_node.dm @@ -24,8 +24,8 @@ var/list/design_ids = list() /// CALCULATED FROM OTHER NODE'S PREREQUISITIES. Associated list id = TRUE var/list/unlock_ids = list() - /// Associative list, path = list(point type = point_value) - var/list/boost_item_paths = list() + /// List of items you need to deconstruct to unlock this node. + var/list/required_items_to_unlock = list() /// Boosting this will autounlock this node var/autounlock_by_boost = TRUE /// The points cost to research the node, type = amount diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 3da5c4bb23405..9a3d9ac526107 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -1877,6 +1877,18 @@ ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) +/datum/techweb_node/paddy + id = "mech_paddy" + display_name = "EXOSUIT: APLU \"Paddy\"" + description = "Paddy exosuit designs" + prereq_ids = list("adv_mecha", "adv_mecha_armor") + design_ids = list( + "paddyupgrade", + "mech_hydraulic_claw" + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + discount_experiments = list(/datum/experiment/scanning/points/machinery_tiered_scan/tier3_mechbay = 5000) + /datum/techweb_node/gygax id = "mech_gygax" display_name = "EXOSUIT: Gygax" @@ -2148,7 +2160,7 @@ display_name = "Alien Technology" description = "Things used by the greys." prereq_ids = list("biotech","engineering") - boost_item_paths = list( + required_items_to_unlock = list( /obj/item/stack/sheet/mineral/abductor, /obj/item/abductor, /obj/item/cautery/alien, @@ -2191,7 +2203,7 @@ "alien_scalpel", ) - boost_item_paths = list( + required_items_to_unlock = list( /obj/item/abductor, /obj/item/cautery/alien, /obj/item/circuitboard/machine/abductor, @@ -2230,7 +2242,7 @@ "alien_wrench", ) - boost_item_paths = list( + required_items_to_unlock = list( /obj/item/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/crowbar/abductor, @@ -2283,12 +2295,12 @@ /datum/techweb_node/syndicate_basic/proc/register_uplink_items() SIGNAL_HANDLER UnregisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE) - boost_item_paths = list() + required_items_to_unlock = list() for(var/datum/uplink_item/item_path as anything in SStraitor.uplink_items_by_type) var/datum/uplink_item/item = SStraitor.uplink_items_by_type[item_path] if(!item.item || !item.illegal_tech) continue - boost_item_paths |= item.item //allows deconning to unlock. + required_items_to_unlock |= item.item //allows deconning to unlock. ////////////////////////B.E.P.I.S. Locked Techs//////////////////////// diff --git a/code/modules/research/xenobiology/crossbreeding/burning.dm b/code/modules/research/xenobiology/crossbreeding/burning.dm index 0ababd344223d..7c27399b03eaa 100644 --- a/code/modules/research/xenobiology/crossbreeding/burning.dm +++ b/code/modules/research/xenobiology/crossbreeding/burning.dm @@ -14,10 +14,10 @@ Burning extracts: create_reagents(10, INJECTABLE | DRAWABLE) /obj/item/slimecross/burning/attack_self(mob/user) - if(!reagents.has_reagent(/datum/reagent/toxin/plasma,10)) + if(!reagents.has_reagent(/datum/reagent/toxin/plasma, 10)) to_chat(user, span_warning("This extract needs to be full of plasma to activate!")) return - reagents.remove_reagent(/datum/reagent/toxin/plasma,10) + reagents.remove_reagent(/datum/reagent/toxin/plasma, 10) to_chat(user, span_notice("You squeeze the extract, and it absorbs the plasma!")) playsound(src, 'sound/effects/bubbles.ogg', 50, TRUE) playsound(src, 'sound/magic/fireball.ogg', 50, TRUE) diff --git a/code/modules/research/xenobiology/crossbreeding/charged.dm b/code/modules/research/xenobiology/crossbreeding/charged.dm index 8941057453ba1..586a33d2dffdf 100644 --- a/code/modules/research/xenobiology/crossbreeding/charged.dm +++ b/code/modules/research/xenobiology/crossbreeding/charged.dm @@ -15,10 +15,10 @@ Charged extracts: create_reagents(10, INJECTABLE | DRAWABLE) /obj/item/slimecross/charged/attack_self(mob/user) - if(!reagents.has_reagent(/datum/reagent/toxin/plasma,10)) + if(!reagents.has_reagent(/datum/reagent/toxin/plasma, 10)) to_chat(user, span_warning("This extract needs to be full of plasma to activate!")) return - reagents.remove_reagent(/datum/reagent/toxin/plasma,10) + reagents.remove_reagent(/datum/reagent/toxin/plasma, 10) to_chat(user, span_notice("You squeeze the extract, and it absorbs the plasma!")) playsound(src, 'sound/effects/bubbles.ogg', 50, TRUE) playsound(src, 'sound/effects/light_flicker.ogg', 50, TRUE) diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm index c3586437c3276..65c7199a7f0ed 100644 --- a/code/modules/research/xenobiology/crossbreeding/chilling.dm +++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm @@ -14,10 +14,10 @@ Chilling extracts: create_reagents(10, INJECTABLE | DRAWABLE) /obj/item/slimecross/chilling/attack_self(mob/user) - if(!reagents.has_reagent(/datum/reagent/toxin/plasma,10)) + if(!reagents.has_reagent(/datum/reagent/toxin/plasma, 10)) to_chat(user, span_warning("This extract needs to be full of plasma to activate!")) return - reagents.remove_reagent(/datum/reagent/toxin/plasma,10) + reagents.remove_reagent(/datum/reagent/toxin/plasma, 10) to_chat(user, span_notice("You squeeze the extract, and it absorbs the plasma!")) playsound(src, 'sound/effects/bubbles.ogg', 50, TRUE) playsound(src, 'sound/effects/glassbr1.ogg', 50, TRUE) diff --git a/code/modules/research/xenobiology/crossbreeding/industrial.dm b/code/modules/research/xenobiology/crossbreeding/industrial.dm index 5222ab3608c09..da878b77b5a05 100644 --- a/code/modules/research/xenobiology/crossbreeding/industrial.dm +++ b/code/modules/research/xenobiology/crossbreeding/industrial.dm @@ -32,11 +32,11 @@ Industrial extracts: var/IsWorking = FALSE if(reagents.has_reagent(/datum/reagent/toxin/plasma,amount = 2) && plasmarequired > 1) //Can absorb as much as 2 IsWorking = TRUE - reagents.remove_reagent(/datum/reagent/toxin/plasma,2) + reagents.remove_reagent(/datum/reagent/toxin/plasma, 2) plasmaabsorbed += 2 else if(reagents.has_reagent(/datum/reagent/toxin/plasma,amount = 1)) //Can absorb as little as 1 IsWorking = TRUE - reagents.remove_reagent(/datum/reagent/toxin/plasma,1) + reagents.remove_reagent(/datum/reagent/toxin/plasma, 1) plasmaabsorbed += 1 if(plasmaabsorbed >= plasmarequired) diff --git a/code/modules/shuttle/computer.dm b/code/modules/shuttle/computer.dm index 4065591582e26..cf53fef368c1b 100644 --- a/code/modules/shuttle/computer.dm +++ b/code/modules/shuttle/computer.dm @@ -13,7 +13,7 @@ icon_keyboard = "tech_key" light_color = LIGHT_COLOR_CYAN req_access = list() - interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_SET_MACHINE + interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON /// ID of the attached shuttle var/shuttleId /// Possible destinations of the attached shuttle diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index a3948b0e26c5f..4411eb17c7987 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -1,38 +1,38 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( /mob/living, - /obj/structure/blob, - /obj/effect/rune, - /obj/item/disk/nuclear, - /obj/machinery/nuclearbomb, - /obj/item/beacon, - /obj/narsie, - /obj/tear_in_reality, - /obj/machinery/teleport/station, - /obj/machinery/teleport/hub, - /obj/machinery/quantumpad, - /obj/effect/mob_spawn, + /obj/docking_port, /obj/effect/hierophant, - /obj/structure/receiving_pad, - /obj/item/warp_cube, - /obj/machinery/rnd/production, //print tracking beacons, send shuttle - /obj/machinery/autolathe, //same - /obj/projectile/beam/wormhole, + /obj/effect/mob_spawn, /obj/effect/portal, - /obj/item/shared_storage, - /obj/structure/extraction_point, - /obj/machinery/syndicatebomb, + /obj/effect/rune, + /obj/item/beacon, + /obj/item/disk/nuclear, + /obj/item/gps, /obj/item/hilbertshotel, - /obj/item/swapper, - /obj/docking_port, - /obj/machinery/launchpad, - /obj/machinery/exodrone_launcher, - /obj/machinery/disposal, - /obj/structure/disposalpipe, /obj/item/mail, + /obj/item/shared_storage, + /obj/item/swapper, + /obj/item/warp_cube, + /obj/machinery/autolathe, // In case you manage to get it to print a beacon while in transit /obj/machinery/camera, - /obj/item/gps, - /obj/structure/checkoutmachine, + /obj/machinery/disposal, + /obj/machinery/exodrone_launcher, /obj/machinery/fax, + /obj/machinery/launchpad, + /obj/machinery/nuclearbomb, + /obj/machinery/quantumpad, + /obj/machinery/rnd/production, + /obj/machinery/syndicatebomb, + /obj/machinery/teleport/hub, + /obj/machinery/teleport/station, + /obj/narsie, + /obj/projectile/beam/wormhole, + /obj/structure/blob, + /obj/structure/checkoutmachine, + /obj/structure/disposalpipe, + /obj/structure/extraction_point, + /obj/structure/guardian_beacon, + /obj/tear_in_reality, ))) /// How many goody orders we can fit in a lockbox before we upgrade to a crate @@ -160,14 +160,14 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( var/price var/pack_cost var/list/goodies_by_buyer = list() // if someone orders more than GOODY_FREE_SHIPPING_MAX goodies, we upcharge to a normal crate so they can't carry around 20 combat shotties - var/list/rejected_orders = list() //list of all orders that exceeded the available budget and are uncancelable + var/list/clean_up_orders = list() // orders to remove since we are done with them for(var/datum/supply_order/spawning_order in SSshuttle.shopping_list) if(!empty_turfs.len) break price = spawning_order.get_final_cost() - //department orders EARN money for cargo, not the other way around + // department orders EARN money for cargo, not the other way around var/datum/bank_account/paying_for_this if(!spawning_order.department_destination && spawning_order.charge_on_purchase) if(spawning_order.paying_account) //Someone paid out of pocket @@ -185,8 +185,9 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( if(!paying_for_this.adjust_money(-price, "Cargo: [spawning_order.pack.name]")) if(spawning_order.paying_account) paying_for_this.bank_card_talk("Cargo order #[spawning_order.id] rejected due to lack of funds. Credits required: [price]") - if(!spawning_order.can_be_cancelled) //only if it absolutely cannot be canceled by the player do we cancel it for them - rejected_orders += spawning_order + if(!spawning_order.can_be_cancelled) //only if it absolutly cannot be canceled by the player do we cancel it for them + SSshuttle.shopping_list -= spawning_order + clean_up_orders += spawning_order continue pack_cost = spawning_order.pack.get_cost() @@ -202,9 +203,6 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( var/datum/bank_account/department/cargo = SSeconomy.get_dep_account(ACCOUNT_CAR) cargo.adjust_money(price - pack_cost) //Cargo gets the handling fee value += pack_cost - SSshuttle.shopping_list -= spawning_order - SSshuttle.order_history += spawning_order - QDEL_NULL(spawning_order.applied_coupon) if(!spawning_order.pack.goody) //we handle goody crates below var/obj/structure/closet/crate = spawning_order.generate(pick_n_take(empty_turfs)) @@ -219,10 +217,9 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( message_admins("\A [spawning_order.pack.name] ordered by [ADMIN_LOOKUPFLW(spawning_order.orderer_ckey)], paid by [from_whom] has shipped.") purchases++ - //clear out all rejected uncancellable orders - for(var/datum/supply_order/rejected_order in rejected_orders) - SSshuttle.shopping_list -= rejected_order - qdel(rejected_order) + // done dealing with order. Time to remove & delete it + SSshuttle.shopping_list -= spawning_order + clean_up_orders += spawning_order // we handle packing all the goodies last, since the type of crate we use depends on how many goodies they ordered. If it's more than GOODY_FREE_SHIPPING_MAX // then we send it in a crate (including the CRATE_TAX cost), otherwise send it in a free shipping case @@ -255,7 +252,10 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( order.generateCombo(miscboxes[miscbox], miscbox, misc_contents[miscbox], misc_costs[miscbox]) qdel(order) - SSeconomy.import_total += value + //clean up all dealt with orders + for(var/datum/supply_order/completed_order in clean_up_orders) + qdel(completed_order) + var/datum/bank_account/cargo_budget = SSeconomy.get_dep_account(ACCOUNT_CAR) investigate_log("[purchases] orders in this shipment, worth [value] credits. [cargo_budget.account_balance] credits left.", INVESTIGATE_CARGO) @@ -290,7 +290,6 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( msg += export_text + "\n" cargo_budget.adjust_money(report.total_value[exported_datum]) - SSeconomy.export_total += (cargo_budget.account_balance - presale_points) SSshuttle.centcom_message = msg investigate_log("contents sold for [cargo_budget.account_balance - presale_points] credits. Contents: [report.exported_atoms ? report.exported_atoms.Join(",") + "." : "none."] Message: [SSshuttle.centcom_message || "none."]", INVESTIGATE_CARGO) diff --git a/code/modules/spells/spell_types/pointed/mind_transfer.dm b/code/modules/spells/spell_types/pointed/mind_transfer.dm index 72441362b652e..fa401c3b432f6 100644 --- a/code/modules/spells/spell_types/pointed/mind_transfer.dm +++ b/code/modules/spells/spell_types/pointed/mind_transfer.dm @@ -69,7 +69,7 @@ return FALSE if(isguardian(cast_on)) - var/mob/living/simple_animal/hostile/guardian/stand = cast_on + var/mob/living/basic/guardian/stand = cast_on if(stand.summoner && stand.summoner == owner) to_chat(owner, span_warning("Swapping minds with your own guardian would just put you back into your own head!")) return FALSE @@ -96,7 +96,7 @@ var/mob/living/to_swap = cast_on if(isguardian(cast_on)) - var/mob/living/simple_animal/hostile/guardian/stand = cast_on + var/mob/living/basic/guardian/stand = cast_on if(stand.summoner) to_swap = stand.summoner diff --git a/code/modules/spells/spell_types/self/personality_commune.dm b/code/modules/spells/spell_types/self/personality_commune.dm deleted file mode 100644 index cd10c2b7736aa..0000000000000 --- a/code/modules/spells/spell_types/self/personality_commune.dm +++ /dev/null @@ -1,56 +0,0 @@ -// This can probably be changed to use mind linker at some point -/datum/action/cooldown/spell/personality_commune - name = "Personality Commune" - desc = "Sends thoughts to your alternate consciousness." - button_icon_state = "telepathy" - cooldown_time = 0 SECONDS - spell_requirements = NONE - - /// Fluff text shown when a message is sent to the pair - var/fluff_text = span_boldnotice("You hear an echoing voice in the back of your head...") - /// The message to send to the corresponding person on cast - var/to_send - -/datum/action/cooldown/spell/personality_commune/New(Target) - . = ..() - if(!istype(target, /datum/brain_trauma/severe/split_personality)) - stack_trace("[type] was created on a target that isn't a /datum/brain_trauma/severe/split_personality, this doesn't work.") - qdel(src) - -/datum/action/cooldown/spell/personality_commune/is_valid_target(atom/cast_on) - return isliving(cast_on) - -/datum/action/cooldown/spell/personality_commune/before_cast(atom/cast_on) - . = ..() - if(. & SPELL_CANCEL_CAST) - return - - var/datum/brain_trauma/severe/split_personality/trauma = target - if(!istype(trauma)) // hypothetically impossible but you never know - return . | SPELL_CANCEL_CAST - - to_send = tgui_input_text(cast_on, "What would you like to tell your other self?", "Commune") - if(QDELETED(src) || QDELETED(trauma) || QDELETED(cast_on) || QDELETED(trauma.owner) || !can_cast_spell()) - return . | SPELL_CANCEL_CAST - if(!to_send) - reset_cooldown() - return . | SPELL_CANCEL_CAST - -// Pillaged and adapted from telepathy code -/datum/action/cooldown/spell/personality_commune/cast(mob/living/cast_on) - . = ..() - var/datum/brain_trauma/severe/split_personality/trauma = target - - var/user_message = span_boldnotice("You concentrate and send thoughts to your other self:") - var/user_message_body = span_notice("[to_send]") - - to_chat(cast_on, "[user_message] [user_message_body]") - - trauma.owner.balloon_alert(trauma.owner, "you hear a voice") - to_chat(trauma.owner, "[fluff_text] [user_message_body]") - - log_directed_talk(cast_on, trauma.owner, to_send, LOG_SAY, "[name]") - for(var/dead_mob in GLOB.dead_mob_list) - if(!isobserver(dead_mob)) - continue - to_chat(dead_mob, "[FOLLOW_LINK(dead_mob, cast_on)] [span_boldnotice("[cast_on] [name]:")] [span_notice("\"[to_send]\" to")] [span_name("[trauma]")]") diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 574e3bbc13c7c..883ede92ff06d 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -175,8 +175,8 @@ var/unarmed_damage_low = 1 ///Highest possible punch damage this bodypart can ive. var/unarmed_damage_high = 1 - ///Damage at which attacks from this bodypart will stun - var/unarmed_stun_threshold = 2 + ///Determines the accuracy bonus, armor penetration and knockdown probability. + var/unarmed_effectiveness = 10 /// How many pixels this bodypart will offset the top half of the mob, used for abnormally sized torsos and legs var/top_offset = 0 diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 149490b4a11ab..1c17578eab4d1 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -23,7 +23,7 @@ unarmed_miss_sound = 'sound/weapons/bite.ogg' unarmed_damage_low = 1 // Yeah, biteing is pretty weak, blame the monkey super-nerf unarmed_damage_high = 3 - unarmed_stun_threshold = 4 + unarmed_effectiveness = 0 bodypart_trait_source = HEAD_TRAIT var/mob/living/brain/brainmob //The current occupant. diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index f80364fcb5db2..c93fdf10b4733 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -215,3 +215,5 @@ . = "#fff4e6" if("orange") . = "#ffc905" + if("green") + . = "#a8e61d" diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index 0ebc781085212..f6faa73094d7d 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -109,9 +109,8 @@ body_damage_coeff = 0.75 can_be_disabled = TRUE unarmed_attack_verb = "punch" /// The classic punch, wonderfully classic and completely random - unarmed_damage_low = 1 + unarmed_damage_low = 5 unarmed_damage_high = 10 - unarmed_stun_threshold = 10 body_zone = BODY_ZONE_L_ARM /// Datum describing how to offset things worn on the hands of this arm, note that an x offset won't do anything here var/datum/worn_feature_offset/worn_glove_offset @@ -216,7 +215,7 @@ dmg_overlay_type = SPECIES_MONKEY unarmed_damage_low = 1 /// monkey punches must be really weak, considering they bite people instead and their bites are weak as hell. unarmed_damage_high = 2 - unarmed_stun_threshold = 3 + unarmed_effectiveness = 0 appendage_noun = "paw" /obj/item/bodypart/arm/left/alien @@ -321,7 +320,7 @@ dmg_overlay_type = SPECIES_MONKEY unarmed_damage_low = 1 unarmed_damage_high = 2 - unarmed_stun_threshold = 3 + unarmed_effectiveness = 0 appendage_noun = "paw" /obj/item/bodypart/arm/right/alien @@ -350,9 +349,9 @@ unarmed_attack_effect = ATTACK_EFFECT_KICK body_zone = BODY_ZONE_L_LEG unarmed_attack_verb = "kick" // The lovely kick, typically only accessable by attacking a grouded foe. 1.5 times better than the punch. - unarmed_damage_low = 2 + unarmed_damage_low = 7 unarmed_damage_high = 15 - unarmed_stun_threshold = 10 + unarmed_effectiveness = 15 /// Datum describing how to offset things worn on the foot of this leg, note that an x offset won't do anything here var/datum/worn_feature_offset/worn_foot_offset @@ -440,7 +439,7 @@ dmg_overlay_type = SPECIES_MONKEY unarmed_damage_low = 2 unarmed_damage_high = 3 - unarmed_stun_threshold = 4 + unarmed_effectiveness = 0 /obj/item/bodypart/leg/left/alien icon = 'icons/mob/human/species/alien/bodyparts.dmi' @@ -534,7 +533,7 @@ dmg_overlay_type = SPECIES_MONKEY unarmed_damage_low = 2 unarmed_damage_high = 3 - unarmed_stun_threshold = 4 + unarmed_effectiveness = 0 /obj/item/bodypart/leg/right/alien icon = 'icons/mob/human/species/alien/bodyparts.dmi' diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index 062f5fe4b9d7e..332cd9a02c472 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -4,11 +4,13 @@ is_dimorphic = FALSE burn_modifier = 2 head_flags = HEAD_EYESPRITES|HEAD_DEBRAIN + biological_state = (BIO_FLESH|BIO_BLOODED) /obj/item/bodypart/chest/snail limb_id = SPECIES_SNAIL is_dimorphic = FALSE burn_modifier = 2 + biological_state = (BIO_FLESH|BIO_BLOODED) wing_types = NONE /obj/item/bodypart/arm/left/snail @@ -17,6 +19,7 @@ unarmed_attack_effect = ATTACK_EFFECT_DISARM unarmed_damage_high = 0.5 //snails are soft and squishy burn_modifier = 2 + biological_state = (BIO_FLESH|BIO_BLOODED) /obj/item/bodypart/arm/right/snail limb_id = SPECIES_SNAIL @@ -24,18 +27,21 @@ unarmed_attack_effect = ATTACK_EFFECT_DISARM unarmed_damage_high = 0.5 burn_modifier = 2 + biological_state = (BIO_FLESH|BIO_BLOODED) /obj/item/bodypart/leg/left/snail limb_id = SPECIES_SNAIL unarmed_damage_high = 0.5 burn_modifier = 2 speed_modifier = 3 //disgustingly slow + biological_state = (BIO_FLESH|BIO_BLOODED) /obj/item/bodypart/leg/right/snail limb_id = SPECIES_SNAIL unarmed_damage_high = 0.5 burn_modifier = 2 speed_modifier = 3 //disgustingly slow + biological_state = (BIO_FLESH|BIO_BLOODED) ///ABDUCTOR /obj/item/bodypart/head/abductor @@ -86,25 +92,25 @@ wing_types = NONE /obj/item/bodypart/arm/left/jelly - biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null burn_modifier = 0.5 // = 1/2x generic burn damage /obj/item/bodypart/arm/right/jelly - biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null burn_modifier = 0.5 // = 1/2x generic burn damage /obj/item/bodypart/leg/left/jelly - biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null burn_modifier = 0.5 // = 1/2x generic burn damage /obj/item/bodypart/leg/right/jelly - biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null burn_modifier = 0.5 // = 1/2x generic burn damage @@ -123,11 +129,11 @@ wing_types = NONE /obj/item/bodypart/arm/left/slime - biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_SLIMEPERSON /obj/item/bodypart/arm/right/slime - biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_SLIMEPERSON /obj/item/bodypart/leg/left/slime @@ -135,7 +141,7 @@ limb_id = SPECIES_SLIMEPERSON /obj/item/bodypart/leg/right/slime - biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_SLIMEPERSON ///LUMINESCENT @@ -152,19 +158,19 @@ wing_types = NONE /obj/item/bodypart/arm/left/luminescent - biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_LUMINESCENT /obj/item/bodypart/arm/right/luminescent - biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_LUMINESCENT /obj/item/bodypart/leg/left/luminescent - biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_LUMINESCENT /obj/item/bodypart/leg/right/luminescent - biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_LUMINESCENT ///ZOMBIE @@ -378,21 +384,21 @@ limb_id = SPECIES_MUSHROOM unarmed_damage_low = 6 unarmed_damage_high = 14 - unarmed_stun_threshold = 14 + unarmed_effectiveness = 15 burn_modifier = 1.25 /obj/item/bodypart/arm/right/mushroom limb_id = SPECIES_MUSHROOM unarmed_damage_low = 6 unarmed_damage_high = 14 - unarmed_stun_threshold = 14 + unarmed_effectiveness = 15 burn_modifier = 1.25 /obj/item/bodypart/leg/left/mushroom limb_id = SPECIES_MUSHROOM unarmed_damage_low = 9 unarmed_damage_high = 21 - unarmed_stun_threshold = 14 + unarmed_effectiveness = 20 burn_modifier = 1.25 speed_modifier = 0.75 //big big fungus @@ -400,7 +406,7 @@ limb_id = SPECIES_MUSHROOM unarmed_damage_low = 9 unarmed_damage_high = 21 - unarmed_stun_threshold = 14 + unarmed_effectiveness = 20 burn_modifier = 1.25 speed_modifier = 0.75 //big fungus big fungus @@ -495,7 +501,7 @@ bodypart_traits = list(TRAIT_CHUNKYFINGERS, TRAIT_FIST_MINING) unarmed_damage_low = 5 unarmed_damage_high = 14 - unarmed_stun_threshold = 11 + unarmed_effectiveness = 20 /obj/item/bodypart/arm/left/golem/Initialize(mapload) held_hand_offset = new( @@ -529,7 +535,7 @@ bodypart_traits = list(TRAIT_CHUNKYFINGERS, TRAIT_FIST_MINING) unarmed_damage_low = 5 unarmed_damage_high = 14 - unarmed_stun_threshold = 11 + unarmed_effectiveness = 20 /obj/item/bodypart/arm/right/golem/Initialize(mapload) held_hand_offset = new( @@ -562,7 +568,7 @@ dmg_overlay_type = null unarmed_damage_low = 7 unarmed_damage_high = 21 - unarmed_stun_threshold = 11 + unarmed_effectiveness = 25 /obj/item/bodypart/leg/right/golem icon = 'icons/mob/human/species/golems.dmi' @@ -575,7 +581,7 @@ dmg_overlay_type = null unarmed_damage_low = 7 unarmed_damage_high = 21 - unarmed_stun_threshold = 11 + unarmed_effectiveness = 25 ///flesh diff --git a/code/modules/surgery/organs/external/spines.dm b/code/modules/surgery/organs/external/spines.dm index 28a5ab3cf1a52..d7b9dd785d033 100644 --- a/code/modules/surgery/organs/external/spines.dm +++ b/code/modules/surgery/organs/external/spines.dm @@ -21,6 +21,7 @@ . = ..() if(.) paired_tail = locate(/obj/item/organ/external/tail/lizard) in receiver.organs //We want specifically a lizard tail, so we don't use the slot. + paired_tail?.paired_spines = src /obj/item/organ/external/spines/Remove(mob/living/carbon/organ_owner, special, moving) . = ..() @@ -39,7 +40,7 @@ return GLOB.spines_list /datum/bodypart_overlay/mutant/spines/get_base_icon_state() - return (wagging ? "wagging" : "") + sprite_datum.icon_state //add the wagging tag if we be wagging + return (wagging ? "wagging_" : "") + sprite_datum.icon_state //add the wagging tag if we be wagging /datum/bodypart_overlay/mutant/spines/can_draw_on_bodypart(mob/living/carbon/human/human) . = ..() diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index f509f8cd6c04c..65db70f70b5be 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -149,18 +149,16 @@ paired_spines = null /obj/item/organ/external/tail/lizard/start_wag() - . = ..() - if(paired_spines) var/datum/bodypart_overlay/mutant/spines/accessory = paired_spines.bodypart_overlay accessory.wagging = TRUE + return ..() /obj/item/organ/external/tail/lizard/stop_wag() - . = ..() - if(paired_spines) var/datum/bodypart_overlay/mutant/spines/accessory = paired_spines.bodypart_overlay accessory.wagging = FALSE + return ..() ///Lizard tail bodypart overlay datum /datum/bodypart_overlay/mutant/tail/lizard diff --git a/code/modules/surgery/organs/internal/appendix/appendix_golem.dm b/code/modules/surgery/organs/internal/appendix/appendix_golem.dm index 03b076b1b2a13..ede8dfa1e6b0b 100644 --- a/code/modules/surgery/organs/internal/appendix/appendix_golem.dm +++ b/code/modules/surgery/organs/internal/appendix/appendix_golem.dm @@ -2,7 +2,7 @@ /obj/item/organ/internal/appendix/golem name = "internal forge" desc = "This expanded digestive chamber allows golems to smelt minerals, provided that they are immersed in lava." - icon_state = "ethereal_heart" + icon_state = "ethereal_heart-off" color = COLOR_GOLEM_GRAY organ_flags = ORGAN_MINERAL /// Action which performs smelting diff --git a/code/modules/surgery/organs/internal/heart/_heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm index fb97ca7eda00b..8a5646d18146b 100644 --- a/code/modules/surgery/organs/internal/heart/_heart.dm +++ b/code/modules/surgery/organs/internal/heart/_heart.dm @@ -10,54 +10,84 @@ healing_factor = STANDARD_ORGAN_HEALING decay_factor = 2.5 * STANDARD_ORGAN_DECAY //designed to fail around 6 minutes after death - low_threshold_passed = "Prickles of pain appear then die out from within your chest..." - high_threshold_passed = "Something inside your chest hurts, and the pain isn't subsiding. You notice yourself breathing far faster than before." - now_fixed = "Your heart begins to beat again." - high_threshold_cleared = "The pain in your chest has died down, and your breathing becomes more relaxed." + low_threshold_passed = span_info("Prickles of pain appear then die out from within your chest...") + high_threshold_passed = span_warning("Something inside your chest hurts, and the pain isn't subsiding. You notice yourself breathing far faster than before.") + now_fixed = span_info("Your heart begins to beat again.") + high_threshold_cleared = span_info("The pain in your chest has died down, and your breathing becomes more relaxed.") - // Heart attack code is in code/modules/mob/living/carbon/human/life.dm - var/beating = TRUE attack_verb_continuous = list("beats", "thumps") attack_verb_simple = list("beat", "thump") - var/beat = BEAT_NONE//is this mob having a heatbeat sound played? if so, which? - var/failed = FALSE //to prevent constantly running failing code - var/operated = FALSE //whether the heart's been operated on to fix some of its damages + + // Heart attack code is in code/modules/mob/living/carbon/human/life.dm + + /// Whether the heart is currently beating. + /// Do not set this directly. Use Restart() and Stop() instead. + VAR_PRIVATE/beating = TRUE + + /// is this mob having a heatbeat sound played? if so, which? + var/beat = BEAT_NONE + /// whether the heart's been operated on to fix some of its damages + var/operated = FALSE /obj/item/organ/internal/heart/update_icon_state() + . = ..() icon_state = "[base_icon_state]-[beating ? "on" : "off"]" - return ..() /obj/item/organ/internal/heart/Remove(mob/living/carbon/heartless, special = 0) . = ..() if(!special) - addtimer(CALLBACK(src, PROC_REF(stop_if_unowned)), 120) + addtimer(CALLBACK(src, PROC_REF(stop_if_unowned)), 12 SECONDS) + beat = BEAT_NONE + owner?.stop_sound_channel(CHANNEL_HEARTBEAT) /obj/item/organ/internal/heart/proc/stop_if_unowned() - if(!owner) + if(QDELETED(src)) + return + if(IS_ROBOTIC_ORGAN(src)) + return + if(isnull(owner)) Stop() /obj/item/organ/internal/heart/attack_self(mob/user) - ..() + . = ..() + if(.) + return + if(!beating) - user.visible_message("[user] squeezes [src] to \ - make it beat again!",span_notice("You squeeze [src] to make it beat again!")) + user.visible_message( + span_notice("[user] squeezes [src] to make it beat again!"), + span_notice("You squeeze [src] to make it beat again!"), + ) Restart() - addtimer(CALLBACK(src, PROC_REF(stop_if_unowned)), 80) + addtimer(CALLBACK(src, PROC_REF(stop_if_unowned)), 8 SECONDS) + return TRUE /obj/item/organ/internal/heart/proc/Stop() + if(!beating) + return FALSE + beating = FALSE update_appearance() + beat = BEAT_NONE + owner?.stop_sound_channel(CHANNEL_HEARTBEAT) return TRUE /obj/item/organ/internal/heart/proc/Restart() + if(beating) + return FALSE + beating = TRUE update_appearance() return TRUE /obj/item/organ/internal/heart/OnEatFrom(eater, feeder) . = ..() - beating = FALSE - update_appearance() + Stop() + +/// Checks if the heart is beating. +/// Can be overridden to add more conditions for more complex hearts. +/obj/item/organ/internal/heart/proc/is_beating() + return beating /obj/item/organ/internal/heart/on_life(seconds_per_tick, times_fired) ..() @@ -66,34 +96,32 @@ if(!owner.needs_heart()) return - if(owner.client && beating) - failed = FALSE - var/sound/slowbeat = sound('sound/health/slowbeat.ogg', repeat = TRUE) - var/sound/fastbeat = sound('sound/health/fastbeat.ogg', repeat = TRUE) + // Handle "sudden" heart attack + if(!beating || (organ_flags & ORGAN_FAILING)) + if(owner.can_heartattack() && Stop()) + if(owner.stat == CONSCIOUS) + owner.visible_message(span_danger("[owner] clutches at [owner.p_their()] chest as if [owner.p_their()] heart is stopping!")) + to_chat(owner, span_userdanger("You feel a terrible pain in your chest, as if your heart has stopped!")) + return + + // Beyond deals with sound effects, so nothing needs to be done if no client + if(isnull(owner.client)) + return - if(owner.health <= owner.crit_threshold && beat != BEAT_SLOW) + if(owner.stat == SOFT_CRIT) + if(beat != BEAT_SLOW) beat = BEAT_SLOW - owner.playsound_local(get_turf(owner), slowbeat, 40, 0, channel = CHANNEL_HEARTBEAT, use_reverb = FALSE) to_chat(owner, span_notice("You feel your heart slow down...")) - if(beat == BEAT_SLOW && owner.health > owner.crit_threshold) - owner.stop_sound_channel(CHANNEL_HEARTBEAT) - beat = BEAT_NONE - - if(owner.has_status_effect(/datum/status_effect/jitter)) - if(owner.health > HEALTH_THRESHOLD_FULLCRIT && (!beat || beat == BEAT_SLOW)) - owner.playsound_local(get_turf(owner), fastbeat, 40, 0, channel = CHANNEL_HEARTBEAT, use_reverb = FALSE) - beat = BEAT_FAST - - else if(beat == BEAT_FAST) - owner.stop_sound_channel(CHANNEL_HEARTBEAT) - beat = BEAT_NONE - - if(organ_flags & ORGAN_FAILING && owner.can_heartattack() && !(HAS_TRAIT(src, TRAIT_STABLEHEART))) //heart broke, stopped beating, death imminent... unless you have veins that pump blood without a heart - if(owner.stat == CONSCIOUS) - owner.visible_message(span_danger("[owner] clutches at [owner.p_their()] chest as if [owner.p_their()] heart is stopping!"), \ - span_userdanger("You feel a terrible pain in your chest, as if your heart has stopped!")) - owner.set_heartattack(TRUE) - failed = TRUE + SEND_SOUND(owner, sound('sound/health/slowbeat.ogg', repeat = TRUE, channel = CHANNEL_HEARTBEAT, volume = 40)) + + else if(owner.stat == HARD_CRIT) + if(beat != BEAT_FAST && owner.has_status_effect(/datum/status_effect/jitter)) + SEND_SOUND(owner, sound('sound/health/fastbeat.ogg', repeat = TRUE, channel = CHANNEL_HEARTBEAT, volume = 40)) + beat = BEAT_FAST + + else if(beat == BEAT_SLOW) + owner.stop_sound_channel(CHANNEL_HEARTBEAT) + beat = BEAT_NONE /obj/item/organ/internal/heart/get_availability(datum/species/owner_species, mob/living/owner_mob) return owner_species.mutantheart @@ -222,4 +250,3 @@ owner.heal_overall_damage(brute = 15, burn = 15, required_bodytype = BODYTYPE_ORGANIC) if(owner.reagents.get_reagent_amount(/datum/reagent/medicine/ephedrine) < 20) owner.reagents.add_reagent(/datum/reagent/medicine/ephedrine, 10) - diff --git a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm index 8ad9301fe7412..78ee55b0b2841 100644 --- a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm +++ b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm @@ -1,6 +1,7 @@ /obj/item/organ/internal/heart/ethereal name = "crystal core" - icon_state = "ethereal_heart" //Welp. At least it's more unique in functionaliy. + icon_state = "ethereal_heart-on" + base_icon_state = "ethereal_heart" visual = TRUE //This is used by the ethereal species for color desc = "A crystal-like organ that functions similarly to a heart for Ethereals. It can revive its owner." @@ -18,6 +19,7 @@ /obj/item/organ/internal/heart/ethereal/Initialize(mapload) . = ..() add_atom_colour(ethereal_color, FIXED_COLOUR_PRIORITY) + update_appearance() /obj/item/organ/internal/heart/ethereal/Insert(mob/living/carbon/heart_owner, special = FALSE, drop_if_replaced = TRUE) . = ..() @@ -36,7 +38,7 @@ /obj/item/organ/internal/heart/ethereal/update_overlays() . = ..() - var/mutable_appearance/shine = mutable_appearance(icon, icon_state = "[icon_state]_shine") + var/mutable_appearance/shine = mutable_appearance(icon, icon_state = "[base_icon_state]_overlay-[beating ? "on" : "off"]") shine.appearance_flags = RESET_COLOR //No color on this, just pure white . += shine @@ -193,13 +195,13 @@ add_atom_colour(ethereal_heart.ethereal_color, FIXED_COLOUR_PRIORITY) crystal_heal_timer = addtimer(CALLBACK(src, PROC_REF(heal_ethereal)), CRYSTALIZE_HEAL_TIME, TIMER_STOPPABLE) set_light(4, 10, ethereal_heart.ethereal_color) - update_icon() + update_appearance(UPDATE_OVERLAYS) flick("ethereal_crystal_forming", src) addtimer(CALLBACK(src, PROC_REF(start_crystalization)), 1 SECONDS) /obj/structure/ethereal_crystal/proc/start_crystalization() being_built = FALSE - update_icon() + update_appearance(UPDATE_OVERLAYS) /obj/structure/ethereal_crystal/atom_destruction(damage_flag) playsound(get_turf(ethereal_heart.owner), 'sound/effects/ethereal_revive_fail.ogg', 100) diff --git a/code/modules/surgery/organs/internal/stomach/_stomach.dm b/code/modules/surgery/organs/internal/stomach/_stomach.dm index 63fefca156ccb..d97b883817dca 100644 --- a/code/modules/surgery/organs/internal/stomach/_stomach.dm +++ b/code/modules/surgery/organs/internal/stomach/_stomach.dm @@ -82,7 +82,7 @@ // transfer the reagents over to the body at the rate of the stomach metabolim // this way the body is where all reagents that are processed and react // the stomach manages how fast they are feed in a drip style - reagents.trans_id_to(body, bit.type, amount=amount) + reagents.trans_to(body, amount, target_id = bit.type) //Handle disgust if(body) diff --git a/code/modules/surgery/organs/internal/stomach/stomach_golem.dm b/code/modules/surgery/organs/internal/stomach/stomach_golem.dm index 79d3976f22d6b..5f721fa52b147 100644 --- a/code/modules/surgery/organs/internal/stomach/stomach_golem.dm +++ b/code/modules/surgery/organs/internal/stomach/stomach_golem.dm @@ -74,7 +74,7 @@ return TRUE /datum/status_effect/golem_statued/get_examine_text() - return span_warning("[owner.p_They()] are as still as a statue!") + return span_warning("[owner.p_They()] [owner.p_are()] as still as a statue!") /datum/status_effect/golem_statued/on_remove() owner.visible_message(span_notice("[owner] slowly stirs back into motion!"), span_notice("You have gathered enough strength to move your body once more.")) diff --git a/code/modules/surgery/organs/internal/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm index 9bd6bec8ccdb5..ca5e3873a2b64 100644 --- a/code/modules/surgery/organs/internal/tongue/_tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -94,8 +94,10 @@ /obj/item/organ/internal/tongue/proc/handle_speech(datum/source, list/speech_args) SIGNAL_HANDLER - if(speech_args[SPEECH_LANGUAGE] in languages_native) - return FALSE //no changes + if(speech_args[SPEECH_LANGUAGE] in languages_native) // Speaking a native language? + return FALSE // Don't modify speech + if(HAS_TRAIT(source, TRAIT_SIGN_LANG)) // No modifiers for signers - I hate this but I simply cannot get these to combine into one statement + return FALSE // Don't modify speech modify_speech(source, speech_args) /obj/item/organ/internal/tongue/proc/modify_speech(datum/source, list/speech_args) diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index c5f62883b5f11..83b1b0705ef86 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -597,33 +597,31 @@ ui.open() /obj/item/blood_filter/ui_data(mob/user) - var/list/data = list() - var/list/chem_names = list() + . = list() + + .["whitelist"] = list() for(var/key in whitelist) - chem_names += whitelist[key] - data["whitelist"] = chem_names - return data + .["whitelist"] += whitelist[key] /obj/item/blood_filter/ui_act(action, params) . = ..() if(.) return + . = TRUE switch(action) if("add") - var/selected_reagent = tgui_input_list(usr, "Select reagent to filter", "Whitelist reagent", GLOB.chemical_name_list) + var/selected_reagent = tgui_input_list(usr, "Select reagent to filter", "Whitelist reagent", GLOB.name2reagent) if(!selected_reagent) - return TRUE + return FALSE - var/chem_id = get_chem_id(selected_reagent) + var/datum/reagent/chem_id = GLOB.name2reagent[selected_reagent] if(!chem_id) - return TRUE + return FALSE if(!(chem_id in whitelist)) whitelist[chem_id] = selected_reagent - - if("remove") var/chem_name = params["reagent"] var/chem_id = get_chem_id(chem_name) diff --git a/code/modules/unit_tests/barsigns.dm b/code/modules/unit_tests/barsigns.dm index f5bb27f10643e..d1242da3d5769 100644 --- a/code/modules/unit_tests/barsigns.dm +++ b/code/modules/unit_tests/barsigns.dm @@ -35,3 +35,24 @@ TEST_FAIL("[sign_type] does not have a unique name.") existing_names += sign.name + +/** + * Test that an emped barsign displays correctly + */ +/datum/unit_test/barsigns_emp + +/datum/unit_test/barsigns_emp/Run() + var/obj/machinery/barsign/testing_sign = allocate(/obj/machinery/barsign) + var/datum/barsign/hiddensigns/empbarsign/emp_bar_sign = /datum/barsign/hiddensigns/empbarsign + + testing_sign.emp_act(EMP_HEAVY) + + // make sure we get the correct chosen_sign set + if(!istype(testing_sign.chosen_sign, emp_bar_sign)) + TEST_FAIL("[testing_sign] got EMPed but did not get its chosen_sign set correctly.") + + // make sure the sign's icon_state actually got set + var/expected_icon_state = initial(emp_bar_sign.icon_state) + if(testing_sign.icon_state != expected_icon_state) + TEST_FAIL("[testing_sign]'s icon_state was [testing_sign.icon_state] when it should have been [expected_icon_state].") + diff --git a/code/modules/unit_tests/baseturfs.dm b/code/modules/unit_tests/baseturfs.dm index 2ac016f38b9a5..9bc561deeebb0 100644 --- a/code/modules/unit_tests/baseturfs.dm +++ b/code/modules/unit_tests/baseturfs.dm @@ -53,7 +53,7 @@ // Do this instead of just ChangeTurf to guarantee that baseturfs is completely default on-init behavior RESET_TO_EXPECTED(run_loc_floor_bottom_left) - run_loc_floor_bottom_left.PlaceOnBottom(fake_turf_type = /turf/closed/wall/rock) + run_loc_floor_bottom_left.place_on_bottom(/turf/closed/wall/rock) TEST_ASSERT_EQUAL(run_loc_floor_bottom_left.type, EXPECTED_FLOOR_TYPE, "PlaceOnBottom shouldn't have changed turf") run_loc_floor_bottom_left.ScrapeAway() diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_cyberpolice.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_glitch.png similarity index 100% rename from code/modules/unit_tests/screenshots/screenshot_antag_icons_cyberpolice.png rename to code/modules/unit_tests/screenshots/screenshot_antag_icons_glitch.png diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm index d5e1e773c9256..5bc4e7d82b468 100644 --- a/code/modules/unit_tests/simple_animal_freeze.dm +++ b/code/modules/unit_tests/simple_animal_freeze.dm @@ -51,26 +51,10 @@ /mob/living/simple_animal/hostile/asteroid/elite/legionnaire, /mob/living/simple_animal/hostile/asteroid/elite/legionnairehead, /mob/living/simple_animal/hostile/asteroid/elite/pandora, - /mob/living/simple_animal/hostile/asteroid/gutlunch, - /mob/living/simple_animal/hostile/asteroid/gutlunch/grublunch, - /mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck, - /mob/living/simple_animal/hostile/asteroid/gutlunch/guthen, /mob/living/simple_animal/hostile/asteroid/polarbear, /mob/living/simple_animal/hostile/asteroid/polarbear/lesser, /mob/living/simple_animal/hostile/asteroid/wolf, /mob/living/simple_animal/hostile/dark_wizard, - /mob/living/simple_animal/hostile/guardian, - /mob/living/simple_animal/hostile/guardian/assassin, - /mob/living/simple_animal/hostile/guardian/charger, - /mob/living/simple_animal/hostile/guardian/dextrous, - /mob/living/simple_animal/hostile/guardian/explosive, - /mob/living/simple_animal/hostile/guardian/gaseous, - /mob/living/simple_animal/hostile/guardian/gravitokinetic, - /mob/living/simple_animal/hostile/guardian/lightning, - /mob/living/simple_animal/hostile/guardian/protector, - /mob/living/simple_animal/hostile/guardian/ranged, - /mob/living/simple_animal/hostile/guardian/standard, - /mob/living/simple_animal/hostile/guardian/support, /mob/living/simple_animal/hostile/illusion, /mob/living/simple_animal/hostile/illusion/escape, /mob/living/simple_animal/hostile/illusion/mirage, diff --git a/code/modules/unit_tests/spell_shapeshift.dm b/code/modules/unit_tests/spell_shapeshift.dm index 9b5804e352062..3b598e9994200 100644 --- a/code/modules/unit_tests/spell_shapeshift.dm +++ b/code/modules/unit_tests/spell_shapeshift.dm @@ -87,7 +87,7 @@ shift.shapeshift_type = shift.possible_shapes[1] shift.Grant(dummy) - var/mob/living/simple_animal/hostile/guardian/test_stand = allocate(/mob/living/simple_animal/hostile/guardian) + var/mob/living/basic/guardian/test_stand = allocate(/mob/living/basic/guardian) test_stand.set_summoner(dummy) // The stand's summoner is dummy. diff --git a/code/modules/unit_tests/strange_reagent.dm b/code/modules/unit_tests/strange_reagent.dm index 345be4befe977..6c3add3092d58 100644 --- a/code/modules/unit_tests/strange_reagent.dm +++ b/code/modules/unit_tests/strange_reagent.dm @@ -97,6 +97,8 @@ /datum/unit_test/strange_reagent/proc/test_death_no_damage(target_type) var/mob/living/target = allocate_new_target(target_type) target.death() + if(QDELETED(target)) + return update_amounts(target) strange_reagent.expose_mob(target, INGEST, amount_needed_to_revive) TEST_ASSERT_NOTEQUAL(target.stat, DEAD, "Strange Reagent did not revive a dead target type [target.type].") @@ -107,6 +109,8 @@ return target.death() + if(QDELETED(target)) + return update_amounts(target) strange_reagent.expose_mob(target, INGEST, amount_needed_to_revive) TEST_ASSERT_NOTEQUAL(target.stat, DEAD, "Strange Reagent did not revive a dead target type [target.type].") @@ -126,6 +130,8 @@ return target.death() + if(QDELETED(target)) + return update_amounts(target) strange_reagent.expose_mob(target, INGEST, amount_needed_to_full_heal) TEST_ASSERT_EQUAL(target_max_health, get_target_organic_health_manual(target), "Strange Reagent did not fully heal a dead target type [target.type] with the expected amount.") @@ -134,6 +140,8 @@ var/mob/living/target = allocate_new_target(target_type) if(!damage_target_to_percentage(target, strange_reagent.max_revive_damage_ratio * 0.9)) // 10% under the damage cap return + if(QDELETED(target)) + return update_amounts(target) strange_reagent.expose_mob(target, INGEST, amount_needed_to_revive) @@ -143,7 +151,9 @@ var/mob/living/target = allocate_new_target(target_type) if(!damage_target_to_percentage(target, strange_reagent.max_revive_damage_ratio * 1.1)) // 10% over the damage cap return - + if(QDELETED(target)) + return + update_amounts(target) strange_reagent.expose_mob(target, INGEST, amount_needed_to_revive) TEST_ASSERT_EQUAL(target.stat, DEAD, "Strange Reagent revived a target type [target.type] with more than double their max health in damage.") diff --git a/code/modules/uplink/uplink_items/bundle.dm b/code/modules/uplink/uplink_items/bundle.dm index a930784fe1462..f236aa4da253a 100644 --- a/code/modules/uplink/uplink_items/bundle.dm +++ b/code/modules/uplink/uplink_items/bundle.dm @@ -146,13 +146,13 @@ Rumored to contain a valuable assortment of items based on your current reputation, but you never know. Contents are sorted to always be worth 80 TC. \ The Syndicate will only provide one surplus item per agent." cost = 20 - item = /obj/structure/closet/crate/syndicrate + item = /obj/structure/closet/crate/secure/syndicrate stock_key = UPLINK_SHARED_STOCK_SURPLUS crate_tc_value = 80 - crate_type = /obj/structure/closet/crate/syndicrate + crate_type = /obj/structure/closet/crate/secure/syndicrate /// edited version of fill crate for super surplus to ensure it can only be unlocked with the syndicrate key -/datum/uplink_item/bundles_tc/surplus/united/fill_crate(obj/structure/closet/crate/syndicrate/surplus_crate, list/possible_items) +/datum/uplink_item/bundles_tc/surplus/united/fill_crate(obj/structure/closet/crate/secure/syndicrate/surplus_crate, list/possible_items) if(!istype(surplus_crate)) return var/tc_budget = crate_tc_value diff --git a/code/modules/uplink/uplink_items/dangerous.dm b/code/modules/uplink/uplink_items/dangerous.dm index f1788c6e1dec3..e84657e7884f9 100644 --- a/code/modules/uplink/uplink_items/dangerous.dm +++ b/code/modules/uplink/uplink_items/dangerous.dm @@ -82,7 +82,7 @@ desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an \ organic host as a home base and source of fuel. Holoparasites come in various types and share damage with their host." progression_minimum = 30 MINUTES - item = /obj/item/guardiancreator/tech/choose/traitor + item = /obj/item/guardian_creator/tech cost = 18 surplus = 0 purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) diff --git a/code/modules/uplink/uplink_items/job.dm b/code/modules/uplink/uplink_items/job.dm index 01bef40289eb4..d0c1379c0061a 100644 --- a/code/modules/uplink/uplink_items/job.dm +++ b/code/modules/uplink/uplink_items/job.dm @@ -146,6 +146,13 @@ cost = 11 restricted_roles = list(JOB_STATION_ENGINEER, JOB_CHIEF_ENGINEER) +/datum/uplink_item/role_restricted/rebarxbowsyndie + name = "Syndicate Rebar Crossbow" + desc = "A much more proffessional version of the engineer's bootleg rebar crossbow. 3 shot mag, quicker loading, and better ammo. Owners manual included." + item = /obj/item/storage/box/syndie_kit/rebarxbowsyndie + cost = 10 + restricted_roles = list(JOB_STATION_ENGINEER, JOB_CHIEF_ENGINEER) + /datum/uplink_item/role_restricted/magillitis_serum name = "Magillitis Serum Autoinjector" desc = "A single-use autoinjector which contains an experimental serum that causes rapid muscular growth in Hominidae. \ diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm index f586a9656e82b..2323eb942e4a9 100644 --- a/code/modules/vehicles/mecha/_mecha.dm +++ b/code/modules/vehicles/mecha/_mecha.dm @@ -521,7 +521,8 @@ if(!overclock_mode && overclock_temp > 0) overclock_temp -= seconds_per_tick return - overclock_temp = min(overclock_temp + seconds_per_tick, overclock_temp_danger * 2) + var/temp_gain = seconds_per_tick * (1 + 1 / movedelay) + overclock_temp = min(overclock_temp + temp_gain, overclock_temp_danger * 2) if(overclock_temp < overclock_temp_danger) return if(overclock_temp >= overclock_temp_danger && overclock_safety) diff --git a/code/modules/vehicles/mecha/combat/savannah_ivanov.dm b/code/modules/vehicles/mecha/combat/savannah_ivanov.dm index 1851e6b39b19a..1aa4223b98c64 100644 --- a/code/modules/vehicles/mecha/combat/savannah_ivanov.dm +++ b/code/modules/vehicles/mecha/combat/savannah_ivanov.dm @@ -292,7 +292,7 @@ /** * ## end_missile_targeting * - * Called by the ivanov strike datum action or other actions that would end targetting + * Called by the ivanov strike datum action or other actions that would end targeting * Unhooks signals into clicking to call drop_missile plus other flavor like the overlay */ /datum/action/vehicle/sealed/mecha/ivanov_strike/proc/end_missile_targeting() diff --git a/code/modules/vehicles/mecha/equipment/mecha_equipment.dm b/code/modules/vehicles/mecha/equipment/mecha_equipment.dm index aea1a21c0829e..6c8d178c5b991 100644 --- a/code/modules/vehicles/mecha/equipment/mecha_equipment.dm +++ b/code/modules/vehicles/mecha/equipment/mecha_equipment.dm @@ -121,7 +121,7 @@ * Cooldown proc variant for using do_afters between activations instead of timers * Example of usage is mech drills, rcds * arguments: - * * target: targetted atom for action activation + * * target: targeted atom for action activation * * user: occupant to display do after for * * interaction_key: interaction key to pass to [/proc/do_after] */ diff --git a/code/modules/vehicles/mecha/equipment/tools/medical_tools.dm b/code/modules/vehicles/mecha/equipment/tools/medical_tools.dm index ca3b4f2f47945..e16a142dd2e04 100644 --- a/code/modules/vehicles/mecha/equipment/tools/medical_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/medical_tools.dm @@ -198,7 +198,7 @@ log_message("Injecting [patient] with [to_inject] units of [R.name].", LOG_MECHA) for(var/driver in chassis.return_drivers()) log_combat(driver, patient, "injected", "[name] ([R] - [to_inject] units)") - SG.reagents.trans_id_to(patient,R.type,to_inject) + SG.reagents.trans_to(patient, to_inject, target_id = R.type) /obj/item/mecha_parts/mecha_equipment/medical/sleeper/container_resist_act(mob/living/user) go_out() diff --git a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm index b2a69357a82c2..5e27fb39dff94 100644 --- a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm @@ -17,31 +17,30 @@ var/killer_clamp = FALSE ///How much base damage this clamp does var/clamp_damage = 20 - ///Var for the chassis we are attached to, needed to access ripley contents and such - var/obj/vehicle/sealed/mecha/ripley/cargo_holder ///Audio for using the hydraulic clamp var/clampsound = 'sound/mecha/hydraulic.ogg' + ///Chassis but typed for the cargo_hold var + var/obj/vehicle/sealed/mecha/ripley/workmech /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/attach(obj/vehicle/sealed/mecha/new_mecha) . = ..() - if(istype(chassis, /obj/vehicle/sealed/mecha/ripley)) - cargo_holder = chassis + workmech = chassis ADD_TRAIT(chassis, TRAIT_OREBOX_FUNCTIONAL, TRAIT_MECH_EQUIPMENT(type)) /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/detach(atom/moveto) REMOVE_TRAIT(chassis, TRAIT_OREBOX_FUNCTIONAL, TRAIT_MECH_EQUIPMENT(type)) - cargo_holder = null + workmech = null return ..() /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/action(mob/living/source, atom/target, list/modifiers) if(!action_checks(target)) return - if(!cargo_holder) - return + if(!workmech.cargo_hold) + CRASH("Mech [chassis] has a clamp device, but no internal storage. This should be impossible.") if(ismecha(target)) var/obj/vehicle/sealed/mecha/M = target var/have_ammo - for(var/obj/item/mecha_ammo/box in cargo_holder.cargo) + for(var/obj/item/mecha_ammo/box in workmech.cargo_hold.contents) if(istype(box, /obj/item/mecha_ammo) && box.rounds) have_ammo = TRUE if(M.ammo_resupply(box, source, TRUE)) @@ -66,7 +65,7 @@ if(clamptarget.anchored) to_chat(source, "[icon2html(src, source)][span_warning("[target] is firmly secured!")]") return - if(LAZYLEN(cargo_holder.cargo) >= cargo_holder.cargo_capacity) + if(workmech.cargo_hold.contents.len >= workmech.cargo_hold.cargo_capacity) to_chat(source, "[icon2html(src, source)][span_warning("Not enough room in cargo compartment!")]") return playsound(chassis, clampsound, 50, FALSE, -6) @@ -75,13 +74,12 @@ if(!do_after_cooldown(target, source)) clamptarget.set_anchored(initial(clamptarget.anchored)) return - LAZYADD(cargo_holder.cargo, clamptarget) - clamptarget.forceMove(chassis) + clamptarget.forceMove(workmech.cargo_hold) clamptarget.set_anchored(FALSE) - if(!cargo_holder.ore_box && istype(clamptarget, /obj/structure/ore_box)) - cargo_holder.ore_box = clamptarget + if(!chassis.ore_box && istype(clamptarget, /obj/structure/ore_box)) + chassis.ore_box = clamptarget to_chat(source, "[icon2html(src, source)][span_notice("[target] successfully loaded.")]") - log_message("Loaded [clamptarget]. Cargo compartment capacity: [cargo_holder.cargo_capacity - LAZYLEN(cargo_holder.cargo)]", LOG_MECHA) + log_message("Loaded [clamptarget]. Cargo compartment capacity: [workmech.cargo_hold.cargo_capacity - workmech.cargo_hold.contents.len]", LOG_MECHA) else if(isliving(target)) var/mob/living/M = target @@ -172,7 +170,7 @@ var/datum/reagents/water_reagents = new /datum/reagents(required_amount/8) //required_amount/8, because the water usage is split between eight sprays. As of this comment, required_amount/8 = 10u each. water.reagents = water_reagents water_reagents.my_atom = water - reagents.trans_to(water, required_amount/8) + reagents.trans_to(water, required_amount / 8) water.move_at(get_step(chassis, get_dir(targetturf, chassis)), 2, 4) //Target is the tile opposite of the mech as the starting turf. playsound(chassis, 'sound/effects/extinguish.ogg', 75, TRUE, -3) @@ -331,15 +329,17 @@ //Dunno where else to put this so shrug /obj/item/mecha_parts/mecha_equipment/ripleyupgrade name = "Ripley MK-II Conversion Kit" - desc = "A pressurized canopy attachment kit for an Autonomous Power Loader Unit \"Ripley\" MK-I mecha, to convert it to the slower, but space-worthy MK-II design. This kit cannot be removed, once applied." + desc = "A pressurized canopy attachment kit for an Autonomous Power Loader Unit \"Ripley\" MK-I exosuit, to convert it to the slower, but space-worthy MK-II design. This kit cannot be removed, once applied." icon_state = "ripleyupgrade" mech_flags = EXOSUIT_MODULE_RIPLEY + var/result = /obj/vehicle/sealed/mecha/ripley/mk2 /obj/item/mecha_parts/mecha_equipment/ripleyupgrade/can_attach(obj/vehicle/sealed/mecha/ripley/mecha, attach_right = FALSE, mob/user) if(mecha.type != /obj/vehicle/sealed/mecha/ripley) to_chat(user, span_warning("This conversion kit can only be applied to APLU MK-I models.")) return FALSE - if(LAZYLEN(mecha.cargo)) + var/obj/vehicle/sealed/mecha/ripley/workmech = mecha + if(LAZYLEN(workmech.cargo_hold)) to_chat(user, span_warning("[mecha]'s cargo hold must be empty before this conversion kit can be applied.")) return FALSE if(!(mecha.mecha_flags & PANEL_OPEN)) //non-removable upgrade, so lets make sure the pilot or owner has their say. @@ -354,43 +354,56 @@ return TRUE /obj/item/mecha_parts/mecha_equipment/ripleyupgrade/attach(obj/vehicle/sealed/mecha/markone, attach_right = FALSE) - var/obj/vehicle/sealed/mecha/ripley/mk2/marktwo = new (get_turf(markone),1) - if(!marktwo) + var/obj/vehicle/sealed/mecha/newmech = new result(get_turf(markone),1) + if(!newmech) return - QDEL_NULL(marktwo.cell) + QDEL_NULL(newmech.cell) if (markone.cell) - marktwo.cell = markone.cell - markone.cell.forceMove(marktwo) + newmech.cell = markone.cell + markone.cell.forceMove(newmech) markone.cell = null - QDEL_NULL(marktwo.scanmod) + QDEL_NULL(newmech.scanmod) if (markone.scanmod) - marktwo.scanmod = markone.scanmod - markone.scanmod.forceMove(marktwo) + newmech.scanmod = markone.scanmod + markone.scanmod.forceMove(newmech) markone.scanmod = null - QDEL_NULL(marktwo.capacitor) + QDEL_NULL(newmech.capacitor) if (markone.capacitor) - marktwo.capacitor = markone.capacitor - markone.capacitor.forceMove(marktwo) + newmech.capacitor = markone.capacitor + markone.capacitor.forceMove(newmech) markone.capacitor = null - QDEL_NULL(marktwo.servo) + QDEL_NULL(newmech.servo) if (markone.servo) - marktwo.servo = markone.servo - markone.servo.forceMove(marktwo) + newmech.servo = markone.servo + markone.servo.forceMove(newmech) markone.servo = null - marktwo.update_part_values() + newmech.update_part_values() for(var/obj/item/mecha_parts/mecha_equipment/equipment in markone.flat_equipment) //Move the equipment over... if(istype(equipment, /obj/item/mecha_parts/mecha_equipment/ejector)) - continue //the MK2 already has one. + continue //the new mech already has one. var/righthandgun = markone.equip_by_category[MECHA_R_ARM] == equipment - equipment.detach(marktwo) - equipment.attach(marktwo, righthandgun) - marktwo.dna_lock = markone.dna_lock - marktwo.mecha_flags = markone.mecha_flags - marktwo.strafe = markone.strafe + equipment.detach(newmech) + equipment.attach(newmech, righthandgun) + newmech.dna_lock = markone.dna_lock + newmech.mecha_flags = markone.mecha_flags + newmech.strafe = markone.strafe //Integ set to the same percentage integ as the old mecha, rounded to be whole number - marktwo.update_integrity(round((markone.get_integrity() / markone.max_integrity) * marktwo.get_integrity())) + newmech.update_integrity(round((markone.get_integrity() / markone.max_integrity) * newmech.get_integrity())) if(markone.name != initial(markone.name)) - marktwo.name = markone.name + newmech.name = markone.name markone.wreckage = FALSE qdel(markone) - playsound(get_turf(marktwo),'sound/items/ratchet.ogg',50,TRUE) + playsound(get_turf(newmech),'sound/items/ratchet.ogg',50,TRUE) + +/obj/item/mecha_parts/mecha_equipment/ripleyupgrade/paddy + name = "Paddy Conversion Kit" + desc = "A hardpoint modification kit for an Autonomous Power Loader Unit \"Ripley\" MK-I exosuit, to convert it to the Paddy lightweight security design. This kit cannot be removed, once applied." + icon_state = "paddyupgrade" + mech_flags = EXOSUIT_MODULE_RIPLEY + result = /obj/vehicle/sealed/mecha/ripley/paddy + +/obj/item/mecha_parts/mecha_equipment/ripleyupgrade/paddy/can_attach(obj/vehicle/sealed/mecha/ripley/mecha, attach_right = FALSE, mob/user) + if(mecha.equip_by_category[MECHA_L_ARM] || mecha.equip_by_category[MECHA_R_ARM]) //Paddys can't use RIPLEY-type equipment + to_chat(user, span_warning("This kit cannot be applied with hardpoint equipment attached.")) + return FALSE + return ..() diff --git a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm index a879341629650..bd2198025151f 100644 --- a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm +++ b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm @@ -540,3 +540,76 @@ equip_cooldown = 60 det_time = 20 mech_flags = EXOSUIT_MODULE_HONK + +///long claw of the law +/obj/item/mecha_parts/mecha_equipment/weapon/paddy_claw + name = "hydraulic claw" + desc = "A modified hydraulic clamp, for use exclusively with the Paddy exosuit. Non-lethally apprehends suspects." + icon_state = "paddy_claw" + equip_cooldown = 15 + energy_drain = 10 + tool_behaviour = TOOL_RETRACTOR + range = MECHA_MELEE + toolspeed = 0.8 + mech_flags = EXOSUIT_MODULE_PADDY + ///Chassis but typed for the cargo_hold var + var/obj/vehicle/sealed/mecha/ripley/secmech + ///Audio for using the hydraulic clamp + var/clampsound = 'sound/mecha/hydraulic.ogg' + ///Var for the cuff type. Basically stole how cuffing works from secbots + var/cuff_type = /obj/item/restraints/handcuffs/cable/zipties/used + ///Var for autocuff, can be toggled in the mech interface. + var/autocuff = TRUE + + +/obj/item/mecha_parts/mecha_equipment/weapon/paddy_claw/attach(obj/vehicle/sealed/mecha/new_mecha) + . = ..() + secmech = chassis + +/obj/item/mecha_parts/mecha_equipment/weapon/paddy_claw/detach(atom/moveto) + secmech = null + return ..() + +/obj/item/mecha_parts/mecha_equipment/weapon/paddy_claw/action(mob/living/source, atom/target, list/modifiers) + if(!secmech.cargo_hold) //We did try + CRASH("Mech [chassis] has a claw device, but no internal storage. This should be impossible.") + if(ismob(target)) + var/mob/living/mobtarget = target + if(mobtarget.move_resist == MOVE_FORCE_OVERPOWERING) //No megafauna or bolted AIs, please. + to_chat(source, "[span_warning("[src] is unable to lift [mobtarget].")]") + return + if(secmech.cargo_hold.contents.len >= secmech.cargo_hold.cargo_capacity) + to_chat(source, "[icon2html(src, source)][span_warning("Not enough room in cargo compartment!")]") + return + + playsound(chassis, clampsound, 50, FALSE, -6) + mobtarget.visible_message(span_notice("[chassis] lifts [mobtarget] into its internal holding cell."),span_userdanger("[chassis] grips you with [src] and prepares to load you into [secmech.cargo_hold]!")) + if(!do_after_cooldown(mobtarget, source)) + return + mobtarget.forceMove(secmech.cargo_hold) + log_message("Loaded [mobtarget]. Cargo compartment capacity: [secmech.cargo_hold.cargo_capacity - secmech.cargo_hold.contents.len]", LOG_MECHA) + to_chat(source, "[icon2html(src, source)][span_notice("[mobtarget] successfully loaded.")]") + to_chat(mobtarget, "[span_warning("You have been moved into [secmech.cargo_hold]. You can attempt to resist out if you wish.")]") + if(autocuff && iscarbon(target)) + var/mob/living/carbon/carbontarget = target + carbontarget.set_handcuffed(new cuff_type(carbontarget)) + carbontarget.update_handcuffed() + return + + if(!istype(target, /obj/machinery/door)) + return + var/obj/machinery/door/target_door = target + playsound(chassis, clampsound, 50, FALSE, -6) + target_door.try_to_crowbar(src, source) + +/obj/item/mecha_parts/mecha_equipment/weapon/paddy_claw/get_snowflake_data() + return list( + "snowflake_id" = MECHA_SNOWFLAKE_ID_CLAW, + "autocuff" = autocuff, + ) + +/obj/item/mecha_parts/mecha_equipment/weapon/paddy_claw/handle_ui_act(action, list/params) + switch(action) + if("togglecuff") + autocuff = !autocuff + return TRUE diff --git a/code/modules/vehicles/mecha/mech_fabricator.dm b/code/modules/vehicles/mecha/mech_fabricator.dm index 56b3cd2138c5e..c3e5abc39f0fc 100644 --- a/code/modules/vehicles/mecha/mech_fabricator.dm +++ b/code/modules/vehicles/mecha/mech_fabricator.dm @@ -403,9 +403,6 @@ . = TRUE - add_fingerprint(usr) - usr.set_machine(src) - switch(action) if("build") var/designs = params["designs"] @@ -499,15 +496,5 @@ return FALSE return default_deconstruction_crowbar(I) -/obj/machinery/mecha_part_fabricator/proc/is_insertion_ready(mob/user) - if(panel_open) - to_chat(user, span_warning("You can't load [src] while it's opened!")) - return FALSE - if(being_built) - to_chat(user, span_warning("\The [src] is currently processing! Please wait until completion.")) - return FALSE - - return TRUE - /obj/machinery/mecha_part_fabricator/maint link_on_init = FALSE diff --git a/code/modules/vehicles/mecha/mecha_construction_paths.dm b/code/modules/vehicles/mecha/mecha_construction_paths.dm index fb572f7d1282e..3ff01b511669d 100644 --- a/code/modules/vehicles/mecha/mecha_construction_paths.dm +++ b/code/modules/vehicles/mecha/mecha_construction_paths.dm @@ -503,7 +503,7 @@ list( "key" = /obj/item/circuitboard/mecha/honker/targeting, "action" = ITEM_DELETE, - "desc" = "Prank targetting board can be added!", + "desc" = "Prank targeting board can be added!", "forward_message" = "added prank" ), list( diff --git a/code/modules/vehicles/mecha/mecha_control_console.dm b/code/modules/vehicles/mecha/mecha_control_console.dm index 771ed97268bfd..6cb5ec6bde853 100644 --- a/code/modules/vehicles/mecha/mecha_control_console.dm +++ b/code/modules/vehicles/mecha/mecha_control_console.dm @@ -36,9 +36,9 @@ tracker_ref = REF(MT) ) if(istype(M, /obj/vehicle/sealed/mecha/ripley)) - var/obj/vehicle/sealed/mecha/ripley/RM = M + var/obj/vehicle/sealed/mecha/ripley/workmech = M mech_data += list( - cargo_space = round((LAZYLEN(RM.cargo) / RM.cargo_capacity) * 100) + cargo_space = round(workmech.cargo_hold.contents.len / workmech.cargo_hold.cargo_capacity * 100) ) data["mechs"] += list(mech_data) @@ -101,8 +101,8 @@ Pilot: [english_list(chassis.return_drivers(), nothing_text = "None")]
Location: [get_area_name(chassis, TRUE) || "Unknown"]"} if(istype(chassis, /obj/vehicle/sealed/mecha/ripley)) - var/obj/vehicle/sealed/mecha/ripley/RM = chassis - answer += "
Used Cargo Space: [round((LAZYLEN(RM.cargo) / RM.cargo_capacity * 100), 0.01)]%" + var/obj/item/mecha_parts/mecha_equipment/ejector/cargo_holder = locate(/obj/item/mecha_parts/mecha_equipment/ejector) in chassis.equip_by_category[MECHA_UTILITY] + answer += "
Used Cargo Space: [round((cargo_holder.contents.len / cargo_holder.cargo_capacity * 100), 0.01)]%" return answer diff --git a/code/modules/vehicles/mecha/mecha_damage.dm b/code/modules/vehicles/mecha/mecha_damage.dm index 08f294f202f94..8a06aaf298fa5 100644 --- a/code/modules/vehicles/mecha/mecha_damage.dm +++ b/code/modules/vehicles/mecha/mecha_damage.dm @@ -9,7 +9,7 @@ * Pretty simple, adds armor, you can choose against what * ## Internal damage * When taking damage will force you to take some time to repair, encourages improvising in a fight - * Targetting different def zones will damage them to encurage a more strategic approach to fights + * Targeting different def zones will damage them to encurage a more strategic approach to fights * where they target the "dangerous" modules */ diff --git a/code/modules/vehicles/mecha/mecha_defense.dm b/code/modules/vehicles/mecha/mecha_defense.dm index 3df6ba94992d8..746039e755268 100644 --- a/code/modules/vehicles/mecha/mecha_defense.dm +++ b/code/modules/vehicles/mecha/mecha_defense.dm @@ -9,11 +9,11 @@ * Pretty simple, adds armor, you can choose against what * ## Internal damage * When taking damage will force you to take some time to repair, encourages improvising in a fight - * Targetting different def zones will damage them to encurage a more strategic approach to fights + * Targeting different def zones will damage them to encurage a more strategic approach to fights * where they target the "dangerous" modules */ -/// tries to damage mech equipment depending on damage and where is being targetted +/// tries to damage mech equipment depending on damage and where is being targeted /obj/vehicle/sealed/mecha/proc/try_damage_component(damage, def_zone) if(damage < component_damage_threshold) return diff --git a/code/modules/vehicles/mecha/mecha_wreckage.dm b/code/modules/vehicles/mecha/mecha_wreckage.dm index 3540891d336cd..8f3e821a5bfae 100644 --- a/code/modules/vehicles/mecha/mecha_wreckage.dm +++ b/code/modules/vehicles/mecha/mecha_wreckage.dm @@ -165,6 +165,10 @@ name = "\improper Ripley MK-II wreckage" icon_state = "ripleymkii-broken" +/obj/structure/mecha_wreckage/ripley/paddy + name = "\improper Paddy wreckage" + icon_state = "paddy-broken" + /obj/structure/mecha_wreckage/clarke name = "\improper Clarke wreckage" icon_state = "clarke-broken" diff --git a/code/modules/vehicles/mecha/working/clarke.dm b/code/modules/vehicles/mecha/working/clarke.dm index e31690f65b929..2ec0b4a473648 100644 --- a/code/modules/vehicles/mecha/working/clarke.dm +++ b/code/modules/vehicles/mecha/working/clarke.dm @@ -7,6 +7,7 @@ max_temperature = 65000 max_integrity = 200 movedelay = 1.25 + overclock_coeff = 1.25 resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF lights_power = 7 step_energy_drain = 12 //slightly higher energy drain since you movin those wheels FAST diff --git a/code/modules/vehicles/mecha/working/ripley.dm b/code/modules/vehicles/mecha/working/ripley.dm index d2b13d48d26ab..9bc6ea7575110 100644 --- a/code/modules/vehicles/mecha/working/ripley.dm +++ b/code/modules/vehicles/mecha/working/ripley.dm @@ -5,6 +5,7 @@ base_icon_state = "ripley" silicon_icon_state = "ripley-empty" movedelay = 1.5 //Move speed, lower is faster. + overclock_coeff = 1.25 max_temperature = 20000 max_integrity = 200 lights_power = 7 @@ -35,10 +36,8 @@ ) /// Amount of Goliath hides attached to the mech var/hides = 0 - /// List of all things in Ripley's Cargo Compartment - var/list/cargo - /// How much things Ripley can carry in their Cargo Compartment - var/cargo_capacity = 15 + /// Reference to the Cargo Hold equipment. + var/obj/item/mecha_parts/mecha_equipment/ejector/cargo_hold /// How fast the mech is in low pressure var/fast_pressure_step_in = 1.5 /// How fast the mech is in normal pressure @@ -66,13 +65,6 @@ bullet = 5 laser = 5 -/obj/vehicle/sealed/mecha/ripley/Destroy() - for(var/atom/movable/A in cargo) - A.forceMove(drop_location()) - step_rand(A) - QDEL_LIST(cargo) - return ..() - /obj/vehicle/sealed/mecha/ripley/mk2 desc = "Autonomous Power Loader Unit MK-II. This prototype Ripley is refitted with a pressurized cabin, trading its prior speed for atmospheric protection and armor." name = "\improper APLU MK-II \"Ripley\"" @@ -99,6 +91,110 @@ fire = 100 acid = 100 +/obj/vehicle/sealed/mecha/ripley/paddy + desc = "Autonomous Power Loader Unit Subtype Paddy. A Modified MK-I Ripley design intended for light security use." + name = "\improper APLU \"Paddy\"" + icon_state = "paddy" + base_icon_state = "paddy" + max_temperature = 20000 + max_integrity = 250 + mech_type = EXOSUIT_MODULE_PADDY + possible_int_damage = MECHA_INT_FIRE|MECHA_INT_CONTROL_LOST|MECHA_INT_SHORT_CIRCUIT + accesses = list(ACCESS_MECH_SCIENCE, ACCESS_MECH_SECURITY) + armor_type = /datum/armor/mecha_paddy + wreckage = /obj/structure/mecha_wreckage/ripley/paddy + silicon_icon_state = "paddy-empty" + equip_by_category = list( + MECHA_L_ARM = null, + MECHA_R_ARM = null, + MECHA_UTILITY = list(/obj/item/mecha_parts/mecha_equipment/ejector/seccage), + MECHA_POWER = list(), + MECHA_ARMOR = list(), + ) + ///Siren Lights/Sound State + var/siren = FALSE + ///Overlay for Siren Lights + var/mutable_appearance/sirenlights + ///Looping sound datum for the Siren audio + var/datum/looping_sound/siren/weewooloop + +/datum/armor/mecha_paddy + melee = 40 + bullet = 20 + laser = 10 + energy = 20 + bomb = 40 + fire = 100 + acid = 100 + +/obj/vehicle/sealed/mecha/ripley/paddy/Initialize(mapload) + . = ..() + weewooloop = new(src, FALSE, FALSE) + weewooloop.volume = 100 + +/obj/vehicle/sealed/mecha/ripley/paddy/generate_actions() + . = ..() + initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/siren) + +/obj/vehicle/sealed/mecha/ripley/paddy/mob_exit(mob/M, silent = FALSE, randomstep = FALSE, forced = FALSE) + var/obj/item/mecha_parts/mecha_equipment/ejector/seccage/cargo_holder = locate(/obj/item/mecha_parts/mecha_equipment/ejector/seccage) in equip_by_category[MECHA_UTILITY] + for(var/mob/contained in cargo_holder) + cargo_holder.cheese_it(contained) + togglesiren(force_off = TRUE) + return ..() + +/obj/vehicle/sealed/mecha/ripley/paddy/proc/togglesiren(force_off = FALSE) + if(force_off || siren) + weewooloop.stop() + siren = FALSE + else + weewooloop.start() + siren = TRUE + for(var/mob/occupant as anything in occupants) + balloon_alert(occupant, "siren [siren ? "activated" : "disabled"]") + var/datum/action/act = locate(/datum/action/vehicle/sealed/mecha/siren) in occupant.actions + act.button_icon_state = "mech_siren_[siren ? "on" : "off"]" + act.build_all_button_icons() + update_appearance(UPDATE_OVERLAYS) + +/obj/vehicle/sealed/mecha/ripley/paddy/update_overlays() + . = ..() + if(!siren) + return + sirenlights = new() + sirenlights.icon = icon + sirenlights.icon_state = "paddy_sirens" + SET_PLANE_EXPLICIT(sirenlights, ABOVE_LIGHTING_PLANE, src) + . += sirenlights + +/obj/vehicle/sealed/mecha/ripley/paddy/Destroy() + QDEL_NULL(weewooloop) + return ..() + +/datum/action/vehicle/sealed/mecha/siren + name = "Toggle External Siren and Lights" + button_icon_state = "mech_siren_off" + +/datum/action/vehicle/sealed/mecha/siren/New() + . = ..() + var/obj/vehicle/sealed/mecha/ripley/paddy/secmech = chassis + button_icon_state = "mech_siren_[secmech?.siren ? "on" : "off"]" + +/datum/action/vehicle/sealed/mecha/siren/Trigger(trigger_flags, forced_state = FALSE) + var/obj/vehicle/sealed/mecha/ripley/paddy/secmech = chassis + secmech.togglesiren() + +/obj/vehicle/sealed/mecha/ripley/paddy/preset + accesses = list(ACCESS_SECURITY) + mecha_flags = CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE | ID_LOCK_ON + equip_by_category = list( + MECHA_L_ARM = /obj/item/mecha_parts/mecha_equipment/weapon/energy/disabler, + MECHA_R_ARM = /obj/item/mecha_parts/mecha_equipment/weapon/paddy_claw, + MECHA_UTILITY = list(/obj/item/mecha_parts/mecha_equipment/ejector/seccage), + MECHA_POWER = list(), + MECHA_ARMOR = list(), + ) + /obj/vehicle/sealed/mecha/ripley/deathripley desc = "OH SHIT IT'S THE DEATHSQUAD WE'RE ALL GONNA DIE" name = "\improper DEATH-RIPLEY" @@ -193,37 +289,54 @@ GLOBAL_DATUM(cargo_ripley, /obj/vehicle/sealed/mecha/ripley/cargo) servo = new /obj/item/stock_parts/servo(src) update_part_values() -/obj/vehicle/sealed/mecha/ripley/Exit(atom/movable/leaving, direction) - if(leaving in cargo) - return FALSE - return ..() - -/obj/vehicle/sealed/mecha/ripley/contents_explosion(severity, target) - for(var/i in cargo) - var/obj/cargoobj = i - if(prob(10 * severity)) - LAZYREMOVE(cargo, cargoobj) - cargoobj.forceMove(drop_location()) - return ..() - /obj/item/mecha_parts/mecha_equipment/ejector - name = "Cargo compartment" + name = "cargo compartment" desc = "Holds cargo loaded with a hydraulic clamp." icon_state = "mecha_bin" equipment_slot = MECHA_UTILITY detachable = FALSE + ///Number of atoms we can store + var/cargo_capacity = 15 + +/obj/item/mecha_parts/mecha_equipment/ejector/attach() + . = ..() + var/obj/vehicle/sealed/mecha/ripley/workmech = chassis + workmech.cargo_hold = src + + +/obj/item/mecha_parts/mecha_equipment/ejector/Destroy() + for(var/atom/stored in contents) + forceMove(stored, drop_location()) + step_rand(stored) + return ..() + +/obj/item/mecha_parts/mecha_equipment/ejector/contents_explosion(severity, target) + for(var/obj/stored in contents) + if(prob(10 * severity)) + stored.forceMove(drop_location()) + return ..() + +/obj/item/mecha_parts/mecha_equipment/ejector/relay_container_resist_act(mob/living/user, obj/container) + to_chat(user, span_notice("You lean on the back of [container] and start pushing so it falls out of [src].")) + if(do_after(user, 300, target = container)) + if(!user || user.stat != CONSCIOUS || user.loc != src || container.loc != src ) + return + to_chat(user, span_notice("You successfully pushed [container] out of [src]!")) + container.forceMove(drop_location()) + else + if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded. + to_chat(user, span_warning("You fail to push [container] out of [src]!")) /obj/item/mecha_parts/mecha_equipment/ejector/get_snowflake_data() - var/obj/vehicle/sealed/mecha/ripley/miner = chassis var/list/data = list( "snowflake_id" = MECHA_SNOWFLAKE_ID_EJECTOR, - "cargo_capacity" = miner.cargo_capacity, + "cargo_capacity" = cargo_capacity, "cargo" = list() ) - for(var/obj/crate in miner.cargo) + for(var/atom/entry in contents) data["cargo"] += list(list( - "name" = crate.name, - "ref" = REF(crate), + "name" = entry.name, + "ref" = REF(entry), )) return data @@ -232,30 +345,89 @@ GLOBAL_DATUM(cargo_ripley, /obj/vehicle/sealed/mecha/ripley/cargo) if(.) return TRUE if(action == "eject") - var/obj/vehicle/sealed/mecha/ripley/miner = chassis - var/obj/crate = locate(params["cargoref"]) in miner.cargo + var/obj/crate = locate(params["cargoref"]) in contents if(!crate) return FALSE - to_chat(miner.occupants, "[icon2html(src, miner.occupants)][span_notice("You unload [crate].")]") + to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][span_notice("You unload [crate].")]") crate.forceMove(drop_location()) - LAZYREMOVE(miner.cargo, crate) - if(crate == miner.ore_box) - miner.ore_box = null + if(crate == chassis.ore_box) + chassis.ore_box = null playsound(chassis, 'sound/weapons/tap.ogg', 50, TRUE) - log_message("Unloaded [crate]. Cargo compartment capacity: [miner.cargo_capacity - LAZYLEN(miner.cargo)]", LOG_MECHA) + log_message("Unloaded [crate]. Cargo compartment capacity: [cargo_capacity - contents.len]", LOG_MECHA) return TRUE -/obj/vehicle/sealed/mecha/ripley/relay_container_resist_act(mob/living/user, obj/O) - to_chat(user, span_notice("You lean on the back of [O] and start pushing so it falls out of [src].")) - if(do_after(user, 300, target = O)) - if(!user || user.stat != CONSCIOUS || user.loc != src || O.loc != src ) - return - to_chat(user, span_notice("You successfully pushed [O] out of [src]!")) - O.forceMove(drop_location()) - LAZYREMOVE(cargo, O) - else - if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded. - to_chat(user, span_warning("You fail to push [O] out of [src]!")) +/obj/item/mecha_parts/mecha_equipment/ejector/seccage + name = "holding cell" + desc = "Holds suspects loaded with a hydraulic claw." + cargo_capacity = 4 + +/obj/item/mecha_parts/mecha_equipment/ejector/seccage/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_MOB_REMOVING_CUFFS, PROC_REF(stop_cuff_removal)) + +/obj/item/mecha_parts/mecha_equipment/ejector/seccage/Destroy() + UnregisterSignal(src, COMSIG_MOB_REMOVING_CUFFS) + for(var/mob/freebird in contents) //Let's not qdel people iside the mech kthx + cheese_it(freebird) + return ..() + +/obj/item/mecha_parts/mecha_equipment/ejector/seccage/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) + RegisterSignal(arrived, COMSIG_MOB_REMOVING_CUFFS, PROC_REF(stop_cuff_removal)) + return ..() + +/obj/item/mecha_parts/mecha_equipment/ejector/seccage/Exited(atom/movable/gone, direction) + UnregisterSignal(gone, COMSIG_MOB_REMOVING_CUFFS) + return ..() + +/obj/item/mecha_parts/mecha_equipment/ejector/seccage/proc/stop_cuff_removal(datum/source, obj/item/cuffs) + SIGNAL_HANDLER + to_chat(source, span_warning("You don't have the room to remove [cuffs]!")) + return COMSIG_MOB_BLOCK_CUFF_REMOVAL + +/obj/item/mecha_parts/mecha_equipment/ejector/seccage/ui_act(action, list/params) + if(action == "eject") + var/mob/passenger = locate(params["cargoref"]) in contents + if(!passenger) + return FALSE + to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][span_notice("You unload [passenger].")]") + passenger.forceMove(drop_location()) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(_step), passenger, chassis.dir), 1) //That's right, one tick. Just enough to cause the tile move animation. + playsound(chassis, 'sound/weapons/tap.ogg', 50, TRUE) + log_message("Unloaded [passenger]. Cargo compartment capacity: [cargo_capacity - contents.len]", LOG_MECHA) + return TRUE + return ..() + +/obj/item/mecha_parts/mecha_equipment/ejector/seccage/container_resist_act(mob/living/user) + to_chat(user, span_notice("You begin attempting a breakout. (This will take around 45 seconds and [chassis] need to remain stationary.)")) + if(!do_after(user, 1 MINUTES, target = chassis)) + return + to_chat(user, span_notice("You break out of the [src].")) + playsound(chassis, 'sound/items/crowbar.ogg', 100, TRUE) + cheese_it(user) + for(var/mob/freebird in contents) + if(user != freebird) + to_chat(freebird, span_warning("[user] has managed to open the hatch, and you fall out with him. You're free!")) + cheese_it(freebird) + +/obj/item/mecha_parts/mecha_equipment/ejector/seccage/proc/cheese_it(mob/living/escapee) + var/range = rand(1, 3) + var/variance = rand(-45, 45) + var/angle = 180 + var/turf/current_turf = get_turf(src) + switch (chassis?.dir) + if(NORTH) + angle = 270 + if(EAST) + angle = 180 + if(SOUTH) + angle = 90 + if(WEST) + angle = 0 + var/target_x = round(range * cos(angle + variance), 1) + current_turf.x + var/target_y = round(range * sin(angle + variance), 1) + current_turf.y + escapee.Knockdown(1) //Otherwise everyone hits eachother while being thrown + escapee.forceMove(drop_location()) + escapee.throw_at(locate(target_x, target_y, current_turf.z), range, 1) /** * Makes the mecha go faster and halves the mecha drill cooldown if in Lavaland pressure. diff --git a/config/config.txt b/config/config.txt index a26b6938496f0..2c552361c6bb4 100644 --- a/config/config.txt +++ b/config/config.txt @@ -410,8 +410,8 @@ MINUTE_CLICK_LIMIT 400 ## Game Chat Message Options ## Various messages to be sent to connected chat channels. -## Uncommenting these will enable them, by default they will be broadcast to Game chat channels on TGS3 or non-admin channels on TGS4. -## If using TGS4, the string option can be set as one of more chat channel tags (separated by ','s) to limit the message to channels with that tag name (case-sensitive). This will have no effect on TGS3. +## Uncommenting these will enable them, by default they will be broadcast to Game chat channels on TGS3 or non-admin channels on TGS>=4. +## If using TGS>=4, the string option can be set as one of more chat channel tags (separated by ','s) to limit the message to channels with that tag name (case-sensitive). This will have no effect on TGS3. ## i.e. CHANNEL_ANNOUNCE_NEW_GAME chat_channel_tag ## Which channel will have a message about a new game starting, message includes the station name. diff --git a/html/changelogs/archive/2023-11.yml b/html/changelogs/archive/2023-11.yml index 32f6ef3c98b41..a5d281d8dd76e 100644 --- a/html/changelogs/archive/2023-11.yml +++ b/html/changelogs/archive/2023-11.yml @@ -329,3 +329,391 @@ slimy slimes, instead of getting away with using phasing powers in pipes. - bugfix: All vehicles (such as VIMs operated by a mouse or a lizard) will no longer be able to phase through containment fields. +2023-11-09: + GPeckman: + - balance: Flightpotion wings will no longer make health analyzers list you as nonhuman. + KingkumaArt: + - rscadd: Enginenering rebar crossbows + tot kit + - rscadd: Added a bunch of ammos and crafting junk to make the ammo exist + - image: added icond for all the above + Melbert: + - rscadd: Anomalies, portals, and bluespace rifts will now wibble a bit. + SyncIt21: + - bugfix: Material market buy buttons greys out correctly and thus prevent you from + placing orders that exceeds the available budget. + - qol: machines/devices that ask you to pick a reagent name from an input list have + their names sorted alphabetically & preserves white space between words making + them more readable. + - qol: improves performance of plumbing reaction chamber furthur + - code_imp: cleaned up code for portable chem mixer & chem dispenser. converted + their ui to typescript + Toastgoats: + - balance: Venus human traps now take 12.5 damage per second instead of 20 while + off kudzu. + necromanceranne: + - rscadd: With the flood of Chi within the Spinward Sector receding, various masters + of The Tunnel Arts, colloquially known as 'Maint-fu Masters', have started to + refine the basics of their martial techniques. New forms have started to develop + within Spacestation 13's hidden maintenance dojos. + - rscadd: Someone shoved off-balance makes them vulnerable to more guaranteed unarmed + strikes, knockdowns from a successful punch, and more difficult to escape grabs. + - rscadd: Grabbing someone (as well as kicking them while they're on the floor) + makes them more vulnerable to taking unarmed attack damage, even if they have + armor. + - balance: Unarmed strikes made with human-equivalent limbs have higher damage floors, + meaning you overall do more damage on average while not increasing the overall + damage potential. It's more consistent! + - refactor: Significantly changed how punching accuracy and knockdowns are calculated. + - balance: Golem and mushroom limbs are a lot more effective at punching as a result + of these various changes. As they should be. + xXPawnStarrXx: + - rscadd: Three new plants; Peppercorn, Saltcane and Butterbeans. + - rscadd: Soysauce fermentation to soybeans. + - rscadd: Saltcane can be dried into a replacement seaweedsheet for sushi. + zergspower: + - balance: NPC Syndicate Shotgunners range requirement returned +2023-11-10: + Jacquerel: + - qol: Adds the capability for some player-controlled mobs with ranged attacks to + repeatedly fire their natural weapons by holding down the mouse button. + Profakos: + - spellcheck: Renamed Knock to Locks, and changed most of the flavor text of knowledge + gain, and renamed some items and knowledges from the path. + SyncIt21: + - bugfix: Examining circuit boards now displays their detailed names(tier included) + correctly if required. + - bugfix: plumbing factories should not rarely/randomly brick at volumes like 0.9999(when + in fact it should have been 1) + - code_imp: removed order history, import & export value from cargo & economy subsystems. + Allow supply packs to be properly deleted. In general memory savings + Thunder12345: + - rscadd: New Oranges' Juicery bar sign for the OJ connoisseurs. + TwistedSilicon: + - bugfix: Cryo cells now use their direction to orient their initial connection + instead of defaulting to South. + Zxaber, DrDiasyl, Maurukas: + - rscadd: A new security-focused combat mech, the Paddy, has been added, intended + to be particularly helpful for lone sec officers. You will find one in the Security + main office, and a replacement can be built with late-game mech research. + - bugfix: Ripley MK-I and MK-II mechs no longer qdel their stored items when destroyed. + san7890: + - bugfix: Nanotrasen has clarified an issue with their manual publishers, and these + guides should now contain actual user-pertinent content. + starrm4nn: + - qol: Bandolier can quick gather items now. + - balance: Bandolier capacity increased to 24 and can carry .357 ammo now. + timothymtorres: + - bugfix: Fix holodeck items from being juiced or grinded with a biogenerator or + pestle and mortar + - rscdel: Removed duplicate shutter from HoP office in birdboat, air alarm in northstar + maint, and portable air pump in northstar maint. +2023-11-11: + DaCoolBoss: + - rscadd: 4 new space ruins + Jacquerel: + - image: Adds yet another bar sign, this one mining themed + KingkumaArt: + - bugfix: fixed engi crossbow being able to be used onehanded + ability to craft + with sci inducers + MTandi: + - qol: Ordnance burn, freezing and supermatter chamber air alarms now show the air + contents on the tile of the connected sensor inside the chamber. + nikothedude: + - balance: Snails no longer receive blunt wounds, meaning sharp weapons can dismember + them more easily + - balance: Slimes can no longer receive dislocations + timothymtorres: + - bugfix: Fix mapping linter not identifying duplicate blacklisted objects on a + turf + - code_imp: Add a mapping linter to check for stacked machinery + - rscdel: Remove duplicate windows from birdshot, delta, and anomaly research ruin. +2023-11-12: + DaCoolBoss: + - spellcheck: Fixed typos in the examine text for the lead pipe & lead-acid battery. + Jacquerel: + - refactor: Guardians/Powerminers/Holoparasites now use the basic mob framework. + Please report any unexpected changes or behaviour. + - qol: The verbs used to communicate with, recall, or banish your Guardian are now + action buttons. + - balance: If (as a Guardian) your host moves slightly out of range you will now + be dragged back into range if possible, rather than being instantly teleported + to them. + - balance: Protectors now have a shorter leash range rather than a longer one, in + order to more easily take advantage of their ability to drag their charge out + of danger. + - balance: Ranged Guardians can now hold down the mouse button to fire automatically. + - balance: People riding vehicles or other mobs now inherit all of their movement + traits, so riding a flying mob (or vehicle, if we have any of those) will allow + you to cross chasms and lava safely. + Melbert: + - bugfix: Split persons can talk to their host once again + - bugfix: AI controlled mobs which are immobilized are now properly immobilized + - bugfix: People with copied memories can modify their bank account ID as normal. + - rscdel: The Stethoscope no longer tells you if the target is missing a heart or + lungs. Now, it will simply say the target is lacking a pulse or not breathing. + vinylspiders: + - code_imp: gets rid of the rest of the instances of 'targetted' typo from code +2023-11-13: + DATA_: + - spellcheck: The examine message for a carbon with an empty golem stomach now properly + matches said carbon's gender. + Jacquerel: + - bugfix: Goats will now calm down after getting grumpy without causing a runtime + error. + JohnFulpWillard: + - bugfix: '[Mafia] Obsessed now knows who their target is in their role description, + and people playing on PDA are told in their chat.' + Melbert: + - bugfix: Fix being unable to resist out of ice cubes + Momo8289: + - spellcheck: Made the remembrance day greeting message more tasteful. + SethLafuente: + - bugfix: fixes holodeck missing medical tools + Vishenka0704: + - bugfix: Now you can refuse the pirates request. + YesterdaysPromise: + - bugfix: Replaces the jetpack in Interdyne pirates' suit storage with air tanks. + They need to breath, and already got the suit for speed. + necromanceranne: + - bugfix: The Dread Disciples of Maint Khan, notorious Tunnel Arts practitioner + and maintenance warlord, have been driven from Nanotrasen stations within the + Spinward Sector. The average punch accuracy has been increased as a direct result, + with the most exhausted puncher now having a max potential inaccuracy of 80%, + rather than the absurd 20% of the Disciples. + nikothedude: + - code_imp: Quirks are now customizable on the quirks page instead of on the character + prefs page + vinylspiders: + - bugfix: emped bar signs will now display the correct sprite + - image: added a more detailed lightmask for the emp bar sign sprite + zxaber: + - bugfix: Ashwalker Tendril Revives no longer ghost the player being revived. +2023-11-14: + 1393F: + - bugfix: The Sleeping Carp scroll no longer says deflect using throw mode. + Ben10Omintrix: + - refactor: gutlunches have been refactored into basic mobs. please report any bugs + - rscadd: ashwalkers have a small ranch they can manage + - bugfix: wall tearer compnent wont runtime when interacting with mineral walls + BlueMemesauce: + - bugfix: Fixed tcomms relays being weird, they should be sabotagable again + Danny Boy: + - bugfix: Fixed Signer eyebrow raising/lowering indicators and emotes + - bugfix: Fixed Signer RuneChat punctuation + - bugfix: Signers no longer sign with their species' tongue + GPeckman: + - qol: Fixed/improved feedback when failing to apply a direct law change to a cyborg. + - bugfix: Borgs who are unsynced from a malf AI now lose the zeroth law as intended. + Hatterhat: + - bugfix: Kronkaine's action speed buff now stops when metabolized out. + - bugfix: Drug-related moodlets should now time out properly. They still linger + after metabolization ends, but they no longer last forever. + Likteer: + - rscadd: Green Beer has an overdose effect now. It will permeate your skin. + MTandi: + - balance: Mech overclock coefficient is down to 1.25 from the default 1.5 for Ripley + and Clarke. + - balance: Mech overclock heating now scales with movespeed, higher speed - faster + overheat. + - bugfix: fixed pipe painter not applying pipe color properly + - qol: made spraycans work also as pipe painters + - qol: spraycans now have basic color presets for quick selection + - image: Crates got new sprites + - image: Added more crate styles + Majkl-J: + - bugfix: You can now eject blank IDs from modular computers + Melbert: + - balance: Body temperature from being lit on fire will soft cap at 1,200 K. It + will still increase beyond this, but with diminishing returns. For example, + at 5,000 K, fire will heat 67x weaker. + - bugfix: Fixes some potential exploits and issues involving shielded equipment. + OrionTheFox: + - image: Resprites the Reactive Anomaly Armor + Rhials: + - bugfix: The full mining lockers in the Lavaland Mafia map have been replaced with + (empty) mining carts. + SethLafuente: + - bugfix: fixes half-covering glassware protecting eyes from chemicals + SyncIt21: + - bugfix: suite storage units can be locked again. Remember to install a card reader + or set the access levels in the airlock electronics inside its stock parts & + finally swipe your ID to properly enforce access control. + distributivgesetz: + - bugfix: Removes some roundstart active turfs. + - bugfix: The PDA painter and the emergency shield generator can now be destroyed. + - code_imp: Atoms no longer break again after they are hit when broken, making them + hopefully more stable in the future. + larentoun: + - qol: 'Gunpoint: Examining the target will show who is holding them at gunpoint' + - qol: 'Gunpoint: Examining the shooter will show who they are holding at gunpoint' + - balance: 'Gunpoint: If the target tries to grab, they will trigger the shot' + - balance: 'Gunpoint: If the target or the shooter are shoved, it will cancel the + gunpoint' + - balance: 'Gunpoint: If the target is pulled, it will cancel the gunpoint' + - balance: Both the target and the shooter can't be bumped anymore to avoid cheesing + charged shot or removing the gunpoint by just moving around + - bugfix: Clicking the alert button of the shooter will now correctly remove gunpoint + mc-oofert: + - bugfix: tramstation cargo disposals outlet has been repositioned to not softlock + whoever cannot lay down + san7890: + - bugfix: Gorillas and Regal Rats will no longer show up in the ghost-control menu + if they died without anyone ever taking control of them. + timothymtorres: + - rscadd: Add bamboo seeds to ash walker den. This lets them craft blowguns, crude + syringes, bamboo spears, punji stick traps, and more! +2023-11-15: + Ben10Omintrix: + - bugfix: bileworms will now attack + D4C-420: + - spellcheck: hopefully changed all instances of the word 'mjolnir' to 'mjollnir' + Ghommie: + - bugfix: Fixed a small issue with disposal outlets leaving contents about to be + ejected stuck inside the pipe beneath it if deleted. + Jacquerel: + - balance: Sapient brimdemons can't hurt themselves with their own beams + JohnFulpWillard: + - refactor: Destructive Analyzers now have a TGUI menu. + - bugfix: PDAs now log that they've been emagged, but will no longer log any further + programs they open beyond that. This means Nukies don't sell themselves out + by opening their disk tracking app. + LT3: + - bugfix: Bad luck omen again raises your chance of getting shocked by the tram + plate + - bugfix: Tram plate checks and energizes when the tram is moving + - code_imp: Omen component now applies the cursed trait + Melbert: + - code_imp: General heart code cleanup. + - bugfix: Heartbeat sound effects are no longer sourced to the exact tile you fell + into crit at + - bugfix: Abductors glands are less likely to become invisible or look wrong + - bugfix: Ethereal hearts are less likely to become invisible or look wrong, and + now properly spawn with their shine overlay + - image: Adds heartbeat animation to beating Ethereal Hearts + - bugfix: Fixes hallucination and encrypted announcements printing to the Newscaster. + SyncIt21: + - bugfix: drying rack now shows correct examines & screen tips. + - code_imp: tone of code organization for smart fridges overall. changed ui to typescript. + - qol: added more detailed examines & screen tips for smart fridges. drying racks + can be dismantled with a crowbar and not simply pried open with it. + TwistedSilicon: + - bugfix: invisimin verb now makes you invisible to all HUDs too! No more floating + healthbars or job identifiers giving you away while you sneak around. + jjpark-kb: + - qol: looms will now attempt to loop through stackable items (cotton as an example) + larentoun: + - rscadd: Emote Panel TGUI added in IC category. + mc-oofert: + - bugfix: The plaguebearer can no longer depower virology on Tramstation + san7890: + - bugfix: Safeties in the code have been added to prevent things in disposals going + into nullspace whenever they get ejected from a pipe - you will just magically + spawn at the turf that you were meant to be flung towards. + - qol: You will no longer be added to the list for ghost-orbit role polls if you + have opted out of getting antag ghost roles in your preferences. + - qol: You will get a tgui_alert to accept the ghost role if you were selected via + the orbit poll, instead of it just throwing you intot he role. + san7890, Ghommie: + - bugfix: The Blessing of Insanity now grants no damage slowdown and free hyperspace + movement correctly. +2023-11-16: + ArcaneMusic: + - bugfix: The Galactic Material Market now respects quantity of materials purchased, + removing them from the market when bought and preventing you from ordering more + than are available at a given time. + Fikou: + - qol: Dead human examines count as "soul departed" when the client is disconnected + or the human doesn't have a brain anymore. + Shroopy: + - bugfix: Molotovs now splash before burning, not after + deathrobotpunch: + - qol: the donksoft vendor refill cartridge is now available at the service lathe + falconignite: + - bugfix: Lizard tail wagging graphics + san7890: + - balance: Male Goats should no longer spawn with an udder, instead of it just being + Pete. +2023-11-17: + CRITAWAKETS: + - qol: The supermatter filters have been flipped on BirdshotStation to work like + the supermatters on every round, meaning the filtered gas goes in, and the non-filtered + gas comes out. + Dalm: + - image: A tea room sign for the bar + Fikou: + - bugfix: grabs no longer trigger krav maga + GPeckman: + - rscadd: Androids now have robotic brains instead of organic brains. + Ghommie: + - bugfix: Fixed catwalks over open space not making a sound when walked over. + - rscadd: The mother hallucination has more possible one-liners now. + Melbert: + - balance: Stop, drop, and roll no longer instantly clears 5 fire stacks off of + you - Instead, it will clear 1 fire stack off of you every time you roll, with + a roll every 0.8 seconds. + - balance: Stop, drop, and roll no longer stuns you for 6 seconds. Instead, it will + knock you to the floor while you are rolling. Moving around or getting up will + cancel the roll, and you cannot use items while rolling around. + - balance: Stop, drop, and roll will now repeat until the fire is put out or you + get up. + RedBaronFlyer: + - image: light tube inhand sprites are now grey, as are the icons for the light + bulb/tube/mixed boxes + Shadow-Quill: + - bugfix: 'The CRAB-17 will now only take whole credits, as fractional credits were + found to be worth less. + + :cl:' + SyncIt21: + - code_imp: removed redundant procs `get_master_reagent_id()` & `get_master_reagent_name()` + - code_imp: merged `remove_all_type()` proc with `remove_reagent()` now this proc + can perform both functions. `remove_reagent()` now returns the total volume + of reagents removed rather than a simple TRUE/FALSE. + - code_imp: merged `trans_id_to()` proc with `trans_to()` now this proc can perform + both functions + - refactor: plumbing reaction chamber will now use only a single tick to balance + ph of a solution making it less efficient but more faster. Just make the reaction + chamber wait for longer periods of time to accurately balance ph + - refactor: reagent holder code has been condensed. Report any bugs on GitHub + Vekter (on behalf of Constellado): + - image: 'Added a new bar sign as one of the winners of our Bar Sign Contest: "The + Assembly Line".' + YesterdaysPromise: + - rscadd: Adds a chance that, when sharpened, a sufficiently potent carrot will + turn into a sword instead of a shiv. + Zergspower: + - bugfix: Space Ruin - All American Diner - Soda Machine now is scooted out of the + way + jlsnow301: + - rscadd: Bitrunning Patch 1 features a host of changes! + - rscadd: Added randomized mobs to virtual domains, which will be indicated with + a unique icon. + - rscadd: New emag interaction with the quantum server. Antags will spawn more frequently, + and they can hack themselves onto the station. You have been warned. + - rscadd: Both living and dead players can now see which mob is going to spawn an + antagonist in the vdom. + - rscadd: 'Two new vdom antagonists: Cyber Tac and the NetGuardian. These unlock + at specific thresholds.' + - balance: You can no longer stack copies of the same ability with bitrunning disks. + - balance: Some of the disk items have been replaced with stronger versions. + - bugfix: You can no longer spy on crew using the advanced camera console on syndicate + assault. + - bugfix: Fixed the spawning mechanism of virtual domain antagonists. You should + now have a chance of playing as one. This chance increases as more domains are + completed. + - bugfix: Vdom antagonists shouldn't spawn at the end of the run any longer. + - bugfix: The preference for vdom antagonists has been changed to factor in the + new types. Check your preferences! + - bugfix: The quantum server will now show its balloon alerts to all observers. + - bugfix: Random domains should be fully random again. + mc-oofert: + - qol: if you die in a mech you automatically eject + mogeoko: + - bugfix: Turbine parts will now use an amount of materials no greater than needed + for the upgrade + san7890: + - bugfix: Bar Bots (and several other mobs) will no longer aggro on you if you click + on them with a "forceful" item from halfway across the room. + - balance: After a string of unfortunate incidents, persons with telekinesis have + been strongly warned against playing Russian Roulette, as they tend to hyperfixate + on the gun a bit too much and end up firing it directly at their head. diff --git a/icons/area/areas_station.dmi b/icons/area/areas_station.dmi index cbfe463efa516..f2182c6e9189a 100644 Binary files a/icons/area/areas_station.dmi and b/icons/area/areas_station.dmi differ diff --git a/icons/effects/bitrunning.dmi b/icons/effects/bitrunning.dmi index bfdc7c63436c2..8efa429389c3a 100644 Binary files a/icons/effects/bitrunning.dmi and b/icons/effects/bitrunning.dmi differ diff --git a/icons/effects/bitrunning_48.dmi b/icons/effects/bitrunning_48.dmi new file mode 100644 index 0000000000000..e7c5bf37d8e89 Binary files /dev/null and b/icons/effects/bitrunning_48.dmi differ diff --git a/icons/effects/bitrunning_64.dmi b/icons/effects/bitrunning_64.dmi new file mode 100644 index 0000000000000..397b4709c83b3 Binary files /dev/null and b/icons/effects/bitrunning_64.dmi differ diff --git a/icons/mob/actions/actions_mecha.dmi b/icons/mob/actions/actions_mecha.dmi index 5ae25522434ef..7c659ca3b573c 100644 Binary files a/icons/mob/actions/actions_mecha.dmi and b/icons/mob/actions/actions_mecha.dmi differ diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi index dc519380cfd7a..289443dd0520e 100644 Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ diff --git a/icons/mob/clothing/belt.dmi b/icons/mob/clothing/belt.dmi index 9ed1f1652359a..e789546f1e859 100644 Binary files a/icons/mob/clothing/belt.dmi and b/icons/mob/clothing/belt.dmi differ diff --git a/icons/mob/clothing/belt_mirror.dmi b/icons/mob/clothing/belt_mirror.dmi index 0c1b8457be7c3..eb06288d800bc 100644 Binary files a/icons/mob/clothing/belt_mirror.dmi and b/icons/mob/clothing/belt_mirror.dmi differ diff --git a/icons/mob/clothing/modsuit/mod_clothing.dmi b/icons/mob/clothing/modsuit/mod_clothing.dmi index 537b1ffd3ebdd..793c14ce115ff 100644 Binary files a/icons/mob/clothing/modsuit/mod_clothing.dmi and b/icons/mob/clothing/modsuit/mod_clothing.dmi differ diff --git a/icons/mob/clothing/suits/armor.dmi b/icons/mob/clothing/suits/armor.dmi index d10ca4add997b..dc5fae0172cc4 100644 Binary files a/icons/mob/clothing/suits/armor.dmi and b/icons/mob/clothing/suits/armor.dmi differ diff --git a/icons/mob/human/species/lizard/lizard_spines.dmi b/icons/mob/human/species/lizard/lizard_spines.dmi index eaadb820ebc1f..82eb636b339c6 100644 Binary files a/icons/mob/human/species/lizard/lizard_spines.dmi and b/icons/mob/human/species/lizard/lizard_spines.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index f544eeb753a81..a2347dc667abc 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 85c6accc80c36..bb2a425194bd2 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/guns_lefthand.dmi b/icons/mob/inhands/weapons/guns_lefthand.dmi index 3e29ac726f995..7e8297c848d3d 100644 Binary files a/icons/mob/inhands/weapons/guns_lefthand.dmi and b/icons/mob/inhands/weapons/guns_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/guns_righthand.dmi b/icons/mob/inhands/weapons/guns_righthand.dmi index 1a640935e0c6a..366f285789a0a 100644 Binary files a/icons/mob/inhands/weapons/guns_righthand.dmi and b/icons/mob/inhands/weapons/guns_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/hammers_lefthand.dmi b/icons/mob/inhands/weapons/hammers_lefthand.dmi index 090bcb2ab9e0a..7f6985e1de5ec 100644 Binary files a/icons/mob/inhands/weapons/hammers_lefthand.dmi and b/icons/mob/inhands/weapons/hammers_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/hammers_righthand.dmi b/icons/mob/inhands/weapons/hammers_righthand.dmi index 3b0af0743f8d1..2dd4f4b64c5cf 100644 Binary files a/icons/mob/inhands/weapons/hammers_righthand.dmi and b/icons/mob/inhands/weapons/hammers_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/swords_lefthand.dmi b/icons/mob/inhands/weapons/swords_lefthand.dmi index 98a037e5c8ea0..7544d3cbaf2f8 100644 Binary files a/icons/mob/inhands/weapons/swords_lefthand.dmi and b/icons/mob/inhands/weapons/swords_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/swords_righthand.dmi b/icons/mob/inhands/weapons/swords_righthand.dmi index b60f65194d57a..300e4c2e616f1 100644 Binary files a/icons/mob/inhands/weapons/swords_righthand.dmi and b/icons/mob/inhands/weapons/swords_righthand.dmi differ diff --git a/icons/mob/mecha.dmi b/icons/mob/mecha.dmi index 845b1cdf140da..f6dcbdec2b7ee 100644 Binary files a/icons/mob/mecha.dmi and b/icons/mob/mecha.dmi differ diff --git a/icons/mob/mecha_equipment.dmi b/icons/mob/mecha_equipment.dmi index 18fe707cafe6e..90f0ce8c736cf 100644 Binary files a/icons/mob/mecha_equipment.dmi and b/icons/mob/mecha_equipment.dmi differ diff --git a/icons/mob/nonhuman-player/netguardian.dmi b/icons/mob/nonhuman-player/netguardian.dmi new file mode 100644 index 0000000000000..057e7a066c2be Binary files /dev/null and b/icons/mob/nonhuman-player/netguardian.dmi differ diff --git a/icons/mob/simple/lavaland/lavaland_monsters.dmi b/icons/mob/simple/lavaland/lavaland_monsters.dmi index f68e3db4a6cb9..90fdbaac0e6d6 100644 Binary files a/icons/mob/simple/lavaland/lavaland_monsters.dmi and b/icons/mob/simple/lavaland/lavaland_monsters.dmi differ diff --git a/icons/obj/clothing/belt_overlays.dmi b/icons/obj/clothing/belt_overlays.dmi index 740a832a023ee..7a215dcb9b1cc 100644 Binary files a/icons/obj/clothing/belt_overlays.dmi and b/icons/obj/clothing/belt_overlays.dmi differ diff --git a/icons/obj/clothing/modsuit/mod_clothing.dmi b/icons/obj/clothing/modsuit/mod_clothing.dmi index 7eb92f1c3519c..5070dbb145c9c 100644 Binary files a/icons/obj/clothing/modsuit/mod_clothing.dmi and b/icons/obj/clothing/modsuit/mod_clothing.dmi differ diff --git a/icons/obj/clothing/suits/armor.dmi b/icons/obj/clothing/suits/armor.dmi index 48fe5c92c339d..4bf43e07e970c 100644 Binary files a/icons/obj/clothing/suits/armor.dmi and b/icons/obj/clothing/suits/armor.dmi differ diff --git a/icons/obj/machines/barsigns.dmi b/icons/obj/machines/barsigns.dmi index 4101f256495dd..f3cfe8eaed92f 100644 Binary files a/icons/obj/machines/barsigns.dmi and b/icons/obj/machines/barsigns.dmi differ diff --git a/icons/obj/machines/bitrunning.dmi b/icons/obj/machines/bitrunning.dmi index b3f8ad63a6c99..d61e910d195be 100644 Binary files a/icons/obj/machines/bitrunning.dmi and b/icons/obj/machines/bitrunning.dmi differ diff --git a/icons/obj/machines/computer.dmi b/icons/obj/machines/computer.dmi index 9cb0dda4967fd..cba0069cf6f38 100644 Binary files a/icons/obj/machines/computer.dmi and b/icons/obj/machines/computer.dmi differ diff --git a/icons/obj/medical/organs/organs.dmi b/icons/obj/medical/organs/organs.dmi index 94ba46568c929..0d04f7fae3ce4 100644 Binary files a/icons/obj/medical/organs/organs.dmi and b/icons/obj/medical/organs/organs.dmi differ diff --git a/icons/obj/service/hydroponics/growing.dmi b/icons/obj/service/hydroponics/growing.dmi index fcf738998636a..aee567daa5445 100644 Binary files a/icons/obj/service/hydroponics/growing.dmi and b/icons/obj/service/hydroponics/growing.dmi differ diff --git a/icons/obj/service/hydroponics/growing_vegetables.dmi b/icons/obj/service/hydroponics/growing_vegetables.dmi index bf49c72ba79b5..30f02e862e037 100644 Binary files a/icons/obj/service/hydroponics/growing_vegetables.dmi and b/icons/obj/service/hydroponics/growing_vegetables.dmi differ diff --git a/icons/obj/service/hydroponics/harvest.dmi b/icons/obj/service/hydroponics/harvest.dmi index f4489b01fa053..b15a34105dec2 100644 Binary files a/icons/obj/service/hydroponics/harvest.dmi and b/icons/obj/service/hydroponics/harvest.dmi differ diff --git a/icons/obj/service/hydroponics/seeds.dmi b/icons/obj/service/hydroponics/seeds.dmi index db6f93878d06f..830086686547e 100644 Binary files a/icons/obj/service/hydroponics/seeds.dmi and b/icons/obj/service/hydroponics/seeds.dmi differ diff --git a/icons/obj/service/library.dmi b/icons/obj/service/library.dmi index 8229c1fc3947e..79a06dd4b8f91 100644 Binary files a/icons/obj/service/library.dmi and b/icons/obj/service/library.dmi differ diff --git a/icons/obj/storage/box.dmi b/icons/obj/storage/box.dmi index c06fe4d8112b6..6cae3e75dffd6 100644 Binary files a/icons/obj/storage/box.dmi and b/icons/obj/storage/box.dmi differ diff --git a/icons/obj/storage/crates.dmi b/icons/obj/storage/crates.dmi index 7f78d049302bf..1a8f697781b4c 100644 Binary files a/icons/obj/storage/crates.dmi and b/icons/obj/storage/crates.dmi differ diff --git a/icons/obj/storage/wrapping.dmi b/icons/obj/storage/wrapping.dmi index acd91a3d7006d..944a6b84752f2 100644 Binary files a/icons/obj/storage/wrapping.dmi and b/icons/obj/storage/wrapping.dmi differ diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi index a41aa161d0f10..8707b394c2e9f 100644 Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ diff --git a/icons/obj/weapons/guns/ammo.dmi b/icons/obj/weapons/guns/ammo.dmi index a36b593706f76..07a4bde661a64 100644 Binary files a/icons/obj/weapons/guns/ammo.dmi and b/icons/obj/weapons/guns/ammo.dmi differ diff --git a/icons/obj/weapons/guns/ballistic.dmi b/icons/obj/weapons/guns/ballistic.dmi index 9dd25af2a9219..5cd823cc9c412 100644 Binary files a/icons/obj/weapons/guns/ballistic.dmi and b/icons/obj/weapons/guns/ballistic.dmi differ diff --git a/icons/obj/weapons/guns/projectiles.dmi b/icons/obj/weapons/guns/projectiles.dmi index 05ad142ff58d3..168f9fb716c80 100644 Binary files a/icons/obj/weapons/guns/projectiles.dmi and b/icons/obj/weapons/guns/projectiles.dmi differ diff --git a/icons/obj/weapons/hammer.dmi b/icons/obj/weapons/hammer.dmi index c210f8b436b3a..6c454462f48cf 100644 Binary files a/icons/obj/weapons/hammer.dmi and b/icons/obj/weapons/hammer.dmi differ diff --git a/icons/obj/weapons/sword.dmi b/icons/obj/weapons/sword.dmi index 8e6ee6bdd2fef..255c3b0cffd0e 100644 Binary files a/icons/obj/weapons/sword.dmi and b/icons/obj/weapons/sword.dmi differ diff --git a/icons/ui_icons/achievements/achievements.dmi b/icons/ui_icons/achievements/achievements.dmi index b3e64c9d09f83..5f6626c7993fc 100644 Binary files a/icons/ui_icons/achievements/achievements.dmi and b/icons/ui_icons/achievements/achievements.dmi differ diff --git a/strings/modular_maps/generic.toml b/strings/modular_maps/generic.toml new file mode 100644 index 0000000000000..050b75bb78c10 --- /dev/null +++ b/strings/modular_maps/generic.toml @@ -0,0 +1,31 @@ +directory = "_maps/modular_generic/" + +[rooms.station_small] +modules = ["station_s_kitchen.dmm", "station_s_chasm.dmm", "station_s_garden.dmm", "station_s_mime.dmm", "station_s_vault.dmm"] + +[rooms.station_medium] +modules = ["station_m_tools.dmm", "station_m_evidence.dmm", "station_m_kitchen.dmm", "station_m_shipping.dmm", "station_m_showroom.dmm", "station_m_arcade.dmm", "station_m_breakroom.dmm", "station_m_shuttle.dmm"] + +[rooms.station_large] +modules = ["station_l_morgue.dmm", "station_l_crates.dmm", "station_l_webs.dmm", "station_l_bathroom.dmm", "station_l_kitchen.dmm", "station_l_security.dmm", "station_l_kilojan.dmm"] + +[rooms.beach_medium] +modules = ["beach_m_shipping.dmm", "beach_m_oasis.dmm"] + +[rooms.beach_large] +modules = ["beach_l_ribs.dmm"] + +[rooms.jungle_medium] +modules = ["jungle_m_armory.dmm"] + +[rooms.jungle_large] +modules = ["jungle_l_dock.dmm"] + +[rooms.ice_small] +modules = ["ice_s_freezer.dmm"] + +[rooms.ice_medium] +modules = ["ice_m_comms.dmm"] + +[rooms.ice_large] +modules = ["ice_l_trophyroom.dmm", "ice_l_storage.dmm"] diff --git a/strings/mother.json b/strings/mother.json new file mode 100644 index 0000000000000..ed122a86c1a3d --- /dev/null +++ b/strings/mother.json @@ -0,0 +1,49 @@ +{ + "do_something": [ + "CLEAN YOUR ROOM THIS INSTANT!", + "DON'T SIT THAT CLOSE TO THE TV!", + "FOR GOD'S SAKE, GO TAKE A SHOWER!!", + "IT'S TIME TO WAKE UP FOR SCHOOL!!", + "PAUSE THAT ONLINE GAME! NOW!", + "PUT SOME CLOTHES ON! YOU'LL CATCH A COLD!", + "STOP ASKING FOR MONEY, I'M NOT AN ATM!", + "WATCH YOUR MOUTH, CHILD!!", + "WHY DON'T YOU ANSWER MY PHONE CALLS?!", + "YOU SHOULD @pick(verb) YOUR @pick(relative) ONCE IN A WHILE!" + ], + + "be_upset": [ + "BECAUSE I SAID SO!", + "I DON'T CARE WHAT YOU SAY!", + "I'M NOT ASKING; I'M TELLING!!", + "I WASN'T BORN YESTERDAY!", + "MONEY DOESN'T GROW ON TREES!", + "WHAT DID I DO TO DESERVE A KID LIKE THIS...", + "USELESS!", + "YOU INSULT YOUR GRANDPARENTS!" + ], + + "get_reprimanded": [ + "I BROUGHT YOU INTO THIS WORLD, I CAN TAKE YOU OUT!!!", + "I'M GOING TO THROW A FLIP-FLOP AT YOU!!", + "NO VIDEOGAMES FOR THE REST OF THE DAY!", + "WAIT UNTIL YOUR FATHER GETS HOME!", + "YOU'LL THANK ME ONE DAY!", + "YOU'RE DISOWNED!!!", + "YOU'RE GROUNDED!!" + ], + + "verb": [ + "CALL", + "HELP", + "VISIT" + ], + + "relative": [ + "AUNT AND UNCLE", + "DAD", + "GRANDPARENTS", + "MOM" + ] + +} diff --git a/strings/names/guardian_descriptions.txt b/strings/names/guardian_descriptions.txt new file mode 100644 index 0000000000000..678ec61fef63a --- /dev/null +++ b/strings/names/guardian_descriptions.txt @@ -0,0 +1,24 @@ +Black +Blazing +Bloody +Blue +Bronze +Dawn +Dusk +Gold +Green +Grey +Iron +Midnight +Orange +Pink +Plastitanium +Purple +Red +Shimmering +Shining +Silver +Sparkling +Steel +White +Yellow diff --git a/strings/names/guardian_gamepieces.txt b/strings/names/guardian_gamepieces.txt new file mode 100644 index 0000000000000..10a99cf38fb4a --- /dev/null +++ b/strings/names/guardian_gamepieces.txt @@ -0,0 +1,13 @@ +Ace +Bishop +Club +Diamond +Heart +Jack +Joker +King +Knight +Pawn +Queen +Rook +Spade diff --git a/strings/names/guardian_tarot.txt b/strings/names/guardian_tarot.txt new file mode 100644 index 0000000000000..5772c90d7ae85 --- /dev/null +++ b/strings/names/guardian_tarot.txt @@ -0,0 +1,23 @@ +Chariot +Death +Devil +Emperor +Empress +Fool +Fortune +Hangman +Hermit +Hierophant +Judgement +Justice +Lover +Magician +Moon +Priestess +Star +Strength +Sun +Temperance +Tower +Wheel +World diff --git a/tgstation.dme b/tgstation.dme index e8b7d9ff89a5b..94c653ac7f1bc 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -364,6 +364,7 @@ #include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_arcade.dm" #include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_basic.dm" #include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_carbon.dm" +#include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_guardian.dm" #include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_living.dm" #include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_main.dm" #include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_silicon.dm" @@ -378,7 +379,6 @@ #include "code\__HELPERS\_string_lists.dm" #include "code\__HELPERS\admin.dm" #include "code\__HELPERS\ai.dm" -#include "code\__HELPERS\animations.dm" #include "code\__HELPERS\areas.dm" #include "code\__HELPERS\atmospherics.dm" #include "code\__HELPERS\atoms.dm" @@ -458,6 +458,7 @@ #include "code\__HELPERS\varset_callback.dm" #include "code\__HELPERS\verbs.dm" #include "code\__HELPERS\view.dm" +#include "code\__HELPERS\visual_effects.dm" #include "code\__HELPERS\weakref.dm" #include "code\__HELPERS\logging\_logging.dm" #include "code\__HELPERS\logging\admin.dm" @@ -567,10 +568,19 @@ #include "code\_onclick\hud\screentip.dm" #include "code\_onclick\hud\parallax\parallax.dm" #include "code\_onclick\hud\parallax\random_layer.dm" -#include "code\_onclick\hud\rendering\plane_master.dm" #include "code\_onclick\hud\rendering\plane_master_controller.dm" #include "code\_onclick\hud\rendering\plane_master_group.dm" #include "code\_onclick\hud\rendering\render_plate.dm" +#include "code\_onclick\hud\rendering\plane_masters\_plane_master.dm" +#include "code\_onclick\hud\rendering\plane_masters\camera_static.dm" +#include "code\_onclick\hud\rendering\plane_masters\clickcatcher.dm" +#include "code\_onclick\hud\rendering\plane_masters\core_game_planes.dm" +#include "code\_onclick\hud\rendering\plane_masters\default.dm" +#include "code\_onclick\hud\rendering\plane_masters\in_world_chat.dm" +#include "code\_onclick\hud\rendering\plane_masters\lighting.dm" +#include "code\_onclick\hud\rendering\plane_masters\parallax.dm" +#include "code\_onclick\hud\rendering\plane_masters\pipecrawl.dm" +#include "code\_onclick\hud\rendering\plane_masters\simple_plane_masters.dm" #include "code\controllers\admin.dm" #include "code\controllers\controller.dm" #include "code\controllers\failsafe.dm" @@ -809,6 +819,7 @@ #include "code\datums\actions\mobs\meteors.dm" #include "code\datums\actions\mobs\mobcooldown.dm" #include "code\datums\actions\mobs\open_mob_commands.dm" +#include "code\datums\actions\mobs\personality_commune.dm" #include "code\datums\actions\mobs\projectileattack.dm" #include "code\datums\actions\mobs\sign_language.dm" #include "code\datums\actions\mobs\sneak.dm" @@ -830,18 +841,18 @@ #include "code\datums\ai\basic_mobs\basic_ai_behaviors\basic_attacking.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\climb_tree.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\find_parent.dm" -#include "code\datums\ai\basic_mobs\basic_ai_behaviors\nearest_targetting.dm" +#include "code\datums\ai\basic_mobs\basic_ai_behaviors\nearest_targeting.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\pick_up_item.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\run_away_from_target.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\set_travel_destination.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\step_towards_turf.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\stop_and_stare.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\targeted_mob_ability.dm" -#include "code\datums\ai\basic_mobs\basic_ai_behaviors\targetting.dm" +#include "code\datums\ai\basic_mobs\basic_ai_behaviors\targeting.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\tipped_reaction.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\travel_towards.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\ventcrawling.dm" -#include "code\datums\ai\basic_mobs\basic_ai_behaviors\wounded_targetting.dm" +#include "code\datums\ai\basic_mobs\basic_ai_behaviors\wounded_targeting.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\write_on_paper.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\attack_adjacent_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\attack_obstacle_in_path.dm" @@ -877,11 +888,11 @@ #include "code\datums\ai\basic_mobs\pet_commands\fetch.dm" #include "code\datums\ai\basic_mobs\pet_commands\pet_command_planning.dm" #include "code\datums\ai\basic_mobs\pet_commands\pet_follow_friend.dm" -#include "code\datums\ai\basic_mobs\pet_commands\pet_use_targetted_ability.dm" +#include "code\datums\ai\basic_mobs\pet_commands\pet_use_targeted_ability.dm" #include "code\datums\ai\basic_mobs\pet_commands\play_dead.dm" -#include "code\datums\ai\basic_mobs\targetting_datums\basic_targetting_datum.dm" -#include "code\datums\ai\basic_mobs\targetting_datums\dont_target_friends.dm" -#include "code\datums\ai\basic_mobs\targetting_datums\with_object.dm" +#include "code\datums\ai\basic_mobs\targeting_strategies\basic_targeting_strategy.dm" +#include "code\datums\ai\basic_mobs\targeting_strategies\dont_target_friends.dm" +#include "code\datums\ai\basic_mobs\targeting_strategies\with_object.dm" #include "code\datums\ai\cursed\cursed_behaviors.dm" #include "code\datums\ai\cursed\cursed_controller.dm" #include "code\datums\ai\cursed\cursed_subtrees.dm" @@ -979,6 +990,7 @@ #include "code\datums\components\bloodysoles.dm" #include "code\datums\components\boomerang.dm" #include "code\datums\components\boss_music.dm" +#include "code\datums\components\breeding.dm" #include "code\datums\components\bullet_intercepting.dm" #include "code\datums\components\bumpattack.dm" #include "code\datums\components\burning.dm" @@ -1007,10 +1019,12 @@ #include "code\datums\components\curse_of_polymorph.dm" #include "code\datums\components\customizable_reagent_holder.dm" #include "code\datums\components\damage_aura.dm" +#include "code\datums\components\damage_chain.dm" #include "code\datums\components\deadchat_control.dm" #include "code\datums\components\death_linked.dm" #include "code\datums\components\dejavu.dm" #include "code\datums\components\deployable.dm" +#include "code\datums\components\direct_explosive_trap.dm" #include "code\datums\components\drift.dm" #include "code\datums\components\earprotection.dm" #include "code\datums\components\echolocation.dm" @@ -1059,6 +1073,7 @@ #include "code\datums\components\knockoff.dm" #include "code\datums\components\label.dm" #include "code\datums\components\leash.dm" +#include "code\datums\components\life_link.dm" #include "code\datums\components\light_eater.dm" #include "code\datums\components\ling_decoy_brain.dm" #include "code\datums\components\lock_on_cursor.dm" @@ -1093,6 +1108,7 @@ #include "code\datums\components\radioactive_emitter.dm" #include "code\datums\components\radioactive_exposure.dm" #include "code\datums\components\ranged_attacks.dm" +#include "code\datums\components\ranged_mob_full_auto.dm" #include "code\datums\components\reagent_refiller.dm" #include "code\datums\components\recharging_attacks.dm" #include "code\datums\components\redirect_attack_hand_from_turf.dm" @@ -1384,6 +1400,7 @@ #include "code\datums\elements\noticable_organ.dm" #include "code\datums\elements\obj_regen.dm" #include "code\datums\elements\openspace_item_click_handler.dm" +#include "code\datums\elements\ore_collecting.dm" #include "code\datums\elements\organ_set_bonus.dm" #include "code\datums\elements\pet_bonus.dm" #include "code\datums\elements\plant_backfire.dm" @@ -1568,6 +1585,7 @@ #include "code\datums\proximity_monitor\fields\projectile_dampener.dm" #include "code\datums\proximity_monitor\fields\timestop.dm" #include "code\datums\quirks\_quirk.dm" +#include "code\datums\quirks\_quirk_constant_data.dm" #include "code\datums\quirks\negative_quirks\allergic.dm" #include "code\datums\quirks\negative_quirks\bad_back.dm" #include "code\datums\quirks\negative_quirks\bad_touch.dm" @@ -1706,6 +1724,7 @@ #include "code\datums\status_effects\wound_effects.dm" #include "code\datums\status_effects\buffs\food_haste.dm" #include "code\datums\status_effects\buffs\food_traits.dm" +#include "code\datums\status_effects\buffs\stop_drop_roll.dm" #include "code\datums\status_effects\buffs\stun_absorption.dm" #include "code\datums\status_effects\debuffs\blindness.dm" #include "code\datums\status_effects\debuffs\choke.dm" @@ -1791,10 +1810,6 @@ #include "code\datums\wounds\pierce.dm" #include "code\datums\wounds\slash.dm" #include "code\datums\wounds\scars\_scars.dm" -#include "code\game\alternate_appearance.dm" -#include "code\game\atom_defense.dm" -#include "code\game\atoms.dm" -#include "code\game\atoms_initializing_EXPENSIVE.dm" #include "code\game\atoms_movable.dm" #include "code\game\communications.dm" #include "code\game\data_huds.dm" @@ -1830,6 +1845,22 @@ #include "code\game\area\areas\station\service.dm" #include "code\game\area\areas\station\solars.dm" #include "code\game\area\areas\station\telecomm.dm" +#include "code\game\atom\_atom.dm" +#include "code\game\atom\alternate_appearance.dm" +#include "code\game\atom\atom_act.dm" +#include "code\game\atom\atom_appearance.dm" +#include "code\game\atom\atom_color.dm" +#include "code\game\atom\atom_defense.dm" +#include "code\game\atom\atom_examine.dm" +#include "code\game\atom\atom_greyscale.dm" +#include "code\game\atom\atom_invisibility.dm" +#include "code\game\atom\atom_materials.dm" +#include "code\game\atom\atom_merger.dm" +#include "code\game\atom\atom_orbit.dm" +#include "code\game\atom\atom_storage.dm" +#include "code\game\atom\atom_tool_acts.dm" +#include "code\game\atom\atom_vv.dm" +#include "code\game\atom\atoms_initializing_EXPENSIVE.dm" #include "code\game\gamemodes\events.dm" #include "code\game\gamemodes\game_mode.dm" #include "code\game\gamemodes\objective.dm" @@ -2209,7 +2240,6 @@ #include "code\game\objects\items\shooting_range.dm" #include "code\game\objects\items\shrapnel.dm" #include "code\game\objects\items\signs.dm" -#include "code\game\objects\items\singularityhammer.dm" #include "code\game\objects\items\skub.dm" #include "code\game\objects\items\spear.dm" #include "code\game\objects\items\sticker.dm" @@ -2228,6 +2258,8 @@ #include "code\game\objects\items\virgin_mary.dm" #include "code\game\objects\items\wall_mounted.dm" #include "code\game\objects\items\weaponry.dm" +#include "code\game\objects\items\wiki_manuals.dm" +#include "code\game\objects\items\wizard_weapons.dm" #include "code\game\objects\items\AI_modules\_AI_modules.dm" #include "code\game\objects\items\AI_modules\freeform.dm" #include "code\game\objects\items\AI_modules\full_lawsets.dm" @@ -2325,6 +2357,7 @@ #include "code\game\objects\items\granters\crafting\death_sandwich.dm" #include "code\game\objects\items\granters\crafting\desserts.dm" #include "code\game\objects\items\granters\crafting\pipegun.dm" +#include "code\game\objects\items\granters\crafting\rebarxbowsyndie.dm" #include "code\game\objects\items\granters\crafting\regal_condor.dm" #include "code\game\objects\items\granters\magic\_spell_granter.dm" #include "code\game\objects\items\granters\magic\barnyard.dm" @@ -2515,6 +2548,7 @@ #include "code\game\objects\structures\morgue.dm" #include "code\game\objects\structures\mystery_box.dm" #include "code\game\objects\structures\noticeboard.dm" +#include "code\game\objects\structures\ore_containers.dm" #include "code\game\objects\structures\petrified_statue.dm" #include "code\game\objects\structures\pinatas.dm" #include "code\game\objects\structures\plasticflaps.dm" @@ -2939,20 +2973,20 @@ #include "code\modules\antagonists\heretic\items\heretic_necks.dm" #include "code\modules\antagonists\heretic\items\hunter_rifle.dm" #include "code\modules\antagonists\heretic\items\keyring.dm" -#include "code\modules\antagonists\heretic\items\lintel.dm" +#include "code\modules\antagonists\heretic\items\labyrinth_handbook.dm" #include "code\modules\antagonists\heretic\items\madness_mask.dm" #include "code\modules\antagonists\heretic\knowledge\ash_lore.dm" #include "code\modules\antagonists\heretic\knowledge\blade_lore.dm" #include "code\modules\antagonists\heretic\knowledge\cosmic_lore.dm" #include "code\modules\antagonists\heretic\knowledge\flesh_lore.dm" #include "code\modules\antagonists\heretic\knowledge\general_side.dm" -#include "code\modules\antagonists\heretic\knowledge\knock_lore.dm" +#include "code\modules\antagonists\heretic\knowledge\lock_lore.dm" #include "code\modules\antagonists\heretic\knowledge\rust_lore.dm" #include "code\modules\antagonists\heretic\knowledge\side_ash_flesh.dm" #include "code\modules\antagonists\heretic\knowledge\side_blade_rust.dm" #include "code\modules\antagonists\heretic\knowledge\side_cosmos_ash.dm" #include "code\modules\antagonists\heretic\knowledge\side_flesh_void.dm" -#include "code\modules\antagonists\heretic\knowledge\side_knock_flesh.dm" +#include "code\modules\antagonists\heretic\knowledge\side_lock_flesh.dm" #include "code\modules\antagonists\heretic\knowledge\side_rust_cosmos.dm" #include "code\modules\antagonists\heretic\knowledge\side_void_blade.dm" #include "code\modules\antagonists\heretic\knowledge\starting_lore.dm" @@ -3003,7 +3037,7 @@ #include "code\modules\antagonists\heretic\status_effects\ghoul.dm" #include "code\modules\antagonists\heretic\status_effects\mark_effects.dm" #include "code\modules\antagonists\heretic\structures\carving_knife.dm" -#include "code\modules\antagonists\heretic\structures\knock_final.dm" +#include "code\modules\antagonists\heretic\structures\lock_final.dm" #include "code\modules\antagonists\heretic\structures\mawed_crucible.dm" #include "code\modules\antagonists\highlander\highlander.dm" #include "code\modules\antagonists\hypnotized\hypnotized.dm" @@ -3303,13 +3337,18 @@ #include "code\modules\bitrunning\job.dm" #include "code\modules\bitrunning\outfits.dm" #include "code\modules\bitrunning\turfs.dm" +#include "code\modules\bitrunning\antagonists\_parent.dm" #include "code\modules\bitrunning\antagonists\cyber_police.dm" +#include "code\modules\bitrunning\antagonists\cyber_tac.dm" +#include "code\modules\bitrunning\antagonists\netguardian.dm" #include "code\modules\bitrunning\components\avatar_connection.dm" #include "code\modules\bitrunning\components\bitrunning_points.dm" +#include "code\modules\bitrunning\components\glitch.dm" #include "code\modules\bitrunning\components\netpod_healing.dm" -#include "code\modules\bitrunning\components\virtual_elite_mob.dm" +#include "code\modules\bitrunning\components\npc_friendly.dm" #include "code\modules\bitrunning\objects\byteforge.dm" #include "code\modules\bitrunning\objects\clothing.dm" +#include "code\modules\bitrunning\objects\debug.dm" #include "code\modules\bitrunning\objects\disks.dm" #include "code\modules\bitrunning\objects\hololadder.dm" #include "code\modules\bitrunning\objects\host_monitor.dm" @@ -3321,13 +3360,18 @@ #include "code\modules\bitrunning\orders\disks.dm" #include "code\modules\bitrunning\orders\flair.dm" #include "code\modules\bitrunning\orders\tech.dm" +#include "code\modules\bitrunning\server\_parent.dm" #include "code\modules\bitrunning\server\loot.dm" #include "code\modules\bitrunning\server\map_handling.dm" #include "code\modules\bitrunning\server\obj_generation.dm" -#include "code\modules\bitrunning\server\quantum_server.dm" #include "code\modules\bitrunning\server\signal_handlers.dm" #include "code\modules\bitrunning\server\threats.dm" #include "code\modules\bitrunning\server\util.dm" +#include "code\modules\bitrunning\util\digital_aura.dm" +#include "code\modules\bitrunning\util\service_style.dm" +#include "code\modules\bitrunning\util\virtual_megafauna.dm" +#include "code\modules\bitrunning\util\virtual_mob.dm" +#include "code\modules\bitrunning\virtual_domain\modular_mob_segment.dm" #include "code\modules\bitrunning\virtual_domain\safehouses.dm" #include "code\modules\bitrunning\virtual_domain\virtual_domain.dm" #include "code\modules\bitrunning\virtual_domain\domains\ash_drake.dm" @@ -3712,6 +3756,7 @@ #include "code\modules\economy\account.dm" #include "code\modules\economy\holopay.dm" #include "code\modules\emoji\emoji_parse.dm" +#include "code\modules\emote_panel\emote_panel.dm" #include "code\modules\error_handler\error_handler.dm" #include "code\modules\error_handler\error_viewer.dm" #include "code\modules\escape_menu\details.dm" @@ -4233,6 +4278,7 @@ #include "code\modules\mafia\roles\town\town_protective.dm" #include "code\modules\mafia\roles\town\town_support.dm" #include "code\modules\mapfluff\centcom\nuke_ops.dm" +#include "code\modules\mapfluff\ruins\generic.dm" #include "code\modules\mapfluff\ruins\lavaland_ruin_code.dm" #include "code\modules\mapfluff\ruins\icemoonruin_code\hotsprings.dm" #include "code\modules\mapfluff\ruins\icemoonruin_code\library.dm" @@ -4442,6 +4488,22 @@ #include "code\modules\mob\living\basic\farm_animals\gorilla\gorilla_accessories.dm" #include "code\modules\mob\living\basic\farm_animals\gorilla\gorilla_ai.dm" #include "code\modules\mob\living\basic\farm_animals\gorilla\gorilla_emotes.dm" +#include "code\modules\mob\living\basic\guardian\guardian.dm" +#include "code\modules\mob\living\basic\guardian\guardian_creator.dm" +#include "code\modules\mob\living\basic\guardian\guardian_fluff.dm" +#include "code\modules\mob\living\basic\guardian\guardian_helpers.dm" +#include "code\modules\mob\living\basic\guardian\guardian_verbs.dm" +#include "code\modules\mob\living\basic\guardian\guardian_types\assassin.dm" +#include "code\modules\mob\living\basic\guardian\guardian_types\charger.dm" +#include "code\modules\mob\living\basic\guardian\guardian_types\dextrous.dm" +#include "code\modules\mob\living\basic\guardian\guardian_types\explosive.dm" +#include "code\modules\mob\living\basic\guardian\guardian_types\gaseous.dm" +#include "code\modules\mob\living\basic\guardian\guardian_types\gravitokinetic.dm" +#include "code\modules\mob\living\basic\guardian\guardian_types\lightning.dm" +#include "code\modules\mob\living\basic\guardian\guardian_types\protector.dm" +#include "code\modules\mob\living\basic\guardian\guardian_types\ranged.dm" +#include "code\modules\mob\living\basic\guardian\guardian_types\standard.dm" +#include "code\modules\mob\living\basic\guardian\guardian_types\support.dm" #include "code\modules\mob\living\basic\heretic\_heretic_summon.dm" #include "code\modules\mob\living\basic\heretic\ash_spirit.dm" #include "code\modules\mob\living\basic\heretic\fire_shark.dm" @@ -4488,6 +4550,10 @@ #include "code\modules\mob\living\basic\lavaland\goliath\goliath_ai.dm" #include "code\modules\mob\living\basic\lavaland\goliath\goliath_trophy.dm" #include "code\modules\mob\living\basic\lavaland\goliath\tentacle.dm" +#include "code\modules\mob\living\basic\lavaland\gutlunchers\gutluncher_foodtrough.dm" +#include "code\modules\mob\living\basic\lavaland\gutlunchers\gutlunchers.dm" +#include "code\modules\mob\living\basic\lavaland\gutlunchers\gutlunchers_ai.dm" +#include "code\modules\mob\living\basic\lavaland\gutlunchers\gutlunchers_inherit_datum.dm" #include "code\modules\mob\living\basic\lavaland\hivelord\hivelord.dm" #include "code\modules\mob\living\basic\lavaland\hivelord\hivelord_ai.dm" #include "code\modules\mob\living\basic\lavaland\hivelord\spawn_hivelord_brood.dm" @@ -4625,6 +4691,7 @@ #include "code\modules\mob\living\basic\vermin\mouse.dm" #include "code\modules\mob\living\basic\vermin\space_bat.dm" #include "code\modules\mob\living\brain\brain.dm" +#include "code\modules\mob\living\brain\brain_cybernetic.dm" #include "code\modules\mob\living\brain\brain_item.dm" #include "code\modules\mob\living\brain\brain_say.dm" #include "code\modules\mob\living\brain\death.dm" @@ -4787,19 +4854,6 @@ #include "code\modules\mob\living\simple_animal\friendly\cat.dm" #include "code\modules\mob\living\simple_animal\friendly\gondola.dm" #include "code\modules\mob\living\simple_animal\friendly\pet.dm" -#include "code\modules\mob\living\simple_animal\guardian\guardian.dm" -#include "code\modules\mob\living\simple_animal\guardian\guardian_creator.dm" -#include "code\modules\mob\living\simple_animal\guardian\types\assassin.dm" -#include "code\modules\mob\living\simple_animal\guardian\types\charger.dm" -#include "code\modules\mob\living\simple_animal\guardian\types\dextrous.dm" -#include "code\modules\mob\living\simple_animal\guardian\types\explosive.dm" -#include "code\modules\mob\living\simple_animal\guardian\types\gaseous.dm" -#include "code\modules\mob\living\simple_animal\guardian\types\gravitokinetic.dm" -#include "code\modules\mob\living\simple_animal\guardian\types\lightning.dm" -#include "code\modules\mob\living\simple_animal\guardian\types\protector.dm" -#include "code\modules\mob\living\simple_animal\guardian\types\ranged.dm" -#include "code\modules\mob\living\simple_animal\guardian\types\standard.dm" -#include "code\modules\mob\living\simple_animal\guardian\types\support.dm" #include "code\modules\mob\living\simple_animal\hostile\alien.dm" #include "code\modules\mob\living\simple_animal\hostile\dark_wizard.dm" #include "code\modules\mob\living\simple_animal\hostile\hostile.dm" @@ -4819,7 +4873,6 @@ #include "code\modules\mob\living\simple_animal\hostile\megafauna\legion.dm" #include "code\modules\mob\living\simple_animal\hostile\megafauna\wendigo.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\curse_blob.dm" -#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\gutlunch.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\mining_mobs.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\polarbear.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\wolf.dm" @@ -5475,7 +5528,6 @@ #include "code\modules\spells\spell_types\self\lichdom.dm" #include "code\modules\spells\spell_types\self\mime_vow.dm" #include "code\modules\spells\spell_types\self\mutate.dm" -#include "code\modules\spells\spell_types\self\personality_commune.dm" #include "code\modules\spells\spell_types\self\rod_form.dm" #include "code\modules\spells\spell_types\self\sanguine_strike.dm" #include "code\modules\spells\spell_types\self\smoke.dm" diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss index 48d146451deea..0d62901c17a9a 100644 --- a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss +++ b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss @@ -505,6 +505,11 @@ em { font-size: 90%; } +.bolditalic { + font-style: italic; + font-weight: bold; +} + .boldnotice { color: #6685f5; font-weight: bold; diff --git a/tgui/packages/tgui/interfaces/AntagInfoCyberAuth.tsx b/tgui/packages/tgui/interfaces/AntagInfoCyberAuth.tsx deleted file mode 100644 index 21d872ed6a052..0000000000000 --- a/tgui/packages/tgui/interfaces/AntagInfoCyberAuth.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { useBackend } from '../backend'; -import { Divider, Section, Stack } from '../components'; -import { Window } from '../layouts'; -import { Objective } from './common/Objectives'; - -type Info = { - antag_name: string; - objectives: Objective[]; -}; - -const textStyles = { - variable: { - color: 'white', - }, - danger: { - color: 'red', - }, -} as const; - -export const AntagInfoCyberAuth = (props, context) => { - const { data } = useBackend(context); - const { objectives = [] } = data; - - return ( - - -
- - FN CYBER AUTHORITY UNIT (REF) - - - - You are a cyber authority unit. - - - - Your mission: Eliminate{' '} - organic intruders to maintain the integrity of the system. - - - Bitrunning is a crime. To - assist your task, your program has been loaded with cutting edge{' '} - martial arts skills. - - - Ranged weaponry is{' '} - forbidden. Ballistic - defense is frowned upon. Style is paramount. - - - {objectives[0].explanation} - - - - const TARGETS ={' '} - - - system. - INTRUDERS; - - - while TARGETS.LIFE !={' '} - stat.DEAD - - - action. - KILL() - - cyber_authority_unit([0x70cf4020]) - -
-
-
- ); -}; diff --git a/tgui/packages/tgui/interfaces/AntagInfoGlitch.tsx b/tgui/packages/tgui/interfaces/AntagInfoGlitch.tsx new file mode 100644 index 0000000000000..ca6ac70ccb39d --- /dev/null +++ b/tgui/packages/tgui/interfaces/AntagInfoGlitch.tsx @@ -0,0 +1,109 @@ +import { useBackend } from '../backend'; +import { Divider, Section, Stack } from '../components'; +import { Window } from '../layouts'; +import { Objective } from './common/Objectives'; + +type Data = { + antag_name: string; + objectives: Objective[]; +}; + +const textStyles = { + variable: { + color: 'white', + }, + danger: { + color: 'red', + }, +} as const; + +export const AntagInfoGlitch = (props, context) => { + const { data } = useBackend(context); + const { antag_name, objectives = [] } = data; + + return ( + + +
+ + FN TERMINATE_INTRUDERS (REF) + + + Initialize({antag_name}) + + + Bitrunning is a crime. Your + mission: Eliminate{' '} + organic intruders to maintain the integrity of the system. + + + + {objectives[0]?.explanation} + + + + const TARGETS ={' '} + + + system. + INTRUDERS; + + + while TARGETS.LIFE !={' '} + stat.DEAD + + + action. + KILL() + + terminate_intruders([0x70cf4020]) + +
+
+
+ ); +}; + +const SpecificInfo = (props, context) => { + const { data } = useBackend(context); + const { antag_name } = data; + + switch (antag_name) { + case 'Cyber Police': + return ( + <> + + To assist your task, your program has been loaded with cutting edge{' '} + martial arts skills. + + + Ranged weaponry is forbidden. + Ballistic defense is frowned upon. Style is paramount. + + + ); + case 'Cyber Tac': + return ( + <> + + You are an advanced combat unit. You have been outfitted with{' '} + lethal weaponry. + + + Terminate organic life at any + cost. + + + ); + case 'NetGuardian Prime': + return ( + + + ORGANIC LIFE MUST BE TERMINATED. + + + ); + default: + return null; + } +}; diff --git a/tgui/packages/tgui/interfaces/ChemDispenser.js b/tgui/packages/tgui/interfaces/ChemDispenser.tsx similarity index 82% rename from tgui/packages/tgui/interfaces/ChemDispenser.js rename to tgui/packages/tgui/interfaces/ChemDispenser.tsx index c4d7d158b643d..f724ad71629ab 100644 --- a/tgui/packages/tgui/interfaces/ChemDispenser.js +++ b/tgui/packages/tgui/interfaces/ChemDispenser.tsx @@ -1,22 +1,49 @@ import { toFixed } from 'common/math'; +import { BooleanLike } from 'common/react'; import { toTitleCase } from 'common/string'; -import { Fragment } from 'inferno'; import { useBackend, useLocalState } from '../backend'; import { AnimatedNumber, Box, Button, Icon, LabeledList, ProgressBar, Section } from '../components'; import { Window } from '../layouts'; +export type BeakerReagent = { + name: string; + volume: number; +}; + +export type Beaker = { + maxVolume: number; + transferAmounts: number[]; + pH: number; + currentVolume: number; + contents: BeakerReagent[]; +}; + +type DispensableReagent = { + title: string; + id: string; + pH: number; + pHCol: string; +}; + +type Data = { + showpH: BooleanLike; + amount: number; + energy: number; + maxEnergy: number; + chemicals: DispensableReagent[]; + recipes: string[]; + recordingRecipe: string[]; + recipeReagents: string[]; + beaker: Beaker; +}; + export const ChemDispenser = (props, context) => { - const { act, data } = useBackend(context); + const { act, data } = useBackend(context); const recording = !!data.recordingRecipe; - const { recipeReagents = [] } = data; + const { recipeReagents = [], recipes = [], beaker } = data; const [hasCol, setHasCol] = useLocalState(context, 'has_col', false); - // TODO: Change how this piece of shit is built on server side - // It has to be a list, not a fucking OBJECT! - const recipes = Object.keys(data.recipes).map((name) => ({ - name, - contents: data.recipes[name], - })); - const beakerTransferAmounts = data.beakerTransferAmounts || []; + + const beakerTransferAmounts = beaker ? beaker.transferAmounts : []; const beakerContents = (recording && Object.keys(data.recordingRecipe).map((id) => ({ @@ -24,7 +51,7 @@ export const ChemDispenser = (props, context) => { name: toTitleCase(id.replace(/_/, ' ')), volume: data.recordingRecipe[id], }))) || - data.beakerContents || + beaker?.contents || []; return ( @@ -41,10 +68,10 @@ export const ChemDispenser = (props, context) => { )} + + + + + + + }> + + + {emotes + .filter( + (emote) => + emote.key && + (searchText.length > 0 + ? emote.key + .toLowerCase() + .includes(searchText.toLowerCase()) || + emote.name.toLowerCase().includes(searchText.toLowerCase()) + : true) && + (filterVisible ? emote.visible : true) && + (filterAudible ? emote.audible : true) && + (filterSound ? emote.sound : true) && + (filterHands ? emote.hands : true) && + (filterUseParams ? emote.use_params : true) + ) + .sort((a, b) => (a.name > b.name ? 1 : -1)) + .map((emote) => ( + + ))} + + + + + ); +}; + +const EmoteIcons = (props, context) => { + const { visible, audible, sound, hands, use_params, margin } = props; + + return ( + + + + + + + + ); +}; + +export const EmotePanel = (props, context) => { + return ( + + + + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/MafiaPanel.tsx b/tgui/packages/tgui/interfaces/MafiaPanel.tsx index 528f6260b8d72..ee63d105dd11b 100644 --- a/tgui/packages/tgui/interfaces/MafiaPanel.tsx +++ b/tgui/packages/tgui/interfaces/MafiaPanel.tsx @@ -1,4 +1,4 @@ -import { classes } from 'common/react'; +import { BooleanLike, classes } from 'common/react'; import { decodeHtmlEntities } from 'common/string'; import { multiline } from 'common/string'; import { useBackend, useLocalState } from '../backend'; @@ -16,6 +16,7 @@ type RoleInfo = { type PlayerInfo = { name: string; + is_you: BooleanLike; ref: string; alive: string; possible_actions: ActionInfo[]; @@ -431,7 +432,8 @@ const MafiaPlayers = (props, context) => { - {player.name} {!player.alive && '(DEAD)'} + {player.name} + {player.is_you && ' (YOU)'} {!player.alive && '(DEAD)'} {player.votes !== undefined && diff --git a/tgui/packages/tgui/interfaces/MatMarket.tsx b/tgui/packages/tgui/interfaces/MatMarket.tsx index 38ecfec2c1808..55f0985c47e64 100644 --- a/tgui/packages/tgui/interfaces/MatMarket.tsx +++ b/tgui/packages/tgui/interfaces/MatMarket.tsx @@ -21,10 +21,11 @@ type Data = { orderBalance: number; materials: Material[]; catastrophe: BooleanLike; + CARGO_CRATE_VALUE: number; }; export const MatMarket = (props, context) => { - const { act, data } = useBackend(context); // this will tell your editor that data is the type listed above + const { act, data } = useBackend(context); const { orderingPrive, @@ -33,7 +34,14 @@ export const MatMarket = (props, context) => { orderBalance, materials = [], catastrophe, + CARGO_CRATE_VALUE, } = data; + + // offset cost with crate value if there is currently nothing in the order + const total_order_cost = orderBalance || CARGO_CRATE_VALUE; + // multiplier of 1.1 for private orders + const multiplier = orderingPrive ? 1.1 : 1; + return ( @@ -126,7 +134,8 @@ export const MatMarket = (props, context) => { disabled={ catastrophe === 1 || material.price <= 0 || - creditBalance - orderBalance < material.price || + creditBalance - total_order_cost < + material.price * multiplier || material.requested + 1 > material.quantity } tooltip={material.price * 1} @@ -142,7 +151,8 @@ export const MatMarket = (props, context) => { disabled={ catastrophe === 1 || material.price <= 0 || - creditBalance - orderBalance < material.price * 5 || + creditBalance - total_order_cost < + material.price * 5 * multiplier || material.requested + 5 > material.quantity } tooltip={material.price * 5} @@ -158,7 +168,8 @@ export const MatMarket = (props, context) => { disabled={ catastrophe === 1 || material.price <= 0 || - creditBalance - orderBalance < material.price * 10 || + creditBalance - total_order_cost < + material.price * 10 * multiplier || material.requested + 10 > material.quantity } tooltip={material.price * 10} @@ -174,7 +185,8 @@ export const MatMarket = (props, context) => { disabled={ catastrophe === 1 || material.price <= 0 || - creditBalance - orderBalance < material.price * 25 || + creditBalance - total_order_cost < + material.price * 25 * multiplier || material.requested + 25 > material.quantity } tooltip={material.price * 25} @@ -190,7 +202,8 @@ export const MatMarket = (props, context) => { disabled={ catastrophe === 1 || material.price <= 0 || - creditBalance - orderBalance < material.price * 50 || + creditBalance - total_order_cost < + material.price * 50 * multiplier || material.requested + 50 > material.quantity } tooltip={material.price * 50} diff --git a/tgui/packages/tgui/interfaces/Mecha/ModulesPane.tsx b/tgui/packages/tgui/interfaces/Mecha/ModulesPane.tsx index 04a1100fa1338..e891337c275fc 100644 --- a/tgui/packages/tgui/interfaces/Mecha/ModulesPane.tsx +++ b/tgui/packages/tgui/interfaces/Mecha/ModulesPane.tsx @@ -290,6 +290,7 @@ const MECHA_SNOWFLAKE_ID_RADIO = 'radio_snowflake'; const MECHA_SNOWFLAKE_ID_AIR_TANK = 'air_tank_snowflake'; const MECHA_SNOWFLAKE_ID_WEAPON_BALLISTIC = 'ballistic_weapon_snowflake'; const MECHA_SNOWFLAKE_ID_GENERATOR = 'generator_snowflake'; +const MECHA_SNOWFLAKE_ID_CLAW = 'lawclaw_snowflake'; export const ModuleDetailsExtra = (props: { module: MechModule }, context) => { const module = props.module; @@ -308,6 +309,8 @@ export const ModuleDetailsExtra = (props: { module: MechModule }, context) => { return ; case MECHA_SNOWFLAKE_ID_GENERATOR: return ; + case MECHA_SNOWFLAKE_ID_CLAW: + return ; default: return null; } @@ -887,3 +890,27 @@ const SnowflakeGeneraor = (props, context) => { ); }; + +const SnowflakeLawClaw = (props, context) => { + const { act, data } = useBackend(context); + const { ref } = props.module; + const { autocuff } = props.module.snowflake; + return ( + + act('equip_act', { + ref: ref, + gear_action: 'togglecuff', + }) + } + /> + } + /> + ); +}; diff --git a/tgui/packages/tgui/interfaces/NtosMain.js b/tgui/packages/tgui/interfaces/NtosMain.js index 8debe5d93be8e..e7e0fc584467c 100644 --- a/tgui/packages/tgui/interfaces/NtosMain.js +++ b/tgui/packages/tgui/interfaces/NtosMain.js @@ -83,7 +83,7 @@ export const NtosMain = (props, context) => { ) }> - {(data.contents.length === 0 && ( + {contents.length === 0 ? ( Unfortunately, this {data.name} is empty. - )) || ( + ) : ( Item - {data.verb ? data.verb : 'Dispense'} + {data.isdryer ? 'Take' : 'Dispense'} - {map((value, key) => ( + {Object.values(contents).map((value, key) => ( {value.name} @@ -58,7 +71,7 @@ export const SmartVend = (props, context) => { /> - ))(data.contents)} + ))}
)} diff --git a/tools/UpdatePaths/Scripts/79473_guardian_creator_repath.txt b/tools/UpdatePaths/Scripts/79473_guardian_creator_repath.txt new file mode 100644 index 0000000000000..92f9e379d9a8e --- /dev/null +++ b/tools/UpdatePaths/Scripts/79473_guardian_creator_repath.txt @@ -0,0 +1,5 @@ +/obj/item/guardiancreator/choose/wizard : /obj/item/guardian_creator/wizard{@OLD} +/obj/item/guardiancreator/tech/@SUBTYPES : /obj/item/guardian_creator/tech/@SUBTYPES{@OLD} +/obj/item/guardiancreator/carp/@SUBTYPES : /obj/item/guardian_creator/carp/@SUBTYPES{@OLD} +/obj/item/guardian_creator/miner/@SUBTYPES : /obj/item/guardian_creator/miner/@SUBTYPES{@OLD} +/obj/item/guardiancreator/@SUBTYPES : /obj/item/guardian_creator/@SUBTYPES{@OLD} diff --git a/tools/UpdatePaths/Scripts/79508_gutlunchers.txt b/tools/UpdatePaths/Scripts/79508_gutlunchers.txt new file mode 100644 index 0000000000000..f6a07058fb800 --- /dev/null +++ b/tools/UpdatePaths/Scripts/79508_gutlunchers.txt @@ -0,0 +1,5 @@ +/mob/living/simple_animal/hostile/asteroid/gutlunch : /mob/living/basic/mining/gutlunch{@OLD} +/mob/living/simple_animal/hostile/asteroid/gutlunch/grublunch : /mob/living/basic/mining/gutlunch/grub{@OLD} +/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck : /mob/living/basic/mining/gutlunch/milk{@OLD} +/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen : /mob/living/basic/mining/gutlunch/warrior{@OLD} + diff --git a/tools/UpdatePaths/Scripts/79508_ore_container.txt b/tools/UpdatePaths/Scripts/79508_ore_container.txt new file mode 100644 index 0000000000000..d3851e0628cdb --- /dev/null +++ b/tools/UpdatePaths/Scripts/79508_ore_container.txt @@ -0,0 +1 @@ +/obj/structure/material_stand : /obj/structure/ore_container/material_stand{@OLD} \ No newline at end of file diff --git a/tools/UpdatePaths/Scripts/79542_knock_lock.txt b/tools/UpdatePaths/Scripts/79542_knock_lock.txt new file mode 100644 index 0000000000000..a6249e01af369 --- /dev/null +++ b/tools/UpdatePaths/Scripts/79542_knock_lock.txt @@ -0,0 +1,5 @@ +/area/centcom/heretic_sacrifice/knock : /area/centcom/heretic_sacrifice/lock{@OLD} +/obj/effect/landmark/heretic/knock: /obj/effect/landmark/heretic/lock{@OLD} +/obj/item/melee/sickly_blade/knock: /obj/item/melee/sickly_blade/lock{@OLD} +/obj/effect/knock_portal: /obj/effect/knock_portal{@OLD} +/obj/item/heretic_lintel: /obj/item/heretic_labyrinth_handbook{@OLD} \ No newline at end of file diff --git a/tools/maplint/lints/multiple_machinery.yml b/tools/maplint/lints/multiple_machinery.yml new file mode 100644 index 0000000000000..942d72b401e56 --- /dev/null +++ b/tools/maplint/lints/multiple_machinery.yml @@ -0,0 +1,4 @@ +/obj/machinery: + banned_neighbors: + /obj/machinery: + identical: true diff --git a/tools/maplint/lints/multiple_windows.yml b/tools/maplint/lints/multiple_windows.yml new file mode 100644 index 0000000000000..9af1c4d73221a --- /dev/null +++ b/tools/maplint/lints/multiple_windows.yml @@ -0,0 +1,4 @@ +/obj/structure/window: + banned_neighbors: + /obj/structure/window: + identical: true diff --git a/tools/maplint/source/lint.py b/tools/maplint/source/lint.py index 4af9ad5c1cfd4..ee86d29be52b4 100644 --- a/tools/maplint/source/lint.py +++ b/tools/maplint/source/lint.py @@ -66,7 +66,13 @@ def __init__(self, typepath, data = {}): def matches(self, identified: Content, neighbor: Content): if self.identical: - return neighbor == identified + if identified.path != neighbor.path: + return False + + if identified.var_edits != neighbor.var_edits: + return False + + return True if self.typepath is not None: if self.typepath.matches_path(neighbor.path):