diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_ore_vent.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_ore_vent.dmm new file mode 100644 index 000000000000..51584f90f86a --- /dev/null +++ b/_maps/RandomRuins/IceRuins/icemoon_surface_ore_vent.dmm @@ -0,0 +1,27 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"l" = ( +/turf/open/misc/asteroid/snow/icemoon, +/area/icemoon/surface/outdoors/unexplored/rivers/no_monsters) +"L" = ( +/obj/structure/ore_vent/random/icebox, +/turf/open/misc/asteroid/snow/icemoon, +/area/icemoon/surface/outdoors/unexplored/rivers/no_monsters) + +(1,1,1) = {" +a +l +a +"} +(2,1,1) = {" +l +L +l +"} +(3,1,1) = {" +a +l +a +"} diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_ore_vent.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_ore_vent.dmm new file mode 100644 index 000000000000..db409d08c8cf --- /dev/null +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_ore_vent.dmm @@ -0,0 +1,27 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"l" = ( +/turf/open/misc/asteroid/snow/icemoon, +/area/icemoon/underground/unexplored) +"L" = ( +/obj/structure/ore_vent/random/icebox/lower, +/turf/open/misc/asteroid/snow/icemoon, +/area/icemoon/underground/unexplored) + +(1,1,1) = {" +a +l +a +"} +(2,1,1) = {" +l +L +l +"} +(3,1,1) = {" +a +l +a +"} diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_ore_vent.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_ore_vent.dmm new file mode 100644 index 000000000000..6379b7f084ba --- /dev/null +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_ore_vent.dmm @@ -0,0 +1,27 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"l" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"L" = ( +/obj/structure/ore_vent/random, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) + +(1,1,1) = {" +a +l +a +"} +(2,1,1) = {" +l +L +l +"} +(3,1,1) = {" +a +l +a +"} diff --git a/_maps/blueshift.json b/_maps/blueshift.json index 2a685910e3c0..89fc5993f3f1 100644 --- a/_maps/blueshift.json +++ b/_maps/blueshift.json @@ -3,6 +3,7 @@ "map_name": "Blueshift", "map_path": "map_files/Blueshift", "map_file": "Blueshift.dmm", + "space_ruin_levels": 2, "shuttles": { "cargo": "cargo_nova", "whiteship": "whiteship_blueshift", diff --git a/_maps/map_files/Blueshift/Blueshift.dmm b/_maps/map_files/Blueshift/Blueshift.dmm index df77cc074b12..9c931e4eae42 100644 --- a/_maps/map_files/Blueshift/Blueshift.dmm +++ b/_maps/map_files/Blueshift/Blueshift.dmm @@ -148,10 +148,6 @@ }, /turf/open/floor/iron, /area/station/commons/fitness/recreation) -"act" = ( -/obj/structure/disposalpipe/segment, -/turf/closed/wall/r_wall, -/area/station/cargo/quartermaster) "acx" = ( /obj/machinery/conveyor{ dir = 1; @@ -989,6 +985,16 @@ /obj/structure/cable, /turf/closed/wall/r_wall, /area/station/ai_monitored/turret_protected/ai) +"akd" = ( +/obj/structure/aquarium, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "akf" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -1127,12 +1133,6 @@ /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/station/command/captain_dining) -"alN" = ( -/obj/machinery/light/small/directional/north, -/obj/structure/disposalpipe/segment, -/obj/effect/landmark/start/quartermaster, -/turf/open/floor/carpet, -/area/station/cargo/quartermaster) "alQ" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, @@ -1389,14 +1389,6 @@ /obj/machinery/atmospherics/pipe/bridge_pipe/yellow/visible, /turf/open/space/basic, /area/space/nearstation) -"aoq" = ( -/obj/structure/chair/office{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron, -/area/station/maintenance/thruster_room/central) "aor" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -1974,13 +1966,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/security/prison/upper) -"auf" = ( -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "auv" = ( /obj/effect/turf_decal/bot_white/left, /obj/effect/spawner/random/structure/crate, @@ -2676,15 +2661,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) -"aBw" = ( -/obj/structure/chair/office{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/assistant, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/wood/parquet, -/area/station/common/arcade) "aBz" = ( /obj/item/storage/secure/safe/directional/east, /turf/open/floor/carpet/green, @@ -2771,6 +2747,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/service/chapel/office) +"aCe" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/cable, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/stone, +/area/station/service/forge) "aCf" = ( /obj/machinery/status_display/evac/directional/east, /obj/structure/chair/stool/directional/north, @@ -4434,12 +4419,6 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos/pumproom) -"aTf" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/drone_dispenser/preloaded, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron, -/area/station/science/research/abandoned) "aTg" = ( /obj/structure/bodycontainer/morgue, /obj/effect/turf_decal/bot_white, @@ -4853,6 +4832,11 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, /area/station/medical/surgery) +"aXz" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/grass, +/area/station/service/hydroponics/garden/abandoned) "aXB" = ( /obj/structure/lattice, /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ @@ -5931,23 +5915,6 @@ }, /turf/open/floor/iron/white, /area/station/science/xenobiology/control) -"biD" = ( -/obj/structure/table/wood, -/obj/item/coin/gold{ - desc = "A limited edition coin printed with a FTU cargo hauler on the tail's side and the FTU logo on the head's side.. only 500 of these were ever made as a celebration to the passing of lessened trade regulations in the frontier sector."; - name = "FTU special edition collector's coin" - }, -/obj/item/toy/figure/clown{ - desc = "Aside from the engraving on the back of this figurine it's identical to any old NT departmental action figure, yet these sell for eye watering prices on the open market."; - name = "Comedycon edition clown action figure" - }, -/obj/item/reagent_containers/cup/glass/bottle/wine{ - desc = "A vintage wine bottle that appears to be produced on terra around the early 20th century.. the label is written in an ancient human language that sounds indecipherable.. le.. chateau.. what now?"; - name = "Vintage Terran red wine bottle" - }, -/obj/item/clothing/head/collectable/petehat, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "biE" = ( /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/north, @@ -6384,6 +6351,13 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/maintenance/disposal/incinerator) +"bmS" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/carpet, +/area/station/service/theater/abandoned) "bmT" = ( /obj/machinery/photocopier, /obj/effect/turf_decal/bot, @@ -7483,6 +7457,12 @@ }, /turf/open/floor/iron/dark, /area/station/security/prison/upper) +"bwW" = ( +/obj/structure/flora/bush/jungle/b/style_2, +/obj/structure/flora/bush/flowers_pp, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "bwY" = ( /obj/machinery/bluespace_vendor/directional/east, /turf/open/floor/iron/dark/side{ @@ -7798,22 +7778,6 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/station/hallway/primary/port) -"bzO" = ( -/obj/machinery/door/airlock/corporate{ - id_tag = "BSdoor"; - name = "Blueshield's Office" - }, -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/effect/landmark/navigate_destination, -/turf/open/floor/wood, -/area/station/command/heads_quarters/blueshield) "bzQ" = ( /obj/machinery/disposal/bin, /obj/effect/turf_decal/delivery, @@ -8133,10 +8097,6 @@ }, /turf/open/floor/grass, /area/station/security/prison/garden) -"bCR" = ( -/obj/structure/disposalpipe/segment, -/turf/open/floor/carpet, -/area/station/cargo/quartermaster) "bCW" = ( /obj/structure/chair/office, /obj/effect/turf_decal/vg_decals/numbers/four, @@ -8715,16 +8675,6 @@ /obj/machinery/light/directional/east, /turf/open/floor/wood, /area/station/command/captain_dining) -"bJM" = ( -/obj/structure/aquarium, -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "bJS" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/bot, @@ -9194,25 +9144,6 @@ /obj/machinery/atmospherics/pipe/smart/simple/yellow/visible, /turf/open/floor/plating, /area/station/science/ordnance/freezerchamber) -"bNE" = ( -/obj/item/trash/syndi_cakes, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/broken_floor, -/obj/machinery/door/firedoor, -/obj/machinery/door/poddoor/shutters{ - id = "Starboardbowmaints"; - name = "Starboard Bow Maintenance" - }, -/obj/machinery/button/door/directional/north{ - id = "Starboardbowmaints"; - name = "Shutter control"; - pixel_x = 24; - pixel_y = 0 - }, -/turf/open/floor/plating, -/area/station/maintenance/fore/upper) "bNL" = ( /obj/structure/table/reinforced, /obj/item/aicard, @@ -9273,13 +9204,6 @@ dir = 4 }, /area/station/common/locker_room_shower) -"bOo" = ( -/obj/structure/chair{ - dir = 4 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/carpet, -/area/station/service/theater/abandoned) "bOu" = ( /obj/structure/railing{ dir = 4 @@ -9488,15 +9412,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) -"bPR" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/segment, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron, -/area/station/maintenance/starboard/fore) "bPS" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -10429,11 +10344,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"bZx" = ( -/obj/structure/bed, -/obj/item/bedsheet/qm, -/turf/open/floor/carpet, -/area/station/cargo/quartermaster) "bZC" = ( /obj/structure/table, /obj/machinery/reagentgrinder{ @@ -10937,28 +10847,6 @@ dir = 4 }, /area/station/engineering/gravity_generator) -"cen" = ( -/obj/structure/table/wood, -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/item/folder/yellow, -/obj/item/stamp/head/qm, -/obj/item/reagent_containers/cup/glass/drinkingglass/shotglass{ - pixel_x = 6; - pixel_y = 16 - }, -/obj/item/reagent_containers/cup/glass/drinkingglass/shotglass{ - pixel_x = -4; - pixel_y = 16 - }, -/obj/item/hand_labeler_refill{ - pixel_x = -8; - pixel_y = -8 - }, -/obj/structure/disposalpipe/segment, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "cev" = ( /obj/structure/chair/sofa/bench/left{ dir = 4; @@ -11043,6 +10931,18 @@ "ceX" = ( /turf/open/floor/iron/dark, /area/station/hallway/primary/central) +"cfa" = ( +/obj/item/storage/backpack/blueshield, +/obj/item/storage/backpack/duffelbag/blueshield, +/obj/item/storage/backpack/satchel/blueshield, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/item/clothing/neck/mantle/bsmantle, +/obj/machinery/duct, +/obj/structure/closet/secure_closet/blueshield, +/turf/open/floor/carpet/executive, +/area/station/command/heads_quarters/blueshield) "cfb" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 @@ -11128,14 +11028,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood, /area/station/service/hydroponics/garden/abandoned) -"cfZ" = ( -/obj/item/kirbyplants/random, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/airalarm/directional/south, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "cgc" = ( /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/hidden{ dir = 6 @@ -11763,16 +11655,6 @@ }, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"cmE" = ( -/obj/machinery/light/directional/south, -/obj/structure/cable, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/obj/machinery/duct, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/cafeteria, -/area/station/commons/toilet/auxiliary) "cmG" = ( /obj/effect/turf_decal/bot_white, /turf/open/floor/iron/dark/smooth_large/airless, @@ -11845,13 +11727,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/aft/upper) -"cns" = ( -/obj/structure/cable, -/obj/structure/chair/stool/bar, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/carpet/green, -/area/station/service/abandoned_gambling_den) "cnv" = ( /obj/effect/turf_decal/trimline/red/filled/warning{ dir = 1 @@ -13026,6 +12901,16 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/prison/workout) +"cxO" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/carpet, +/area/station/service/library/printer) "cxW" = ( /obj/structure/window/reinforced/spawner/directional/south, /obj/structure/rack, @@ -13515,6 +13400,10 @@ dir = 1 }, /area/station/ai_monitored/security/armory) +"cBG" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/aft/upper) "cBJ" = ( /obj/structure/railing{ dir = 1 @@ -13730,6 +13619,15 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/grimy, /area/station/security/detectives_office/private_investigators_office) +"cDG" = ( +/obj/effect/turf_decal/siding/brown{ + dir = 1 + }, +/obj/machinery/computer/cargo{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/station/cargo/quartermaster) "cDI" = ( /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ dir = 5 @@ -14157,12 +14055,6 @@ /obj/structure/cable, /turf/open/floor/wood, /area/station/command/heads_quarters/hop) -"cGG" = ( -/obj/structure/flora/bush/jungle/a/style_2, -/obj/structure/flora/bush/flowers_yw/style_2, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "cGH" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -14576,15 +14468,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark/textured_large, /area/station/security/office) -"cJQ" = ( -/obj/effect/turf_decal/siding/brown{ - dir = 1 - }, -/obj/machinery/computer/piratepad_control{ - dir = 1 - }, -/turf/open/floor/iron/dark, -/area/station/cargo/quartermaster) "cJU" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -15430,10 +15313,6 @@ /obj/effect/mapping_helpers/airlock/locked, /turf/open/floor/engine, /area/station/science/ordnance/burnchamber) -"cSH" = ( -/obj/structure/chair/office, -/turf/open/floor/carpet/executive, -/area/station/command/heads_quarters/blueshield) "cSI" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -16110,6 +15989,15 @@ /obj/effect/spawner/random/trash/garbage, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"cZI" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron, +/area/station/maintenance/starboard/fore) "cZL" = ( /obj/effect/turf_decal/delivery, /obj/machinery/door/window/brigdoor/left/directional/east{ @@ -16595,11 +16483,6 @@ /obj/effect/spawner/random/trash/mess, /turf/open/floor/plating, /area/station/maintenance/law) -"dfo" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/grass, -/area/station/service/hydroponics/garden/abandoned) "dfr" = ( /obj/structure/sink/directional/east, /obj/machinery/camera/directional/west{ @@ -17666,12 +17549,6 @@ /obj/machinery/door/airlock/maintenance, /turf/open/floor/plating, /area/station/maintenance/aft/upper) -"dqh" = ( -/obj/structure/flora/bush/jungle/b/style_2, -/obj/structure/flora/bush/flowers_pp/style_3, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "dqk" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 @@ -18192,6 +18069,21 @@ "dvB" = ( /turf/closed/wall/r_wall, /area/station/engineering/storage/tech) +"dvI" = ( +/obj/effect/turf_decal/siding/brown{ + dir = 1 + }, +/obj/machinery/computer/security/qm{ + dir = 1 + }, +/obj/machinery/requests_console/directional/south{ + department = "Quartermaster's Office"; + name = "Quartermaster's Requests Console" + }, +/obj/effect/mapping_helpers/requests_console/announcement, +/obj/effect/mapping_helpers/requests_console/supplies, +/turf/open/floor/iron/dark, +/area/station/cargo/quartermaster) "dvL" = ( /obj/structure/table/wood, /obj/structure/showcase/machinery/microwave{ @@ -18486,6 +18378,16 @@ /obj/structure/liquid_barrier, /turf/open/floor/iron/white, /area/station/science/xenobiology/control) +"dzr" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/duct, +/obj/structure/cable, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/commons/dorms/vacantroom) "dzs" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -18582,24 +18484,6 @@ /obj/machinery/suit_storage_unit/standard_unit, /turf/open/floor/iron/dark, /area/station/ai_monitored/command/storage/eva/upper) -"dAw" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/firedoor, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/door/poddoor/shutters{ - id = "Portbowmaints"; - name = "Port Bow Maintenance" - }, -/obj/machinery/button/door/directional/north{ - id = "Portbowmaints"; - name = "Shutter control"; - pixel_x = 24; - pixel_y = 0 - }, -/turf/open/floor/iron/stairs/right, -/area/station/maintenance/port/upper) "dAB" = ( /obj/structure/closet/crate/bin, /turf/open/floor/iron, @@ -19728,6 +19612,12 @@ /obj/effect/decal/cleanable/dirt, /turf/closed/wall, /area/station/medical/power_station) +"dKI" = ( +/obj/structure/flora/bush/jungle/b/style_2, +/obj/structure/flora/bush/flowers_pp/style_3, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "dKK" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -20017,20 +19907,11 @@ }, /turf/open/floor/plating, /area/station/maintenance/department/engineering/engine_aft_port) -"dNr" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/power/apc/auto_name/directional/west, -/obj/structure/cable, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) -"dNx" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/white, -/area/station/medical/aslyum) +"dNs" = ( +/obj/machinery/duct, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/carpet/executive, +/area/station/command/heads_quarters/blueshield) "dNC" = ( /obj/effect/spawner/random/vending/colavend, /obj/effect/turf_decal/siding/thinplating_new{ @@ -21079,6 +20960,10 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"dYV" = ( +/obj/structure/disposalpipe/segment, +/turf/closed/wall/r_wall, +/area/station/cargo/quartermaster) "dZa" = ( /obj/effect/turf_decal/delivery, /obj/effect/turf_decal/stripes{ @@ -21821,12 +21706,6 @@ /obj/machinery/duct, /turf/open/floor/iron/dark, /area/station/common/night_club) -"ehv" = ( -/obj/structure/chair/office{ - dir = 8 - }, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "ehw" = ( /obj/machinery/power/apc/auto_name/directional/west, /obj/structure/cable, @@ -22986,6 +22865,24 @@ dir = 8 }, /area/station/security/brig) +"eul" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/firedoor, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/poddoor/shutters{ + id = "Portbowmaints"; + name = "Port Bow Maintenance" + }, +/obj/machinery/button/door/directional/north{ + id = "Portbowmaints"; + name = "Shutter control"; + pixel_x = 24; + pixel_y = 0 + }, +/turf/open/floor/iron/stairs/right, +/area/station/maintenance/port/upper) "eum" = ( /obj/structure/cable, /obj/effect/landmark/event_spawn, @@ -24155,6 +24052,22 @@ dir = 4 }, /area/station/command/secure_bunker) +"eDY" = ( +/obj/machinery/door/airlock/corporate{ + id_tag = "BSdoor"; + name = "Blueshield's Office" + }, +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/navigate_destination, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/wood, +/area/station/command/heads_quarters/blueshield) "eDZ" = ( /obj/effect/turf_decal/stripes/end{ dir = 1 @@ -25417,12 +25330,6 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/plating, /area/station/maintenance/port/upper) -"ePR" = ( -/obj/structure/flora/bush/jungle/a/style_2, -/obj/structure/flora/bush/flowers_yw/style_3, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "ePU" = ( /obj/structure/table/reinforced, /obj/machinery/recharger{ @@ -25708,6 +25615,10 @@ /obj/machinery/newscaster/directional/east, /turf/open/floor/iron/dark/corner, /area/station/hallway/primary/central) +"eSI" = ( +/obj/machinery/suit_storage_unit/industrial/loader, +/turf/open/floor/plating, +/area/station/cargo/storage) "eSN" = ( /turf/closed/wall, /area/station/service/bar/backroom) @@ -26013,10 +25924,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) -"eVJ" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/aft/upper) "eVK" = ( /obj/structure/table, /obj/item/folder/blue{ @@ -26838,6 +26745,11 @@ /obj/effect/mapping_helpers/airlock/access/all/medical/surgery, /turf/open/floor/iron/white, /area/station/medical/coldroom) +"fdB" = ( +/obj/structure/bed, +/obj/item/bedsheet/qm, +/turf/open/floor/carpet, +/area/station/cargo/quartermaster) "fdD" = ( /obj/structure/window/reinforced/spawner/directional/east, /obj/effect/turf_decal/trimline/blue/line{ @@ -27398,6 +27310,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"fiG" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/station/cargo/quartermaster) "fiI" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/iron, @@ -27938,9 +27856,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/engineering/transit_tube) -"fpe" = ( -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "fpl" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, @@ -28331,12 +28246,6 @@ }, /turf/open/floor/iron/dark, /area/station/security/prison/upper) -"fsX" = ( -/obj/structure/flora/bush/jungle/c/style_3, -/obj/structure/flora/bush/flowers_yw/style_3, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "fsY" = ( /obj/effect/spawner/random/trash/cigbutt, /obj/effect/decal/cleanable/dirt, @@ -28540,15 +28449,6 @@ /obj/structure/sign/warning/radiation/directional/east, /turf/open/floor/iron/dark, /area/station/engineering/gravity_generator) -"fvd" = ( -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "fvp" = ( /obj/structure/chair/office{ dir = 1 @@ -28831,10 +28731,6 @@ /obj/structure/closet/firecloset, /turf/open/floor/iron, /area/station/science/explab) -"fxQ" = ( -/obj/structure/decorative/shelf/alcohol_assortment, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "fxR" = ( /obj/effect/decal/cleanable/blood/old, /turf/open/floor/plating, @@ -29491,12 +29387,6 @@ /obj/effect/landmark/start/assistant, /turf/open/floor/iron, /area/station/common/wrestling/lobby) -"fGg" = ( -/obj/machinery/duct, -/obj/effect/spawner/random/trash/mess, -/obj/effect/landmark/start/gary, -/turf/open/floor/carpet, -/area/station/commons/dorms/vacantroom) "fGm" = ( /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -32132,6 +32022,19 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/security/execution/education) +"gia" = ( +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/siding/wood, +/obj/machinery/door/airlock/mining{ + name = "Deliveries" + }, +/obj/effect/mapping_helpers/airlock/access/all/supply/qm, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "gib" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -32189,6 +32092,13 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white/side, /area/station/science) +"giW" = ( +/obj/structure/disposalpipe/segment, +/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/stairs/old, +/area/station/cargo/office) "gjd" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -32871,6 +32781,11 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/aft/upper) +"gpf" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "gpn" = ( /obj/machinery/disposal/delivery_chute{ dir = 8 @@ -33344,6 +33259,10 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating/airless, /area/station/maintenance/fore/upper) +"gtW" = ( +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/iron, +/area/station/commons/vacant_room/commissary) "gtZ" = ( /obj/effect/turf_decal/caution/stand_clear, /obj/structure/cable, @@ -33570,6 +33489,15 @@ "gwf" = ( /turf/open/floor/plating, /area/station/hallway/secondary/construction) +"gwg" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "gwh" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/trash/moisture_trap, @@ -34210,6 +34138,12 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/starboard) +"gBx" = ( +/obj/structure/flora/bush/jungle, +/obj/structure/flora/bush/flowers_yw/style_3, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "gBz" = ( /obj/effect/spawner/random/trash/bacteria, /obj/effect/decal/cleanable/dirt, @@ -34557,6 +34491,16 @@ /obj/item/toy/figure/cmo, /turf/open/floor/carpet/blue, /area/station/command/heads_quarters/cmo) +"gFQ" = ( +/obj/machinery/light/directional/south, +/obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/machinery/duct, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/cafeteria, +/area/station/commons/toilet/auxiliary) "gFS" = ( /obj/machinery/door/poddoor/shutters{ id = "evashutters4"; @@ -34600,6 +34544,15 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"gGm" = ( +/obj/effect/turf_decal/siding/wood, +/obj/machinery/door/airlock/mining{ + name = "Deliveries" + }, +/obj/effect/mapping_helpers/airlock/access/all/supply/qm, +/obj/structure/disposalpipe/segment, +/turf/open/floor/carpet, +/area/station/cargo/quartermaster) "gGo" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark/side{ @@ -35226,6 +35179,11 @@ /obj/machinery/duct, /turf/open/floor/iron, /area/station/commons/locker) +"gNs" = ( +/obj/structure/chair/office, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/carpet/executive, +/area/station/command/heads_quarters/blueshield) "gNv" = ( /obj/machinery/smartfridge, /turf/open/floor/iron/dark, @@ -36840,27 +36798,6 @@ /obj/structure/sign/warning/vacuum/external/directional/east, /turf/open/floor/plating, /area/station/maintenance/fore/upper) -"heD" = ( -/obj/structure/table/wood, -/obj/effect/turf_decal/siding/wood{ - dir = 5 - }, -/obj/item/reagent_containers/cup/glass/bottle/rum{ - pixel_x = -7; - pixel_y = 10 - }, -/obj/item/storage/fancy/cigarettes/cigars/cohiba, -/obj/item/storage/fancy/cigarettes/cigars/havana{ - pixel_y = 4 - }, -/obj/item/clothing/mask/cigarette/rollie/cannabis{ - pixel_x = 8; - pixel_y = 15 - }, -/obj/item/lighter, -/obj/structure/disposalpipe/segment, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "heN" = ( /obj/effect/turf_decal/siding/thinplating/dark{ dir = 1 @@ -37080,6 +37017,13 @@ }, /turf/open/floor/iron/dark, /area/station/security/prison/mess) +"hgI" = ( +/obj/structure/bed/dogbed, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "hgL" = ( /obj/structure/toilet{ dir = 1 @@ -38007,6 +37951,15 @@ /obj/effect/turf_decal/tile/green/opposingcorners, /turf/open/floor/iron/white, /area/station/medical/virology) +"hpv" = ( +/obj/effect/turf_decal/siding/brown{ + dir = 1 + }, +/obj/machinery/computer/piratepad_control{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/station/cargo/quartermaster) "hpF" = ( /obj/effect/turf_decal/tile/dark_blue/half/contrasted, /obj/machinery/power/apc/auto_name/directional/south, @@ -38294,6 +38247,14 @@ dir = 5 }, /area/station/security/prison) +"htj" = ( +/obj/item/kirbyplants/random, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/airalarm/directional/south, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "htq" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -38573,6 +38534,12 @@ /obj/structure/window/spawner/directional/south, /turf/open/floor/plating, /area/station/maintenance/department/security/greater) +"hwe" = ( +/obj/structure/flora/bush/jungle/a/style_2, +/obj/structure/flora/bush/flowers_yw/style_2, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "hwi" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -38899,12 +38866,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/hallway/secondary/service) -"hAk" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "hAn" = ( /obj/structure/closet/crate{ name = "Stations and Syndicate Starter Bundle" @@ -39581,10 +39542,6 @@ "hGf" = ( /turf/closed/wall/r_wall, /area/station/security/brig) -"hGg" = ( -/obj/machinery/suit_storage_unit/industrial/loader, -/turf/open/floor/plating, -/area/station/cargo/storage) "hGi" = ( /obj/machinery/computer/mecha, /obj/effect/turf_decal/tile/purple, @@ -39677,11 +39634,6 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron, /area/station/hallway/primary/upper) -"hHm" = ( -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "hHn" = ( /obj/structure/window/reinforced/spawner/directional/south, /obj/structure/chair{ @@ -40967,6 +40919,10 @@ "hTp" = ( /turf/closed/wall, /area/station/command/heads_quarters/captain) +"hTx" = ( +/obj/structure/dresser, +/turf/open/floor/carpet, +/area/station/cargo/quartermaster) "hTD" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -41056,6 +41012,19 @@ }, /turf/open/floor/iron/dark, /area/station/security/courtroom) +"hUu" = ( +/obj/structure/table/wood, +/obj/structure/closet/crate/cardboard{ + pixel_y = 5 + }, +/obj/item/clothing/shoes/jackboots/timbs, +/obj/item/clothing/suit/brownfurrich/public, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "hUw" = ( /obj/structure/cable, /obj/effect/turf_decal/stripes/line{ @@ -41206,12 +41175,6 @@ }, /turf/open/floor/glass/reinforced/airless, /area/space/nearstation) -"hWd" = ( -/obj/structure/flora/bush/jungle/b/style_2, -/obj/structure/flora/bush/flowers_pp, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "hWj" = ( /turf/open/floor/plating, /area/station/security/prison/mess) @@ -42028,6 +41991,25 @@ }, /turf/open/floor/iron/dark, /area/station/security/brig) +"ier" = ( +/obj/machinery/button/door/directional/west{ + id = "QMdoor"; + name = "Door lock"; + normaldoorcontrol = 1; + pixel_x = -32; + pixel_y = -6; + req_access = list("qm"); + specialfunctions = 4 + }, +/obj/machinery/button/door{ + id = "qmprivacy"; + name = "Privacy Control"; + pixel_x = -32; + pixel_y = 7; + req_access = list("qm") + }, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "ies" = ( /obj/effect/turf_decal/siding/wood{ dir = 9 @@ -42438,25 +42420,6 @@ dir = 4 }, /area/station/command/secure_bunker) -"iiy" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/random/trash/mess, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/firedoor, -/obj/machinery/button/door/directional/north{ - id = "Starboardbowmaints"; - name = "Shutter control"; - pixel_x = 24; - pixel_y = 0 - }, -/obj/machinery/door/poddoor/shutters{ - id = "Starboardbowmaints"; - name = "Starboard Bow Maintenance" - }, -/turf/open/floor/plating, -/area/station/maintenance/fore/upper) "iiC" = ( /obj/structure/cable, /obj/machinery/door/airlock/maintenance{ @@ -42696,20 +42659,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/service) -"ikF" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 10 - }, -/obj/structure/chair/office{ - dir = 8 - }, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/structure/cable, -/obj/effect/landmark/start/gary, -/turf/open/floor/carpet, -/area/station/maintenance/abandon_psych) "ikG" = ( /obj/effect/decal/cleanable/oil, /turf/open/floor/iron/dark, @@ -44101,25 +44050,20 @@ /obj/structure/railing, /turf/open/floor/iron/dark/side, /area/station/ai_monitored/command/storage/eva) +"izG" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/service/electronic_marketing_den) "izM" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 }, /turf/open/floor/wood/parquet, /area/station/command/heads_quarters/cmo) -"izO" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/effect/turf_decal/siding/wood/corner, -/obj/machinery/door/airlock/corporate{ - name = "Blueshield's Quarters" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/turf/open/floor/wood, -/area/station/command/heads_quarters/blueshield) "izS" = ( /obj/machinery/light/small/directional/west, /obj/structure/table/reinforced, @@ -45271,6 +45215,12 @@ "iMc" = ( /turf/closed/wall/r_wall, /area/station/common/pool) +"iMf" = ( +/obj/structure/flora/bush/jungle/c/style_3, +/obj/structure/flora/bush/flowers_br, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "iMj" = ( /obj/structure/closet, /obj/effect/turf_decal/delivery, @@ -45608,6 +45558,23 @@ }, /turf/open/floor/plating, /area/station/security/interrogation) +"iQW" = ( +/obj/structure/table/wood, +/obj/item/coin/gold{ + desc = "A limited edition coin printed with a FTU cargo hauler on the tail's side and the FTU logo on the head's side.. only 500 of these were ever made as a celebration to the passing of lessened trade regulations in the frontier sector."; + name = "FTU special edition collector's coin" + }, +/obj/item/toy/figure/clown{ + desc = "Aside from the engraving on the back of this figurine it's identical to any old NT departmental action figure, yet these sell for eye watering prices on the open market."; + name = "Comedycon edition clown action figure" + }, +/obj/item/reagent_containers/cup/glass/bottle/wine{ + desc = "A vintage wine bottle that appears to be produced on terra around the early 20th century.. the label is written in an ancient human language that sounds indecipherable.. le.. chateau.. what now?"; + name = "Vintage Terran red wine bottle" + }, +/obj/item/clothing/head/collectable/petehat, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "iQX" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/bot, @@ -45793,6 +45760,9 @@ "iTN" = ( /turf/open/floor/carpet/green, /area/station/service/abandoned_gambling_den) +"iTO" = ( +/turf/closed/wall, +/area/station/cargo/quartermaster) "iTP" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/curtain/cloth/fancy/mechanical{ @@ -46124,6 +46094,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/carpet/blue, /area/station/command/captain_dining) +"iWF" = ( +/obj/structure/flora/bush/jungle/c/style_3, +/obj/structure/flora/bush/flowers_yw/style_3, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "iWJ" = ( /obj/structure/bed, /obj/item/bedsheet/medical, @@ -46502,6 +46478,15 @@ /obj/structure/lattice/catwalk, /turf/open/openspace, /area/station/maintenance/department/medical/central) +"iZA" = ( +/obj/structure/chair/office{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/assistant, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/wood/parquet, +/area/station/common/arcade) "iZC" = ( /obj/structure/table/wood, /obj/structure/window/reinforced/spawner/directional/west, @@ -47155,14 +47140,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/department/engineering/engine_aft_port) -"jhc" = ( -/obj/structure/chair/wood/wings{ - dir = 8 - }, -/obj/effect/landmark/start/librarian, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/carpet, -/area/station/service/library/lounge) "jhe" = ( /obj/effect/turf_decal/stripes/white/line{ dir = 1 @@ -47458,6 +47435,10 @@ dir = 8 }, /area/station/commons/fitness) +"jjN" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/iron, +/area/station/hallway/secondary/construction) "jjP" = ( /obj/effect/spawner/random/structure/crate, /turf/open/floor/plating, @@ -48624,12 +48605,6 @@ /obj/effect/turf_decal/siding/thinplating/dark, /turf/open/floor/circuit, /area/station/ai_monitored/turret_protected/ai) -"jvl" = ( -/obj/structure/flora/bush/jungle/c/style_3, -/obj/structure/flora/bush/flowers_br, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "jvm" = ( /obj/effect/turf_decal/siding/wood{ dir = 5 @@ -48890,6 +48865,12 @@ }, /turf/open/floor/carpet/blue, /area/station/command/heads_quarters/captain/private) +"jxK" = ( +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk, +/obj/structure/sign/calendar/directional/north, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "jxM" = ( /obj/machinery/disposal/bin, /obj/effect/turf_decal/delivery, @@ -49071,6 +49052,23 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/service/library/private) +"jzZ" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/firedoor, +/obj/machinery/button/door/directional/north{ + id = "Portbowmaints"; + name = "Shutter control"; + pixel_x = -24; + pixel_y = 0 + }, +/obj/machinery/door/poddoor/shutters{ + id = "Portbowmaints"; + name = "Port Bow Maintenance" + }, +/turf/open/floor/iron/stairs/left{ + dir = 1 + }, +/area/station/maintenance/port/upper) "jAa" = ( /obj/machinery/vending/coffee, /obj/effect/turf_decal/bot, @@ -49418,12 +49416,6 @@ /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, /turf/open/floor/iron, /area/station/engineering/atmos) -"jDl" = ( -/obj/structure/flora/bush/jungle/b, -/obj/structure/flora/bush/flowers_yw, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "jDp" = ( /obj/machinery/atmospherics/pipe/layer_manifold/brown/visible, /obj/effect/spawner/structure/window/reinforced/plasma, @@ -50052,6 +50044,12 @@ /obj/effect/landmark/start/assistant, /turf/open/floor/iron/dark, /area/station/common/gaskiosk) +"jJh" = ( +/obj/structure/flora/bush/jungle/c/style_3, +/obj/structure/flora/bush/flowers_pp/style_3, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "jJi" = ( /obj/structure/railing, /obj/effect/turf_decal/stripes, @@ -51249,10 +51247,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/disposal) -"jUq" = ( -/obj/effect/landmark/start/quartermaster, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "jUt" = ( /obj/structure/table/wood/poker, /obj/effect/spawner/random/entertainment/gambling, @@ -51470,14 +51464,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/port) -"jVS" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/service/electronic_marketing_den) "jVT" = ( /obj/effect/mapping_helpers/broken_floor, /obj/machinery/power/smes/engineering, @@ -51920,6 +51906,27 @@ dir = 4 }, /area/station/hallway/primary/port) +"jZU" = ( +/obj/structure/table/wood, +/obj/effect/turf_decal/siding/wood{ + dir = 5 + }, +/obj/item/reagent_containers/cup/glass/bottle/rum{ + pixel_x = -7; + pixel_y = 10 + }, +/obj/item/storage/fancy/cigarettes/cigars/cohiba, +/obj/item/storage/fancy/cigarettes/cigars/havana{ + pixel_y = 4 + }, +/obj/item/clothing/mask/cigarette/rollie/cannabis{ + pixel_x = 8; + pixel_y = 15 + }, +/obj/item/lighter, +/obj/structure/disposalpipe/segment, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "jZZ" = ( /obj/structure/window/spawner/directional/north, /obj/effect/decal/cleanable/dirt, @@ -52105,6 +52112,13 @@ /obj/structure/cable, /turf/open/floor/wood, /area/station/common/pool/sauna) +"kcU" = ( +/obj/structure/cable, +/obj/structure/chair/stool/bar, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/carpet/green, +/area/station/service/abandoned_gambling_den) "kcZ" = ( /obj/effect/turf_decal/bot, /obj/structure/liquid_pump, @@ -53297,6 +53311,12 @@ }, /turf/open/floor/iron/dark, /area/station/security/prison/workout) +"knr" = ( +/obj/structure/flora/bush/jungle/a, +/obj/structure/flora/bush/flowers_br/style_3, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "knt" = ( /obj/structure/chair/pew/right{ dir = 8 @@ -53362,6 +53382,44 @@ }, /turf/open/floor/iron/dark/side, /area/station/security/prison/upper) +"knG" = ( +/obj/structure/table/wood, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/item/paper_bin{ + pixel_x = -12; + pixel_y = 3 + }, +/obj/item/pen/fourcolor{ + pixel_x = -12; + pixel_y = 5 + }, +/obj/item/hand_labeler{ + pixel_y = 17 + }, +/obj/item/computer_disk/quartermaster{ + pixel_x = 6; + pixel_y = 5 + }, +/obj/item/computer_disk/quartermaster{ + pixel_x = 6; + pixel_y = 5 + }, +/obj/item/computer_disk/quartermaster{ + pixel_x = 6; + pixel_y = 5 + }, +/obj/item/flashlight/lamp/green{ + pixel_y = 1 + }, +/obj/structure/disposalpipe/segment, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "knM" = ( /obj/effect/turf_decal/tile/neutral, /obj/structure/extinguisher_cabinet/directional/east, @@ -53494,19 +53552,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/science/xenobiology) -"kpQ" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/machinery/door/airlock/highsecurity{ - name = "Blueshield's Equipment Room" - }, -/obj/machinery/door/firedoor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/turf/open/floor/wood, -/area/station/command/heads_quarters/blueshield) "kpS" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/curtain/cloth/fancy/mechanical{ @@ -55133,6 +55178,12 @@ dir = 8 }, /area/station/science) +"kER" = ( +/obj/structure/flora/bush/jungle/a/style_3, +/obj/structure/flora/bush/flowers_br/style_2, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "kFd" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/mining{ @@ -56518,6 +56569,13 @@ /obj/structure/closet/crate/freezer/blood, /turf/open/floor/iron/white, /area/station/medical/coldroom) +"kVe" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "kVx" = ( /obj/structure/sink/directional/east, /turf/open/floor/iron/kitchen{ @@ -56993,12 +57051,6 @@ }, /turf/open/floor/iron/dark/side, /area/station/security/prison) -"laH" = ( -/obj/structure/flora/bush/jungle/a/style_3, -/obj/structure/flora/bush/flowers_br/style_2, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "laI" = ( /obj/structure/cable, /turf/open/floor/iron/dark, @@ -57422,9 +57474,6 @@ dir = 4 }, /area/station/hallway/primary/port) -"lei" = ( -/turf/closed/wall/r_wall, -/area/station/hallway/primary/upper) "lej" = ( /obj/effect/turf_decal/trimline/purple/filled/line, /obj/machinery/status_display/ai/directional/south, @@ -57729,15 +57778,6 @@ dir = 8 }, /area/station/maintenance/solars/port/fore) -"lhn" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/door/poddoor/shutters/preopen{ - dir = 4; - id = "qmprivacy"; - name = "Quartermaster's Privacy Shutters" - }, -/turf/open/floor/plating, -/area/station/cargo/quartermaster) "lhr" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 @@ -59695,6 +59735,10 @@ /obj/structure/curtain/bounty, /turf/open/floor/plating, /area/station/medical/virology/isolation) +"lBX" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/central) "lCe" = ( /obj/structure/window/reinforced/spawner/directional/west, /obj/structure/window/reinforced/spawner/directional/east, @@ -60101,12 +60145,6 @@ /obj/structure/extinguisher_cabinet/directional/south, /turf/open/floor/iron/kitchen, /area/station/service/kitchen/diner) -"lGg" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/cafeteria, -/area/station/maintenance/abandon_diner) "lGl" = ( /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -60656,10 +60694,6 @@ /obj/machinery/light/small/directional/north, /turf/open/floor/iron/dark, /area/station/engineering/atmos/pumproom) -"lLF" = ( -/obj/structure/cable, -/turf/open/floor/iron/solarpanel/airless, -/area/station/solars/starboard/aft) "lLJ" = ( /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -60989,13 +61023,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/office) -"lPh" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "lPl" = ( /obj/effect/spawner/random/trash/moisture_trap, /turf/open/floor/plating, @@ -61159,6 +61186,14 @@ /obj/effect/spawner/random/exotic/languagebook, /turf/open/floor/plating, /area/station/maintenance/department/science/lower) +"lRb" = ( +/obj/structure/chair/office{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron, +/area/station/maintenance/thruster_room/central) "lRf" = ( /obj/structure/table, /obj/item/storage/photo_album, @@ -61567,13 +61602,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/upper) -"lVl" = ( -/obj/structure/closet/secure_closet/quartermaster, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/iron/dark, -/area/station/cargo/quartermaster) "lVm" = ( /obj/structure/window/reinforced/spawner/directional/east, /obj/structure/closet/crate/coffin, @@ -61768,6 +61796,18 @@ "lXw" = ( /turf/closed/wall, /area/station/command/heads_quarters/captain/private) +"lXx" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; + id = "qmprivacy"; + name = "Quartermaster's Privacy Shutters" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/cargo/quartermaster) "lXy" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -61885,10 +61925,6 @@ /obj/structure/sign/warning/radiation/directional/east, /turf/open/floor/iron/dark, /area/station/engineering/supermatter/room) -"lYB" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/central) "lYD" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -62008,11 +62044,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/hos) -"lZi" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/aft/upper) "lZl" = ( /obj/item/kirbyplants/random, /turf/open/floor/iron, @@ -62180,6 +62211,10 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/iron/freezer, /area/station/maintenance/abandon_kitchen_upper) +"mba" = ( +/obj/structure/cable, +/turf/open/floor/iron/solarpanel/airless, +/area/station/solars/starboard/aft) "mbb" = ( /obj/machinery/light/floor/has_bulb, /obj/effect/turf_decal/bot_white, @@ -62465,6 +62500,13 @@ dir = 4 }, /area/station/hallway/secondary/entry) +"mdB" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "mdF" = ( /obj/machinery/power/supermatter_crystal/engine, /obj/effect/turf_decal/stripes/box, @@ -62586,14 +62628,6 @@ /obj/effect/turf_decal/bot_white/right, /turf/open/floor/iron/dark, /area/station/command/gateway) -"meH" = ( -/obj/structure/altar_of_gods, -/obj/structure/railing{ - dir = 4 - }, -/obj/item/book/bible, -/turf/open/floor/carpet, -/area/station/service/chapel) "meJ" = ( /obj/effect/turf_decal/stripes{ dir = 5 @@ -62701,13 +62735,6 @@ /obj/effect/mapping_helpers/airlock/unres, /turf/open/floor/plating, /area/station/maintenance/department/engineering/engine_aft_port) -"mgb" = ( -/obj/structure/disposalpipe/segment, -/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/stairs/old, -/area/station/cargo/office) "mgi" = ( /obj/structure/chair/sofa/corp/corner{ dir = 8 @@ -63973,12 +64000,6 @@ dir = 1 }, /area/station/command/secure_bunker) -"muJ" = ( -/obj/structure/flora/bush/jungle/b/style_2, -/obj/structure/flora/bush/flowers_br/style_3, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "muK" = ( /obj/structure/cable, /obj/machinery/door/airlock/hatch{ @@ -64257,20 +64278,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) -"mxr" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/carpet, -/area/station/service/library/printer) -"mxu" = ( -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/iron, -/area/station/commons/vacant_room/commissary) "mxE" = ( /obj/structure/table/reinforced, /obj/item/paper_bin{ @@ -64293,6 +64300,20 @@ /obj/item/radio/intercom/directional/south, /turf/open/floor/iron/white, /area/station/science/xenobiology) +"mxX" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 10 + }, +/obj/structure/chair/office{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/structure/cable, +/obj/effect/landmark/start/gary, +/turf/open/floor/carpet, +/area/station/maintenance/abandon_psych) "mya" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -64451,6 +64472,9 @@ /obj/machinery/light/directional/south, /turf/open/floor/wood, /area/station/command/heads_quarters/captain/private) +"mzu" = ( +/turf/closed/wall/r_wall, +/area/station/hallway/primary/upper) "mzv" = ( /obj/machinery/duct, /turf/open/floor/iron/freezer, @@ -64959,21 +64983,6 @@ /obj/machinery/plumbing/input, /turf/open/floor/iron/dark, /area/station/science/cytology) -"mEK" = ( -/obj/effect/turf_decal/siding/brown{ - dir = 1 - }, -/obj/machinery/computer/security/qm{ - dir = 1 - }, -/obj/machinery/requests_console/directional/south{ - department = "Quartermaster's Office"; - name = "Quartermaster's Requests Console" - }, -/obj/effect/mapping_helpers/requests_console/announcement, -/obj/effect/mapping_helpers/requests_console/supplies, -/turf/open/floor/iron/dark, -/area/station/cargo/quartermaster) "mER" = ( /obj/machinery/light/directional/east, /obj/machinery/computer/department_orders/engineering{ @@ -65710,13 +65719,6 @@ /obj/effect/landmark/generic_maintenance_landmark, /turf/open/floor/plating, /area/station/maintenance/aft/upper) -"mLV" = ( -/obj/structure/chair/office, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/security/detectives_office/private_investigators_office) "mLX" = ( /obj/item/food/cheese/wheel, /turf/open/misc/sandy_dirt, @@ -66654,6 +66656,12 @@ }, /turf/open/floor/engine/hull/reinforced, /area/space/nearstation) +"mVh" = ( +/obj/structure/flora/bush/jungle/b, +/obj/structure/flora/bush/flowers_yw, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "mVi" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 4 @@ -66948,6 +66956,12 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/external, /turf/open/floor/plating, /area/station/maintenance/aft/upper) +"mYp" = ( +/obj/machinery/holopad, +/obj/effect/turf_decal/bot, +/obj/effect/landmark/start/quartermaster, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "mYx" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, @@ -67720,12 +67734,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/engineering/atmos) -"ngF" = ( -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk, -/obj/structure/sign/calendar/directional/north, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "ngG" = ( /obj/machinery/door/airlock/grunge{ name = "Chapel Hall" @@ -68211,6 +68219,12 @@ dir = 4 }, /area/station/security/checkpoint/escape) +"nlV" = ( +/obj/effect/landmark/event_spawn, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/gary, +/turf/open/floor/carpet/red, +/area/station/service/library/abandoned) "nlW" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -68750,6 +68764,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/stairs/left, /area/station/cargo/storage) +"nsx" = ( +/obj/structure/disposalpipe/segment, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "nsy" = ( /obj/structure/ladder, /obj/effect/turf_decal/stripes/white/box, @@ -69523,6 +69541,13 @@ }, /turf/open/floor/plating, /area/station/security/checkpoint/customs) +"nAy" = ( +/obj/structure/chair/comfy/black{ + dir = 4 + }, +/obj/effect/landmark/start/quartermaster, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "nAD" = ( /obj/machinery/light/directional/north, /obj/structure/disposalpipe/segment{ @@ -69597,6 +69622,12 @@ /obj/structure/closet/radiation, /turf/open/floor/plating, /area/station/engineering/atmos) +"nBp" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/drone_dispenser/preloaded, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron, +/area/station/science/research/abandoned) "nBu" = ( /obj/structure/cable, /obj/machinery/duct, @@ -69669,18 +69700,6 @@ /obj/item/radio/intercom/directional/east, /turf/open/floor/carpet, /area/station/medical/patients_rooms) -"nBW" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/door/poddoor/shutters/preopen{ - dir = 4; - id = "qmprivacy"; - name = "Quartermaster's Privacy Shutters" - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/plating, -/area/station/cargo/quartermaster) "nBY" = ( /obj/structure/flora/bush/reed{ pixel_y = 8 @@ -70054,6 +70073,14 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron, /area/station/hallway/primary/starboard) +"nFV" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/clown_chamber) "nFX" = ( /obj/machinery/power/apc/auto_name/directional/north, /obj/structure/cable, @@ -70607,25 +70634,6 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron/dark, /area/station/security/brig) -"nLg" = ( -/obj/machinery/button/door/directional/west{ - id = "QMdoor"; - name = "Door lock"; - normaldoorcontrol = 1; - pixel_x = -32; - pixel_y = -6; - req_access = list("qm"); - specialfunctions = 4 - }, -/obj/machinery/button/door{ - id = "qmprivacy"; - name = "Privacy Control"; - pixel_x = -32; - pixel_y = 7; - req_access = list("qm") - }, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "nLh" = ( /obj/machinery/atmospherics/components/binary/pump/on{ dir = 1; @@ -72248,12 +72256,6 @@ /obj/machinery/newscaster/directional/north, /turf/open/floor/carpet, /area/station/security/detectives_office) -"obY" = ( -/obj/structure/flora/bush/jungle/c, -/obj/structure/flora/bush/flowers_pp/style_2, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "oci" = ( /obj/effect/turf_decal/trimline/red/filled/corner{ color = "#DE3A3A"; @@ -72587,14 +72589,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"ofh" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/event_spawn, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/gary, -/turf/open/floor/eighties, -/area/station/maintenance/abandon_arcade) "ofm" = ( /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -72945,16 +72939,6 @@ }, /turf/open/floor/stone, /area/station/hallway/primary/central) -"ohE" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/machinery/door/airlock/highsecurity{ - name = "Blueshield's Equipment Room" - }, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/turf/open/floor/wood, -/area/station/command/heads_quarters/blueshield) "ohH" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -73198,6 +73182,10 @@ /obj/item/kirbyplants/organic/plant21, /turf/open/floor/iron, /area/station/service/chapel) +"okm" = ( +/obj/structure/decorative/shelf/alcohol_assortment, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "okq" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -74342,9 +74330,6 @@ /obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/department/security/greater) -"ovy" = ( -/turf/closed/wall, -/area/station/cargo/quartermaster) "ovC" = ( /obj/machinery/growing/soil, /turf/open/floor/grass, @@ -77314,6 +77299,28 @@ }, /turf/open/floor/iron/dark, /area/station/maintenance/disposal/incinerator) +"oYQ" = ( +/obj/structure/table/wood, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/item/folder/yellow, +/obj/item/stamp/head/qm, +/obj/item/reagent_containers/cup/glass/drinkingglass/shotglass{ + pixel_x = 6; + pixel_y = 16 + }, +/obj/item/reagent_containers/cup/glass/drinkingglass/shotglass{ + pixel_x = -4; + pixel_y = 16 + }, +/obj/item/hand_labeler_refill{ + pixel_x = -8; + pixel_y = -8 + }, +/obj/structure/disposalpipe/segment, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "oYT" = ( /obj/structure/lattice/catwalk, /obj/structure/railing{ @@ -77844,12 +77851,6 @@ /obj/item/storage/crayons, /turf/open/floor/iron, /area/station/commons/fitness/recreation) -"pew" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/chair/stool/bar/directional/north, -/obj/effect/landmark/start/gary, -/turf/open/floor/carpet, -/area/station/maintenance/rus_gambling) "peD" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/tile/bar/opposingcorners, @@ -78215,6 +78216,12 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/common/wrestling/arena) +"pit" = ( +/obj/structure/flora/bush/jungle/c, +/obj/structure/flora/bush/flowers_pp/style_2, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "piw" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 6 @@ -78579,6 +78586,19 @@ /obj/item/chicken_book, /turf/open/floor/iron/dark/herringbone, /area/station/common/night_club/back_stage) +"pmq" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wood/corner, +/obj/machinery/door/airlock/corporate{ + name = "Blueshield's Quarters" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/wood, +/area/station/command/heads_quarters/blueshield) "pmr" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -78876,6 +78896,18 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/transit_tube) +"ppK" = ( +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/obj/machinery/camera/directional/south{ + c_tag = "Cargo - Quartermaster's office"; + dir = 1 + }, +/obj/structure/table/wood, +/obj/item/modular_computer/laptop, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "ppP" = ( /obj/effect/turf_decal/stripes{ dir = 4 @@ -79857,6 +79889,16 @@ "pyO" = ( /turf/closed/wall, /area/station/science/research/abandoned) +"pyS" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/machinery/door/airlock/highsecurity{ + name = "Blueshield's Equipment Room" + }, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/wood, +/area/station/command/heads_quarters/blueshield) "pzi" = ( /obj/item/clothing/head/utility/welding, /obj/effect/decal/cleanable/dirt, @@ -80038,6 +80080,14 @@ /obj/machinery/atm/directional/south, /turf/open/floor/iron/white, /area/station/science) +"pAL" = ( +/obj/machinery/photocopier, +/obj/effect/turf_decal/bot, +/obj/structure/noticeboard/qm{ + pixel_y = 32 + }, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "pAO" = ( /obj/structure/chair/office{ dir = 8 @@ -81702,44 +81752,6 @@ /obj/machinery/duct, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"pSL" = ( -/obj/structure/table/wood, -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/item/paper_bin{ - pixel_x = -12; - pixel_y = 3 - }, -/obj/item/pen/fourcolor{ - pixel_x = -12; - pixel_y = 5 - }, -/obj/item/hand_labeler{ - pixel_y = 17 - }, -/obj/item/computer_disk/quartermaster{ - pixel_x = 6; - pixel_y = 5 - }, -/obj/item/computer_disk/quartermaster{ - pixel_x = 6; - pixel_y = 5 - }, -/obj/item/computer_disk/quartermaster{ - pixel_x = 6; - pixel_y = 5 - }, -/obj/item/flashlight/lamp/green{ - pixel_y = 1 - }, -/obj/structure/disposalpipe/segment, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "pSM" = ( /obj/machinery/power/shuttle_engine/heater{ dir = 1 @@ -83466,6 +83478,12 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/plating, /area/station/maintenance/pool_maintenance) +"qkT" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/trash/popcorn, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/abandon_art_studio) "qkW" = ( /obj/effect/turf_decal/stripes/end{ dir = 4 @@ -84077,19 +84095,6 @@ /obj/structure/grille, /turf/open/floor/plating, /area/station/maintenance/fore/upper) -"qrq" = ( -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/siding/wood, -/obj/machinery/door/airlock/mining{ - name = "Deliveries" - }, -/obj/effect/mapping_helpers/airlock/access/all/supply/qm, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "qru" = ( /obj/structure/rack, /obj/item/stack/cable_coil{ @@ -85412,6 +85417,12 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"qDe" = ( +/obj/structure/flora/bush/jungle/a/style_2, +/obj/structure/flora/bush/flowers_yw/style_3, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "qDf" = ( /obj/effect/turf_decal/siding/thinplating/dark{ dir = 1 @@ -85741,6 +85752,14 @@ /obj/structure/flora/bush/lavendergrass, /turf/open/floor/grass, /area/station/service/hydroponics) +"qGh" = ( +/obj/structure/flora/bush/sparsegrass{ + pixel_x = 7; + pixel_y = 3 + }, +/obj/structure/reagent_dispensers/watertank/high, +/turf/open/floor/grass, +/area/station/security/prison/garden) "qGm" = ( /obj/effect/turf_decal/bot_white, /obj/structure/cable, @@ -85945,14 +85964,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/upper) -"qIq" = ( -/obj/structure/flora/bush/sparsegrass{ - pixel_x = 7; - pixel_y = 3 - }, -/obj/structure/reagent_dispensers/watertank/high, -/turf/open/floor/grass, -/area/station/security/prison/garden) "qIs" = ( /turf/closed/wall/r_wall, /area/station/common/arcade) @@ -86158,22 +86169,6 @@ /obj/structure/drain, /turf/open/floor/iron/checker, /area/station/science/ordnance) -"qKb" = ( -/obj/structure/table/wood, -/obj/item/clipboard{ - pixel_y = 19 - }, -/obj/item/toy/figure/qm{ - pixel_y = 18 - }, -/obj/machinery/light/directional/west, -/obj/machinery/fax{ - fax_name = "Quartermaster's Office"; - name = "Quartermaster's Fax Machine"; - pixel_y = 3 - }, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "qKp" = ( /obj/structure/railing{ dir = 8 @@ -86270,12 +86265,6 @@ /obj/machinery/vending/medical, /turf/open/floor/iron, /area/station/medical/storage) -"qLP" = ( -/obj/structure/flora/bush/jungle/b, -/obj/structure/flora/bush/flowers_br, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "qLQ" = ( /obj/effect/turf_decal/bot_white/left, /obj/structure/closet/crate/hydroponics, @@ -87812,9 +87801,6 @@ initial_gas_mix = "TEMP=2.7" }, /area/station/science/ordnance/bomb) -"raX" = ( -/turf/closed/wall/r_wall, -/area/station/cargo/quartermaster) "rba" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/siding/thinplating_new/dark{ @@ -88601,10 +88587,6 @@ /obj/effect/landmark/start/assistant, /turf/open/floor/stone, /area/station/hallway/primary/central) -"rim" = ( -/obj/structure/dresser, -/turf/open/floor/carpet, -/area/station/cargo/quartermaster) "rix" = ( /obj/structure/table, /obj/item/storage/medkit/regular, @@ -90057,12 +90039,6 @@ }, /turf/open/floor/wood/large, /area/station/science/auxlab/firing_range) -"rwR" = ( -/obj/structure/flora/bush/jungle/c/style_3, -/obj/structure/flora/bush/flowers_pp/style_3, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "rwS" = ( /obj/structure/chair/sofa/bench/left{ dir = 4; @@ -90878,6 +90854,12 @@ /obj/machinery/camera/autoname/directional/north, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) +"rEB" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/white, +/area/station/medical/aslyum) "rED" = ( /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 8 @@ -91207,6 +91189,10 @@ /obj/effect/decal/cleanable/blood/old, /turf/open/floor/mineral/plastitanium, /area/station/maintenance/cult_chapel_maint) +"rHz" = ( +/obj/structure/disposalpipe/segment, +/turf/open/floor/carpet, +/area/station/cargo/quartermaster) "rHB" = ( /obj/item/trash/chips, /turf/open/floor/plating, @@ -91409,12 +91395,6 @@ /obj/machinery/light_switch/directional/south, /turf/open/floor/carpet/blue, /area/station/service/lawoffice) -"rJl" = ( -/obj/effect/decal/cleanable/dirt, -/obj/item/trash/popcorn, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/abandon_art_studio) "rJm" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted, /obj/machinery/newscaster/directional/south, @@ -91456,6 +91436,9 @@ }, /turf/open/floor/iron/dark/side, /area/station/hallway/primary/central) +"rJF" = ( +/turf/closed/wall/r_wall, +/area/station/cargo/quartermaster) "rJL" = ( /obj/structure/table/wood, /obj/item/food/grown/harebell, @@ -91807,15 +91790,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/port/upper) -"rNW" = ( -/obj/structure/disposalpipe/segment{ - dir = 9 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "rNY" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -91912,10 +91886,6 @@ /obj/item/coffee_cartridge, /turf/open/floor/iron, /area/station/hallway/secondary/service) -"rPj" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/iron, -/area/station/hallway/secondary/construction) "rPm" = ( /obj/machinery/shower/directional/west, /obj/structure/drain, @@ -92344,16 +92314,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/department/engineering/engine_aft_port) -"rUn" = ( -/obj/structure/chair/office{ - dir = 8 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "rUt" = ( /obj/structure/disposalpipe/segment, /obj/machinery/duct, @@ -93467,13 +93427,6 @@ /obj/structure/chair/wood, /turf/open/floor/wood, /area/station/service/cafeteria) -"sfP" = ( -/obj/structure/chair/comfy/black{ - dir = 4 - }, -/obj/effect/landmark/start/quartermaster, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "sfS" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/spawner/random/structure/steam_vent, @@ -93526,6 +93479,12 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/security/checkpoint/customs/auxiliary) +"sgt" = ( +/obj/structure/flora/bush/jungle/b, +/obj/structure/flora/bush/flowers_br, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "sgv" = ( /obj/structure/window/reinforced/spawner/directional/east, /obj/effect/turf_decal/stripes/white/line{ @@ -94414,14 +94373,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/department/science/lower) -"sqK" = ( -/obj/machinery/duct, -/obj/effect/turf_decal/tile/blue/opposingcorners{ - dir = 8 - }, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/cafeteria, -/area/station/commons/locker) "sqL" = ( /obj/machinery/airalarm/directional/west, /obj/machinery/light_switch/directional/south, @@ -95179,6 +95130,14 @@ /obj/effect/spawner/random/decoration/glowstick, /turf/open/floor/iron, /area/station/maintenance/department/medical/central) +"sxg" = ( +/obj/structure/altar_of_gods, +/obj/structure/railing{ + dir = 4 + }, +/obj/item/book/bible, +/turf/open/floor/carpet, +/area/station/service/chapel) "sxl" = ( /obj/structure/closet/emcloset, /obj/effect/decal/cleanable/dirt, @@ -95439,23 +95398,6 @@ dir = 8 }, /area/station/command/gateway) -"sAn" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/door/firedoor, -/obj/machinery/button/door/directional/north{ - id = "Portbowmaints"; - name = "Shutter control"; - pixel_x = -24; - pixel_y = 0 - }, -/obj/machinery/door/poddoor/shutters{ - id = "Portbowmaints"; - name = "Port Bow Maintenance" - }, -/turf/open/floor/iron/stairs/left{ - dir = 1 - }, -/area/station/maintenance/port/upper) "sAs" = ( /obj/effect/turf_decal/delivery/white, /obj/machinery/status_display/supply{ @@ -95499,12 +95441,6 @@ }, /turf/open/floor/iron, /area/station/commons/fitness) -"sAJ" = ( -/obj/effect/landmark/event_spawn, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/gary, -/turf/open/floor/carpet/red, -/area/station/service/library/abandoned) "sAW" = ( /obj/structure/railing{ dir = 8 @@ -97096,22 +97032,6 @@ "sPI" = ( /turf/open/floor/grass, /area/station/service/hydroponics/garden/abandoned) -"sPM" = ( -/obj/structure/table/wood, -/obj/item/reagent_containers/cup/glass/bottle/fernet{ - pixel_x = -8; - pixel_y = 14 - }, -/obj/item/reagent_containers/cup/glass/bottle/lizardwine{ - pixel_x = 7; - pixel_y = 6 - }, -/obj/item/reagent_containers/cup/glass/bottle/champagne{ - pixel_y = 11 - }, -/obj/machinery/digital_clock/directional/north, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "sPS" = ( /obj/effect/turf_decal/siding/wood, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -97524,18 +97444,6 @@ /obj/machinery/duct, /turf/open/floor/iron, /area/station/commons/dorms) -"sUv" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/door/poddoor/shutters/preopen{ - dir = 4; - id = "qmprivacy"; - name = "Quartermaster's Privacy Shutters" - }, -/obj/structure/disposalpipe/trunk/multiz{ - dir = 4 - }, -/turf/open/floor/plating, -/area/station/cargo/quartermaster) "sUJ" = ( /obj/structure/window/spawner/directional/east, /obj/effect/turf_decal/delivery, @@ -98408,6 +98316,14 @@ }, /turf/open/floor/plating, /area/station/hallway/secondary/entry) +"tbD" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/power/apc/auto_name/directional/west, +/obj/structure/cable, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "tbH" = ( /obj/structure/chair/pew/left{ dir = 4 @@ -99009,6 +98925,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/engineering/transit_tube) +"thb" = ( +/obj/structure/chair/wood/wings{ + dir = 8 + }, +/obj/effect/landmark/start/librarian, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/carpet, +/area/station/service/library/lounge) "thj" = ( /obj/effect/spawner/random/structure/table_or_rack, /obj/effect/spawner/random/maintenance, @@ -99663,6 +99587,14 @@ /obj/effect/spawner/random/trash/moisture, /turf/open/floor/plating, /area/station/maintenance/port/upper) +"tov" = ( +/obj/machinery/duct, +/obj/effect/turf_decal/tile/blue/opposingcorners{ + dir = 8 + }, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/cafeteria, +/area/station/commons/locker) "toB" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -101040,10 +100972,6 @@ }, /turf/open/floor/iron, /area/station/maintenance/starboard/fore) -"tCj" = ( -/obj/machinery/duct, -/turf/open/floor/carpet/executive, -/area/station/command/heads_quarters/blueshield) "tCm" = ( /obj/docking_port/stationary{ dheight = 4; @@ -101899,6 +101827,22 @@ /obj/machinery/atmospherics/components/unary/portables_connector/visible, /turf/open/floor/iron, /area/station/engineering/atmos/test_chambers) +"tKU" = ( +/obj/structure/table/wood, +/obj/item/clipboard{ + pixel_y = 19 + }, +/obj/item/toy/figure/qm{ + pixel_y = 18 + }, +/obj/machinery/light/directional/west, +/obj/machinery/fax{ + fax_name = "Quartermaster's Office"; + name = "Quartermaster's Fax Machine"; + pixel_y = 3 + }, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "tKX" = ( /obj/item/clothing/head/utility/welding, /turf/open/floor/plating, @@ -102498,6 +102442,16 @@ /obj/effect/spawner/random/contraband/permabrig_gear, /turf/open/floor/plating, /area/station/security/prison/mess) +"tQe" = ( +/obj/structure/chair/office{ + dir = 8 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "tQg" = ( /obj/effect/turf_decal/vg_decals/numbers/four, /obj/effect/landmark/start/prisoner, @@ -102654,19 +102608,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/atmos/hfr_room) -"tRo" = ( -/obj/structure/table/wood, -/obj/structure/closet/crate/cardboard{ - pixel_y = 5 - }, -/obj/item/clothing/shoes/jackboots/timbs, -/obj/item/clothing/suit/brownfurrich/public, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "tRu" = ( /obj/structure/table, /obj/item/paper_bin{ @@ -102818,15 +102759,15 @@ dir = 8 }, /area/station/hallway/secondary/service) +"tTf" = ( +/obj/structure/chair/office{ + dir = 8 + }, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "tTg" = ( /turf/closed/wall/mineral/wood, /area/station/common/pool/sauna) -"tTk" = ( -/obj/structure/flora/bush/jungle, -/obj/structure/flora/bush/flowers_yw/style_3, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "tTm" = ( /obj/effect/turf_decal/stripes{ dir = 8 @@ -103472,14 +103413,6 @@ }, /turf/open/floor/iron/dark, /area/station/hallway/secondary/command) -"uaq" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/clown_chamber) "uaL" = ( /obj/machinery/light/directional/west, /turf/open/floor/iron, @@ -104536,6 +104469,16 @@ /obj/effect/landmark/start/librarian, /turf/open/floor/carpet, /area/station/service/library/lounge) +"ukH" = ( +/obj/structure/sign/directions/command{ + dir = 1; + pixel_y = 3 + }, +/obj/structure/sign/directions/science{ + pixel_y = -3 + }, +/turf/closed/wall/r_wall, +/area/station/hallway/primary/upper) "ukI" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -105963,6 +105906,15 @@ }, /turf/open/floor/plating, /area/station/medical/pharmacy) +"uyB" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "uyC" = ( /turf/open/floor/engine{ name = "Holodeck Projector Floor" @@ -106631,10 +106583,6 @@ dir = 8 }, /area/station/security/prison) -"uED" = ( -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/cult, -/area/station/maintenance/cult_chapel_maint) "uEE" = ( /obj/machinery/door/firedoor, /obj/effect/turf_decal/tile/yellow/half/contrasted{ @@ -107035,6 +106983,19 @@ /obj/machinery/duct, /turf/open/floor/plating, /area/station/maintenance/night_club) +"uIJ" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/machinery/door/airlock/highsecurity{ + name = "Blueshield's Equipment Room" + }, +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/wood, +/area/station/command/heads_quarters/blueshield) "uIM" = ( /obj/machinery/power/smes, /obj/structure/cable, @@ -107227,6 +107188,12 @@ /obj/machinery/newscaster/directional/east, /turf/open/floor/wood, /area/station/hallway/secondary/service) +"uKB" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/chair/stool/bar/directional/north, +/obj/effect/landmark/start/gary, +/turf/open/floor/carpet, +/area/station/maintenance/rus_gambling) "uKG" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/iron, @@ -107270,6 +107237,12 @@ /obj/structure/flora/bush/leafy, /turf/open/floor/grass, /area/station/hallway/primary/central) +"uLt" = ( +/obj/machinery/duct, +/obj/effect/spawner/random/trash/mess, +/obj/effect/landmark/start/gary, +/turf/open/floor/carpet, +/area/station/commons/dorms/vacantroom) "uLA" = ( /obj/effect/spawner/structure/window, /turf/open/floor/plating, @@ -108082,6 +108055,14 @@ /obj/effect/spawner/random/medical/memeorgans, /turf/open/floor/plating, /area/station/maintenance/abandon_surgery) +"uTO" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/event_spawn, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/gary, +/turf/open/floor/eighties, +/area/station/maintenance/abandon_arcade) "uTQ" = ( /obj/effect/turf_decal/trimline/blue/line{ dir = 10 @@ -108871,12 +108852,6 @@ dir = 4 }, /area/station/science/xenobiology) -"vcx" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/closed/wall/r_wall, -/area/station/cargo/quartermaster) "vcz" = ( /obj/structure/extinguisher_cabinet/directional/south, /obj/structure/chair/comfy/brown{ @@ -109359,12 +109334,6 @@ /obj/machinery/holopad, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) -"vhw" = ( -/obj/structure/flora/bush/jungle/a, -/obj/structure/flora/bush/flowers_br/style_3, -/obj/structure/window/reinforced/fulltile, -/turf/open/floor/grass, -/area/station/hallway/primary/upper) "vhy" = ( /obj/structure/table, /obj/effect/decal/cleanable/dirt, @@ -109813,6 +109782,15 @@ /obj/structure/table, /turf/open/floor/iron/dark, /area/station/commons/dorms) +"vlp" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; + id = "qmprivacy"; + name = "Quartermaster's Privacy Shutters" + }, +/turf/open/floor/plating, +/area/station/cargo/quartermaster) "vlu" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/siding/wood, @@ -113680,6 +113658,25 @@ /obj/machinery/light/directional/east, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"vWp" = ( +/obj/item/trash/syndi_cakes, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/door/firedoor, +/obj/machinery/door/poddoor/shutters{ + id = "Starboardbowmaints"; + name = "Starboard Bow Maintenance" + }, +/obj/machinery/button/door/directional/north{ + id = "Starboardbowmaints"; + name = "Shutter control"; + pixel_x = 24; + pixel_y = 0 + }, +/turf/open/floor/plating, +/area/station/maintenance/fore/upper) "vWN" = ( /obj/structure/sign/warning/vacuum/external/directional/south, /turf/open/floor/iron, @@ -114095,12 +114092,6 @@ dir = 1 }, /area/station/hallway/primary/central/fore) -"wbm" = ( -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "wbq" = ( /obj/machinery/atmospherics/pipe/smart/simple/green/visible{ dir = 4 @@ -114409,6 +114400,12 @@ }, /turf/open/floor/iron, /area/station/maintenance/starboard/fore) +"wdN" = ( +/obj/structure/flora/bush/jungle/b/style_2, +/obj/structure/flora/bush/flowers_br/style_3, +/obj/structure/window/reinforced/fulltile, +/turf/open/floor/grass, +/area/station/hallway/primary/upper) "wdS" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 4 @@ -114540,6 +114537,18 @@ /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plating, /area/station/science/research/abandoned) +"weQ" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; + id = "qmprivacy"; + name = "Quartermaster's Privacy Shutters" + }, +/obj/structure/disposalpipe/trunk/multiz{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/cargo/quartermaster) "weT" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -114600,6 +114609,25 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/external, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"wfp" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/mess, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/firedoor, +/obj/machinery/button/door/directional/north{ + id = "Starboardbowmaints"; + name = "Shutter control"; + pixel_x = 24; + pixel_y = 0 + }, +/obj/machinery/door/poddoor/shutters{ + id = "Starboardbowmaints"; + name = "Starboard Bow Maintenance" + }, +/turf/open/floor/plating, +/area/station/maintenance/fore/upper) "wfr" = ( /obj/effect/spawner/liquids_spawner{ reagent_list = list(/datum/reagent/water=600) @@ -114695,6 +114723,12 @@ dir = 4 }, /area/station/hallway/primary/central/aft) +"wfY" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/closed/wall/r_wall, +/area/station/cargo/quartermaster) "wge" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -114971,16 +115005,6 @@ }, /turf/open/floor/wood/parquet, /area/station/common/tailoring) -"wiC" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/broken_floor, -/obj/machinery/duct, -/obj/structure/cable, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/commons/dorms/vacantroom) "wiF" = ( /obj/effect/turf_decal/bot, /obj/effect/turf_decal/stripes/corner{ @@ -115092,6 +115116,9 @@ }, /turf/open/floor/wood, /area/station/command/captain_dining) +"wjW" = ( +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "wjY" = ( /obj/structure/rack, /obj/effect/turf_decal/bot, @@ -115818,15 +115845,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/dark, /area/station/hallway/secondary/command) -"wro" = ( -/obj/effect/turf_decal/siding/brown{ - dir = 1 - }, -/obj/machinery/computer/cargo{ - dir = 1 - }, -/turf/open/floor/iron/dark, -/area/station/cargo/quartermaster) "wrq" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/machinery/button/door/directional/north{ @@ -116077,6 +116095,12 @@ /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, /area/station/maintenance/fore/upper) +"wsT" = ( +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "wsU" = ( /obj/effect/spawner/random/engineering/tracking_beacon, /turf/open/floor/plating/reinforced{ @@ -116359,13 +116383,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/brig) -"wvs" = ( -/obj/structure/bed/dogbed, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "wvt" = ( /obj/structure/reagent_dispensers/watertank, /obj/item/reagent_containers/cup/bucket, @@ -116904,10 +116921,6 @@ }, /turf/open/floor/iron, /area/station/commons/dorms) -"wBb" = ( -/obj/structure/disposalpipe/segment, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "wBn" = ( /obj/machinery/atmospherics/components/binary/pump{ name = "Port to Filter" @@ -117803,15 +117816,6 @@ /obj/machinery/light/directional/west, /turf/open/floor/carpet, /area/station/science/ordnance/office) -"wJJ" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/machinery/power/apc/auto_name/directional/north, -/obj/structure/cable, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/stone, -/area/station/service/forge) "wJQ" = ( /obj/structure/chair/office{ dir = 8 @@ -117918,6 +117922,13 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/service/hydroponics) +"wLK" = ( +/obj/structure/chair/office, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/security/detectives_office/private_investigators_office) "wLM" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -118331,6 +118342,10 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) +"wPC" = ( +/obj/effect/landmark/start/quartermaster, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "wPG" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/trash/garbage, @@ -118877,6 +118892,13 @@ /obj/structure/flora/rock/pile, /turf/open/floor/grass, /area/station/hallway/primary/central) +"wVh" = ( +/obj/structure/closet/secure_closet/quartermaster, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/station/cargo/quartermaster) "wVn" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -118949,6 +118971,12 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/station/service/theater) +"wWf" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/cafeteria, +/area/station/maintenance/abandon_diner) "wWi" = ( /obj/machinery/power/shuttle_engine/heater{ dir = 4 @@ -119736,14 +119764,6 @@ /obj/item/radio/intercom/directional/south, /turf/open/floor/circuit, /area/station/command/gateway) -"xeB" = ( -/obj/machinery/photocopier, -/obj/effect/turf_decal/bot, -/obj/structure/noticeboard/qm{ - pixel_y = 32 - }, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "xeE" = ( /obj/item/trash/syndi_cakes, /obj/structure/cable, @@ -119905,6 +119925,11 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/station/service/cafeteria) +"xgk" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/aft/upper) "xgr" = ( /obj/structure/chair/stool, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -120061,12 +120086,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"xhM" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/iron/dark, -/area/station/cargo/quartermaster) "xhZ" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -120575,6 +120594,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"xnA" = ( +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/cult, +/area/station/maintenance/cult_chapel_maint) "xnC" = ( /obj/structure/railing{ dir = 8 @@ -121197,6 +121220,22 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/service/chapel/funeral) +"xtv" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/cup/glass/bottle/fernet{ + pixel_x = -8; + pixel_y = 14 + }, +/obj/item/reagent_containers/cup/glass/bottle/lizardwine{ + pixel_x = 7; + pixel_y = 6 + }, +/obj/item/reagent_containers/cup/glass/bottle/champagne{ + pixel_y = 11 + }, +/obj/machinery/digital_clock/directional/north, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "xtB" = ( /obj/structure/chair/pew/left{ dir = 1; @@ -121823,15 +121862,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, /area/station/science/research) -"xAn" = ( -/obj/effect/turf_decal/siding/wood, -/obj/machinery/door/airlock/mining{ - name = "Deliveries" - }, -/obj/effect/mapping_helpers/airlock/access/all/supply/qm, -/obj/structure/disposalpipe/segment, -/turf/open/floor/carpet, -/area/station/cargo/quartermaster) "xAz" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -122453,6 +122483,12 @@ }, /turf/open/floor/iron, /area/station/commons/dorms) +"xGr" = ( +/obj/machinery/light/small/directional/north, +/obj/structure/disposalpipe/segment, +/obj/effect/landmark/start/quartermaster, +/turf/open/floor/carpet, +/area/station/cargo/quartermaster) "xGu" = ( /obj/structure/chair/office, /obj/structure/window/spawner/directional/west, @@ -122638,18 +122674,6 @@ /obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/disposal) -"xIz" = ( -/obj/effect/turf_decal/siding/wood/corner{ - dir = 4 - }, -/obj/machinery/camera/directional/south{ - c_tag = "Cargo - Quartermaster's office"; - dir = 1 - }, -/obj/structure/table/wood, -/obj/item/modular_computer/laptop, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "xIB" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/trash/mopbucket, @@ -122811,16 +122835,6 @@ }, /turf/open/floor/wood/parquet, /area/station/command/gateway) -"xKm" = ( -/obj/structure/sign/directions/command{ - dir = 1; - pixel_y = 3 - }, -/obj/structure/sign/directions/science{ - pixel_y = -3 - }, -/turf/closed/wall/r_wall, -/area/station/hallway/primary/upper) "xKr" = ( /obj/structure/table, /obj/item/paper_bin{ @@ -123135,12 +123149,6 @@ /obj/machinery/light/directional/north, /turf/open/floor/iron, /area/station/engineering/storage/tech) -"xNp" = ( -/obj/machinery/holopad, -/obj/effect/turf_decal/bot, -/obj/effect/landmark/start/quartermaster, -/turf/open/floor/wood/parquet, -/area/station/cargo/quartermaster) "xNy" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/liquids_spawner, @@ -123877,6 +123885,12 @@ }, /turf/open/floor/iron, /area/station/command/bridge) +"xVU" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/turf/open/floor/wood/parquet, +/area/station/cargo/quartermaster) "xVV" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -124893,17 +124907,6 @@ /obj/structure/cable, /turf/open/floor/iron/smooth, /area/station/cargo/power_station/upper) -"yeG" = ( -/obj/item/storage/backpack/blueshield, -/obj/item/storage/backpack/duffelbag/blueshield, -/obj/item/storage/backpack/satchel/blueshield, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/item/clothing/neck/mantle/bsmantle, -/obj/machinery/duct, -/turf/open/floor/carpet/executive, -/area/station/command/heads_quarters/blueshield) "yeH" = ( /obj/structure/railing{ dir = 4 @@ -144370,7 +144373,7 @@ vdX szo khB wsY -pew +uKB sCE oHL mqQ @@ -145340,7 +145343,7 @@ dEa dEa uEt bQL -aBw +iZA ihY pCR aUf @@ -146920,7 +146923,7 @@ gJC kvS tyO qCy -wJJ +aCe oDK xKQ rii @@ -147726,7 +147729,7 @@ jFf qMb uns gib -mLV +wLK nLn qjL nEA @@ -148735,7 +148738,7 @@ tKM uDf tFG tyB -rPj +jjN hLJ tyB fWT @@ -149757,7 +149760,7 @@ tej gcU lmf mFM -cmE +gFQ jQA jQA uDf @@ -150755,7 +150758,7 @@ pWa lOb eiM ukF -jhc +thb ocy efJ kQJ @@ -151531,7 +151534,7 @@ qlY qlY sPz tWx -mxr +cxO xFB wjx snu @@ -151802,7 +151805,7 @@ tvB oPW hoT qon -meH +sxg hhb csC uZH @@ -154331,7 +154334,7 @@ aGF grq uDg xvc -lYB +lBX kOW pjw pjw @@ -160550,7 +160553,7 @@ pEc cwD iWN uAV -mxu +gtW uAV lmE iWN @@ -161044,12 +161047,12 @@ mVk mVk mVk ueR -raX -raX -raX -vcx -raX -raX +rJF +rJF +rJF +wfY +rJF +rJF hmV vqa vqa @@ -161301,12 +161304,12 @@ mVk kVb gIS gIS -raX -sPM -qKb -dNr -biD -wro +rJF +xtv +tKU +tbD +iQW +cDG hmV hHn jrw @@ -161558,12 +161561,12 @@ eBe yde azk azk -raX -xIz -fpe -lPh -jUq -mEK +rJF +ppK +wjW +kVe +wPC +dvI hmV roO sNu @@ -161810,17 +161813,17 @@ mkM wsl tAt gIS -raX -raX -raX -raX -xeB -nLg -hAk -sfP -tRo -fpe -cJQ +rJF +rJF +rJF +rJF +pAL +ier +xVU +nAy +hUu +wjW +hpv hmV knm oQD @@ -162067,17 +162070,17 @@ eTy aTu npf hfr -raX -lVl -xhM -ovy -ngF -wBb -heD -cen -pSL -bJM -raX +rJF +wVh +fiG +iTO +jxK +nsx +jZU +oYQ +knG +akd +rJF hmV vqa vqa @@ -162324,17 +162327,17 @@ fsS oQw tAt oUr -act -alN -bCR -xAn -wBb -wbm -ehv -xNp -rUn -cfZ -raX +dYV +xGr +rHz +gGm +nsx +wsT +tTf +mYp +tQe +htj +rJF bHe gSu gSA @@ -162581,18 +162584,18 @@ iru cRO tAt eye -raX -bZx -rim -ovy -fxQ -wvs -auf -hHm -rNW -fvd -qrq -mgb +rJF +fdB +hTx +iTO +okm +hgI +mdB +gpf +gwg +uyB +gia +giW mvF foY uVh @@ -162838,17 +162841,17 @@ hZB gvR eGI kVb -raX -raX -raX -raX -lhn -nBW -nBW -sUv -lhn -raX -raX +rJF +rJF +rJF +rJF +vlp +lXx +lXx +weQ +vlp +rJF +rJF fOp pYr cZV @@ -164603,7 +164606,7 @@ xhv tCi tgb gjd -bPR +cZI hdS fRA xPk @@ -164828,7 +164831,7 @@ jEz eCw kkM fzZ -qIq +qGh aFR wpP vTa @@ -165922,7 +165925,7 @@ pMQ eGW nKK eFn -hGg +eSI oTl mXK ipg @@ -167181,7 +167184,7 @@ dVy rtr iTN nli -cns +kcU kfl iTN sfw @@ -209393,7 +209396,7 @@ soz uAj mAK ibw -sAJ +nlV mtu iCe wpF @@ -211378,7 +211381,7 @@ lEO lxt hZy oIe -sqK +tov gyh jyY mqj @@ -211412,7 +211415,7 @@ drQ xPd fHi reO -fGg +uLt soC eVg hnW @@ -212440,7 +212443,7 @@ fXT lGF fHi xbC -wiC +dzr czZ eVg kmc @@ -212900,7 +212903,7 @@ qhz ybT ybT oIL -sAn +jzZ gPC bZe gPC @@ -213166,7 +213169,7 @@ jQY fnc dEf hrJ -dAw +eul cXM kTV kTV @@ -213768,7 +213771,7 @@ lec sJw vzq bZD -dfo +aXz bqc ovC aDV @@ -215746,8 +215749,8 @@ gSB iVh hEi ami -yeG -tCj +cfa +dNs lPx sZp ktv @@ -216260,7 +216263,7 @@ aXo ide ide sZp -izO +pmq pRa pRa sZp @@ -216600,7 +216603,7 @@ vIq smt pTE gDk -lGg +wWf dHC cDP fne @@ -216876,7 +216879,7 @@ tcq sba sXD tpk -eVJ +cBG cct akA soz @@ -217287,10 +217290,10 @@ hCT aXo ide sZp -ohE +pyS sZp sZp -kpQ +uIJ sZp sZp sOm @@ -217894,7 +217897,7 @@ tfJ pjf tUm bgI -ofh +uTO wbv mrX kCj @@ -218012,7 +218015,7 @@ ulI kNf pcs mYx -aTf +nBp rof bta bCe @@ -218058,7 +218061,7 @@ kAP wKd ide qzx -cSH +gNs qOZ wbO utQ @@ -218415,7 +218418,7 @@ kCj jKs gVx lWr -lZi +xgk tpk urs iVF @@ -218832,7 +218835,7 @@ gXP gWh sZp uLF -bzO +eDY uLF sZp cRb @@ -221943,11 +221946,11 @@ pQF tYT tYT tYT -lei -jDl -jvl -tTk -xKm +mzu +mVh +iMf +gBx +ukH qJk qJk lcX @@ -222200,11 +222203,11 @@ eRh cfl cfl cfl -hWd +bwW wfr cMo tiA -lei +mzu coT gST lcX @@ -222457,11 +222460,11 @@ eRh cfl eLB cfl -laH +kER rko wfr xtV -rwR +jJh cfl cfl gyk @@ -222714,11 +222717,11 @@ eRh mkE wMo wMo -cGG +hwe pgY xVz xLg -qLP +sgt cfl cfl lcX @@ -222971,11 +222974,11 @@ eRh cfl uGh cfl -muJ +wdN oqO mPK xtV -ePR +qDe cfl cfl gyk @@ -223228,11 +223231,11 @@ eRh cfl cfl cfl -obY +pit mMJ xtV eUH -lei +mzu ugc uol lcX @@ -223485,11 +223488,11 @@ pQF akt akt akt -lei -fsX -vhw -dqh -xKm +mzu +iWF +knr +dKI +ukH wiK wiK lcX @@ -228392,7 +228395,7 @@ aQY dsQ dRf bwO -dNx +rEB leE vYX vYX @@ -231167,7 +231170,7 @@ gTZ goM ojU qOK -rJl +qkT gta dNp xiB @@ -231493,7 +231496,7 @@ buD psl nNt ukK -bOo +bmS iki sus ulx @@ -231924,7 +231927,7 @@ hrN vzh omu hLk -aoq +lRb arj lKb vQQ @@ -232517,7 +232520,7 @@ kPf kPf qzz gyV -uaq +nFV rjO jHG xrT @@ -233048,7 +233051,7 @@ jVg sKy myL wrz -uED +xnA cSf kLR sdx @@ -233217,7 +233220,7 @@ mjZ vyd wql mdY -jVS +izG cmf ufd cHh @@ -233549,13 +233552,13 @@ usu gLc kWO gLc -lLF +mba gLc -lLF +mba gLc -lLF +mba gLc -lLF +mba kta xxS hXr @@ -233802,17 +233805,17 @@ usu nPy usu gLc -lLF +mba gLc kWO gLc -lLF +mba gLc kWO gLc kWO gLc -lLF +mba cwF xxS ydM @@ -233966,13 +233969,13 @@ nao rHT cKJ rHT -iiy +wfp rUd xiE rHT rHT afm -bNE +vWp qPC xbB exN @@ -234061,13 +234064,13 @@ klU gLc klU gLc -lLF +mba gLc -lLF +mba gLc kWO gLc -lLF +mba gLc kWO cwF @@ -234318,13 +234321,13 @@ klU mQV klU gLc -lLF +mba gLc -lLF +mba gLc kWO gLc -lLF +mba gLc kWO kta @@ -234768,7 +234771,7 @@ eDF pMa fdF yda -ikF +mxX sBF syc ssb @@ -234832,15 +234835,15 @@ klU mQV gTL gLc -lLF +mba loJ -lLF +mba gLc -lLF +mba gLc kWO gLc -lLF +mba kta kta kta @@ -235089,15 +235092,15 @@ klU gLc klU gLc -lLF +mba fKh kWO gLc -lLF +mba gLc kWO gLc -lLF +mba gLc gLc cwF @@ -235346,13 +235349,13 @@ klU gLc klU gLc -lLF +mba gLc kWO gLc -lLF +mba gLc -lLF +mba gLc kWO gLc diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 253b34157f4a..1f1bce7a8fde 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -516,6 +516,20 @@ /obj/structure/sign/departments/maint/directional/south, /turf/open/floor/iron/dark, /area/station/hallway/secondary/entry) +"ajR" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 8 + }, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/stone, +/area/station/smithing) "ajT" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -1645,6 +1659,11 @@ /obj/machinery/duct, /turf/open/floor/iron/dark, /area/station/medical/morgue) +"aDR" = ( +/obj/effect/landmark/blobstart, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/maintenance/port/fore) "aDS" = ( /obj/machinery/washing_machine, /obj/machinery/light/small/directional/east, @@ -2217,6 +2236,12 @@ }, /turf/open/floor/carpet/executive, /area/station/command/heads_quarters/blueshield) +"aNZ" = ( +/obj/structure/chair/comfy/black, +/obj/structure/cable, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/wood, +/area/station/command/heads_quarters/blueshield) "aOj" = ( /obj/effect/turf_decal/trimline/green/line{ dir = 4 @@ -2590,10 +2615,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/dark, /area/station/maintenance/disposal/incinerator) -"aTt" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port) "aTv" = ( /obj/structure/chair/stool/directional/south, /obj/machinery/flasher/directional/west{ @@ -3394,6 +3415,18 @@ }, /turf/open/floor/iron/dark, /area/station/hallway/secondary/entry) +"bgW" = ( +/obj/effect/turf_decal/siding/dark_blue{ + dir = 5 + }, +/obj/effect/turf_decal/siding/dark_blue/corner{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/light/floor/has_bulb, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/carpet/neon/simple/blue/nodots, +/area/station/command/heads_quarters/blueshield) "bhd" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -4253,11 +4286,6 @@ /obj/effect/landmark/start/paramedic, /turf/open/floor/iron, /area/station/medical/paramedic) -"buH" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "buR" = ( /obj/effect/turf_decal/trimline/brown/filled/line, /obj/structure/cable, @@ -4836,16 +4864,6 @@ }, /turf/open/floor/iron/dark, /area/station/commons/vacant_room/commissary) -"bFn" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/structure/chair/wood{ - dir = 4 - }, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/wood, -/area/station/service/library/lounge) "bFv" = ( /obj/machinery/firealarm/directional/north, /obj/machinery/camera/autoname/directional/north, @@ -5820,6 +5838,17 @@ /obj/structure/cable, /turf/open/floor/iron/dark/side, /area/station/service/hydroponics/garden) +"bVm" = ( +/obj/machinery/door/airlock/corporate{ + name = "Blueshield's Quarters" + }, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/wood, +/area/station/command/heads_quarters/blueshield) "bVs" = ( /obj/machinery/light/small/directional/south, /obj/machinery/camera/autoname/directional/south, @@ -5909,10 +5938,6 @@ }, /turf/open/floor/grass, /area/station/medical/medbay/central) -"bXe" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/carpet, -/area/station/maintenance/starboard/fore) "bXo" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -6554,15 +6579,6 @@ dir = 4 }, /area/station/commons/fitness/recreation) -"cgL" = ( -/obj/effect/turf_decal/tile/yellow/half/contrasted{ - dir = 1 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/gibs/old, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron, -/area/station/maintenance/starboard/aft) "cgP" = ( /obj/effect/turf_decal/trimline/green/filled/line, /obj/effect/turf_decal/trimline/green/line{ @@ -8698,6 +8714,11 @@ /obj/machinery/light/small/directional/north, /turf/open/floor/iron/dark, /area/station/cargo/sorting) +"cSu" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron, +/area/station/maintenance/starboard/aft) "cSv" = ( /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ @@ -9023,15 +9044,6 @@ dir = 8 }, /area/station/service/hydroponics/garden) -"cWr" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/glass, -/obj/effect/spawner/random/trash/cigbutt, -/obj/item/broken_bottle, -/obj/machinery/duct, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "cWy" = ( /obj/effect/turf_decal/trimline/dark_blue/filled/line{ dir = 1 @@ -9481,6 +9493,13 @@ }, /turf/open/floor/iron, /area/station/science/robotics/lab) +"det" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/sepia, +/area/station/service/library/artgallery) "deB" = ( /obj/effect/spawner/random/vending/snackvend, /turf/open/floor/iron/dark, @@ -9925,12 +9944,6 @@ /obj/effect/turf_decal/trimline/yellow/line, /turf/open/floor/iron, /area/station/hallway/primary/aft) -"dlz" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/duct, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "dlC" = ( /obj/docking_port/stationary{ dir = 8; @@ -11185,6 +11198,12 @@ }, /turf/open/floor/engine, /area/station/ai_monitored/turret_protected/aisat_interior) +"dIu" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/restraints/handcuffs/cable/zipties/used, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "dIE" = ( /obj/effect/turf_decal/tile/dark_blue/fourcorners, /obj/structure/disposalpipe/junction/flip{ @@ -11994,11 +12013,6 @@ /obj/machinery/firealarm/directional/north, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/blueshield) -"dXK" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "dXL" = ( /obj/structure/table, /obj/item/electronics/airlock{ @@ -12157,6 +12171,14 @@ /obj/machinery/duct, /turf/open/floor/iron, /area/station/service/hydroponics) +"dZz" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/dark, +/area/station/maintenance/department/cargo) "dZE" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -12769,17 +12791,6 @@ /obj/machinery/holopad, /turf/open/floor/iron/dark/smooth_large, /area/station/ai_monitored/command/nuke_storage) -"ekL" = ( -/obj/structure/cable, -/obj/machinery/door/airlock/corporate{ - id_tag = "BSdoor"; - name = "Blueshield's Office" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/turf/open/floor/carpet/executive, -/area/station/command/heads_quarters/blueshield) "ekU" = ( /obj/effect/spawner/random/structure/table, /obj/item/assembly/timer, @@ -13923,17 +13934,6 @@ dir = 1 }, /area/station/commons/dorms) -"eDW" = ( -/obj/effect/turf_decal/siding/dark_blue{ - dir = 5 - }, -/obj/effect/turf_decal/siding/dark_blue/corner{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/light/floor/has_bulb, -/turf/open/floor/carpet/neon/simple/blue/nodots, -/area/station/command/heads_quarters/blueshield) "eED" = ( /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 8 @@ -16647,22 +16647,16 @@ /obj/item/storage/box/bodybags, /turf/open/floor/iron/white, /area/station/security/medical) +"fCi" = ( +/obj/effect/mapping_helpers/burnt_floor, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/plating, +/area/station/maintenance/department/engine/atmos) "fCw" = ( /obj/effect/spawner/random/structure/table, /obj/effect/spawner/random/entertainment/cigarette_pack, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) -"fCE" = ( -/obj/machinery/door/airlock/corporate{ - name = "Blueshield's Quarters" - }, -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/turf/open/floor/wood, -/area/station/command/heads_quarters/blueshield) "fCT" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -16785,15 +16779,6 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/security/checkpoint/supply) -"fEX" = ( -/obj/effect/turf_decal/tile/dark_blue/fourcorners, -/obj/machinery/door/airlock/corporate{ - name = "Blueshield's Quarters" - }, -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/turf/open/floor/iron/dark, -/area/station/command/heads_quarters/blueshield) "fFd" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -16835,6 +16820,11 @@ "fFV" = ( /turf/closed/wall, /area/station/solars/port/aft) +"fGf" = ( +/obj/structure/chair/stool/bar/directional/south, +/obj/effect/landmark/start/gary, +/turf/open/floor/carpet/green, +/area/station/maintenance/starboard/aft) "fGh" = ( /obj/structure/sign/warning/test_chamber/directional/north, /obj/effect/decal/cleanable/dirt, @@ -18705,6 +18695,15 @@ dir = 8 }, /area/station/commons/fitness/recreation) +"gmT" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/glass, +/obj/effect/spawner/random/trash/cigbutt, +/obj/item/broken_bottle, +/obj/machinery/duct, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "gmU" = ( /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 8 @@ -19263,6 +19262,14 @@ }, /turf/open/floor/iron/dark, /area/station/security/checkpoint/engineering) +"gvx" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/structure/altar_of_gods, +/obj/item/book/bible, +/turf/open/floor/carpet, +/area/station/service/chapel) "gvD" = ( /obj/effect/turf_decal/stripes/corner, /obj/effect/turf_decal/stripes/corner{ @@ -19334,6 +19341,11 @@ dir = 1 }, /area/station/service/hydroponics) +"gwI" = ( +/obj/machinery/duct, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/showroomfloor, +/area/station/commons/toilet/restrooms) "gwS" = ( /turf/open/floor/iron/dark, /area/station/commons/vacant_room/commissary) @@ -19762,11 +19774,6 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/foyer) -"gCN" = ( -/obj/structure/chair/stool/bar/directional/south, -/obj/effect/landmark/start/gary, -/turf/open/floor/carpet/green, -/area/station/maintenance/starboard/aft) "gCP" = ( /obj/machinery/space_heater, /turf/open/floor/plating, @@ -21265,6 +21272,15 @@ "gZH" = ( /turf/open/floor/engine/co2, /area/station/engineering/atmos) +"gZM" = ( +/obj/effect/turf_decal/tile/dark_blue/fourcorners, +/obj/machinery/door/airlock/corporate{ + name = "Blueshield's Quarters" + }, +/obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/iron/dark, +/area/station/command/heads_quarters/blueshield) "gZP" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 10 @@ -21333,11 +21349,6 @@ }, /turf/open/floor/iron/dark, /area/station/hallway/primary/central) -"haV" = ( -/obj/effect/mapping_helpers/burnt_floor, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/plating, -/area/station/maintenance/department/engine/atmos) "hbb" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -22238,14 +22249,6 @@ }, /turf/open/floor/iron/dark, /area/station/security/brig) -"hqX" = ( -/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/broken_floor, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "hrk" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/turf_decal/trimline/red/filled/line{ @@ -22859,6 +22862,13 @@ /obj/effect/turf_decal/tile/blue/fourcorners, /turf/open/floor/iron/white, /area/station/medical/office) +"hBG" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/blobstart, +/obj/machinery/duct, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "hBK" = ( /obj/effect/turf_decal/stripes/box, /obj/machinery/camera/autoname/directional/west, @@ -25341,6 +25351,14 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/security/office) +"isD" = ( +/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/broken_floor, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "isM" = ( /obj/machinery/status_display/evac/directional/south, /obj/structure/easel, @@ -25603,13 +25621,6 @@ }, /turf/open/floor/iron/dark, /area/station/hallway/primary/central) -"ivh" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/sepia, -/area/station/service/library/artgallery) "ivi" = ( /obj/structure/displaycase/captain, /turf/open/floor/wood, @@ -27161,6 +27172,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/service/chapel) +"iWE" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/carpet, +/area/station/maintenance/starboard/fore) "iWI" = ( /obj/effect/decal/cleanable/cobweb, /obj/effect/spawner/random/entertainment/coin, @@ -27520,6 +27535,12 @@ /obj/effect/turf_decal/trimline/red/line, /turf/open/floor/iron/dark, /area/station/hallway/secondary/entry) +"jcn" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/duct, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "jct" = ( /obj/effect/turf_decal/trimline/dark_blue/filled/warning{ dir = 4 @@ -27604,6 +27625,16 @@ }, /turf/open/floor/plating, /area/station/maintenance/department/medical) +"jdT" = ( +/obj/machinery/light/floor/has_bulb, +/obj/machinery/door/airlock/highsecurity{ + name = "Blueshield's Equipment Room" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/wood, +/area/station/command/heads_quarters/blueshield) "jdV" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -28205,14 +28236,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/main) -"jqu" = ( -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/dark, -/area/station/maintenance/department/cargo) "jqH" = ( /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ @@ -28366,14 +28389,6 @@ "juc" = ( /turf/open/floor/iron, /area/station/service/hydroponics) -"jud" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/structure/altar_of_gods, -/obj/item/book/bible, -/turf/open/floor/carpet, -/area/station/service/chapel) "jug" = ( /obj/effect/turf_decal/tile/dark_blue/fourcorners, /obj/structure/cable, @@ -29639,6 +29654,13 @@ "jNZ" = ( /turf/open/floor/iron/showroomfloor, /area/station/security/warden) +"jOc" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/commons/vacant_room/office) "jOi" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/structure/chair_maintenance{ @@ -31916,6 +31938,12 @@ /obj/machinery/station_map/engineering/directional/south, /turf/open/floor/iron/dark, /area/station/security/brig) +"kDm" = ( +/obj/effect/landmark/blobstart, +/obj/machinery/duct, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "kDx" = ( /obj/machinery/firealarm/directional/east, /turf/open/floor/iron/dark/side{ @@ -32379,11 +32407,6 @@ }, /turf/open/floor/carpet/blue, /area/station/medical/psychology) -"kMq" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "kMC" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/components/binary/pump/on/supply/hidden/layer4, @@ -34030,14 +34053,6 @@ /obj/machinery/light/small/directional/south, /turf/open/floor/iron/white, /area/station/science/xenobiology) -"lnt" = ( -/obj/machinery/light/broken/directional/east, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/cafeteria, -/area/station/maintenance/starboard/aft) "lnu" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -34375,11 +34390,6 @@ }, /turf/open/floor/engine, /area/station/science/xenobiology) -"ltv" = ( -/obj/effect/landmark/blobstart, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/maintenance/port/fore) "ltB" = ( /obj/structure/cable, /obj/effect/turf_decal/delivery/red, @@ -34578,12 +34588,6 @@ /obj/effect/spawner/random/structure/tank_holder, /turf/open/floor/plating, /area/station/maintenance/department/medical) -"lwi" = ( -/obj/effect/landmark/blobstart, -/obj/machinery/duct, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "lwj" = ( /obj/structure/cable/layer1, /turf/open/floor/plating/airless, @@ -35205,13 +35209,6 @@ /obj/item/camera_film, /turf/open/floor/iron/dark/textured, /area/station/service/library/printer) -"lGA" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/blobstart, -/obj/machinery/duct, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "lGD" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -35773,6 +35770,10 @@ /obj/structure/plasticflaps/opaque, /turf/open/floor/iron/white, /area/station/maintenance/department/medical) +"lOH" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port) "lOJ" = ( /obj/structure/window/reinforced/spawner/directional/south, /turf/open/floor/grass, @@ -36404,11 +36405,6 @@ "mbx" = ( /turf/open/floor/iron/dark, /area/station/hallway/secondary/exit/departure_lounge) -"mby" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron, -/area/station/maintenance/starboard/aft) "mbE" = ( /obj/effect/turf_decal/trimline/red/filled/line{ dir = 6 @@ -36790,16 +36786,6 @@ /obj/machinery/camera/autoname/directional/west, /turf/open/floor/iron/dark/smooth_large, /area/station/engineering/main) -"miU" = ( -/obj/machinery/light/floor/has_bulb, -/obj/machinery/door/airlock/highsecurity{ - name = "Blueshield's Equipment Room" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/turf/open/floor/wood, -/area/station/command/heads_quarters/blueshield) "miX" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/trash/bin, @@ -38787,6 +38773,14 @@ dir = 6 }, /area/station/service/janitor) +"mTo" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/structure/chair_maintenance{ + dir = 8 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "mTp" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -39945,16 +39939,6 @@ }, /turf/open/floor/iron/dark/textured, /area/station/command/teleporter) -"nmw" = ( -/obj/structure/bed/double{ - dir = 4 - }, -/obj/item/bedsheet/nanotrasen/double{ - dir = 4 - }, -/obj/machinery/newscaster/directional/north, -/turf/open/floor/carpet/executive, -/area/station/command/heads_quarters/blueshield) "nmY" = ( /obj/machinery/airalarm/directional/south, /obj/structure/destructible/cult/item_dispenser/archives/library, @@ -40229,11 +40213,6 @@ /obj/machinery/duct, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) -"nrM" = ( -/obj/machinery/duct, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/showroomfloor, -/area/station/commons/toilet/restrooms) "nrN" = ( /obj/structure/flora/bush/fullgrass/style_random, /obj/structure/flora/bush/grassy/style_random, @@ -40642,6 +40621,11 @@ /obj/structure/closet/emcloset/anchored, /turf/open/floor/iron/dark, /area/station/hallway/secondary/exit/departure_lounge) +"nyj" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "nyn" = ( /obj/effect/turf_decal/trimline/dark_blue/filled/line{ dir = 5 @@ -44591,6 +44575,11 @@ dir = 4 }, /area/station/service/hydroponics) +"oLr" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "oLy" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/structure/chair_flipped{ @@ -46615,6 +46604,11 @@ /obj/machinery/icecream_vat, /turf/open/floor/iron/kitchen, /area/station/service/kitchen) +"puW" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "puX" = ( /obj/structure/sign/warning/secure_area/directional/south, /obj/machinery/space_heater, @@ -48514,11 +48508,6 @@ }, /turf/open/floor/iron/dark, /area/station/hallway/primary/central) -"qdV" = ( -/obj/structure/chair/comfy/black, -/obj/structure/cable, -/turf/open/floor/wood, -/area/station/command/heads_quarters/blueshield) "qdZ" = ( /obj/effect/turf_decal/trimline/red/filled/line{ dir = 1 @@ -50232,6 +50221,17 @@ /obj/machinery/light/directional/north, /turf/open/floor/iron/dark, /area/station/engineering/atmos) +"qKB" = ( +/obj/structure/cable, +/obj/machinery/door/airlock/corporate{ + id_tag = "BSdoor"; + name = "Blueshield's Office" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/carpet/executive, +/area/station/command/heads_quarters/blueshield) "qKG" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 4 @@ -51315,14 +51315,6 @@ /obj/machinery/duct, /turf/open/floor/plating, /area/station/maintenance/department/cargo) -"rdA" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 4 - }, -/obj/structure/cable, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/dark, -/area/station/commons/vacant_room/commissary) "rdG" = ( /obj/effect/turf_decal/trimline/purple/filled/line, /obj/machinery/camera/autoname/directional/south, @@ -53193,13 +53185,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/iron/dark, /area/station/security/checkpoint/customs/auxiliary) -"rGP" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 1 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/commons/vacant_room/office) "rGT" = ( /obj/effect/turf_decal/bot, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -57074,6 +57059,17 @@ /obj/machinery/duct, /turf/open/floor/iron/white, /area/station/medical/virology) +"sZg" = ( +/obj/structure/bed/double{ + dir = 4 + }, +/obj/item/bedsheet/nanotrasen/double{ + dir = 4 + }, +/obj/machinery/newscaster/directional/north, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/carpet/executive, +/area/station/command/heads_quarters/blueshield) "sZi" = ( /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, @@ -61456,20 +61452,6 @@ /obj/item/kirbyplants/random, /turf/open/floor/wood, /area/station/service/library/private) -"uvo" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/effect/turf_decal/siding/wood/corner{ - dir = 4 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 8 - }, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/stone, -/area/station/smithing) "uvN" = ( /obj/effect/turf_decal/tile/blue/opposingcorners{ dir = 1 @@ -61888,6 +61870,11 @@ /obj/structure/cable, /turf/open/floor/iron/white, /area/station/medical/office) +"uFo" = ( +/obj/effect/spawner/random/entertainment/coin, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "uFv" = ( /obj/effect/turf_decal/tile/green/anticorner/contrasted, /obj/structure/table, @@ -63608,6 +63595,14 @@ /obj/structure/table, /turf/open/floor/iron/white, /area/station/medical/patients_rooms/room_b) +"vhb" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/obj/structure/cable, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/dark, +/area/station/commons/vacant_room/commissary) "vhd" = ( /obj/effect/turf_decal/trimline/red/filled/warning{ dir = 1 @@ -66376,12 +66371,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, /area/station/science/research) -"weV" = ( -/obj/effect/decal/cleanable/dirt, -/obj/item/restraints/handcuffs/cable/zipties/used, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "wfb" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/trash/moisture_trap, @@ -67510,6 +67499,16 @@ /obj/structure/cable, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"wzb" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/structure/chair/wood{ + dir = 4 + }, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/wood, +/area/station/service/library/lounge) "wzj" = ( /obj/structure/closet/secure_closet/blueshield, /obj/item/storage/bag/garment/blueshield, @@ -69550,6 +69549,15 @@ }, /turf/open/floor/iron/dark, /area/station/security/office) +"xhY" = ( +/obj/effect/turf_decal/tile/yellow/half/contrasted{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/blood/gibs/old, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron, +/area/station/maintenance/starboard/aft) "xih" = ( /obj/effect/landmark/navigate_destination/common/holodeck, /turf/open/floor/engine{ @@ -71067,11 +71075,6 @@ }, /turf/open/floor/iron/dark, /area/station/hallway/secondary/entry) -"xIC" = ( -/obj/effect/spawner/random/entertainment/coin, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "xIH" = ( /obj/machinery/firealarm/directional/east, /turf/open/floor/iron/dark, @@ -71453,14 +71456,6 @@ dir = 8 }, /area/station/command/heads_quarters/cmo) -"xRe" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/random/structure/chair_maintenance{ - dir = 8 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "xRh" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -72103,6 +72098,14 @@ dir = 4 }, /area/station/service/hydroponics) +"yaQ" = ( +/obj/machinery/light/broken/directional/east, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/cafeteria, +/area/station/maintenance/starboard/aft) "yaT" = ( /obj/effect/turf_decal/tile/blue/fourcorners, /obj/machinery/camera/directional/east{ @@ -80775,7 +80778,7 @@ wZF cRp fby hxM -jqu +dZz sKs qQe xhj @@ -81973,7 +81976,7 @@ ksa ksa fPN whJ -buH +oLr hjc fPN fBd @@ -82750,7 +82753,7 @@ fPN tLs mEg lYe -rGP +jOc mEg nyL ydv @@ -84568,7 +84571,7 @@ fPN giy vXA mNt -nrM +gwI bKL nai uXH @@ -85567,7 +85570,7 @@ fEP uoo nGn pGM -ltv +aDR yhT byj odN @@ -92328,7 +92331,7 @@ cLZ cLZ luw yce -aTt +lOH yce luw nwz @@ -92353,7 +92356,7 @@ eub wEB cuU nwz -kMq +puW cuU vuH jgH @@ -94406,11 +94409,11 @@ tcw eub wEB nwz -weV +dIu nwz jwW ghA -kMq +puW nwz jwW nwz @@ -94418,7 +94421,7 @@ tuu jwW nwz vIQ -lGA +hBG vIQ xba xba @@ -94650,7 +94653,7 @@ mxZ wEB nwz feW -kMq +puW nwz nwz jwW @@ -98215,7 +98218,7 @@ hjB cjW tgq tgq -fEX +gZM tgq tgq tgq @@ -98471,9 +98474,9 @@ gbD hjB xLi tgq -nmw +sZg qkl -fCE +bVm hRl oxS qZF @@ -98732,7 +98735,7 @@ anb eTd qZF tjH -qdV +aNZ oHZ skJ qGt @@ -99243,7 +99246,7 @@ hjB cjW tgq qZF -miU +jdT qZF bFw dzH @@ -99757,11 +99760,11 @@ hjB cjW tgq dXw -eDW +bgW vsc cUF cUF -ekL +qKB fVn hEZ otg @@ -104668,7 +104671,7 @@ mwc ygO blC vwz -rdA +vhb wlw rRZ iyt @@ -105145,7 +105148,7 @@ wEA mZc voi sIW -uvo +ajR vNF tZr aeJ @@ -112151,7 +112154,7 @@ ilj oqK wGN nCa -haV +fCi gRf nLS sZo @@ -115995,7 +115998,7 @@ nBE nBE vJw dgS -lwi +kDm lNF dgS vsB @@ -117257,7 +117260,7 @@ bQY gkM vpL chg -ivh +det sAH fep lvR @@ -117271,11 +117274,11 @@ jOx raC nBE imG -dXK +nyj mhc sxS mhc -dXK +nyj sxi nBE mhc @@ -117285,7 +117288,7 @@ mhc jDj nBE rtJ -cWr +gmT iSr nBE cnU @@ -117537,7 +117540,7 @@ fbT nBE uKp czU -dlz +jcn vkc czU tNd @@ -117722,7 +117725,7 @@ iLB jet enc ulm -bXe +iWE vMt gXK iLB @@ -118001,7 +118004,7 @@ ovM gZc qDZ qDZ -jud +gvx qDZ qDZ qra @@ -118285,7 +118288,7 @@ lAc omZ lAZ owN -bFn +wzb vqc lAZ rOR @@ -119329,7 +119332,7 @@ nBE mhc cNN bcw -lnt +yaQ mhc pCb nep @@ -120621,7 +120624,7 @@ hpY nBE jOi wMo -gCN +fGf tPw plH nBE @@ -121061,7 +121064,7 @@ jxy jxy fXj tvo -hqX +isD aOz gxY jxy @@ -121070,7 +121073,7 @@ iLB lKO jxy iLB -xIC +uFo iLB jxy iLB @@ -121127,7 +121130,7 @@ mhc tZd tZd dsV -mby +cSu tZd mhc hpY @@ -121912,7 +121915,7 @@ khD wtN wzz sZi -dXK +nyj mhc mhc aDe @@ -124155,7 +124158,7 @@ iLB jxy iLB vox -xRe +mTo vox iLB jxy @@ -124479,7 +124482,7 @@ bOr bOr nBE hKC -cgL +xhY xaD nBE byX diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 91450636521f..b70950e0f9ad 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -4001,11 +4001,6 @@ }, /turf/open/floor/iron, /area/station/maintenance/port/aft) -"aTZ" = ( -/obj/effect/turf_decal/siding/wood, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/sepia, -/area/station/service/library/artgallery) "aUo" = ( /obj/effect/turf_decal/tile/neutral/full, /obj/structure/cable, @@ -4345,17 +4340,6 @@ /obj/effect/mapping_helpers/airlock/access/all/command/hop, /turf/open/floor/iron, /area/station/security/checkpoint/customs/aft) -"aYG" = ( -/obj/structure/cable, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/department/electrical) "aYK" = ( /obj/structure/cable, /obj/effect/turf_decal/stripes/line{ @@ -4651,6 +4635,16 @@ /obj/machinery/status_display/ai/directional/west, /turf/open/floor/carpet, /area/station/command/heads_quarters/captain) +"bcJ" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/obj/effect/landmark/blobstart, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron, +/area/station/maintenance/port) "bcR" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/structure/chair/office{ @@ -5550,6 +5544,16 @@ }, /turf/open/floor/plating, /area/station/maintenance/department/chapel) +"bnN" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/obj/structure/chair/wood{ + dir = 4 + }, +/obj/effect/landmark/blobstart, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/service/theater/abandoned) "bnR" = ( /obj/effect/turf_decal/trimline/blue/filled/corner{ dir = 4 @@ -7321,6 +7325,15 @@ /obj/machinery/light/directional/south, /turf/open/floor/iron, /area/station/hallway/secondary/command) +"bIh" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/structure/cable, +/obj/effect/turf_decal/siding/wood, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/stone, +/area/station/smithing) "bIk" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, @@ -8323,12 +8336,6 @@ /obj/machinery/airalarm/directional/north, /turf/open/floor/iron/grimy, /area/station/service/chapel) -"bTc" = ( -/obj/structure/disposalpipe/segment, -/obj/effect/landmark/start/hangover, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/grimy, -/area/station/service/library/lounge) "bTe" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -11933,20 +11940,6 @@ }, /turf/open/floor/iron/grimy, /area/station/command/heads_quarters/hos) -"cLY" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron, -/area/station/maintenance/port) "cMf" = ( /obj/structure/cable, /obj/effect/turf_decal/trimline/red/filled/line{ @@ -13825,12 +13818,6 @@ /obj/machinery/duct, /turf/open/floor/iron/large, /area/station/hallway/secondary/exit/departure_lounge) -"dkM" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/turf/open/floor/carpet/executive, -/area/station/command/heads_quarters/blueshield) "dla" = ( /obj/effect/decal/cleanable/dirt, /obj/item/shard, @@ -14884,6 +14871,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/maintenance/port/aft) +"dzJ" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/radio/intercom/directional/east, +/obj/effect/mapping_helpers/burnt_floor, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/plating, +/area/station/commons/toilet/restrooms) "dAc" = ( /obj/effect/landmark/start/prisoner, /turf/open/floor/iron/dark/side, @@ -16311,6 +16305,13 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/lobby) +"dSj" = ( +/obj/effect/spawner/random/engineering/tracking_beacon, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/blobstart, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/science/research/abandoned) "dSm" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -17608,6 +17609,13 @@ }, /turf/open/floor/iron, /area/station/medical/medbay/lobby) +"eix" = ( +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/wood, +/area/station/security/detectives_office/private_investigators_office) "eiB" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -18012,6 +18020,14 @@ /obj/effect/turf_decal/trimline/purple/filled/warning, /turf/open/floor/iron/white, /area/station/science/research) +"eox" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/hangover, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/wood, +/area/station/commons/dorms) "eoy" = ( /obj/structure/cable, /obj/effect/spawner/structure/window/reinforced, @@ -18272,6 +18288,22 @@ "eqU" = ( /turf/open/space, /area/space) +"erf" = ( +/obj/effect/turf_decal/siding/dark_blue, +/obj/effect/turf_decal/siding/dark_blue{ + dir = 1 + }, +/obj/machinery/door/window/brigdoor/left/directional/east, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/carpet/neon/simple/blue/nodots, +/area/station/command/heads_quarters/blueshield) "erm" = ( /obj/structure/reagent_dispensers/plumbed{ dir = 4; @@ -18779,11 +18811,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/aft) -"ewy" = ( -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/grimy, -/area/station/service/abandoned_gambling_den) "ewQ" = ( /obj/machinery/atmospherics/pipe/smart/simple/cyan/hidden{ dir = 4 @@ -19349,6 +19376,20 @@ /obj/effect/turf_decal/tile/neutral/full, /turf/open/floor/iron/large, /area/station/hallway/secondary/exit/departure_lounge) +"eEA" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/blobstart, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron, +/area/station/maintenance/port) "eEH" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -21965,6 +22006,13 @@ /obj/effect/turf_decal/tile/blue/fourcorners, /turf/open/floor/iron, /area/station/medical/treatment_center) +"fiZ" = ( +/obj/effect/spawner/random/trash/garbage, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/iron, +/area/station/maintenance/department/crew_quarters/bar) "fjf" = ( /obj/structure/lattice/catwalk, /turf/open/space, @@ -22044,6 +22092,12 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/transit_tube) +"fkl" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/glass, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/fore) "fkm" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, /obj/machinery/rnd/server/master, @@ -23681,13 +23735,6 @@ /obj/machinery/status_display/evac/directional/south, /turf/open/floor/iron/white, /area/station/medical/chemistry) -"fEC" = ( -/obj/effect/spawner/random/trash/garbage, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/iron, -/area/station/maintenance/department/crew_quarters/bar) "fEI" = ( /obj/effect/spawner/structure/window/hollow/reinforced/directional{ dir = 9 @@ -24308,19 +24355,6 @@ /obj/effect/spawner/random/engineering/atmospherics_portable, /turf/open/floor/iron, /area/station/maintenance/department/medical/morgue) -"fMY" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/event_spawn, -/obj/structure/chair/stool/directional/west, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "fMZ" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -24959,6 +24993,14 @@ /obj/machinery/airalarm/directional/west, /turf/open/floor/carpet/black, /area/station/security/prison/safe) +"fUQ" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/structure/chair_maintenance, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/maintenance/port/fore) "fUU" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/effect/turf_decal/siding/yellow, @@ -26648,11 +26690,6 @@ }, /turf/open/floor/iron, /area/station/science/auxlab/firing_range) -"gpU" = ( -/obj/item/book/bible, -/obj/structure/altar_of_gods, -/turf/open/floor/iron/grimy, -/area/station/service/chapel) "gpY" = ( /obj/effect/turf_decal/trimline/neutral/warning{ dir = 4 @@ -27949,21 +27986,6 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) -"gED" = ( -/obj/effect/turf_decal/siding/dark_blue, -/obj/effect/turf_decal/siding/dark_blue{ - dir = 1 - }, -/obj/machinery/door/window/brigdoor/left/directional/east, -/obj/machinery/door/firedoor/border_only{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/carpet/neon/simple/blue/nodots, -/area/station/command/heads_quarters/blueshield) "gEF" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -28403,16 +28425,6 @@ }, /turf/open/floor/iron, /area/station/engineering/storage/tech) -"gJX" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/turf_decal/tile/yellow/fourcorners, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron, -/area/station/maintenance/port) "gJZ" = ( /obj/structure/cable, /obj/machinery/computer/records/security{ @@ -28848,6 +28860,11 @@ /obj/structure/cable, /turf/open/floor/iron/smooth, /area/station/maintenance/department/science/xenobiology) +"gPt" = ( +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/plating, +/area/station/commons/toilet/locker) "gPv" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -31285,6 +31302,14 @@ /obj/effect/turf_decal/trimline/blue/filled/line, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) +"huS" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/visible, +/obj/effect/spawner/random/engineering/tracking_beacon, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/mapping_helpers/burnt_floor, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron, +/area/station/maintenance/department/electrical) "huX" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/disposalpipe/segment{ @@ -33603,6 +33628,20 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/service/abandoned_gambling_den) +"hZi" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/landmark/blobstart, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/dark, +/area/station/service/abandoned_gambling_den/gaming) "hZl" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/morgue{ @@ -34277,19 +34316,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/dark, /area/station/hallway/secondary/service) -"ifg" = ( -/obj/machinery/door/airlock/corporate{ - name = "Blueshield's Quarters" - }, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/effect/turf_decal/siding/dark_blue/end{ - dir = 8 - }, -/obj/machinery/door/firedoor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/carpet/neon/simple/blue/nodots, -/area/station/command/heads_quarters/blueshield) "ifi" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/virology/glass{ @@ -34518,6 +34544,12 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/miningoffice) +"iiK" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/landmark/start/hangover, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/grimy, +/area/station/service/library/lounge) "iiP" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -43940,6 +43972,15 @@ /obj/structure/lattice/catwalk, /turf/open/space/basic, /area/space/nearstation) +"kss" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/blobstart, +/obj/machinery/duct, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/medical/abandoned) "ksy" = ( /obj/effect/turf_decal/tile/neutral/anticorner/contrasted{ dir = 8 @@ -44003,6 +44044,13 @@ dir = 8 }, /area/station/hallway/primary/fore) +"ktR" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/event_spawn, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/grimy, +/area/station/commons/vacant_room/office) "ktV" = ( /obj/structure/disposalpipe/sorting/mail{ dir = 4; @@ -44854,12 +44902,6 @@ }, /turf/open/floor/iron/white/textured, /area/station/medical/pathology) -"kEA" = ( -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/structure/table/wood/fancy, -/obj/item/book/bible, -/turf/open/floor/iron/dark, -/area/station/service/chapel/funeral) "kEJ" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, @@ -46235,11 +46277,6 @@ /obj/structure/ghost_critter_spawn, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) -"kWK" = ( -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/plating, -/area/station/commons/toilet/locker) "kWM" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -49234,6 +49271,13 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/aft) +"lGL" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/carpet/executive, +/area/station/command/heads_quarters/blueshield) "lGQ" = ( /obj/effect/spawner/random/structure/crate_loot, /obj/effect/turf_decal/bot, @@ -49375,6 +49419,17 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/cargo/warehouse) +"lIE" = ( +/obj/structure/cable, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/blobstart, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/department/electrical) "lII" = ( /obj/structure/chair/sofa/bench{ dir = 1 @@ -50017,19 +50072,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/medical/treatment_center) -"lPG" = ( -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/machinery/door/airlock/corporate{ - id_tag = "BSdoor"; - name = "Blueshield's Office" - }, -/obj/effect/turf_decal/siding/dark_blue/end, -/obj/machinery/door/firedoor, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/carpet/neon/simple/blue/nodots, -/area/station/command/heads_quarters/blueshield) "lPH" = ( /obj/structure/cable, /obj/effect/turf_decal/trimline/red/filled/line{ @@ -52212,6 +52254,19 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/fore) +"msI" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/blobstart, +/obj/effect/landmark/event_spawn, +/obj/structure/chair/stool/directional/west, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "msJ" = ( /obj/machinery/status_display/evac/directional/east, /obj/effect/turf_decal/stripes/line{ @@ -54628,6 +54683,11 @@ /obj/machinery/plumbing/ooze_compressor, /turf/open/floor/iron/dark, /area/station/science/xenobiology) +"mVi" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/grimy, +/area/station/service/abandoned_gambling_den) "mVo" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -55055,14 +55115,6 @@ }, /turf/open/floor/iron, /area/station/tcommsat/server) -"nay" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/visible, -/obj/effect/spawner/random/engineering/tracking_beacon, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/mapping_helpers/burnt_floor, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron, -/area/station/maintenance/department/electrical) "naB" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/siding/purple{ @@ -57997,15 +58049,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/engineering/atmos) -"nNl" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/structure/cable, -/obj/effect/turf_decal/siding/wood, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/stone, -/area/station/smithing) "nNq" = ( /obj/machinery/button/door/directional/east{ id = "Dorm5"; @@ -60721,6 +60764,11 @@ "oxo" = ( /turf/closed/wall/r_wall, /area/station/science/ordnance/freezerchamber) +"oxB" = ( +/obj/effect/turf_decal/siding/wood, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/sepia, +/area/station/service/library/artgallery) "oxD" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/blue, @@ -61775,12 +61823,6 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos/hfr_room) -"oLa" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/glass, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/fore) "oLd" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/green/visible, /obj/effect/decal/cleanable/dirt, @@ -62403,6 +62445,19 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/maintenance/department/chapel) +"oTo" = ( +/obj/machinery/door/airlock/corporate{ + id_tag = "BSdoor"; + name = "Blueshield's Office" + }, +/obj/effect/turf_decal/siding/dark_blue/end, +/obj/machinery/door/firedoor, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/carpet/neon/simple/blue/nodots, +/area/station/command/heads_quarters/blueshield) "oTs" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -64364,13 +64419,6 @@ /obj/structure/window/spawner/directional/east, /turf/open/floor/iron/dark/textured, /area/station/security/prison/workout) -"prG" = ( -/obj/effect/decal/cleanable/dirt, -/obj/item/radio/intercom/directional/east, -/obj/effect/mapping_helpers/burnt_floor, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/plating, -/area/station/commons/toilet/restrooms) "prJ" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -67614,16 +67662,6 @@ /obj/item/kirbyplants/random, /turf/open/floor/iron, /area/station/service/hydroponics) -"qdv" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/obj/structure/chair/wood{ - dir = 4 - }, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/service/theater/abandoned) "qdA" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/neutral{ @@ -67746,6 +67784,17 @@ }, /turf/open/floor/iron, /area/station/security/processing) +"qfe" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/brown{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/machinery/holopad, +/obj/machinery/firealarm/directional/south, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron, +/area/station/commons/vacant_room/commissary) "qfi" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -71708,14 +71757,6 @@ }, /turf/open/floor/plating, /area/station/science/ordnance/office) -"reX" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/hallway/secondary/construction) "rfd" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -73577,23 +73618,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/command) -"rBC" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/blobstart, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron, -/area/station/service/kitchen/abandoned) "rBI" = ( /obj/structure/window/reinforced/tinted/spawner/directional/east, /obj/machinery/computer/records/security, @@ -74902,6 +74926,15 @@ /obj/effect/turf_decal/siding/white/corner, /turf/open/floor/iron/freezer, /area/station/service/kitchen/coldroom) +"rQV" = ( +/obj/effect/landmark/blobstart, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/event_spawn, +/obj/machinery/growing/soil, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/service/hydroponics/garden/abandoned) "rRa" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -75071,6 +75104,12 @@ }, /turf/open/floor/iron/telecomms, /area/station/tcommsat/server) +"rSO" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/table/wood/fancy, +/obj/item/book/bible, +/turf/open/floor/iron/dark, +/area/station/service/chapel/funeral) "rSR" = ( /obj/machinery/portable_atmospherics/canister/plasma, /obj/effect/turf_decal/bot, @@ -79170,20 +79209,6 @@ }, /turf/open/floor/iron, /area/station/service/hydroponics/garden) -"sSO" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/dark, -/area/station/service/abandoned_gambling_den/gaming) "sTn" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -80834,14 +80859,6 @@ }, /turf/open/floor/iron, /area/station/cargo/quartermaster) -"tpF" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/random/structure/chair_maintenance, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/maintenance/port/fore) "tpI" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -81765,6 +81782,19 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/commons/locker) +"tBd" = ( +/obj/machinery/door/airlock/corporate{ + name = "Blueshield's Quarters" + }, +/obj/effect/turf_decal/siding/dark_blue/end{ + dir = 8 + }, +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/carpet/neon/simple/blue/nodots, +/area/station/command/heads_quarters/blueshield) "tBf" = ( /obj/effect/turf_decal/siding/wood{ dir = 6 @@ -85629,6 +85659,13 @@ }, /turf/open/floor/iron/white, /area/station/science/lobby) +"uwj" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/dark, +/area/station/service/electronic_marketing_den) "uwn" = ( /obj/structure/table/wood, /obj/item/storage/crayons, @@ -86966,13 +87003,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) -"uNj" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/event_spawn, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/grimy, -/area/station/commons/vacant_room/office) "uNx" = ( /obj/structure/table/wood, /obj/item/folder/blue{ @@ -87170,6 +87200,14 @@ }, /turf/open/floor/plating, /area/station/cargo/storage) +"uPq" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/hallway/secondary/construction) "uPx" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -87533,6 +87571,23 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/cargo/storage) +"uTz" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/blobstart, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron, +/area/station/service/kitchen/abandoned) "uTB" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -93030,6 +93085,11 @@ /obj/machinery/door/window/right/directional/south, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"wlj" = ( +/obj/item/book/bible, +/obj/structure/altar_of_gods, +/turf/open/floor/iron/grimy, +/area/station/service/chapel) "wlr" = ( /obj/machinery/holopad, /obj/effect/turf_decal/bot, @@ -93094,15 +93154,6 @@ dir = 1 }, /area/station/maintenance/disposal/incinerator) -"wlO" = ( -/obj/effect/landmark/blobstart, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/event_spawn, -/obj/machinery/growing/soil, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/service/hydroponics/garden/abandoned) "wlS" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/simple/purple/visible{ @@ -94411,17 +94462,6 @@ }, /turf/open/space/basic, /area/space/nearstation) -"wyX" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/brown{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/machinery/holopad, -/obj/machinery/firealarm/directional/south, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron, -/area/station/commons/vacant_room/commissary) "wza" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -96621,13 +96661,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/grimy, /area/station/command/heads_quarters/hop) -"xbI" = ( -/obj/effect/spawner/random/engineering/tracking_beacon, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/science/research/abandoned) "xbJ" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/command{ @@ -98743,13 +98776,6 @@ /obj/machinery/door/poddoor/massdriver_trash, /turf/open/floor/iron, /area/station/maintenance/disposal) -"xCZ" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/dark, -/area/station/service/electronic_marketing_den) "xDc" = ( /obj/effect/landmark/start/hangover, /obj/effect/decal/cleanable/dirt, @@ -99101,15 +99127,6 @@ /obj/structure/cable, /turf/open/floor/iron/white, /area/station/science/research) -"xGm" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/blobstart, -/obj/machinery/duct, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/medical/abandoned) "xGu" = ( /obj/structure/frame/machine{ anchored = 1 @@ -99911,13 +99928,6 @@ /obj/effect/landmark/generic_maintenance_landmark, /turf/open/floor/plating, /area/station/maintenance/department/science) -"xQH" = ( -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/wood, -/area/station/security/detectives_office/private_investigators_office) "xQM" = ( /obj/machinery/holopad, /obj/effect/turf_decal/bot, @@ -101563,14 +101573,6 @@ /obj/machinery/status_display/evac/directional/south, /turf/open/floor/iron, /area/station/commons/toilet/restrooms) -"ymf" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/hangover, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/wood, -/area/station/commons/dorms) "ymi" = ( /obj/machinery/light/directional/south, /obj/item/kirbyplants/random, @@ -122310,7 +122312,7 @@ cRJ mAt mAt pBY -ewy +mVi fUf hSE nsW @@ -127197,7 +127199,7 @@ nEc hrQ kGQ tWl -xbI +dSj bSN iFR lxM @@ -129986,7 +129988,7 @@ rgn pTC pFP pFP -cLY +eEA xbv owY pTC @@ -130251,7 +130253,7 @@ rrU vcB aEJ qcM -gJX +bcJ dMV qhC vcB @@ -130431,7 +130433,7 @@ aaa fIE qHI fLc -xCZ +uwj kzI iFV oYs @@ -130459,12 +130461,12 @@ uTq oYs kXS rTM -wlO +rQV kJr eAI oYs dqC -tpF +fUQ fKk oYs oYs @@ -130696,7 +130698,7 @@ bxg hcL mFH sLx -fMY +msI qDr oYs jjk @@ -131520,7 +131522,7 @@ ilo fdB aqF aqF -nNl +bIh kCi fdB jPf @@ -134028,7 +134030,7 @@ lWu tbC aHC jcT -prG +dzJ hcK vCw pst @@ -134069,7 +134071,7 @@ oyb xbi hRX hUO -uNj +ktR xIR vBc oYs @@ -137155,7 +137157,7 @@ wjO dOZ pwG nEd -dkM +lGL cdA diL uhH @@ -137411,7 +137413,7 @@ uMA wjO dOZ pwG -ifg +tBd siG siG diL @@ -137671,7 +137673,7 @@ kOj hPv jyy fDC -lPG +oTo vsW tFF wou @@ -138183,7 +138185,7 @@ otm dOZ pwG rBI -gED +erf hEC diL ipQ @@ -140227,7 +140229,7 @@ qAV fqn wwV fOP -fEC +fiZ dag tNa qAV @@ -143273,7 +143275,7 @@ jdL kvW uGx gPO -oLa +fkl uaz vkG iql @@ -145081,7 +145083,7 @@ vno jYU llB rxw -sSO +hZi tyU kvK sKC @@ -145842,7 +145844,7 @@ aeF vno nNs ffk -rBC +uTz egs vno rJN @@ -146442,7 +146444,7 @@ gbt hgJ mRh gMM -wyX +qfe tXA nhI nGZ @@ -146471,7 +146473,7 @@ qkj qMf vaE rKL -xQH +eix cjs hJo kfb @@ -147780,7 +147782,7 @@ rMa sDJ rMa iVt -gpU +wlj slr oQM mmM @@ -147983,7 +147985,7 @@ crR szQ iYi bjs -kWK +gPt bEK iYi iYi @@ -148260,7 +148262,7 @@ jEN teU kcv gZU -aTZ +oxB uNf qMf wBF @@ -148782,7 +148784,7 @@ xPK wZE eSU haQ -nay +huS pdb hnH nvM @@ -150082,7 +150084,7 @@ kZc kZc igI qKs -kEA +rSO kRC niE tVD @@ -150324,7 +150326,7 @@ bqS rlw wMj hth -aYG +lIE fZh gmD krx @@ -150572,7 +150574,7 @@ hvm cao gDV aXW -bTc +iiK ajP eLz qMh @@ -152886,7 +152888,7 @@ fPt opZ wEM uen -xGm +kss klE ayA tHd @@ -152894,7 +152896,7 @@ ujU ehy cfR rvu -reX +uPq mIc iFL waI @@ -152905,7 +152907,7 @@ iNE lXm pcc prr -qdv +bnN xnT usy oLT @@ -153890,7 +153892,7 @@ vHY hie qbZ riK -ymf +eox kvM yaI wgE diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index e59a7523e8be..87f88a4b72be 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -2053,18 +2053,6 @@ /obj/effect/turf_decal/tile/blue/opposingcorners, /turf/open/floor/iron/dark, /area/station/command/gateway) -"aJo" = ( -/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/corporate{ - id_tag = "BSdoor"; - name = "Blueshield's Office" - }, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/effect/landmark/navigate_destination, -/turf/open/floor/carpet, -/area/station/command/heads_quarters/blueshield) "aJr" = ( /obj/effect/turf_decal/trimline/yellow/filled/corner{ dir = 4 @@ -2155,15 +2143,6 @@ /obj/machinery/holopad, /turf/open/floor/iron/large, /area/station/commons/storage/tools) -"aKA" = ( -/obj/structure/grille/broken, -/obj/effect/spawner/random/maintenance, -/obj/effect/decal/cleanable/generic, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "aKG" = ( /obj/structure/table, /turf/open/floor/iron/smooth, @@ -3027,14 +3006,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/department/medical/pathology) -"aZg" = ( -/obj/effect/decal/cleanable/glass, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/cafeteria{ - dir = 5 - }, -/area/station/maintenance/port/aft) "aZk" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -6306,13 +6277,6 @@ /obj/effect/spawner/structure/window/reinforced/tinted, /turf/open/floor/iron/dark, /area/station/service/chapel) -"bWv" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/blobstart, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "bWB" = ( /obj/structure/table, /obj/effect/decal/cleanable/cobweb/cobweb2, @@ -6600,6 +6564,13 @@ /obj/machinery/camera/emp_proof/directional/north, /turf/open/floor/iron/cafeteria, /area/station/commons/dorms/laundry) +"caf" = ( +/obj/machinery/light/directional/west, +/obj/item/radio/intercom/directional/west, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/freezer, +/area/station/commons/toilet/locker) "caC" = ( /obj/machinery/door/window/right/directional/south{ dir = 8; @@ -6908,13 +6879,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/iron/dark, /area/station/service/chapel/office) -"cfb" = ( -/obj/machinery/light/directional/west, -/obj/item/radio/intercom/directional/west, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/freezer, -/area/station/commons/toilet/locker) "cfe" = ( /obj/structure/cable, /obj/machinery/holopad/secure, @@ -7283,10 +7247,6 @@ /obj/effect/turf_decal/tile/yellow/opposingcorners, /turf/open/floor/iron/white, /area/station/maintenance/port/fore) -"ckY" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "cll" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -8483,6 +8443,12 @@ /obj/structure/flora/tree/pine/style_random, /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/underground/explored) +"cCc" = ( +/obj/effect/decal/cleanable/plasma, +/obj/effect/landmark/blobstart, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "cCt" = ( /obj/structure/rack, /obj/effect/spawner/random/techstorage/rnd_all, @@ -8661,11 +8627,6 @@ /obj/item/radio/intercom/directional/north, /turf/open/floor/iron/smooth_edge, /area/station/security/lockers) -"cFm" = ( -/obj/structure/table/glass, -/obj/item/book/bible, -/turf/open/floor/iron/chapel, -/area/station/service/chapel) "cFJ" = ( /obj/effect/spawner/random/structure/steam_vent, /turf/open/floor/plating, @@ -9322,6 +9283,11 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/medical/morgue) +"cOv" = ( +/obj/structure/table/wood, +/obj/item/book/bible, +/turf/open/floor/iron/dark, +/area/station/service/chapel/office) "cOz" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/airalarm/directional/north, @@ -9802,11 +9768,6 @@ /obj/effect/turf_decal/arrows, /turf/open/floor/iron, /area/station/cargo/lobby) -"cXj" = ( -/obj/structure/table/wood, -/obj/item/book/bible, -/turf/open/floor/iron/dark, -/area/station/service/chapel/office) "cXl" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -9977,11 +9938,6 @@ "cZD" = ( /turf/open/floor/iron/checker, /area/station/maintenance/port/fore) -"cZE" = ( -/obj/effect/spawner/random/trash/mess, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "cZN" = ( /obj/structure/table/wood, /obj/item/soap/nanotrasen, @@ -10715,13 +10671,6 @@ /obj/effect/landmark/navigate_destination/atmos, /turf/open/floor/iron, /area/station/engineering/lobby) -"djT" = ( -/obj/structure/table/wood, -/obj/machinery/airalarm/directional/north, -/obj/item/book/bible, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/station/service/chapel) "djU" = ( /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, /turf/open/floor/iron, @@ -10992,14 +10941,6 @@ /obj/structure/tank_holder/extinguisher, /turf/open/floor/plating, /area/station/maintenance/department/medical/morgue) -"dpt" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/iron, -/area/station/maintenance/starboard/upper) "dpB" = ( /obj/machinery/firealarm/directional/south, /obj/effect/turf_decal/trimline/yellow/filled/line, @@ -12057,6 +11998,14 @@ /obj/effect/decal/cleanable/food/egg_smudge, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"dGH" = ( +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/iron, +/area/station/maintenance/starboard/upper) "dGK" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -12523,6 +12472,19 @@ }, /turf/open/floor/iron, /area/station/cargo/miningdock) +"dPC" = ( +/obj/item/flashlight/flare/candle{ + pixel_x = -7; + pixel_y = 3 + }, +/obj/item/book{ + name = "Tales from the First"; + pixel_x = 5; + pixel_y = 5 + }, +/obj/structure/table/wood, +/turf/open/floor/plating, +/area/station/maintenance/starboard/lesser) "dPP" = ( /obj/structure/closet/toolcloset, /turf/open/floor/plating, @@ -12545,6 +12507,13 @@ dir = 1 }, /area/station/maintenance/department/cargo) +"dQA" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/blobstart, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "dQI" = ( /obj/effect/landmark/start/assistant, /obj/effect/turf_decal/tile/neutral/half/contrasted{ @@ -12567,11 +12536,6 @@ /obj/structure/sign/departments/rndserver/directional/south, /turf/open/floor/iron/white, /area/station/science/research) -"dQV" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron, -/area/station/maintenance/starboard/fore) "dRc" = ( /obj/structure/table, /obj/machinery/firealarm/directional/west, @@ -16853,6 +16817,11 @@ }, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"fli" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron, +/area/station/maintenance/starboard/fore) "flx" = ( /obj/machinery/navbeacon{ codes_txt = "patrol;next_patrol=HOP"; @@ -18420,6 +18389,13 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/station/maintenance/starboard/upper) +"fMr" = ( +/obj/structure/table/wood, +/obj/machinery/airalarm/directional/north, +/obj/item/book/bible, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/turf/open/floor/iron/dark, +/area/station/service/chapel) "fMJ" = ( /obj/structure/chair{ dir = 1 @@ -18806,6 +18782,14 @@ "fUR" = ( /turf/closed/wall, /area/station/hallway/secondary/entry) +"fVd" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 8 + }, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/stone, +/area/station/smithing) "fVm" = ( /obj/machinery/door/airlock/maintenance{ name = "Chemical Storage" @@ -19079,6 +19063,13 @@ }, /turf/open/floor/iron, /area/station/command/gateway) +"gal" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/duct, +/obj/structure/cable, +/turf/open/floor/iron/white/textured, +/area/station/security/medical) "gam" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/mining/glass{ @@ -20341,6 +20332,15 @@ dir = 1 }, /area/mine/eva/lower) +"gtD" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/catwalk_floor/iron_smooth, +/area/station/maintenance/department/chapel) "gtF" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -22328,14 +22328,6 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/general, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"hch" = ( -/obj/item/book/bible, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/table/wood, -/turf/open/floor/iron/dark, -/area/station/security/prison/rec) "hcv" = ( /obj/machinery/newscaster/directional/north, /obj/effect/turf_decal/tile/neutral{ @@ -22719,6 +22711,13 @@ /obj/effect/mapping_helpers/airalarm/mixingchamber_access, /turf/open/floor/iron/dark, /area/station/science/ordnance/freezerchamber) +"hjA" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/yellow/opposingcorners, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/white, +/area/station/maintenance/port/fore) "hjE" = ( /turf/closed/wall/r_wall, /area/station/science/explab) @@ -24610,6 +24609,10 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron/dark/smooth_corner, /area/station/ai_monitored/command/storage/eva) +"hSn" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "hSp" = ( /obj/effect/turf_decal/stripes/line, /obj/structure/table/reinforced, @@ -24649,6 +24652,14 @@ /obj/machinery/newscaster/directional/south, /turf/open/floor/iron, /area/station/security/processing) +"hSY" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron, +/area/station/maintenance/port/aft) "hSZ" = ( /obj/structure/cable, /obj/effect/turf_decal/trimline/dark_blue/line{ @@ -26315,15 +26326,6 @@ }, /turf/open/floor/iron, /area/station/service/hydroponics) -"iuI" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/wood, -/area/station/service/library) "iuQ" = ( /obj/structure/cable, /obj/machinery/door/airlock/glass{ @@ -26421,14 +26423,6 @@ /obj/structure/railing, /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/underground/explored) -"ixg" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/catwalk_floor/iron_smooth, -/area/station/maintenance/fore/lesser) "ixu" = ( /obj/machinery/camera/directional/north{ c_tag = "Teleporter" @@ -27453,12 +27447,6 @@ }, /turf/open/floor/iron/dark, /area/station/medical/morgue) -"iOr" = ( -/obj/structure/chair/comfy/teal{ - dir = 4 - }, -/turf/open/floor/carpet/cyan, -/area/station/command/heads_quarters/blueshield) "iOs" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/airalarm/directional/south, @@ -27624,12 +27612,6 @@ }, /turf/open/floor/iron/white/side, /area/mine/living_quarters) -"iQy" = ( -/obj/effect/decal/cleanable/plasma, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "iQF" = ( /obj/effect/turf_decal/trimline/yellow/filled/line, /obj/machinery/airalarm/directional/south, @@ -27700,13 +27682,6 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/security/checkpoint/engineering) -"iRu" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/yellow/opposingcorners, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/white, -/area/station/maintenance/port/fore) "iRx" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -28405,6 +28380,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/security/courtroom) +"jbM" = ( +/obj/effect/landmark/event_spawn, +/obj/effect/turf_decal/tile/blue/opposingcorners{ + dir = 1 + }, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/cafeteria, +/area/station/commons/dorms/laundry) "jbT" = ( /obj/structure/cable, /obj/effect/spawner/structure/window/reinforced, @@ -28566,11 +28549,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/wood, /area/station/service/lawoffice) -"jfb" = ( -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/maintenance/fore) "jfc" = ( /turf/closed/wall, /area/station/command/heads_quarters/hop) @@ -30753,15 +30731,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/security/brig/entrance) -"jRa" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/catwalk_floor/iron_smooth, -/area/station/maintenance/department/chapel) "jRu" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -31829,14 +31798,6 @@ /obj/item/kirbyplants/random, /turf/open/floor/iron, /area/station/hallway/primary/starboard) -"khD" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron, -/area/station/maintenance/port/aft) "khE" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -33076,13 +33037,6 @@ /obj/machinery/duct, /turf/open/floor/iron/white/textured, /area/station/security/medical) -"kBE" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/item/book/bible, -/obj/structure/altar_of_gods, -/turf/open/floor/iron/dark, -/area/station/service/chapel) "kBL" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 1 @@ -35619,6 +35573,14 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron/dark, /area/station/service/chapel) +"lqp" = ( +/obj/structure/chair/plastic{ + dir = 0 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/iron, +/area/station/maintenance/starboard/fore) "lqs" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -37113,6 +37075,15 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/textured, /area/mine/mechbay) +"lQi" = ( +/obj/structure/grille/broken, +/obj/effect/spawner/random/maintenance, +/obj/effect/decal/cleanable/generic, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/blobstart, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "lQm" = ( /obj/structure/cable, /turf/open/floor/iron, @@ -39157,6 +39128,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/commons/fitness) +"mAI" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/item/book/bible, +/obj/structure/altar_of_gods, +/turf/open/floor/iron/dark, +/area/station/service/chapel) "mAO" = ( /obj/structure/cable, /turf/open/floor/carpet, @@ -40277,14 +40255,6 @@ /obj/effect/mapping_helpers/airlock/access/any/science/maintenance, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) -"mUx" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/wood, -/area/station/maintenance/aft/greater) "mUM" = ( /obj/item/radio/intercom/directional/north, /obj/effect/turf_decal/tile/red/anticorner{ @@ -41064,6 +41034,11 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/fore) +"ngd" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/maintenance/fore) "ngj" = ( /obj/effect/turf_decal/stripes/asteroid/line{ dir = 9 @@ -43046,12 +43021,6 @@ /obj/structure/barricade/wooden, /turf/open/floor/eighties/red, /area/station/security/prison/safe) -"nIh" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/obj/structure/cable, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/department/crew_quarters/bar) "nIl" = ( /obj/structure/chair/stool/directional/north, /obj/effect/turf_decal/tile/red/half/contrasted{ @@ -45601,6 +45570,13 @@ /obj/machinery/newscaster/directional/east, /turf/open/floor/iron, /area/station/security/prison/workout) +"owm" = ( +/obj/structure/chair/comfy/teal{ + dir = 4 + }, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/carpet/cyan, +/area/station/command/heads_quarters/blueshield) "owC" = ( /turf/closed/wall/r_wall, /area/station/science/server) @@ -49073,6 +49049,14 @@ /obj/machinery/requests_console/auto_name/directional/north, /turf/open/floor/iron, /area/station/service/hydroponics) +"pBv" = ( +/obj/item/book/bible, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/table/wood, +/turf/open/floor/iron/dark, +/area/station/security/prison/rec) "pBA" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -49331,6 +49315,14 @@ /obj/effect/spawner/random/engineering/tracking_beacon, /turf/open/floor/stone, /area/station/smithing) +"pFX" = ( +/obj/effect/decal/cleanable/glass, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/cafeteria{ + dir = 5 + }, +/area/station/maintenance/port/aft) "pFZ" = ( /obj/item/target/syndicate, /obj/effect/decal/cleanable/dirt, @@ -49762,6 +49754,12 @@ }, /turf/open/floor/iron/freezer, /area/station/commons/toilet/locker) +"pLC" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/obj/structure/cable, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/department/crew_quarters/bar) "pLO" = ( /obj/machinery/status_display/evac/directional/east, /obj/structure/cable, @@ -50471,6 +50469,18 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/engineering/atmos) +"pYs" = ( +/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/corporate{ + id_tag = "BSdoor"; + name = "Blueshield's Office" + }, +/obj/effect/landmark/navigate_destination, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/carpet, +/area/station/command/heads_quarters/blueshield) "pYz" = ( /obj/machinery/door/firedoor/border_only, /turf/open/floor/iron/dark/corner{ @@ -53324,6 +53334,14 @@ }, /turf/open/floor/iron/dark/textured, /area/station/engineering/main) +"qWB" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/wood, +/area/station/maintenance/aft/greater) "qWD" = ( /obj/machinery/duct, /turf/open/floor/iron/white, @@ -54399,19 +54417,6 @@ /obj/effect/turf_decal/tile/brown/half/contrasted, /turf/open/floor/iron/dark/side, /area/mine/eva/lower) -"rnD" = ( -/obj/item/flashlight/flare/candle{ - pixel_x = -7; - pixel_y = 3 - }, -/obj/item/book{ - name = "Tales from the First"; - pixel_x = 5; - pixel_y = 5 - }, -/obj/structure/table/wood, -/turf/open/floor/plating, -/area/station/maintenance/starboard/lesser) "rnQ" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -58068,14 +58073,6 @@ /obj/effect/turf_decal/trimline/blue/corner, /turf/open/floor/iron/dark, /area/station/service/hydroponics) -"syN" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/obj/effect/turf_decal/siding/wood/corner{ - dir = 8 - }, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/stone, -/area/station/smithing) "syW" = ( /obj/effect/spawner/structure/window/hollow/reinforced/end, /turf/open/floor/plating, @@ -59316,6 +59313,14 @@ /obj/machinery/light_switch/directional/north, /turf/open/floor/iron/freezer, /area/station/commons/toilet/locker) +"sVF" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/catwalk_floor/iron_smooth, +/area/station/maintenance/fore/lesser) "sVL" = ( /obj/machinery/holopad, /obj/effect/turf_decal/bot, @@ -60838,14 +60843,6 @@ }, /turf/open/floor/iron/smooth_half, /area/station/security/brig/upper) -"txX" = ( -/obj/structure/chair/plastic{ - dir = 0 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/iron, -/area/station/maintenance/starboard/fore) "tyb" = ( /obj/effect/turf_decal/bot, /obj/machinery/holopad, @@ -61900,6 +61897,11 @@ }, /turf/open/floor/iron, /area/station/command/gateway) +"tOp" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/iron, +/area/station/construction) "tOq" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -66954,11 +66956,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/service) -"vxC" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/iron, -/area/station/construction) "vxV" = ( /obj/structure/cable, /obj/machinery/duct, @@ -67654,6 +67651,15 @@ }, /turf/open/floor/iron/white/smooth_large, /area/station/medical/chemistry) +"vHS" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/wood, +/area/station/service/library) "vHT" = ( /obj/effect/spawner/random/trash/mess, /obj/item/storage/box, @@ -70305,14 +70311,6 @@ }, /turf/closed/wall, /area/station/cargo/sorting) -"wBH" = ( -/obj/effect/landmark/event_spawn, -/obj/effect/turf_decal/tile/blue/opposingcorners{ - dir = 1 - }, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/cafeteria, -/area/station/commons/dorms/laundry) "wBS" = ( /obj/structure/table/wood, /obj/machinery/light/directional/west, @@ -70660,13 +70658,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"wGM" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/duct, -/obj/structure/cable, -/turf/open/floor/iron/white/textured, -/area/station/security/medical) "wGN" = ( /obj/machinery/corral_corner{ mapping_id = "2" @@ -70931,6 +70922,11 @@ }, /turf/open/floor/iron, /area/station/command/bridge) +"wKO" = ( +/obj/effect/spawner/random/trash/mess, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "wLk" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers, /obj/machinery/portable_atmospherics/canister/carbon_dioxide, @@ -73649,6 +73645,11 @@ /obj/machinery/nuclearbomb/beer, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"xCG" = ( +/obj/structure/table/glass, +/obj/item/book/bible, +/turf/open/floor/iron/chapel, +/area/station/service/chapel) "xCQ" = ( /obj/structure/table/glass, /obj/item/reagent_containers/cup/beaker/cryoxadone{ @@ -100663,7 +100664,7 @@ hPk bwi vyO dEz -hch +pBv hOA mJX cmh @@ -159564,7 +159565,7 @@ iwS iJM iEh tDG -wBH +jbM xwG qMo iDt @@ -163651,7 +163652,7 @@ qQf qQf qQf fro -ixg +sVF tym jur vqi @@ -173210,7 +173211,7 @@ thA nxM imi nJd -aKA +lQi qck eJI nxM @@ -176556,7 +176557,7 @@ pHD qMz hjM xDU -iQy +cCc sBJ vLY qck @@ -177551,7 +177552,7 @@ fWU aak dMS vJL -nIh +pLC qqC oYx nCJ @@ -179133,7 +179134,7 @@ rmh ieF qHl rwG -bWv +dQA skJ owG hjM @@ -182430,7 +182431,7 @@ jre jre jre jre -rnD +dPC aCo hMw jre @@ -185243,7 +185244,7 @@ thA xMq tBs pwv -jRa +gtD yaP tBs nHQ @@ -187301,7 +187302,7 @@ pxg eRc tBs deP -cXj +cOv pQw cBP wAv @@ -188081,7 +188082,7 @@ aIe wBA uJq smC -kBE +mAI hMr aUO aUO @@ -188850,7 +188851,7 @@ lry oTA hlS wrX -djT +fMr wBA oTA bAF @@ -220985,7 +220986,7 @@ egK nwT ccD aCJ -syN +fVd nsr xSl tKI @@ -223816,7 +223817,7 @@ tOw sVn wlt kEM -cfb +caf kEM vkW kEM @@ -225072,7 +225073,7 @@ qDI xQB whv rSe -iRu +hjA ckQ xJD lJO @@ -226943,7 +226944,7 @@ hjH pRj wwC rlj -aZg +pFX aPV gFH apj @@ -227451,7 +227452,7 @@ ujj pRj xoB hjH -khD +hSY dNC xBX pRj @@ -232813,7 +232814,7 @@ gfr fnv pPM fjt -aJo +pYs umE ujA eYd @@ -233072,7 +233073,7 @@ fsG ktU wxu dVc -iOr +owm yhH usN jfc @@ -234126,7 +234127,7 @@ mZV paM bbo oKY -vxC +tOp iXk hHD pRj @@ -236621,7 +236622,7 @@ bxQ bUx vSh kBx -wGM +gal bui hfg lUw @@ -239203,7 +239204,7 @@ skl skl skl nTK -jfb +ngd cIK jOQ skl @@ -246412,7 +246413,7 @@ kKL kKL kKL kKL -txX +lqp dqy kKL lli @@ -246737,7 +246738,7 @@ cpl npD fWL qUM -mUx +qWB asN xhZ sZF @@ -250513,7 +250514,7 @@ bln bln kKL xpE -cZE +wKO wMT kKL lli @@ -250528,7 +250529,7 @@ kKL gkP kKL sqs -iuI +vHS ogd hff blV @@ -252826,7 +252827,7 @@ bln iyY jLc sEY -dQV +fli rEX rCf rCf @@ -254899,7 +254900,7 @@ oHH tAA efH mJu -cFm +xCG qPL qPL qPL @@ -255985,7 +255986,7 @@ rDZ pcX bgx jCl -ckY +hSn jCl vzD geJ @@ -258527,7 +258528,7 @@ mLJ opn vJk vJk -dpt +dGH vJk vJk qbW diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm index 82d5b0b16afd..248775bfc7eb 100644 --- a/_maps/map_files/KiloStation/KiloStation.dmm +++ b/_maps/map_files/KiloStation/KiloStation.dmm @@ -494,6 +494,11 @@ /obj/machinery/atmospherics/pipe/smart/simple/yellow/visible, /turf/closed/wall/rust, /area/station/engineering/atmos) +"aeN" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/dark/textured, +/area/station/maintenance/starboard/fore) "aeS" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -2314,22 +2319,6 @@ /obj/structure/cable, /turf/open/floor/engine, /area/station/ai_monitored/turret_protected/aisat_interior) -"aKQ" = ( -/obj/structure/railing{ - dir = 8 - }, -/obj/structure/table/wood/fancy/black, -/obj/item/book/bible{ - pixel_x = 6; - pixel_y = 6 - }, -/obj/item/book/bible{ - pixel_x = -6; - pixel_y = 6 - }, -/obj/item/book/bible, -/turf/open/floor/iron/dark, -/area/station/service/chapel) "aKY" = ( /obj/structure/sign/warning/electric_shock, /turf/closed/wall/r_wall, @@ -2701,20 +2690,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/engineering/atmos) -"aSP" = ( -/obj/structure/table/wood, -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/effect/turf_decal/siding/wood/corner{ - dir = 8 - }, -/obj/machinery/door/firedoor/border_only{ - dir = 4 - }, -/obj/item/book/bible, -/turf/open/floor/carpet/red, -/area/station/service/chapel) "aSX" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -5286,6 +5261,12 @@ }, /turf/open/space/basic, /area/space) +"bNu" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/showroomfloor, +/area/station/commons/toilet/restrooms) "bNv" = ( /obj/machinery/telecomms/server/presets/common, /obj/machinery/light/directional/west, @@ -6312,6 +6293,20 @@ dir = 4 }, /area/station/service/chapel) +"cbO" = ( +/obj/structure/table/wood, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 1 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/item/book/bible, +/turf/open/floor/carpet/red, +/area/station/service/chapel) "ccd" = ( /obj/structure/railing{ dir = 4 @@ -6742,6 +6737,21 @@ }, /turf/open/floor/iron/recharge_floor, /area/station/maintenance/port/aft) +"cgW" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/firedoor, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable, +/obj/machinery/door/airlock/corporate{ + id_tag = "BSdoor"; + name = "Blueshield's Office" + }, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/iron/dark, +/area/station/command/heads_quarters/blueshield) "cgX" = ( /obj/structure/rack, /obj/item/wirecutters{ @@ -12167,6 +12177,18 @@ }, /turf/open/floor/iron/showroomfloor, /area/station/security/execution/transfer) +"dTO" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/siding/wood, +/obj/structure/cable, +/obj/machinery/power/apc/auto_name/directional/south, +/obj/structure/chair/comfy/teal{ + dir = 4 + }, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/wood/large, +/area/station/command/heads_quarters/blueshield) "dTQ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/tile/yellow/half/contrasted, @@ -12529,6 +12551,14 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos/pumproom) +"eaB" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/hallway/primary/central/fore) "eaQ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/stripes/line{ @@ -12687,11 +12717,6 @@ }, /turf/open/floor/iron/showroomfloor, /area/station/science/genetics) -"edF" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/generic, -/turf/open/floor/plating, -/area/station/maintenance/department/bridge) "eeb" = ( /obj/effect/turf_decal/tile/blue{ dir = 8 @@ -13173,6 +13198,12 @@ /obj/effect/turf_decal/tile/neutral/half/contrasted, /turf/open/floor/iron/dark, /area/station/maintenance/department/crew_quarters/bar) +"elc" = ( +/obj/effect/landmark/event_spawn, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/maintenance/starboard/fore) "ele" = ( /obj/structure/table/wood, /obj/machinery/door/firedoor, @@ -13292,17 +13323,6 @@ /obj/machinery/door/poddoor/incinerator_atmos_aux, /turf/open/floor/engine, /area/station/maintenance/disposal/incinerator) -"emV" = ( -/obj/machinery/door/poddoor/preopen{ - id = "Biohazard"; - name = "Emergency Research Blast Door" - }, -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/caution/stand_clear, -/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/science/research) "eng" = ( /obj/effect/turf_decal/tile/green, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -13954,6 +13974,10 @@ /obj/structure/closet/emcloset, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"eyl" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/maintenance/port/fore) "eyv" = ( /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -14203,6 +14227,17 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/cargo/warehouse) +"eCI" = ( +/obj/machinery/asteroid_magnet{ + center_x = 176; + center_y = 174; + area_size = 3 + }, +/obj/effect/turf_decal/tile/purple/half/contrasted{ + dir = 1 + }, +/turf/open/floor/iron/showroomfloor, +/area/station/science/explab) "eCU" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -18145,6 +18180,12 @@ }, /turf/open/floor/grass, /area/station/science/genetics) +"fJr" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/start/gary, +/turf/open/floor/carpet/green, +/area/station/maintenance/port/greater) "fJs" = ( /obj/machinery/door/airlock/external{ name = "Labor Camp Shuttle Airlock"; @@ -20088,6 +20129,11 @@ /obj/machinery/digital_clock/directional/south, /turf/open/floor/iron/dark, /area/station/hallway/secondary/exit/departure_lounge) +"gpk" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/plastic, +/area/station/maintenance/starboard/fore) "gpz" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, @@ -20466,18 +20512,6 @@ /obj/effect/turf_decal/tile/red, /turf/open/floor/iron, /area/station/engineering/lobby) -"guY" = ( -/obj/machinery/navbeacon{ - codes_txt = "patrol;next_patrol=Upload"; - location = "Science"; - name = "science navigation beacon" - }, -/obj/structure/cable, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron, -/area/station/hallway/primary/central/fore) "gva" = ( /obj/structure/grille, /turf/closed/wall/r_wall/rust, @@ -21338,6 +21372,22 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/engine, /area/station/engineering/gravity_generator) +"gJw" = ( +/obj/structure/railing{ + dir = 8 + }, +/obj/structure/table/wood/fancy/black, +/obj/item/book/bible{ + pixel_x = 6; + pixel_y = 6 + }, +/obj/item/book/bible{ + pixel_x = -6; + pixel_y = 6 + }, +/obj/item/book/bible, +/turf/open/floor/iron/dark, +/area/station/service/chapel) "gJE" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/stripes/line, @@ -26187,6 +26237,11 @@ }, /turf/open/floor/iron/dark, /area/station/service/janitor) +"igx" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/generic, +/turf/open/floor/plating, +/area/station/maintenance/department/bridge) "igz" = ( /obj/structure/sink/directional/west, /obj/effect/turf_decal/stripes/corner, @@ -26293,17 +26348,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/office) -"iiM" = ( -/obj/machinery/asteroid_magnet{ - center_x = 176; - center_y = 174; - area_size = 3 - }, -/obj/effect/turf_decal/tile/purple/half/contrasted{ - dir = 1 - }, -/turf/open/floor/iron/showroomfloor, -/area/station/science/explab) "ijc" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -26545,6 +26589,18 @@ }, /turf/open/floor/iron/showroomfloor, /area/station/medical/chemistry) +"imc" = ( +/obj/machinery/navbeacon{ + codes_txt = "patrol;next_patrol=Upload"; + location = "Science"; + name = "science navigation beacon" + }, +/obj/structure/cable, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/hallway/primary/central/fore) "imh" = ( /turf/closed/wall/r_wall, /area/station/security/checkpoint/medical) @@ -31524,6 +31580,20 @@ /obj/structure/flora/bush/ferny/style_random, /turf/open/misc/asteroid, /area/space/nearstation) +"jJr" = ( +/obj/structure/table/wood, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 8 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/item/book/bible, +/turf/open/floor/carpet/red, +/area/station/service/chapel) "jJB" = ( /obj/structure/cable, /obj/effect/landmark/start/hangover, @@ -32886,16 +32956,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/stone, /area/station/science/xenobiology) -"kio" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 1 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/hangover, -/obj/effect/turf_decal/tile/neutral/opposingcorners, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/dark, -/area/station/service/library) "kir" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, @@ -34545,6 +34605,12 @@ }, /turf/closed/wall, /area/station/hallway/primary/central) +"kKX" = ( +/obj/effect/turf_decal/bot, +/obj/machinery/holopad, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/wood/large, +/area/station/command/heads_quarters/blueshield) "kLa" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -38034,6 +38100,16 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron/dark, /area/station/security/processing) +"lSa" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/hangover, +/obj/effect/turf_decal/tile/neutral/opposingcorners, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/dark, +/area/station/service/library) "lSs" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -38852,11 +38928,6 @@ /obj/structure/flora/bush/flowers_yw/style_random, /turf/open/floor/grass, /area/station/medical/pathology) -"mgq" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/plastic, -/area/station/maintenance/starboard/fore) "mgx" = ( /obj/structure/bookcase/random/nonfiction, /obj/machinery/computer/security/telescreen/entertainment/directional/north, @@ -41403,12 +41474,6 @@ /obj/machinery/disease2/centrifuge, /turf/open/floor/iron/dark, /area/station/medical/pathology) -"mVK" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/showroomfloor, -/area/station/commons/toilet/restrooms) "mVL" = ( /obj/structure/rack, /obj/effect/turf_decal/bot, @@ -42865,27 +42930,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/aft) -"nuv" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/start/gary, -/turf/open/floor/carpet/green, -/area/station/maintenance/port/greater) -"nuz" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/firedoor, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable, -/obj/machinery/door/airlock/corporate{ - id_tag = "BSdoor"; - name = "Blueshield's Office" - }, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/turf/open/floor/iron/dark, -/area/station/command/heads_quarters/blueshield) "nuF" = ( /obj/item/radio/intercom/directional/north, /obj/machinery/vending/cigarette, @@ -43284,6 +43328,14 @@ /obj/effect/turf_decal/stripes/corner, /turf/open/floor/engine, /area/station/ai_monitored/turret_protected/aisat/atmos) +"nAE" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/event_spawn, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/department/bridge) "nAH" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -43579,11 +43631,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/commons/storage/primary) -"nFt" = ( -/obj/effect/turf_decal/bot, -/obj/machinery/holopad, -/turf/open/floor/wood/large, -/area/station/command/heads_quarters/blueshield) "nFu" = ( /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -44115,6 +44162,20 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark/textured, /area/station/maintenance/starboard/fore) +"nMY" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/blood/gibs/limb, +/obj/effect/landmark/event_spawn, +/obj/structure/cable, +/obj/effect/decal/cleanable/blood/tracks{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard) "nNb" = ( /obj/structure/lattice/catwalk, /turf/open/space/basic, @@ -44545,15 +44606,6 @@ }, /turf/open/floor/iron/dark/herringbone, /area/station/security/prison) -"nVX" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/event_spawn, -/obj/effect/spawner/random/trash/mess, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/department/crew_quarters/bar) "nWg" = ( /obj/item/radio/intercom/directional/east, /obj/effect/turf_decal/siding/purple/corner{ @@ -46289,12 +46341,6 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/main) -"oCp" = ( -/obj/effect/landmark/event_spawn, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/maintenance/starboard/fore) "oCt" = ( /obj/machinery/airalarm/directional/east, /obj/structure/cable, @@ -46767,14 +46813,6 @@ /obj/structure/lattice, /turf/open/space/basic, /area/space/nearstation) -"oLF" = ( -/obj/structure/cable, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/event_spawn, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/department/bridge) "oLG" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/stripes/line, @@ -55786,6 +55824,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/security/processing) +"ryL" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/dark, +/area/station/maintenance/starboard) "ryW" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -56811,20 +56858,6 @@ }, /turf/open/floor/iron/dark, /area/station/science/research) -"rPW" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/dark, -/area/station/maintenance/starboard) -"rQo" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/dark/textured, -/area/station/maintenance/starboard/fore) "rQC" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/effect/decal/cleanable/dirt, @@ -58236,14 +58269,6 @@ /obj/machinery/light/directional/north, /turf/open/floor/iron, /area/station/cargo/storage) -"smh" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron, -/area/station/hallway/primary/central/fore) "smi" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -65804,17 +65829,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/maintenance/starboard) -"uGT" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/siding/wood, -/obj/structure/cable, -/obj/machinery/power/apc/auto_name/directional/south, -/obj/structure/chair/comfy/teal{ - dir = 4 - }, -/turf/open/floor/wood/large, -/area/station/command/heads_quarters/blueshield) "uGU" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, @@ -68935,20 +68949,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/showroomfloor, /area/station/science/explab) -"vDT" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/old, -/obj/effect/decal/cleanable/blood/gibs/limb, -/obj/effect/landmark/event_spawn, -/obj/structure/cable, -/obj/effect/decal/cleanable/blood/tracks{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard) "vDU" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -69152,20 +69152,6 @@ /obj/machinery/light/small/directional/west, /turf/open/floor/wood, /area/station/commons/fitness/recreation) -"vGS" = ( -/obj/structure/table/wood, -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/effect/turf_decal/siding/wood/corner{ - dir = 1 - }, -/obj/machinery/door/firedoor/border_only{ - dir = 4 - }, -/obj/item/book/bible, -/turf/open/floor/carpet/red, -/area/station/service/chapel) "vGY" = ( /obj/machinery/light/directional/east, /obj/machinery/newscaster/directional/north, @@ -73547,6 +73533,17 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/glass, /area/station/maintenance/starboard) +"wSW" = ( +/obj/machinery/door/poddoor/preopen{ + id = "Biohazard"; + name = "Emergency Research Blast Door" + }, +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/caution/stand_clear, +/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/science/research) "wSY" = ( /obj/machinery/camera/directional/south{ c_tag = "Satellite Antechamber"; @@ -76404,20 +76401,6 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/ce, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/ce) -"xRs" = ( -/obj/machinery/door/airlock/research{ - id_tag = "ResearchInt"; - name = "Research Division" - }, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 4 - }, -/obj/effect/landmark/navigate_destination, -/obj/effect/mapping_helpers/airlock/access/all/science/general, -/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/science/research) "xRv" = ( /obj/machinery/recharge_station, /obj/structure/cable, @@ -76684,6 +76667,20 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/fore) +"xVy" = ( +/obj/machinery/door/airlock/research{ + id_tag = "ResearchInt"; + name = "Research Division" + }, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 4 + }, +/obj/effect/landmark/navigate_destination, +/obj/effect/mapping_helpers/airlock/access/all/science/general, +/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/science/research) "xVz" = ( /obj/structure/chair/comfy/brown, /obj/effect/spawner/random/maintenance, @@ -77050,6 +77047,15 @@ }, /turf/open/floor/iron/showroomfloor, /area/station/medical/pathology) +"yaC" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/blobstart, +/obj/effect/landmark/event_spawn, +/obj/effect/spawner/random/trash/mess, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/department/crew_quarters/bar) "yaE" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -77239,10 +77245,6 @@ }, /turf/open/floor/iron/showroomfloor, /area/station/medical/cryo) -"ydf" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/maintenance/port/fore) "ydw" = ( /obj/effect/turf_decal/tile/yellow{ dir = 8 @@ -89215,7 +89217,7 @@ iMx gnh slr rqG -aKQ +gJw tiv rfg vtv @@ -89261,7 +89263,7 @@ whj jKJ vjh jeZ -nuv +fJr kJx paM fvr @@ -89464,11 +89466,11 @@ vmZ vmZ vEv pUb -vGS +cbO jAu qbE jAu -aSP +jJr gnp rxp vrs @@ -95668,7 +95670,7 @@ aeu pVz mkI uHc -ydf +eyl jQR hCV xAK @@ -102090,7 +102092,7 @@ uNO uNO uNO aIh -mVK +bNu qrv sGj xqJ @@ -102377,7 +102379,7 @@ eOl oJV rzr rYK -kio +lSa xcJ krw fgo @@ -103410,7 +103412,7 @@ wpN jCm xVz jVG -nVX +yaC dAU mkB bEe @@ -104958,7 +104960,7 @@ hLu eNz uJh nYG -uGT +dTO hLu vMX mah @@ -105470,7 +105472,7 @@ nvP jyI hLu mlO -nFt +kKX izz nsm hLu @@ -106245,7 +106247,7 @@ hLu hLu hLu hLu -nuz +cgW hLu hLu cEr @@ -109836,7 +109838,7 @@ xPk wtb gfJ bXX -edF +igx wcV tmD fbF @@ -110092,7 +110094,7 @@ guc pyJ gka jeL -oLF +nAE fiy hMZ ygj @@ -110301,7 +110303,7 @@ mOH lyC mzc kCx -rQo +aeN agx izu kXh @@ -110577,7 +110579,7 @@ cIX fvU nUi iVF -oCp +elc hIs jre rsZ @@ -112362,7 +112364,7 @@ wsa lRk oTm dIi -mgq +gpk dIi fvU vBv @@ -114190,7 +114192,7 @@ nJK moD oQH cMj -guY +imc xwn txl vPd @@ -114447,7 +114449,7 @@ vqN bBF vMG maj -smh +eaB ayh byK mCt @@ -114704,7 +114706,7 @@ jBh bBF sxB kBP -emV +wSW kBP vFY ofs @@ -114961,7 +114963,7 @@ wWD wdf sxB sQT -xRs +xVy sxB aND xDM @@ -119055,7 +119057,7 @@ rZV rZV ceu gnE -vDT +nMY mCL vOX rZV @@ -120340,7 +120342,7 @@ ryj seS uUc gqZ -rPW +ryL xoJ tgo uVQ @@ -122895,7 +122897,7 @@ cBp cBp oRy bsf -iiM +eCI nCZ tiL izr diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 68aff567a7b1..775eb74f145f 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -318,11 +318,6 @@ /obj/machinery/atmospherics/pipe/smart/simple/purple/visible, /turf/open/floor/iron, /area/station/engineering/atmos/pumproom) -"ags" = ( -/obj/item/book/bible, -/obj/structure/altar_of_gods, -/turf/open/floor/iron/dark, -/area/station/service/chapel) "agN" = ( /obj/structure/table/glass, /obj/item/radio/intercom/directional/west, @@ -4817,6 +4812,12 @@ }, /turf/open/floor/sandy_dirt, /area/station/service/hydroponics) +"bJC" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "bJQ" = ( /obj/machinery/vending/coffee, /obj/effect/turf_decal/bot, @@ -5764,14 +5765,6 @@ dir = 1 }, /area/station/security/prison) -"cgj" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/plating, -/area/station/medical/abandoned) "cgF" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -7407,6 +7400,13 @@ /obj/machinery/firealarm/directional/west, /turf/open/floor/plating, /area/station/cargo/drone_bay) +"cLS" = ( +/obj/structure/chair/office, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/hangover, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/wood, +/area/station/service/library) "cMb" = ( /obj/effect/turf_decal/stripes/line, /obj/structure/cable, @@ -7417,6 +7417,14 @@ /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible, /turf/open/floor/iron, /area/station/engineering/atmos/pumproom) +"cMN" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/plating, +/area/station/medical/abandoned) "cMQ" = ( /obj/machinery/door/poddoor/shutters/preopen{ id = "hopqueue"; @@ -7641,6 +7649,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/hallway/secondary/entry) +"cRs" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/greater) "cRC" = ( /obj/machinery/light/small/directional/south, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -8689,6 +8701,11 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/iron/dark, /area/station/security/interrogation) +"dkT" = ( +/obj/item/book/bible, +/obj/structure/altar_of_gods, +/turf/open/floor/iron/dark, +/area/station/service/chapel) "dkW" = ( /obj/structure/disposalpipe/trunk{ dir = 1 @@ -9808,6 +9825,20 @@ }, /turf/open/floor/iron/white/smooth_large, /area/station/medical/pharmacy) +"dHV" = ( +/obj/effect/turf_decal/delivery, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/airlock/corporate{ + id_tag = "BSdoor"; + name = "Blueshield's Office" + }, +/obj/effect/landmark/navigate_destination, +/obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/iron, +/area/station/command/heads_quarters/blueshield) "dIy" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -10860,24 +10891,6 @@ /obj/effect/turf_decal/tile/blue/fourcorners, /turf/open/floor/iron, /area/station/hallway/primary/central) -"eaq" = ( -/obj/structure/table, -/obj/item/stack/ducts/fifty, -/obj/item/stack/ducts/fifty, -/obj/item/stack/ducts/fifty, -/obj/item/stack/ducts/fifty, -/obj/item/stack/ducts/fifty, -/obj/item/stack/ducts/fifty, -/obj/item/stack/ducts/fifty, -/obj/item/stack/ducts/fifty, -/obj/item/plunger, -/obj/item/plunger, -/obj/effect/turf_decal/tile/yellow/half/contrasted{ - dir = 4 - }, -/obj/item/construction/plumbing, -/turf/open/floor/iron/white, -/area/station/medical/chemistry) "eau" = ( /obj/effect/turf_decal/trimline/neutral/filled/corner{ dir = 8 @@ -12898,13 +12911,6 @@ }, /turf/closed/wall/r_wall, /area/station/hallway/secondary/command) -"eMe" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/fore) "eMG" = ( /obj/structure/closet/lasertag/blue, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -12982,6 +12988,14 @@ /obj/machinery/power/apc/auto_name/directional/east, /turf/open/floor/iron/dark/telecomms, /area/station/tcommsat/server) +"eNH" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/fore) "eNR" = ( /turf/closed/wall, /area/station/ai_monitored/aisat/exterior) @@ -13075,6 +13089,24 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai_upload) +"eQm" = ( +/obj/structure/table, +/obj/item/stack/ducts/fifty, +/obj/item/stack/ducts/fifty, +/obj/item/stack/ducts/fifty, +/obj/item/stack/ducts/fifty, +/obj/item/stack/ducts/fifty, +/obj/item/stack/ducts/fifty, +/obj/item/stack/ducts/fifty, +/obj/item/stack/ducts/fifty, +/obj/item/plunger, +/obj/item/plunger, +/obj/effect/turf_decal/tile/yellow/half/contrasted{ + dir = 4 + }, +/obj/item/construction/plumbing, +/turf/open/floor/iron/white, +/area/station/medical/chemistry) "eQs" = ( /obj/machinery/air_sensor/air_tank, /turf/open/floor/engine/air, @@ -13334,12 +13366,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/commons/locker) -"eVJ" = ( -/obj/item/storage/toolbox/emergency, -/obj/effect/mapping_helpers/burnt_floor, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port) "eVX" = ( /obj/machinery/firealarm/directional/west, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -13603,6 +13629,14 @@ /obj/structure/displaycase/labcage, /turf/open/floor/engine, /area/station/command/heads_quarters/rd) +"eZZ" = ( +/obj/machinery/light/directional/south, +/obj/structure/chair/comfy/teal{ + dir = 8 + }, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/carpet/cyan, +/area/station/command/heads_quarters/blueshield) "fad" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/carpet, @@ -14694,6 +14728,14 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/engineering/atmospherics_engine) +"fuy" = ( +/obj/machinery/light/small/directional/south, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/power/apc/auto_name/directional/south, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/freezer, +/area/station/commons/toilet/restrooms) "fuA" = ( /obj/effect/turf_decal/trimline/blue/filled/line, /obj/structure/cable, @@ -14703,6 +14745,11 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"fvb" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "fvB" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -16116,11 +16163,6 @@ }, /turf/open/floor/iron/dark/textured, /area/station/engineering/atmos) -"fXz" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "fXK" = ( /obj/effect/turf_decal/trimline/red/filled/corner{ dir = 8 @@ -16205,15 +16247,6 @@ }, /turf/open/floor/iron, /area/station/science/lab) -"fYU" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/turf/open/floor/wood, -/area/station/command/heads_quarters/blueshield) "fYX" = ( /obj/structure/cable, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -24643,14 +24676,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/service) -"iNS" = ( -/obj/machinery/light/small/directional/south, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/power/apc/auto_name/directional/south, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/freezer, -/area/station/commons/toilet/restrooms) "iOc" = ( /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -26607,6 +26632,13 @@ }, /turf/open/floor/iron/white, /area/station/medical/surgery/aft) +"jue" = ( +/obj/effect/spawner/random/trash/garbage{ + spawn_scatter_radius = 1 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "juf" = ( /obj/machinery/telecomms/bus/preset_two, /turf/open/floor/circuit/telecomms/mainframe, @@ -26985,20 +27017,6 @@ }, /turf/open/floor/iron, /area/station/security/office) -"jyO" = ( -/obj/effect/turf_decal/delivery, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/airlock/corporate{ - id_tag = "BSdoor"; - name = "Blueshield's Office" - }, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/effect/landmark/navigate_destination, -/obj/machinery/door/firedoor, -/turf/open/floor/iron, -/area/station/command/heads_quarters/blueshield) "jyQ" = ( /obj/machinery/computer/records/medical{ dir = 8 @@ -29407,6 +29425,14 @@ /obj/effect/landmark/generic_maintenance_landmark, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"ksK" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port) "ksT" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -29890,13 +29916,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/command/teleporter) -"kAE" = ( -/obj/machinery/light/directional/south, -/obj/structure/chair/comfy/teal{ - dir = 8 - }, -/turf/open/floor/carpet/cyan, -/area/station/command/heads_quarters/blueshield) "kAF" = ( /obj/machinery/duct, /turf/open/floor/iron/freezer, @@ -30950,10 +30969,6 @@ }, /turf/open/floor/iron, /area/station/engineering/break_room) -"kVM" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "kVN" = ( /turf/open/floor/carpet, /area/station/service/chapel) @@ -33211,6 +33226,16 @@ /obj/structure/lattice, /turf/open/space/basic, /area/space/nearstation) +"lMN" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/wood, +/area/station/command/heads_quarters/blueshield) "lMW" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -35009,6 +35034,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/fore) +"mst" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "msI" = ( /turf/closed/wall, /area/station/security/bitden) @@ -35641,15 +35670,6 @@ /obj/item/kirbyplants/random/dead, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/rd) -"mCz" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 8 - }, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "mCL" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, @@ -36632,22 +36652,12 @@ /obj/effect/turf_decal/trimline/brown/filled/line, /turf/open/floor/iron, /area/station/cargo/miningoffice) -"mUE" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "mUF" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 }, /turf/open/floor/iron, /area/station/cargo/drone_bay) -"mUI" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/maintenance/port/aft) "mUL" = ( /obj/machinery/door/airlock/atmos{ name = "Hypertorus Fusion Reactor" @@ -36802,6 +36812,15 @@ /obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"mWY" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 8 + }, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/iron, +/area/station/cargo/drone_bay) "mWZ" = ( /obj/item/folder/red, /obj/item/pen, @@ -37132,13 +37151,6 @@ }, /turf/open/floor/iron/dark/textured, /area/station/medical/pathology) -"nbq" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 5 - }, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/wood, -/area/station/smithing) "nbs" = ( /obj/effect/turf_decal/delivery, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -41232,13 +41244,6 @@ }, /turf/open/floor/plating, /area/station/commons/toilet/auxiliary) -"oyB" = ( -/obj/structure/chair/office, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/hangover, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/wood, -/area/station/service/library) "oyO" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -46688,14 +46693,6 @@ /obj/machinery/suit_storage_unit/standard_unit, /turf/open/floor/iron/dark, /area/station/maintenance/aft/lesser) -"qvo" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port) "qvJ" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -47130,6 +47127,12 @@ /obj/machinery/computer/records/medical/laptop, /turf/open/floor/iron/white, /area/station/security/medical) +"qDD" = ( +/obj/item/storage/toolbox/emergency, +/obj/effect/mapping_helpers/burnt_floor, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port) "qDI" = ( /obj/effect/turf_decal/trimline/green/filled/line, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -47462,6 +47465,17 @@ /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"qKD" = ( +/obj/item/book/bible, +/obj/machinery/light/small/directional/north, +/obj/machinery/newscaster/directional/north, +/obj/machinery/camera/directional/north{ + c_tag = "Chapel - Fore" + }, +/obj/structure/table/wood, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/turf/open/floor/iron/dark, +/area/station/service/chapel) "qKR" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/smart/simple/yellow/visible, @@ -49170,13 +49184,6 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/carpet, /area/station/service/theater) -"rqf" = ( -/obj/effect/spawner/random/trash/garbage{ - spawn_scatter_radius = 1 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "rqT" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -49520,6 +49527,14 @@ /obj/machinery/light_switch/directional/south, /turf/open/floor/iron/dark, /area/station/engineering/storage/tech) +"rwB" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port) "rwE" = ( /obj/structure/table, /obj/item/paper_bin{ @@ -49835,6 +49850,15 @@ }, /turf/open/floor/iron, /area/station/engineering/main) +"rBh" = ( +/obj/structure/noticeboard/directional/north{ + desc = "A memorial wall for pinning mementos upon."; + name = "memorial board" + }, +/obj/item/book/bible, +/obj/structure/table/wood, +/turf/open/floor/carpet, +/area/station/service/chapel/funeral) "rBi" = ( /obj/machinery/airalarm/directional/west, /obj/effect/turf_decal/stripes/line{ @@ -51649,10 +51673,6 @@ /obj/structure/sign/directions/evac, /turf/closed/wall/r_wall, /area/station/hallway/primary/aft) -"seP" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/greater) "sfg" = ( /obj/structure/cable, /obj/effect/turf_decal/trimline/red/filled/line{ @@ -53305,6 +53325,13 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/fore) +"sKo" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/fore) "sKr" = ( /obj/structure/window/spawner/directional/south, /obj/structure/window/spawner/directional/east, @@ -54392,14 +54419,6 @@ }, /turf/open/floor/iron/dark, /area/station/medical/morgue) -"tcK" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/fore) "tcN" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -56925,6 +56944,10 @@ }, /turf/open/floor/iron/checker, /area/station/engineering/atmos/storage/gas) +"tYI" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "tYO" = ( /obj/structure/cable, /obj/effect/mapping_helpers/airlock/access/all/science/rd, @@ -57647,14 +57670,6 @@ /obj/structure/fans/tiny, /turf/open/floor/plating, /area/station/service/chapel/funeral) -"ulG" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port) "ulQ" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 1 @@ -62789,15 +62804,6 @@ }, /turf/open/floor/sandy_dirt, /area/station/service/hydroponics) -"wdV" = ( -/obj/structure/noticeboard/directional/north{ - desc = "A memorial wall for pinning mementos upon."; - name = "memorial board" - }, -/obj/item/book/bible, -/obj/structure/table/wood, -/turf/open/floor/carpet, -/area/station/service/chapel/funeral) "wen" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -65624,17 +65630,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/ai_monitored/aisat/exterior) -"xez" = ( -/obj/item/book/bible, -/obj/machinery/light/small/directional/north, -/obj/machinery/newscaster/directional/north, -/obj/machinery/camera/directional/north{ - c_tag = "Chapel - Fore" - }, -/obj/structure/table/wood, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/station/service/chapel) "xeN" = ( /obj/structure/cable, /obj/effect/turf_decal/stripes/line{ @@ -65861,10 +65856,13 @@ "xhh" = ( /turf/open/floor/plating/airless, /area/station/science/ordnance/bomb) -"xin" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) +"xij" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 5 + }, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/wood, +/area/station/smithing) "xip" = ( /obj/machinery/portable_atmospherics/canister/nitrous_oxide, /obj/effect/turf_decal/bot, @@ -65943,6 +65941,10 @@ }, /turf/open/floor/circuit/green, /area/station/ai_monitored/turret_protected/ai) +"xjd" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/maintenance/port/aft) "xjh" = ( /turf/closed/wall, /area/station/security/checkpoint/customs) @@ -82948,7 +82950,7 @@ igV nLG pOa clp -eVJ +qDD jmJ pOa uEO @@ -83219,7 +83221,7 @@ pOa pOa jUb xqn -mUI +xjd fQZ ehv sBL @@ -83729,7 +83731,7 @@ sTq cMb fFu wvr -ulG +ksK tYi jUb eov @@ -84235,7 +84237,7 @@ tON kEm xnr stL -nbq +xij lsu qLP pOa @@ -85541,7 +85543,7 @@ jUb xRB dqN dqN -xin +tYI cNS eNV dqN @@ -86035,7 +86037,7 @@ tmI fjD pOa cIW -qvo +rwB tYi vXH pOa @@ -88608,7 +88610,7 @@ kFM kFM ilC prD -oyB +cLS lIa xjC pOa @@ -88647,7 +88649,7 @@ xGk tBJ xOP ijF -cgj +cMN mMO hdo hzG @@ -88810,7 +88812,7 @@ tdg hkj hkj kuW -mCz +mWY vKg mUF obF @@ -90097,7 +90099,7 @@ aaa jXu uUu oCd -rqf +jue bPM jXu loQ @@ -90203,7 +90205,7 @@ aMf xUX yjW vQg -wdV +rBh hto bnH dLy @@ -91997,7 +91999,7 @@ jJY iDN xtz tSw -xez +qKD iJj uZD hKv @@ -92518,7 +92520,7 @@ phR phR wjV phR -ags +dkT fkT cXw rRZ @@ -95573,7 +95575,7 @@ fvE kKT fBG wPH -eaq +eQm drW jxm bcr @@ -98367,10 +98369,10 @@ syo eDL lSz tst -jyO +dHV xOl iag -kAE +eZZ hJK ocv lVl @@ -98626,7 +98628,7 @@ lSz vQe hJK ecI -fYU +lMN uqK hJK bYn @@ -102686,7 +102688,7 @@ aaa ilh cur cur -tcK +eNH cur ilh rlp @@ -102702,7 +102704,7 @@ ilh ilh ilh dKO -iNS +fuy dIO dIO dIO @@ -103207,7 +103209,7 @@ fEW ilh ssJ msd -eMe +sKo cur sab ilh @@ -105868,7 +105870,7 @@ arg hIZ qlG fPD -kVM +mst eQY fPD nTd @@ -108090,7 +108092,7 @@ qhy qXB dOx jCw -fXz +fvb tjL aGe mFm @@ -109167,7 +109169,7 @@ eol fWA dxk cNm -seP +cRs ret qHO bNn @@ -109886,7 +109888,7 @@ cyS izd jlM jlM -mUE +bJC kXx aIC kVs diff --git a/_maps/map_files/Ouroboros/Ouroboros.dmm b/_maps/map_files/Ouroboros/Ouroboros.dmm index ac58a322d50a..0b7b079e0b61 100644 --- a/_maps/map_files/Ouroboros/Ouroboros.dmm +++ b/_maps/map_files/Ouroboros/Ouroboros.dmm @@ -340,6 +340,14 @@ dir = 4 }, /area/station/hallway/primary/central/fore) +"afa" = ( +/obj/machinery/newscaster/directional/north, +/obj/machinery/camera/directional/north{ + c_tag = "Library - Public Lounge" + }, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/carpet/green, +/area/station/service/library) "afh" = ( /obj/structure/lattice/catwalk, /obj/structure/marker_beacon/bronze, @@ -856,11 +864,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/aft/greater) -"anH" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/dark/smooth_large, -/area/station/cargo/quartermaster) "anI" = ( /obj/structure/trash_pile, /obj/structure/cable, @@ -974,9 +977,6 @@ /obj/effect/landmark/start/shaft_miner, /turf/open/floor/iron/dark, /area/station/cargo/storage) -"apB" = ( -/turf/closed/wall, -/area/station/security/bitden) "apL" = ( /obj/machinery/door/poddoor/shutters/preopen{ id = "vac-office"; @@ -1064,16 +1064,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/service/forge) -"aro" = ( -/obj/structure/chair/wood{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/item/ammo_casing/c45, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/maintenance/port/fore) "arz" = ( /obj/effect/mapping_helpers/broken_floor, /obj/structure/disposalpipe/segment{ @@ -2152,16 +2142,6 @@ dir = 4 }, /area/station/common/wrestling/arena) -"aHK" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "aIg" = ( /obj/effect/turf_decal/siding/wood, /obj/effect/turf_decal/siding/wood/corner{ @@ -3362,6 +3342,12 @@ "bbg" = ( /turf/open/floor/engine/hull/reinforced, /area/space/nearstation) +"bbh" = ( +/obj/structure/bed/maint, +/obj/machinery/light/small/broken/directional/north, +/obj/effect/mapping_helpers/burnt_floor, +/turf/open/floor/iron/dark/small, +/area/station/security/prison/safe) "bbk" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -3652,11 +3638,6 @@ }, /turf/open/floor/iron/small, /area/station/security/checkpoint/escape) -"bft" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable, -/turf/open/floor/plating, -/area/station/cargo/quartermaster) "bfC" = ( /turf/closed/wall, /area/station/commons/dorms/room2) @@ -3959,6 +3940,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/carpet/purple, /area/station/command/heads_quarters/rd) +"bjh" = ( +/obj/machinery/firealarm/directional/west, +/obj/machinery/light_switch/directional/west{ + pixel_y = -9 + }, +/obj/machinery/light/red/directional/west, +/turf/open/floor/iron/dark/small, +/area/station/security/bitden) "bjs" = ( /obj/effect/turf_decal/tile/dark_red{ dir = 8 @@ -4036,6 +4025,25 @@ }, /turf/open/floor/wood/parquet, /area/station/medical/patients_rooms) +"bkh" = ( +/obj/structure/table/wood, +/obj/item/folder/yellow{ + pixel_y = 12; + pixel_x = 5 + }, +/obj/item/stamp/head/qm{ + pixel_y = 5 + }, +/obj/item/stamp{ + pixel_x = 5 + }, +/obj/item/stamp/denied{ + pixel_x = -5 + }, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 8 + }, +/area/station/cargo/quartermaster) "bko" = ( /obj/effect/turf_decal/tile/blue/fourcorners, /obj/structure/cable, @@ -4456,6 +4464,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/small, /area/station/hallway/secondary/entry) +"bps" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/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/smooth_large, +/area/station/cargo/quartermaster) "bpv" = ( /obj/effect/turf_decal/stripes/line, /obj/structure/sign/warning/vacuum/external/directional/north, @@ -4512,6 +4529,20 @@ /obj/effect/turf_decal/stripes/corner, /turf/open/floor/iron, /area/station/engineering/atmos) +"bqN" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/tile/purple/half{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/turf/open/floor/iron/dark/smooth_half{ + dir = 1 + }, +/area/station/security/bitden) "brb" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable, @@ -5911,15 +5942,6 @@ /obj/effect/turf_decal/tile/blue, /turf/open/floor/iron, /area/station/engineering/atmos/upper) -"bMY" = ( -/obj/structure/chair/comfy/brown{ - dir = 8 - }, -/obj/machinery/firealarm/directional/east, -/obj/structure/disposalpipe/segment, -/obj/effect/landmark/start/quartermaster, -/turf/open/floor/iron/dark/small, -/area/station/cargo/quartermaster) "bNc" = ( /obj/structure/railing, /turf/open/openspace, @@ -5934,6 +5956,20 @@ /obj/item/pen, /turf/open/floor/wood, /area/station/maintenance/starboard/fore) +"bNg" = ( +/obj/structure/table, +/obj/effect/turf_decal/bot_white, +/obj/effect/turf_decal/siding/dark{ + dir = 8 + }, +/obj/item/mining_voucher, +/obj/item/gps/mining{ + gpstag = "QM0"; + pixel_y = 4 + }, +/obj/machinery/light_switch/directional/east, +/turf/open/floor/iron/large, +/area/station/cargo/quartermaster) "bNi" = ( /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -6435,6 +6471,26 @@ }, /turf/open/floor/wood/tile, /area/station/service/bar) +"bXd" = ( +/obj/item/paper_bin/carbon{ + pixel_x = -3; + pixel_y = 7 + }, +/obj/item/pen{ + pixel_x = -3; + pixel_y = 7 + }, +/obj/item/computer_disk/quartermaster, +/obj/item/computer_disk/quartermaster, +/obj/structure/table/wood, +/obj/machinery/status_display/supply{ + pixel_y = 32 + }, +/obj/machinery/light/warm/directional/north, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 8 + }, +/area/station/cargo/quartermaster) "bXk" = ( /turf/closed/wall, /area/station/service/janitor) @@ -6442,6 +6498,15 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron/large, /area/station/cargo/storage) +"bXy" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/airlock/grunge{ + id_tag = "Cell3Privacy"; + name = "Cell 3" + }, +/turf/open/floor/iron/dark/smooth_large, +/area/station/security/prison/safe) "bXJ" = ( /obj/effect/turf_decal/tile/dark_blue/half{ dir = 1 @@ -7710,13 +7775,6 @@ dir = 1 }, /area/station/common/wrestling/arena) -"cpa" = ( -/obj/machinery/disposal/bin, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/box, -/obj/structure/disposalpipe/trunk, -/turf/open/floor/iron/dark/smooth_large, -/area/station/cargo/quartermaster) "cpm" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -7978,6 +8036,11 @@ }, /turf/open/floor/plating, /area/station/construction/mining/aux_base) +"cuA" = ( +/obj/structure/window/reinforced/tinted/fulltile, +/obj/structure/hedge/opaque, +/turf/open/floor/iron/dark/smooth_large, +/area/station/cargo/quartermaster) "cuJ" = ( /obj/item/toy/figure/assistant{ pixel_y = 17; @@ -8810,16 +8873,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) -"cHy" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 10 - }, -/obj/machinery/computer/shuttle/mining{ - dir = 4 - }, -/obj/effect/turf_decal/box, -/turf/open/floor/wood, -/area/station/cargo/quartermaster) "cHA" = ( /obj/item/poster/random_official, /obj/effect/spawner/random/maintenance, @@ -8900,20 +8953,6 @@ /obj/structure/chair/office/light, /turf/open/floor/glass/reinforced, /area/station/science/research) -"cJe" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/tile/brown/half{ - dir = 4 - }, -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 4 - }, -/turf/open/floor/iron/dark/smooth_half{ - dir = 1 - }, -/area/station/security/bitden) "cJh" = ( /obj/structure/hedge, /obj/structure/window/reinforced/tinted/fulltile, @@ -9050,6 +9089,9 @@ /obj/item/mod/module/thermal_regulator, /turf/open/floor/iron, /area/station/engineering/supermatter/room) +"cKK" = ( +/turf/closed/wall/r_wall, +/area/station/cargo/quartermaster) "cKN" = ( /obj/structure/lattice/catwalk, /obj/structure/marker_beacon/bronze, @@ -9241,11 +9283,6 @@ }, /turf/open/floor/iron/small, /area/station/hallway/primary/central/aft) -"cMR" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/event_spawn, -/turf/open/floor/iron/dark/small, -/area/station/security/bitden) "cNa" = ( /obj/structure/disposalpipe/sorting/mail/flip, /obj/effect/mapping_helpers/mail_sorting/service/library, @@ -9318,6 +9355,20 @@ /obj/effect/landmark/start/assistant, /turf/open/floor/iron/dark, /area/station/commons/storage/primary) +"cNH" = ( +/obj/effect/turf_decal/bot_white, +/obj/effect/turf_decal/siding/dark{ + dir = 8 + }, +/obj/structure/table, +/obj/machinery/fax{ + fax_name = "Quartermaster's Office"; + name = "Quartermaster's Fax Machine"; + pixel_y = 3 + }, +/obj/machinery/light/warm/directional/east, +/turf/open/floor/iron/large, +/area/station/cargo/quartermaster) "cNL" = ( /obj/effect/turf_decal/stripes/corner{ dir = 1 @@ -9566,6 +9617,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/maintenance/aft/greater) +"cSt" = ( +/obj/machinery/airalarm/directional/north, +/turf/open/floor/iron/dark/small, +/area/station/security/bitden) "cSw" = ( /obj/machinery/door/airlock/maintenance_hatch{ name = "Maintenance Hatch" @@ -9865,14 +9920,6 @@ /obj/effect/spawner/random/engineering/tracking_beacon, /turf/open/floor/iron/white, /area/station/medical/pharmacy) -"cZE" = ( -/obj/machinery/airalarm/directional/south, -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/wood/large, -/area/station/command/heads_quarters/blueshield) "cZO" = ( /obj/machinery/light/directional/east, /obj/item/kirbyplants/organic/plant22, @@ -9894,6 +9941,17 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/security/range) +"dad" = ( +/obj/structure/bed, +/obj/effect/landmark/start/prisoner, +/obj/item/bedsheet/brown, +/obj/machinery/button/curtain{ + id = "Cell3Privacy"; + pixel_x = 24; + pixel_y = 24 + }, +/turf/open/floor/iron/dark, +/area/station/security/prison/safe) "dap" = ( /obj/structure/fluff/paper/stack{ dir = 8 @@ -10194,14 +10252,6 @@ dir = 8 }, /area/station/security/holding_cell) -"ddq" = ( -/obj/machinery/firealarm/directional/west, -/obj/machinery/light_switch/directional/west{ - pixel_y = -9 - }, -/obj/machinery/light/red/directional/west, -/turf/open/floor/iron/dark/small, -/area/station/security/bitden) "ddu" = ( /mob/living/carbon/human/species/monkey, /obj/machinery/camera/directional/north{ @@ -10907,6 +10957,12 @@ }, /turf/open/floor/plating, /area/station/command/heads_quarters/hos) +"dns" = ( +/obj/machinery/airalarm/directional/east, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/iron/dark/small, +/area/station/cargo/quartermaster) "dnu" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable, @@ -15392,6 +15448,14 @@ /obj/item/kirbyplants/organic/plant21, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/teleporter) +"eCD" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark/small, +/area/station/cargo/quartermaster) "eCE" = ( /obj/effect/turf_decal/tile/blue/full, /turf/open/floor/iron/dark/smooth_large, @@ -15865,13 +15929,6 @@ }, /turf/open/floor/wood/large, /area/station/service/chapel/funeral) -"eKa" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/dark, -/area/station/security/prison/safe) "eKb" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -16139,9 +16196,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/engine, /area/station/engineering/atmos/upper) -"ePu" = ( -/turf/open/floor/iron/dark/smooth_large, -/area/station/cargo/quartermaster) "ePv" = ( /obj/structure/cable, /obj/structure/ladder, @@ -16475,6 +16529,11 @@ "eSH" = ( /turf/open/floor/iron, /area/station/maintenance/port/fore) +"eSR" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark/smooth_large, +/area/station/cargo/quartermaster) "eTh" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, /obj/structure/cable, @@ -18555,6 +18614,18 @@ /obj/item/radio/intercom/chapel/directional/west, /turf/open/floor/wood/tile, /area/station/service/chapel/office) +"fAL" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/corporate{ + id_tag = "BSdoor"; + name = "Blueshield's Office" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/navigate_destination, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/iron/dark/smooth_large, +/area/station/command/heads_quarters/blueshield) "fAT" = ( /obj/effect/turf_decal/arrows{ dir = 8; @@ -19253,36 +19324,6 @@ /obj/effect/turf_decal/tile/purple/opposingcorners, /turf/open/floor/iron/dark, /area/station/service/barber) -"fMP" = ( -/obj/effect/turf_decal/tile/dark/diagonal_edge, -/obj/item/storage/box/drinkingglasses{ - pixel_y = 12; - pixel_x = 6 - }, -/obj/structure/table, -/obj/item/reagent_containers/condiment/peppermill{ - desc = "Often used to flavor food or make people sneeze. Fashionably moved to the left side of the table."; - pixel_x = -8; - pixel_y = 6 - }, -/obj/item/reagent_containers/condiment/rice{ - pixel_x = 8; - pixel_y = 5 - }, -/obj/item/reagent_containers/condiment/flour{ - pixel_x = 8 - }, -/obj/item/reagent_containers/condiment/saltshaker{ - pixel_x = -9 - }, -/obj/item/storage/fancy/egg_box{ - pixel_y = -7 - }, -/obj/structure/cable, -/obj/item/kitchen/rollingpin, -/obj/item/knife/plastic, -/turf/open/floor/iron/kitchen/diagonal, -/area/station/security/prison) "fMR" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -19315,11 +19356,6 @@ /obj/machinery/mechpad, /turf/open/floor/iron, /area/station/science/robotics/mechbay) -"fNJ" = ( -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "fNN" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, /obj/structure/cable, @@ -19587,6 +19623,18 @@ }, /turf/open/floor/wood/tile, /area/station/service/lawoffice) +"fRo" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/holopad/secure, +/obj/effect/landmark/event_spawn, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 8 + }, +/area/station/cargo/quartermaster) "fRv" = ( /obj/effect/spawner/random/structure/furniture_parts, /turf/open/floor/plating, @@ -19720,6 +19768,11 @@ /obj/structure/closet/secure_closet/engineering_welding, /turf/open/floor/iron, /area/station/engineering/supermatter/room) +"fUt" = ( +/obj/structure/dresser, +/obj/machinery/light/small/directional/south, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "fUu" = ( /obj/machinery/door/firedoor/border_only{ dir = 8 @@ -20293,9 +20346,6 @@ }, /turf/open/floor/engine, /area/station/engineering/atmos/upper) -"gdb" = ( -/turf/closed/wall/r_wall, -/area/station/cargo/quartermaster) "gdc" = ( /obj/machinery/holopad, /obj/structure/disposalpipe/segment, @@ -20459,6 +20509,16 @@ /obj/machinery/light/warm/directional/east, /turf/open/floor/wood/tile, /area/station/service/bar) +"gfJ" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "gfO" = ( /obj/structure/lattice, /turf/open/openspace, @@ -20859,17 +20919,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/engineering/atmos) -"glr" = ( -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/corporate{ - id_tag = "BSdoor"; - name = "Blueshield's Quarters" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/dark/smooth_large, -/area/station/command/heads_quarters/blueshield) "glu" = ( /obj/effect/spawner/structure/window/reinforced/plasma, /obj/machinery/door/poddoor/preopen{ @@ -21912,9 +21961,6 @@ /obj/machinery/light/directional/south, /turf/open/floor/iron/dark/corner, /area/station/hallway/secondary/recreation) -"gDf" = ( -/turf/open/floor/iron/dark/small, -/area/station/security/bitden) "gDh" = ( /obj/machinery/computer/records/medical{ dir = 1 @@ -22325,6 +22371,16 @@ }, /turf/open/floor/iron/small, /area/station/hallway/primary/central/aft) +"gJx" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/curtain/cloth/fancy/mechanical{ + icon_state = "bounty-open"; + icon_type = "bounty"; + id = "Cell2Privacy"; + name = "curtain" + }, +/turf/open/floor/plating, +/area/station/security/prison/safe) "gJH" = ( /obj/effect/turf_decal/tile/dark_blue{ dir = 8 @@ -22549,6 +22605,15 @@ }, /turf/open/floor/plating, /area/station/command/heads_quarters/hop) +"gMS" = ( +/obj/effect/mapping_helpers/airlock/access/all/security/brig, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/airlock/security{ + id_tag = "IsolationCell"; + name = "Isolation Cell" + }, +/turf/open/floor/iron/dark/smooth_large, +/area/station/security/prison/safe) "gNf" = ( /obj/effect/turf_decal/tile/blue/full, /obj/effect/turf_decal/tile/dark_blue/full, @@ -23433,6 +23498,11 @@ }, /turf/open/floor/iron/dark/smooth_edge, /area/station/service/hydroponics) +"hao" = ( +/obj/structure/bed, +/obj/item/bedsheet/qm, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "hap" = ( /obj/effect/turf_decal/box/corners{ dir = 1 @@ -23982,10 +24052,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/prison) -"hjz" = ( -/obj/machinery/drone_dispenser/preloaded, -/turf/open/floor/plating, -/area/station/maintenance/port/lesser) "hjJ" = ( /turf/closed/wall/r_wall, /area/station/ai_monitored/turret_protected/aisat_interior) @@ -24033,6 +24099,36 @@ /obj/effect/landmark/start/brig_physician, /turf/open/floor/iron/white/smooth_large, /area/station/security/medical) +"hkQ" = ( +/obj/effect/turf_decal/tile/dark/diagonal_edge, +/obj/item/storage/box/drinkingglasses{ + pixel_y = 12; + pixel_x = 6 + }, +/obj/structure/table, +/obj/item/reagent_containers/condiment/peppermill{ + desc = "Often used to flavor food or make people sneeze. Fashionably moved to the left side of the table."; + pixel_x = -8; + pixel_y = 6 + }, +/obj/item/reagent_containers/condiment/rice{ + pixel_x = 8; + pixel_y = 5 + }, +/obj/item/reagent_containers/condiment/flour{ + pixel_x = 8 + }, +/obj/item/reagent_containers/condiment/saltshaker{ + pixel_x = -9 + }, +/obj/item/storage/fancy/egg_box{ + pixel_y = -7 + }, +/obj/structure/cable, +/obj/item/kitchen/rollingpin, +/obj/item/knife/plastic, +/turf/open/floor/iron/kitchen/diagonal, +/area/station/security/prison) "hkU" = ( /obj/effect/turf_decal/tile/dark_blue{ dir = 1 @@ -24282,17 +24378,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) -"hnW" = ( -/obj/effect/turf_decal/bot_white, -/obj/effect/turf_decal/siding/dark{ - dir = 4 - }, -/obj/machinery/light/small/directional/south, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/turf/open/floor/iron/large, -/area/station/cargo/quartermaster) "hoa" = ( /turf/closed/wall, /area/station/commons/dorms/room4) @@ -24851,14 +24936,6 @@ /obj/structure/chair/wood, /turf/open/floor/wood, /area/station/service/chapel) -"hvE" = ( -/obj/structure/chair/office{ - dir = 4 - }, -/obj/structure/cable, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/turf/open/floor/iron/dark/smooth_large, -/area/station/cargo/quartermaster) "hwl" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/yellow/half/contrasted{ @@ -25101,16 +25178,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, /area/station/medical/treatment_center) -"hAP" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/curtain/cloth/fancy/mechanical{ - icon_state = "bounty-open"; - icon_type = "bounty"; - id = "Cell1Privacy"; - name = "curtain" - }, -/turf/open/floor/plating, -/area/station/security/prison/safe) "hBb" = ( /obj/effect/turf_decal/stripes/line{ dir = 6 @@ -25308,18 +25375,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plating, /area/station/maintenance/aft/greater) -"hDF" = ( -/obj/structure/closet/secure_closet/quartermaster, -/obj/effect/turf_decal/bot_white, -/obj/effect/turf_decal/siding/dark{ - dir = 4 - }, -/obj/item/clothing/glasses/material/mining/gar, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 4 - }, -/turf/open/floor/iron/large, -/area/station/cargo/quartermaster) "hDH" = ( /obj/effect/spawner/random/trash/food_packaging, /turf/open/floor/plating, @@ -26115,6 +26170,16 @@ /obj/machinery/status_display/evac/directional/east, /turf/open/floor/iron/dark, /area/station/command/teleporter) +"hQp" = ( +/obj/structure/chair/wood{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/item/ammo_casing/c45, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/maintenance/port/fore) "hQC" = ( /obj/structure/disposalpipe/segment, /obj/machinery/light/small/directional/east, @@ -26259,15 +26324,6 @@ /obj/structure/window/spawner/directional/south, /turf/open/openspace, /area/station/security/brig/upper) -"hRK" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/machinery/requests_console/auto_name/directional/west, -/obj/effect/mapping_helpers/requests_console/information, -/obj/effect/mapping_helpers/requests_console/assistance, -/turf/open/floor/wood, -/area/station/cargo/quartermaster) "hRM" = ( /obj/effect/turf_decal/tile/purple/opposingcorners{ dir = 1 @@ -26450,16 +26506,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/commons/storage/tools) -"hUM" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable, -/obj/machinery/door/poddoor/shutters/preopen{ - dir = 8; - id = "qm"; - name = "Privacy Shutters" - }, -/turf/open/floor/plating, -/area/station/cargo/quartermaster) "hUT" = ( /turf/open/openspace, /area/station/hallway/secondary/command) @@ -26712,6 +26758,13 @@ dir = 8 }, /area/station/hallway/primary/starboard) +"hXA" = ( +/obj/machinery/disposal/bin, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/box, +/obj/structure/disposalpipe/trunk, +/turf/open/floor/iron/dark/smooth_large, +/area/station/cargo/quartermaster) "hXE" = ( /obj/effect/turf_decal/stripes/corner{ dir = 4 @@ -27129,16 +27182,6 @@ /obj/structure/cable, /turf/open/floor/wood/tile, /area/station/security/detectives_office) -"idQ" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 9 - }, -/obj/machinery/computer/security/qm{ - dir = 4 - }, -/obj/effect/turf_decal/box, -/turf/open/floor/wood, -/area/station/cargo/quartermaster) "iec" = ( /obj/structure/cable, /turf/open/floor/plating, @@ -27197,6 +27240,22 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/hallway/primary/port) +"ieG" = ( +/obj/item/radio/intercom/directional/north, +/obj/machinery/light/red/directional/north, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/turf/open/floor/iron/dark/smooth_half{ + dir = 1 + }, +/area/station/security/bitden) "ieH" = ( /obj/structure/closet/secure_closet/medical1{ anchored = 1 @@ -27576,14 +27635,6 @@ /obj/effect/turf_decal/tile/purple/half/contrasted, /turf/open/floor/iron/white, /area/station/science/xenobiology) -"ikk" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 6 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/wood, -/area/station/cargo/quartermaster) "ikm" = ( /obj/effect/turf_decal/siding/white, /obj/structure/table/reinforced, @@ -27653,6 +27704,12 @@ }, /turf/open/floor/engine, /area/station/engineering/atmos/upper) +"ill" = ( +/obj/effect/turf_decal/tile/dark/diagonal_edge, +/obj/machinery/light/warm/directional/north, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron/kitchen/diagonal, +/area/station/security/prison) "ilq" = ( /obj/effect/turf_decal/stripes/line{ dir = 6 @@ -28450,20 +28507,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"ixQ" = ( -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/any/supply/qm, -/obj/machinery/door/airlock/mining/glass{ - name = "Drone Bay" - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/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/smooth_large, -/area/station/cargo/quartermaster) "ixV" = ( /obj/effect/turf_decal/tile/purple/opposingcorners, /obj/machinery/power/apc/auto_name/directional/east, @@ -29074,11 +29117,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/chemistry) -"iHA" = ( -/obj/machinery/light/small/directional/north, -/obj/machinery/netpod, -/turf/open/floor/catwalk_floor/iron_dark, -/area/station/security/bitden) "iHE" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, /obj/machinery/airlock_sensor/incinerator_atmos{ @@ -29427,23 +29465,6 @@ dir = 1 }, /area/station/medical/surgery/aft) -"iME" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/tile/purple/half{ - dir = 4 - }, -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 4 - }, -/turf/open/floor/iron/dark/smooth_half{ - dir = 1 - }, -/area/station/security/bitden) "iMM" = ( /obj/effect/turf_decal/bot, /obj/machinery/vending/cigarette, @@ -29731,6 +29752,15 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"iQD" = ( +/obj/effect/turf_decal/tile/dark_red/opposingcorners{ + dir = 1 + }, +/obj/structure/chair/stool/bar/directional/north, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/checker, +/area/station/maintenance/abandon_diner) "iQI" = ( /obj/effect/turf_decal/tile/dark_red, /obj/structure/cable, @@ -29828,11 +29858,6 @@ /obj/structure/window/reinforced/spawner/directional/north, /turf/open/openspace, /area/station/maintenance/department/security/upper) -"iSr" = ( -/obj/structure/dresser, -/obj/machinery/light/small/directional/south, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "iSx" = ( /obj/structure/chair/plastic{ dir = 4 @@ -29896,13 +29921,6 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron, /area/station/hallway/primary/central) -"iTM" = ( -/obj/effect/turf_decal/siding/white{ - dir = 1 - }, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/iron, -/area/station/service/forge) "iTN" = ( /obj/structure/table, /obj/item/clothing/head/costume/festive{ @@ -30001,6 +30019,14 @@ }, /turf/open/floor/grass, /area/station/medical/virology) +"iUW" = ( +/obj/machinery/photocopier, +/obj/effect/turf_decal/bot_white, +/obj/effect/turf_decal/siding/dark{ + dir = 8 + }, +/turf/open/floor/iron/large, +/area/station/cargo/quartermaster) "iUY" = ( /obj/structure/sign/directions/evac/directional/north{ dir = 4 @@ -30572,6 +30598,9 @@ /obj/machinery/griddle, /turf/open/floor/iron/kitchen/diagonal, /area/station/security/prison) +"jch" = ( +/turf/open/floor/iron/dark/small, +/area/station/security/bitden) "jcw" = ( /obj/structure/window/reinforced/spawner/directional/south, /obj/structure/railing, @@ -30653,26 +30682,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/wood, /area/station/command/meeting_room/council) -"jdT" = ( -/obj/item/paper_bin/carbon{ - pixel_x = -3; - pixel_y = 7 - }, -/obj/item/pen{ - pixel_x = -3; - pixel_y = 7 - }, -/obj/item/computer_disk/quartermaster, -/obj/item/computer_disk/quartermaster, -/obj/structure/table/wood, -/obj/machinery/status_display/supply{ - pixel_y = 32 - }, -/obj/machinery/light/warm/directional/north, -/turf/open/floor/iron/dark/smooth_edge{ - dir = 8 - }, -/area/station/cargo/quartermaster) "jeb" = ( /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 1 @@ -30849,6 +30858,10 @@ /obj/effect/turf_decal/lunar_sand/plating, /turf/open/floor/iron/dark, /area/station/science/cytology) +"jgb" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/station/security/bitden) "jgs" = ( /obj/effect/turf_decal/delivery, /obj/structure/closet/cardboard, @@ -30920,6 +30933,11 @@ "jhs" = ( /turf/closed/wall, /area/station/hallway/primary/central) +"jhw" = ( +/obj/machinery/light/red/directional/east, +/obj/machinery/byteforge, +/turf/open/floor/catwalk_floor, +/area/station/security/bitden) "jhz" = ( /obj/item/clothing/head/cone, /obj/effect/mapping_helpers/burnt_floor, @@ -31229,6 +31247,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark/smooth_large, /area/station/hallway/secondary/command) +"jmY" = ( +/obj/structure/toilet/greyscale{ + dir = 4 + }, +/obj/machinery/light/small/directional/west, +/obj/machinery/airalarm/directional/south, +/turf/open/floor/iron/dark, +/area/station/security/prison/safe) "jnh" = ( /obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral/full, @@ -31329,6 +31355,14 @@ }, /turf/open/floor/iron/white/side, /area/station/science/ordnance) +"joA" = ( +/obj/structure/table, +/obj/effect/turf_decal/tile/dark/diagonal_edge, +/obj/machinery/microwave{ + pixel_y = 6 + }, +/turf/open/floor/iron/kitchen/diagonal, +/area/station/security/prison) "joR" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/effect/mapping_helpers/airlock/access/any/engineering/general, @@ -34627,6 +34661,21 @@ /obj/structure/frame/machine/secured, /turf/open/floor/iron/dark/small, /area/station/science/research) +"kno" = ( +/obj/structure/table, +/obj/effect/turf_decal/tile/dark/full, +/obj/item/storage/bag/tray, +/obj/item/reagent_containers/condiment/saltshaker{ + pixel_x = -3; + pixel_y = 9 + }, +/obj/item/reagent_containers/condiment/peppermill{ + dir = 1; + pixel_x = 3; + pixel_y = 9 + }, +/turf/open/floor/iron/dark/smooth_large, +/area/station/security/prison) "knM" = ( /obj/effect/turf_decal/siding/white{ dir = 8 @@ -34875,14 +34924,6 @@ "kqN" = ( /turf/closed/wall/r_wall, /area/station/engineering/supermatter) -"kqS" = ( -/obj/machinery/newscaster/directional/north, -/obj/machinery/camera/directional/north{ - c_tag = "Library - Public Lounge" - }, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/carpet/green, -/area/station/service/library) "kqU" = ( /obj/structure/table, /obj/effect/spawner/random/entertainment/lighter{ @@ -35129,26 +35170,6 @@ /obj/item/gun/energy/temperature/security, /turf/open/floor/engine, /area/station/ai_monitored/security/armory) -"ksQ" = ( -/obj/machinery/airalarm/directional/south, -/obj/structure/table/wood, -/obj/item/reagent_containers/cup/glass/bottle/rum{ - pixel_y = 12 - }, -/obj/item/reagent_containers/cup/glass/bottle/whiskey{ - pixel_y = 9; - pixel_x = 6 - }, -/obj/item/reagent_containers/cup/glass/drinkingglass/shotglass{ - pixel_y = 5; - pixel_x = -9 - }, -/obj/item/reagent_containers/cup/glass/drinkingglass/shotglass{ - pixel_x = -2 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "ktc" = ( /obj/item/stack/sheet/cardboard, /obj/structure/disposalpipe/segment, @@ -35290,6 +35311,18 @@ /obj/effect/turf_decal/box, /turf/open/floor/iron/dark/smooth_large, /area/station/medical/pharmacy) +"kuQ" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/corporate{ + id_tag = "BSdoor"; + name = "Blueshield's Office" + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/iron/dark/smooth_large, +/area/station/command/meeting_room/council) "kuV" = ( /turf/open/openspace, /area/station/maintenance/port/fore) @@ -35394,21 +35427,6 @@ /obj/effect/turf_decal/lunar_sand/plating, /turf/open/floor/iron/dark, /area/station/science/xenobiology) -"kxn" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/dark/full, -/obj/item/storage/bag/tray, -/obj/item/reagent_containers/condiment/saltshaker{ - pixel_x = -3; - pixel_y = 9 - }, -/obj/item/reagent_containers/condiment/peppermill{ - dir = 1; - pixel_x = 3; - pixel_y = 9 - }, -/turf/open/floor/iron/dark/smooth_large, -/area/station/security/prison) "kxt" = ( /obj/machinery/door/firedoor, /obj/structure/disposalpipe/segment, @@ -36192,9 +36210,6 @@ /obj/structure/cable, /turf/open/floor/iron/dark/smooth_large, /area/station/medical/chemistry) -"kJn" = ( -/turf/closed/wall/r_wall, -/area/station/security/bitden) "kJu" = ( /obj/machinery/status_display/ai/directional/west, /turf/open/floor/iron, @@ -36611,6 +36626,16 @@ /obj/item/radio/intercom/directional/west, /turf/open/floor/carpet, /area/station/commons/vacant_room/office) +"kOW" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/curtain/cloth/fancy/mechanical{ + icon_state = "bounty-open"; + icon_type = "bounty"; + id = "Cell1Privacy"; + name = "curtain" + }, +/turf/open/floor/plating, +/area/station/security/prison/safe) "kOX" = ( /obj/structure/railing{ dir = 4 @@ -37261,14 +37286,6 @@ /obj/machinery/light/cold/directional/east, /turf/open/floor/iron/showroomfloor, /area/station/science/robotics/augments) -"kXq" = ( -/obj/machinery/photocopier, -/obj/effect/turf_decal/bot_white, -/obj/effect/turf_decal/siding/dark{ - dir = 8 - }, -/turf/open/floor/iron/large, -/area/station/cargo/quartermaster) "kXs" = ( /turf/open/floor/iron/dark/smooth_half, /area/station/cargo/storage) @@ -37764,12 +37781,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark/smooth_large, /area/station/security/corrections_officer) -"leH" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/quartermaster, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "leT" = ( /obj/machinery/door/firedoor, /turf/open/floor/iron/dark/smooth_large, @@ -37845,6 +37856,9 @@ /mob/living/simple_animal/bot/secbot/pingsky, /turf/open/floor/wood/large, /area/station/tcommsat/computer) +"lgc" = ( +/turf/closed/wall, +/area/station/security/bitden) "lgd" = ( /obj/effect/turf_decal/tile/red/real_red{ dir = 1 @@ -38146,17 +38160,6 @@ dir = 1 }, /area/station/security/holding_cell) -"ljw" = ( -/obj/structure/bed, -/obj/effect/landmark/start/prisoner, -/obj/item/bedsheet/brown, -/obj/machinery/button/curtain{ - id = "Cell1Privacy"; - pixel_x = 24; - pixel_y = 24 - }, -/turf/open/floor/iron/dark, -/area/station/security/prison/safe) "ljB" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -38425,10 +38428,6 @@ "lot" = ( /turf/closed/wall, /area/station/medical/patients_rooms) -"lov" = ( -/obj/structure/table, -/turf/open/floor/iron/dark/smooth_large, -/area/station/cargo/quartermaster) "loE" = ( /obj/effect/turf_decal/tile/dark_blue/opposingcorners, /obj/machinery/door/firedoor/border_only{ @@ -38642,6 +38641,16 @@ }, /turf/open/floor/plating, /area/station/construction/mining/aux_base) +"lsm" = ( +/obj/structure/table, +/obj/effect/turf_decal/tile/dark/diagonal_edge, +/obj/machinery/chem_dispenser/drinks{ + pixel_y = 6; + pixel_x = -2; + dir = 1 + }, +/turf/open/floor/iron/kitchen/diagonal, +/area/station/security/prison) "lsp" = ( /obj/effect/turf_decal/tile/blue, /obj/machinery/duct, @@ -39009,6 +39018,17 @@ "lyw" = ( /turf/closed/wall/r_wall, /area/station/command/bridge) +"lyO" = ( +/obj/structure/bed, +/obj/effect/landmark/start/prisoner, +/obj/machinery/button/curtain{ + id = "Cell2Privacy"; + pixel_x = 24; + pixel_y = -24 + }, +/obj/item/bedsheet/brown, +/turf/open/floor/iron/dark, +/area/station/security/prison/safe) "lyU" = ( /obj/structure/cable, /obj/effect/spawner/random/structure/table_or_rack, @@ -39068,6 +39088,11 @@ /obj/effect/turf_decal/tile/blue, /turf/open/floor/iron, /area/station/engineering/atmos/upper) +"lzS" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/event_spawn, +/turf/open/floor/iron/dark/small, +/area/station/security/bitden) "lzZ" = ( /obj/machinery/vending/cigarette, /obj/effect/turf_decal/bot_white, @@ -39109,6 +39134,19 @@ /obj/machinery/power/emitter, /turf/open/floor/plating, /area/station/engineering/storage_shared) +"lAE" = ( +/obj/effect/turf_decal/tile/dark/opposingcorners{ + dir = 1 + }, +/obj/effect/turf_decal/siding/white/corner, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/security/prison) "lAJ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -39655,18 +39693,6 @@ }, /turf/open/floor/iron/small, /area/station/hallway/primary/central) -"lJh" = ( -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/machinery/door/airlock/corporate{ - id_tag = "BSdoor"; - name = "Blueshield's Office" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/navigate_destination, -/turf/open/floor/iron/dark/smooth_large, -/area/station/command/heads_quarters/blueshield) "lJk" = ( /obj/machinery/holopad/secure, /obj/structure/cable, @@ -39727,6 +39753,18 @@ /obj/machinery/light/small/red/directional/south, /turf/open/floor/iron/dark, /area/station/service/chapel/funeral) +"lKq" = ( +/obj/machinery/pdapainter/supply, +/obj/effect/turf_decal/bot_white, +/obj/effect/turf_decal/siding/dark{ + dir = 8 + }, +/obj/item/toy/figure/qm{ + pixel_y = 14 + }, +/obj/machinery/light/warm/directional/east, +/turf/open/floor/iron/large, +/area/station/cargo/quartermaster) "lKt" = ( /obj/structure/trash_pile, /turf/open/floor/plating, @@ -40174,15 +40212,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/small, /area/station/hallway/secondary/command) -"lQD" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/airlock/grunge{ - id_tag = "Cell1Privacy"; - name = "Cell 1" - }, -/turf/open/floor/iron/dark/smooth_large, -/area/station/security/prison/safe) "lQL" = ( /obj/effect/turf_decal/tile/yellow/opposingcorners, /obj/effect/turf_decal/tile/yellow, @@ -40545,14 +40574,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron, /area/station/engineering/storage) -"lUq" = ( -/obj/machinery/button/door/directional/south{ - id = "qm"; - name = "Privacy Shutters Control"; - req_access = list("qm") - }, -/turf/open/floor/iron/dark/smooth_large, -/area/station/cargo/quartermaster) "lUt" = ( /obj/effect/turf_decal/lunar_sand, /obj/effect/decal/cleanable/dirt, @@ -40688,6 +40709,14 @@ /obj/structure/cable, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"lWK" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/wood, +/area/station/cargo/quartermaster) "lWS" = ( /obj/machinery/atmospherics/pipe/layer_manifold/scrubbers/visible, /turf/open/floor/engine, @@ -40961,14 +40990,6 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/engineering/atmos/upper) -"maO" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 4 - }, -/obj/structure/mirror/directional/west, -/obj/structure/sink/directional/east, -/turf/open/floor/iron/dark, -/area/station/security/prison/safe) "maU" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -41667,32 +41688,24 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/wood/large, /area/station/service/library) -"mlG" = ( -/obj/machinery/power/apc/auto_name/directional/south, -/obj/structure/cable, -/obj/machinery/computer/quantum_console{ - dir = 1 - }, -/obj/effect/turf_decal/box, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/tile/brown/half{ - dir = 4 - }, -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 4 - }, -/turf/open/floor/iron/dark/smooth_half{ - dir = 1 - }, -/area/station/security/bitden) "mlJ" = ( /obj/machinery/light/cold/directional/north, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /obj/machinery/atm/directional/north, /turf/open/floor/iron, /area/station/hallway/primary/central) +"mlL" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/structure/chair/office{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/quartermaster, +/turf/open/floor/wood, +/area/station/cargo/quartermaster) "mlU" = ( /obj/effect/turf_decal/stripes/line, /obj/structure/table/reinforced, @@ -41733,6 +41746,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/hallway/primary/central) +"mmk" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 10 + }, +/obj/machinery/computer/shuttle/mining{ + dir = 4 + }, +/obj/effect/turf_decal/box, +/turf/open/floor/wood, +/area/station/cargo/quartermaster) "mmp" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -41870,14 +41893,6 @@ "moK" = ( /turf/open/floor/iron, /area/station/engineering/atmos/upper) -"moL" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/dark/diagonal_edge, -/obj/machinery/microwave{ - pixel_y = 6 - }, -/turf/open/floor/iron/kitchen/diagonal, -/area/station/security/prison) "moV" = ( /obj/machinery/chem_dispenser/drinks{ pixel_y = 6; @@ -41913,6 +41928,15 @@ /obj/structure/cable, /turf/open/floor/iron/dark/corner, /area/station/commons/dorms) +"mpL" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/airlock/grunge{ + id_tag = "Cell2Privacy"; + name = "Cell 2" + }, +/turf/open/floor/iron/dark/smooth_large, +/area/station/security/prison/safe) "mpS" = ( /obj/structure/rack, /obj/effect/spawner/random/maintenance/two, @@ -42131,6 +42155,11 @@ /obj/structure/barricade/security, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"mtz" = ( +/obj/machinery/light/small/directional/north, +/obj/machinery/netpod, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/security/bitden) "mtE" = ( /obj/effect/turf_decal/siding/dark_blue/corner{ dir = 1 @@ -43075,6 +43104,11 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/dark, /area/station/service/abandoned_gambling_den) +"mGq" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark/small, +/area/station/security/bitden) "mGK" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted, /obj/effect/turf_decal/tile/blue, @@ -43528,6 +43562,17 @@ /obj/machinery/light_switch/directional/north, /turf/open/floor/iron/dark/small, /area/station/science/circuits) +"mMK" = ( +/obj/structure/chair/office{ + dir = 4 + }, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/machinery/camera/directional/north{ + c_tag = "Cargo - Quartermaster Office" + }, +/obj/structure/cable, +/turf/open/floor/iron/dark/smooth_large, +/area/station/cargo/quartermaster) "mNa" = ( /obj/machinery/conveyor{ id = "QMLoad2" @@ -44001,9 +44046,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/small, /area/station/hallway/secondary/exit/departure_lounge) -"mSw" = ( -/turf/closed/wall/r_wall, -/area/station/security/prison/safe) "mSD" = ( /obj/machinery/disposal/bin, /obj/effect/turf_decal/stripes/end{ @@ -44276,20 +44318,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/hallway/secondary/command) -"mWR" = ( -/obj/structure/table, -/obj/effect/turf_decal/bot_white, -/obj/effect/turf_decal/siding/dark{ - dir = 8 - }, -/obj/item/mining_voucher, -/obj/item/gps/mining{ - gpstag = "QM0"; - pixel_y = 4 - }, -/obj/machinery/light_switch/directional/east, -/turf/open/floor/iron/large, -/area/station/cargo/quartermaster) "mWV" = ( /obj/effect/turf_decal/tile/dark_blue{ dir = 4 @@ -45116,11 +45144,6 @@ }, /turf/open/floor/plating, /area/station/service/kitchen/diner) -"nkG" = ( -/obj/effect/mapping_helpers/burnt_floor, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/aft/greater) "nkH" = ( /obj/structure/chair/pew/left{ dir = 4 @@ -46182,6 +46205,15 @@ /obj/effect/spawner/random/entertainment/cigarette, /turf/open/floor/wood/tile, /area/station/commons/lounge) +"nyK" = ( +/obj/machinery/airalarm/directional/south, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/wood/large, +/area/station/command/heads_quarters/blueshield) "nzg" = ( /obj/structure/stairs/north, /turf/open/floor/plating, @@ -46584,6 +46616,15 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/glass/reinforced, /area/station/science/xenobiology) +"nGb" = ( +/obj/structure/chair/comfy/brown{ + dir = 8 + }, +/obj/machinery/firealarm/directional/east, +/obj/structure/disposalpipe/segment, +/obj/effect/landmark/start/quartermaster, +/turf/open/floor/iron/dark/small, +/area/station/cargo/quartermaster) "nGd" = ( /obj/machinery/modular_computer/preset/engineering{ dir = 8 @@ -46878,6 +46919,16 @@ "nMl" = ( /turf/open/floor/iron, /area/station/hallway/secondary/exit) +"nMm" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 9 + }, +/obj/machinery/computer/security/qm{ + dir = 4 + }, +/obj/effect/turf_decal/box, +/turf/open/floor/wood, +/area/station/cargo/quartermaster) "nMt" = ( /turf/closed/wall/r_wall, /area/station/maintenance/port/fore) @@ -48391,22 +48442,6 @@ "okh" = ( /turf/open/floor/iron/dark, /area/station/command/meeting_room/council) -"oks" = ( -/obj/item/radio/intercom/directional/north, -/obj/machinery/light/red/directional/north, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/tile/brown/half{ - dir = 4 - }, -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 4 - }, -/turf/open/floor/iron/dark/smooth_half{ - dir = 1 - }, -/area/station/security/bitden) "okv" = ( /turf/closed/wall/r_wall, /area/station/engineering/transit_tube) @@ -49215,6 +49250,16 @@ /obj/effect/turf_decal/vg_decals/atmos/nitrous_oxide, /turf/open/floor/engine/n2o, /area/station/engineering/atmos/upper) +"ovR" = ( +/obj/machinery/camera/directional/north{ + c_tag = "Cargo - Bitrunner Office" + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 8 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/turf/open/floor/iron/dark/small, +/area/station/security/bitden) "ovW" = ( /obj/machinery/door/firedoor, /obj/effect/mapping_helpers/airlock/access/all/supply/mining, @@ -50096,20 +50141,6 @@ /obj/item/radio/intercom/directional/south, /turf/open/floor/iron/white/small, /area/station/science/genetics) -"oMj" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/tile/purple/half{ - dir = 4 - }, -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 4 - }, -/turf/open/floor/iron/dark/smooth_half{ - dir = 1 - }, -/area/station/security/bitden) "oMk" = ( /obj/structure/table/glass, /obj/effect/turf_decal/siding/wood/end{ @@ -50162,6 +50193,26 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/small, /area/station/hallway/secondary/exit/departure_lounge) +"oMK" = ( +/obj/machinery/airalarm/directional/south, +/obj/structure/table/wood, +/obj/item/reagent_containers/cup/glass/bottle/rum{ + pixel_y = 12 + }, +/obj/item/reagent_containers/cup/glass/bottle/whiskey{ + pixel_y = 9; + pixel_x = 6 + }, +/obj/item/reagent_containers/cup/glass/drinkingglass/shotglass{ + pixel_y = 5; + pixel_x = -9 + }, +/obj/item/reagent_containers/cup/glass/drinkingglass/shotglass{ + pixel_x = -2 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "oML" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -50264,6 +50315,10 @@ /obj/item/stack/cable_coil/five, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"oOC" = ( +/obj/structure/table, +/turf/open/floor/iron/dark/smooth_large, +/area/station/cargo/quartermaster) "oOH" = ( /obj/structure/closet/secure_closet/security/science, /obj/machinery/requests_console/auto_name/directional/north, @@ -50291,12 +50346,6 @@ /obj/effect/turf_decal/box, /turf/open/floor/engine, /area/station/engineering/atmos) -"oPc" = ( -/obj/effect/turf_decal/tile/dark/opposingcorners{ - dir = 1 - }, -/turf/closed/wall/r_wall, -/area/station/security/prison/safe) "oPz" = ( /obj/structure/fluff/paper/stack, /obj/effect/mapping_helpers/broken_floor, @@ -50669,14 +50718,6 @@ /obj/structure/stairs/east, /turf/open/floor/plating, /area/station/maintenance/department/security/lower) -"oVY" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/wood, -/area/station/cargo/quartermaster) "oVZ" = ( /obj/effect/turf_decal/box/corners{ dir = 4 @@ -50767,25 +50808,6 @@ /obj/structure/stairs/east, /turf/open/floor/plating, /area/station/engineering/supermatter/room) -"oXZ" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/curtain/cloth/fancy/mechanical{ - icon_state = "bounty-open"; - icon_type = "bounty"; - id = "Cell3Privacy"; - name = "curtain" - }, -/turf/open/floor/plating, -/area/station/security/prison/safe) -"oYc" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/airlock/grunge{ - id_tag = "Cell3Privacy"; - name = "Cell 3" - }, -/turf/open/floor/iron/dark/smooth_large, -/area/station/security/prison/safe) "oYe" = ( /obj/effect/spawner/random/structure/crate, /turf/open/floor/plating, @@ -51053,6 +51075,18 @@ /obj/effect/spawner/random/engineering/flashlight, /turf/open/openspace, /area/station/maintenance/starboard/greater) +"pcp" = ( +/obj/structure/closet/secure_closet/quartermaster, +/obj/effect/turf_decal/bot_white, +/obj/effect/turf_decal/siding/dark{ + dir = 4 + }, +/obj/item/clothing/glasses/material/mining/gar, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/turf/open/floor/iron/large, +/area/station/cargo/quartermaster) "pcv" = ( /obj/effect/turf_decal/tile/dark_blue/half, /obj/structure/cable, @@ -51187,6 +51221,26 @@ /obj/machinery/light/cold/no_nightlight/directional/east, /turf/open/openspace, /area/station/medical/chemistry) +"peI" = ( +/obj/machinery/power/apc/auto_name/directional/south, +/obj/structure/cable, +/obj/machinery/computer/quantum_console{ + dir = 1 + }, +/obj/effect/turf_decal/box, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/turf/open/floor/iron/dark/smooth_half{ + dir = 1 + }, +/area/station/security/bitden) "pfs" = ( /obj/machinery/door/firedoor, /obj/machinery/biogenerator, @@ -51365,14 +51419,6 @@ /obj/item/stack/rods/twentyfive, /turf/open/floor/iron/white, /area/station/medical/chemistry) -"piB" = ( -/obj/structure/toilet/greyscale{ - dir = 4 - }, -/obj/machinery/light/small/directional/west, -/obj/machinery/airalarm/directional/south, -/turf/open/floor/iron/dark, -/area/station/security/prison/safe) "piC" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -52086,10 +52132,6 @@ /obj/structure/window/reinforced/spawner/directional/west, /turf/open/floor/iron/dark/smooth_large, /area/station/engineering/atmos/storage) -"ptg" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/station/security/bitden) "ptp" = ( /turf/closed/wall, /area/station/commons/dorms/room6) @@ -52103,15 +52145,6 @@ /obj/effect/landmark/navigate_destination, /turf/open/floor/iron/dark/smooth_large, /area/station/commons/storage/primary) -"ptu" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 8 - }, -/turf/open/floor/iron/dark/small, -/area/station/security/bitden) "pty" = ( /obj/structure/table/reinforced, /obj/item/radio/intercom/directional/west, @@ -52221,6 +52254,10 @@ /mob/living/basic/rabbit/daisy, /turf/open/floor/wood, /area/station/service/library/lounge) +"pux" = ( +/obj/machinery/drone_dispenser/preloaded, +/turf/open/floor/plating, +/area/station/maintenance/port/lesser) "puz" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ @@ -52245,6 +52282,20 @@ /obj/structure/sign/warning/electric_shock/directional/west, /turf/open/floor/iron/dark/smooth_large, /area/station/engineering/main) +"puO" = ( +/obj/structure/table, +/obj/effect/turf_decal/tile/dark/diagonal_edge, +/obj/machinery/camera/directional/east{ + c_tag = "Security - Permabrig Kitchen"; + network = list("ss13","prison") + }, +/obj/machinery/chem_dispenser/drinks/beer{ + pixel_y = 6; + pixel_x = 2; + dir = 1 + }, +/turf/open/floor/iron/kitchen/diagonal, +/area/station/security/prison) "puQ" = ( /obj/machinery/door/airlock/security/glass{ name = "Brig Control" @@ -52791,10 +52842,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/security/prison/visit) -"pCv" = ( -/obj/machinery/smartfridge/food, -/turf/closed/wall/r_wall, -/area/station/security/corrections_officer) "pCB" = ( /obj/machinery/button/door/directional/west{ id = "surgeryleft"; @@ -53101,17 +53148,6 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron, /area/station/engineering/atmos/upper) -"pGD" = ( -/obj/structure/bed, -/obj/effect/landmark/start/prisoner, -/obj/machinery/button/curtain{ - id = "Cell2Privacy"; - pixel_x = 24; - pixel_y = -24 - }, -/obj/item/bedsheet/brown, -/turf/open/floor/iron/dark, -/area/station/security/prison/safe) "pGG" = ( /obj/effect/spawner/random/maintenance, /obj/structure/table, @@ -54137,6 +54173,17 @@ /obj/effect/turf_decal/stripes/white/box, /turf/open/floor/plating, /area/station/ai_monitored/turret_protected/aisat_interior) +"pXd" = ( +/obj/structure/bed, +/obj/effect/landmark/start/prisoner, +/obj/item/bedsheet/brown, +/obj/machinery/button/curtain{ + id = "Cell1Privacy"; + pixel_x = 24; + pixel_y = 24 + }, +/turf/open/floor/iron/dark, +/area/station/security/prison/safe) "pXh" = ( /obj/structure/lattice/catwalk, /obj/structure/disposalpipe/segment{ @@ -54229,25 +54276,6 @@ "pYE" = ( /turf/closed/wall/r_wall, /area/station/tcommsat/server) -"pYJ" = ( -/obj/structure/table/wood, -/obj/item/folder/yellow{ - pixel_y = 12; - pixel_x = 5 - }, -/obj/item/stamp/head/qm{ - pixel_y = 5 - }, -/obj/item/stamp{ - pixel_x = 5 - }, -/obj/item/stamp/denied{ - pixel_x = -5 - }, -/turf/open/floor/iron/dark/smooth_edge{ - dir = 8 - }, -/area/station/cargo/quartermaster) "pYQ" = ( /obj/structure/sign/directions/evac/directional/north{ dir = 4 @@ -54708,6 +54736,15 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron, /area/station/engineering/atmos/upper) +"qeT" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/machinery/requests_console/auto_name/directional/west, +/obj/effect/mapping_helpers/requests_console/information, +/obj/effect/mapping_helpers/requests_console/assistance, +/turf/open/floor/wood, +/area/station/cargo/quartermaster) "qeV" = ( /obj/structure/table, /obj/item/reagent_containers/cup/glass/drinkingglass{ @@ -55573,12 +55610,23 @@ /obj/structure/cable, /turf/open/floor/iron/dark/telecomms, /area/station/tcommsat/server) +"qrR" = ( +/obj/item/assembly/mousetrap/armed, +/obj/item/crowbar/large{ + pixel_y = 20 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/maintenance/starboard/fore) "qrZ" = ( /obj/effect/turf_decal/tile/dark_blue/opposingcorners, /turf/open/floor/iron/dark/side{ dir = 10 }, /area/station/security/brig/entrance) +"qsd" = ( +/turf/closed/wall/r_wall, +/area/station/security/prison/safe) "qsh" = ( /obj/structure/lattice, /obj/item/stack/sheet/iron/fifty, @@ -55875,6 +55923,16 @@ }, /turf/open/floor/iron/white/side, /area/station/hallway/primary/starboard) +"qwQ" = ( +/obj/machinery/door/airlock/mining/glass{ + name = "Drone Bay" + }, +/obj/effect/mapping_helpers/airlock/access/any/supply/qm, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/firedoor, +/turf/open/floor/iron/dark/smooth_large, +/area/station/cargo/quartermaster) "qwT" = ( /obj/effect/turf_decal/tile/green/half/contrasted, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -56105,16 +56163,6 @@ /obj/item/surgery_tray, /turf/open/floor/iron/showroomfloor, /area/station/science/robotics/augments) -"qzh" = ( -/obj/machinery/door/airlock/mining/glass{ - name = "Drone Bay" - }, -/obj/effect/mapping_helpers/airlock/access/any/supply/qm, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/firedoor, -/turf/open/floor/iron/dark/smooth_large, -/area/station/cargo/quartermaster) "qzA" = ( /obj/structure/cable, /obj/machinery/airalarm/directional/south, @@ -56567,11 +56615,6 @@ /obj/structure/cable, /turf/open/floor/engine, /area/station/engineering/gravity_generator) -"qIC" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/dark/small, -/area/station/security/bitden) "qIE" = ( /obj/effect/landmark/start/assistant, /turf/open/floor/glass/reinforced, @@ -56909,6 +56952,20 @@ /obj/effect/spawner/random/engineering/tank, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"qNY" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/turf/open/floor/iron/dark/smooth_half{ + dir = 1 + }, +/area/station/security/bitden) "qOg" = ( /obj/structure/lattice/catwalk, /obj/structure/cable, @@ -58238,15 +58295,6 @@ dir = 4 }, /area/station/service/chapel) -"rjM" = ( -/obj/effect/turf_decal/tile/dark_red/opposingcorners{ - dir = 1 - }, -/obj/structure/chair/stool/bar/directional/north, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/checker, -/area/station/maintenance/abandon_diner) "rjN" = ( /obj/structure/railing{ dir = 8 @@ -58771,6 +58819,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"rud" = ( +/obj/effect/turf_decal/tile/dark/opposingcorners{ + dir = 1 + }, +/turf/closed/wall/r_wall, +/area/station/security/prison/safe) "rue" = ( /obj/effect/turf_decal/tile/dark_blue{ dir = 1 @@ -58964,6 +59018,17 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/diagonal, /area/station/security/courtroom) +"rwC" = ( +/obj/item/reagent_containers/cup/bucket, +/obj/machinery/flasher/directional/south{ + id = "Isolation" + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/effect/mapping_helpers/burnt_floor, +/turf/open/floor/iron/dark/small, +/area/station/security/prison/safe) "rwD" = ( /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/green{ @@ -59086,14 +59151,6 @@ dir = 8 }, /area/station/hallway/secondary/entry) -"ryj" = ( -/obj/item/assembly/mousetrap/armed, -/obj/item/crowbar/large{ - pixel_y = 20 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/maintenance/starboard/fore) "ryx" = ( /obj/structure/window/fulltile, /obj/structure/hedge, @@ -59163,6 +59220,13 @@ /obj/item/trash/syndi_cakes, /turf/open/floor/plating, /area/station/maintenance/department/bridge) +"rzw" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark, +/area/station/security/prison/safe) "rzH" = ( /obj/machinery/atmospherics/components/tank, /obj/machinery/light/cold/directional/south, @@ -59284,14 +59348,6 @@ /obj/effect/turf_decal/box, /turf/open/floor/iron/dark/smooth_large, /area/station/ai_monitored/command/nuke_storage) -"rCw" = ( -/obj/structure/disposalpipe/segment{ - dir = 9 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/dark/small, -/area/station/cargo/quartermaster) "rCS" = ( /obj/effect/turf_decal/box/blue, /obj/item/banner/blue, @@ -59552,11 +59608,6 @@ "rGK" = ( /turf/closed/wall, /area/station/hallway/primary/central/fore) -"rGR" = ( -/obj/structure/bed, -/obj/item/bedsheet/qm, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "rGW" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -59750,6 +59801,10 @@ dir = 4 }, /area/station/security/brig/entrance) +"rLd" = ( +/obj/machinery/smartfridge/food, +/turf/closed/wall/r_wall, +/area/station/security/corrections_officer) "rLh" = ( /obj/structure/railing, /obj/effect/turf_decal/siding/white, @@ -59792,6 +59847,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark/smooth_edge, /area/station/service/hydroponics) +"rMl" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/curtain/cloth/fancy/mechanical{ + icon_state = "bounty-open"; + icon_type = "bounty"; + id = "Cell3Privacy"; + name = "curtain" + }, +/turf/open/floor/plating, +/area/station/security/prison/safe) "rMm" = ( /obj/item/clothing/head/cone, /obj/structure/disposalpipe/segment, @@ -62539,6 +62604,14 @@ }, /turf/open/floor/wood/tile, /area/station/service/theater) +"szf" = ( +/obj/machinery/button/door/directional/south{ + id = "qm"; + name = "Privacy Shutters Control"; + req_access = list("qm") + }, +/turf/open/floor/iron/dark/smooth_large, +/area/station/cargo/quartermaster) "szi" = ( /obj/machinery/firealarm/directional/south, /obj/machinery/camera/directional/south{ @@ -62663,6 +62736,14 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) +"sAK" = ( +/obj/structure/railing{ + dir = 8 + }, +/obj/structure/cable, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/lesser) "sAL" = ( /obj/structure/sign/poster/random/directional/north, /obj/structure/disposalpipe/broken, @@ -63551,6 +63632,17 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/visible, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"sNO" = ( +/obj/effect/turf_decal/bot_white, +/obj/effect/turf_decal/siding/dark{ + dir = 4 + }, +/obj/machinery/light/small/directional/south, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/turf/open/floor/iron/large, +/area/station/cargo/quartermaster) "sNQ" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/hatch{ @@ -63561,10 +63653,6 @@ /obj/structure/cable, /turf/open/floor/iron/dark/smooth_large, /area/station/tcommsat/computer) -"sNS" = ( -/obj/machinery/netpod, -/turf/open/floor/catwalk_floor/iron_dark, -/area/station/security/bitden) "sNT" = ( /obj/structure/table/wood, /obj/effect/spawner/random/bureaucracy/folder{ @@ -63626,6 +63714,11 @@ }, /turf/open/floor/carpet, /area/station/medical/psychology) +"sPb" = ( +/obj/effect/mapping_helpers/burnt_floor, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/aft/greater) "sPj" = ( /obj/effect/turf_decal/tile/purple/opposingcorners, /obj/effect/turf_decal/tile/blue{ @@ -63786,6 +63879,15 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron, /area/station/maintenance/port/aft) +"sRZ" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/airlock/grunge{ + id_tag = "Cell1Privacy"; + name = "Cell 1" + }, +/turf/open/floor/iron/dark/smooth_large, +/area/station/security/prison/safe) "sSc" = ( /obj/effect/turf_decal/weather/dirt, /obj/item/flashlight/lantern{ @@ -63906,20 +64008,6 @@ dir = 8 }, /area/station/hallway/primary/central) -"sUg" = ( -/obj/effect/turf_decal/bot_white, -/obj/effect/turf_decal/siding/dark{ - dir = 8 - }, -/obj/structure/table, -/obj/machinery/fax{ - fax_name = "Quartermaster's Office"; - name = "Quartermaster's Fax Machine"; - pixel_y = 3 - }, -/obj/machinery/light/warm/directional/east, -/turf/open/floor/iron/large, -/area/station/cargo/quartermaster) "sUp" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 4 @@ -64086,12 +64174,6 @@ /obj/effect/spawner/random/structure/closet_maintenance, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"sWM" = ( -/obj/effect/turf_decal/tile/dark/diagonal_edge, -/obj/machinery/light/warm/directional/north, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron/kitchen/diagonal, -/area/station/security/prison) "sWN" = ( /obj/effect/turf_decal/tile/purple, /obj/effect/turf_decal/tile/green{ @@ -64655,16 +64737,6 @@ }, /turf/open/floor/iron, /area/station/security/checkpoint/engineering) -"tfp" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/dark/diagonal_edge, -/obj/machinery/chem_dispenser/drinks{ - pixel_y = 6; - pixel_x = -2; - dir = 1 - }, -/turf/open/floor/iron/kitchen/diagonal, -/area/station/security/prison) "tfq" = ( /obj/effect/turf_decal/tile/dark_blue/half{ dir = 8 @@ -64974,6 +65046,16 @@ /obj/structure/cable, /turf/open/floor/iron/dark/smooth_half, /area/station/service/hydroponics) +"tjZ" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 8; + id = "qm"; + name = "Privacy Shutters" + }, +/turf/open/floor/plating, +/area/station/cargo/quartermaster) "tkj" = ( /obj/machinery/airalarm/directional/east, /obj/machinery/light/warm/directional/east, @@ -65179,18 +65261,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/dark/smooth_large, /area/station/security/evidence) -"tnM" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/holopad/secure, -/obj/effect/landmark/event_spawn, -/turf/open/floor/iron/dark/smooth_edge{ - dir = 8 - }, -/area/station/cargo/quartermaster) "toe" = ( /obj/effect/turf_decal/tile/brown{ dir = 4 @@ -65344,10 +65414,6 @@ /obj/machinery/light_switch/directional/north, /turf/open/floor/iron, /area/station/commons/vacant_room/commissary) -"tql" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "tqq" = ( /obj/machinery/atmospherics/pipe/multiz/purple/visible{ dir = 1; @@ -65476,6 +65542,14 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/science/research) +"tsn" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/wood, +/area/station/cargo/quartermaster) "tsE" = ( /obj/effect/turf_decal/tile/blue/opposingcorners{ dir = 1 @@ -65697,6 +65771,14 @@ /obj/machinery/door/airlock/mining/glass, /turf/open/floor/iron/dark/smooth_large, /area/station/cargo/storage) +"twL" = ( +/obj/structure/toilet/greyscale{ + dir = 4 + }, +/obj/machinery/light/small/directional/west, +/obj/machinery/airalarm/directional/north, +/turf/open/floor/iron/dark, +/area/station/security/prison/safe) "twM" = ( /obj/structure/lattice, /obj/machinery/atmospherics/pipe/heat_exchanging/simple, @@ -66419,15 +66501,6 @@ /obj/item/radio/intercom/directional/south, /turf/open/floor/wood, /area/station/service/library/lounge) -"tJv" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/airlock/grunge{ - id_tag = "Cell2Privacy"; - name = "Cell 2" - }, -/turf/open/floor/iron/dark/smooth_large, -/area/station/security/prison/safe) "tJE" = ( /obj/effect/turf_decal/tile/green, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -66726,19 +66799,6 @@ /obj/structure/transit_tube, /turf/open/floor/plating, /area/station/cargo/lobby) -"tPB" = ( -/obj/effect/turf_decal/tile/dark/opposingcorners{ - dir = 1 - }, -/obj/effect/turf_decal/siding/white/corner, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/firedoor/border_only{ - dir = 1 - }, -/obj/structure/cable, -/turf/open/floor/iron/dark, -/area/station/security/prison) "tPF" = ( /obj/effect/turf_decal/tile/purple, /obj/effect/turf_decal/tile/purple/half/contrasted, @@ -68598,17 +68658,6 @@ /obj/structure/window/reinforced/spawner/directional/east, /turf/open/floor/iron/diagonal, /area/station/security/courtroom) -"uqC" = ( -/obj/structure/bed, -/obj/effect/landmark/start/prisoner, -/obj/item/bedsheet/brown, -/obj/machinery/button/curtain{ - id = "Cell3Privacy"; - pixel_x = 24; - pixel_y = 24 - }, -/turf/open/floor/iron/dark, -/area/station/security/prison/safe) "uqJ" = ( /obj/effect/turf_decal/tile/dark/opposingcorners{ dir = 1 @@ -69557,18 +69606,6 @@ }, /turf/open/floor/engine, /area/station/science/xenobiology) -"uEB" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/structure/chair/office{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/quartermaster, -/turf/open/floor/wood, -/area/station/cargo/quartermaster) "uFd" = ( /obj/effect/spawner/random/maintenance/three, /turf/open/floor/plating, @@ -70020,6 +70057,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/wood/tile, /area/station/commons/lounge) +"uLx" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/obj/structure/mirror/directional/west, +/obj/structure/sink/directional/east, +/turf/open/floor/iron/dark, +/area/station/security/prison/safe) "uLP" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 4 @@ -70391,17 +70436,6 @@ /obj/machinery/light/warm/directional/south, /turf/open/floor/iron/kitchen, /area/station/service/kitchen) -"uQN" = ( -/obj/structure/chair/office{ - dir = 4 - }, -/obj/machinery/power/apc/auto_name/directional/north, -/obj/machinery/camera/directional/north{ - c_tag = "Cargo - Quartermaster Office" - }, -/obj/structure/cable, -/turf/open/floor/iron/dark/smooth_large, -/area/station/cargo/quartermaster) "uQZ" = ( /obj/effect/turf_decal/tile/yellow/half{ dir = 4 @@ -70819,6 +70853,13 @@ /obj/effect/landmark/start/medical_doctor, /turf/open/floor/iron/dark, /area/station/medical/treatment_center) +"uXY" = ( +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/iron, +/area/station/service/forge) "uYc" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/camera/directional/west{ @@ -70873,12 +70914,6 @@ /obj/structure/cable/multilayer/multiz, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"uYG" = ( -/obj/machinery/airalarm/directional/east, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/iron/dark/small, -/area/station/cargo/quartermaster) "uYI" = ( /obj/machinery/power/tracker, /obj/structure/cable, @@ -71229,6 +71264,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/hallway/primary/central) +"vcw" = ( +/obj/machinery/netpod, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/security/bitden) "vcy" = ( /obj/machinery/camera/directional/south{ c_tag = "MiniSat External North-East"; @@ -71322,13 +71361,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/storage) -"veA" = ( -/obj/effect/turf_decal/weather/dirt{ - dir = 8 - }, -/obj/structure/reagent_dispensers/watertank/high, -/turf/open/floor/grass, -/area/station/security/prison) "veB" = ( /obj/structure/sign/warning/secure_area/directional/north, /obj/structure/marker_beacon/burgundy, @@ -71684,18 +71716,6 @@ /obj/item/clothing/glasses/regular, /turf/open/floor/carpet/green, /area/station/service/library/lounge) -"vjl" = ( -/obj/machinery/pdapainter/supply, -/obj/effect/turf_decal/bot_white, -/obj/effect/turf_decal/siding/dark{ - dir = 8 - }, -/obj/item/toy/figure/qm{ - pixel_y = 14 - }, -/obj/machinery/light/warm/directional/east, -/turf/open/floor/iron/large, -/area/station/cargo/quartermaster) "vjq" = ( /obj/machinery/computer/atmos_alert{ dir = 8 @@ -72016,14 +72036,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/wood, /area/station/medical/psychology) -"voG" = ( -/obj/structure/toilet/greyscale{ - dir = 4 - }, -/obj/machinery/light/small/directional/west, -/obj/machinery/airalarm/directional/north, -/turf/open/floor/iron/dark, -/area/station/security/prison/safe) "voI" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/iron, @@ -72133,6 +72145,14 @@ dir = 8 }, /area/station/science/robotics/lab) +"vqq" = ( +/obj/structure/chair/office{ + dir = 4 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/turf/open/floor/iron/dark/smooth_large, +/area/station/cargo/quartermaster) "vqA" = ( /obj/machinery/door/airlock/maintenance_hatch{ name = "Atmospherics Storage Maintenance" @@ -72366,16 +72386,6 @@ }, /turf/open/floor/iron, /area/station/security/prison) -"vuW" = ( -/obj/machinery/camera/directional/north{ - c_tag = "Cargo - Bitrunner Office" - }, -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 8 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/turf/open/floor/iron/dark/small, -/area/station/security/bitden) "vva" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 @@ -72622,6 +72632,20 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, /turf/open/floor/iron/dark/smooth_large, /area/station/ai_monitored/turret_protected/ai) +"vyU" = ( +/obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/access/any/supply/qm, +/obj/machinery/door/airlock/mining/glass{ + name = "Drone Bay" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/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/smooth_large, +/area/station/cargo/quartermaster) "vzd" = ( /obj/structure/sign/warning/radiation/rad_area/directional/north, /obj/effect/turf_decal/tile/yellow{ @@ -72714,6 +72738,12 @@ }, /turf/open/floor/plastic, /area/station/common/carpshop) +"vAq" = ( +/obj/item/restraints/legcuffs/beartrap/prearmed, +/obj/item/stack/sheet/iron/five, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "vAr" = ( /obj/structure/table/reinforced, /turf/open/floor/iron/kitchen, @@ -74182,6 +74212,9 @@ /obj/structure/stairs/south, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) +"vTK" = ( +/turf/open/floor/iron/dark/smooth_large, +/area/station/cargo/quartermaster) "vTQ" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -74502,15 +74535,6 @@ dir = 4 }, /area/station/ai_monitored/turret_protected/aisat/teleporter) -"vYn" = ( -/obj/effect/mapping_helpers/airlock/access/all/security/brig, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/airlock/security{ - id_tag = "IsolationCell"; - name = "Isolation Cell" - }, -/turf/open/floor/iron/dark/smooth_large, -/area/station/security/prison/safe) "vYo" = ( /obj/machinery/atmospherics/pipe/smart/simple/orange/visible{ dir = 9 @@ -74603,6 +74627,13 @@ /obj/structure/railing, /turf/open/floor/iron/dark/smooth_large, /area/station/command/meeting_room/council) +"vZi" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 8 + }, +/obj/structure/reagent_dispensers/watertank/high, +/turf/open/floor/grass, +/area/station/security/prison) "vZj" = ( /obj/structure/chair/sofa/bench/left, /obj/effect/turf_decal/siding/wood{ @@ -74973,6 +75004,10 @@ dir = 5 }, /area/station/service/kitchen/diner) +"weM" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "weN" = ( /obj/structure/lattice/catwalk, /turf/open/openspace, @@ -75208,6 +75243,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/commons/storage/mining) +"win" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/quartermaster, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "wip" = ( /obj/machinery/door/airlock/hatch{ id_tag = "vacant_space"; @@ -75645,18 +75686,6 @@ /obj/structure/cable, /turf/open/floor/iron/dark/smooth_large, /area/station/command/heads_quarters/cmo) -"wnQ" = ( -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/machinery/door/airlock/corporate{ - id_tag = "BSdoor"; - name = "Blueshield's Office" - }, -/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/smooth_large, -/area/station/command/meeting_room/council) "wnX" = ( /obj/structure/chair/pew/left, /turf/open/floor/iron/chapel{ @@ -75821,11 +75850,6 @@ /obj/effect/landmark/blobstart, /turf/open/floor/iron/diagonal, /area/station/security/courtroom) -"wqI" = ( -/obj/structure/window/reinforced/tinted/fulltile, -/obj/structure/hedge/opaque, -/turf/open/floor/iron/dark/smooth_large, -/area/station/cargo/quartermaster) "wrd" = ( /obj/effect/turf_decal/siding/wood{ dir = 4 @@ -75978,17 +76002,6 @@ /obj/structure/closet/secure_closet/personal/patient, /turf/open/floor/wood/parquet, /area/station/medical/patients_rooms) -"wtv" = ( -/obj/item/reagent_containers/cup/bucket, -/obj/machinery/flasher/directional/south{ - id = "Isolation" - }, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/iron/dark/small, -/area/station/security/prison/safe) "wtE" = ( /obj/effect/turf_decal/tile/dark/opposingcorners{ dir = 1 @@ -76476,6 +76489,10 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/medical/surgery/aft) +"wAI" = ( +/obj/machinery/quantum_server, +/turf/open/floor/catwalk_floor, +/area/station/security/bitden) "wAJ" = ( /obj/structure/railing{ dir = 1 @@ -76523,12 +76540,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/starboard/greater) -"wBd" = ( -/obj/item/restraints/legcuffs/beartrap/prearmed, -/obj/item/stack/sheet/iron/five, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "wBk" = ( /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ dir = 4 @@ -76551,20 +76562,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/openspace, /area/station/maintenance/department/security/upper) -"wBv" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/dark/diagonal_edge, -/obj/machinery/camera/directional/east{ - c_tag = "Security - Permabrig Kitchen"; - network = list("ss13","prison") - }, -/obj/machinery/chem_dispenser/drinks/beer{ - pixel_y = 6; - pixel_x = 2; - dir = 1 - }, -/turf/open/floor/iron/kitchen/diagonal, -/area/station/security/prison) "wBw" = ( /obj/structure/cable, /obj/effect/turf_decal/trimline/blue/filled/line{ @@ -77470,15 +77467,6 @@ /obj/structure/stairs/north, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) -"wOl" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/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/smooth_large, -/area/station/cargo/quartermaster) "wOt" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 8 @@ -78504,6 +78492,15 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/hallway/secondary/command) +"xfV" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 8 + }, +/turf/open/floor/iron/dark/small, +/area/station/security/bitden) "xfY" = ( /obj/machinery/door/morgue{ name = "Massage Lounge" @@ -78974,6 +78971,9 @@ dir = 8 }, /area/station/service/salon) +"xnQ" = ( +/turf/closed/wall/r_wall, +/area/station/security/bitden) "xnS" = ( /obj/item/kirbyplants/organic/plant22, /obj/effect/turf_decal/siding/dark/end{ @@ -79148,6 +79148,11 @@ /obj/item/stack/sheet/iron/five, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"xrc" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "xro" = ( /obj/effect/turf_decal/trimline/neutral/warning{ dir = 4 @@ -79181,6 +79186,17 @@ /obj/machinery/light/cold/directional/west, /turf/open/floor/iron/dark, /area/station/security/checkpoint/customs) +"xrM" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/corporate{ + id_tag = "BSdoor"; + name = "Blueshield's Quarters" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/iron/dark/smooth_large, +/area/station/command/heads_quarters/blueshield) "xsq" = ( /obj/effect/spawner/random/trash/grime, /obj/structure/disposalpipe/segment{ @@ -79199,10 +79215,6 @@ /obj/structure/cable, /turf/open/floor/wood, /area/station/commons/dorms/room3) -"xsI" = ( -/obj/machinery/airalarm/directional/north, -/turf/open/floor/iron/dark/small, -/area/station/security/bitden) "xsO" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -79814,6 +79826,11 @@ dir = 8 }, /area/station/maintenance/starboard/fore) +"xCl" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable, +/turf/open/floor/plating, +/area/station/cargo/quartermaster) "xCo" = ( /obj/machinery/light/small/directional/west, /obj/effect/spawner/random/engineering/tank, @@ -80491,12 +80508,6 @@ dir = 1 }, /area/station/security/prison) -"xLH" = ( -/obj/structure/bed/maint, -/obj/machinery/light/small/broken/directional/north, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/iron/dark/small, -/area/station/security/prison/safe) "xLO" = ( /obj/machinery/door/firedoor, /obj/effect/mapping_helpers/airlock/access/all/medical/morgue, @@ -80526,11 +80537,6 @@ "xMC" = ( /turf/open/floor/plating, /area/station/science/xenobiology) -"xMJ" = ( -/obj/machinery/light/red/directional/east, -/obj/machinery/byteforge, -/turf/open/floor/catwalk_floor, -/area/station/security/bitden) "xML" = ( /obj/effect/turf_decal/tile/green{ dir = 4 @@ -80569,16 +80575,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/science/explab) -"xNn" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/curtain/cloth/fancy/mechanical{ - icon_state = "bounty-open"; - icon_type = "bounty"; - id = "Cell2Privacy"; - name = "curtain" - }, -/turf/open/floor/plating, -/area/station/security/prison/safe) "xNW" = ( /obj/machinery/door/firedoor, /obj/effect/turf_decal/tile/green{ @@ -81010,10 +81006,6 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/engineering/lobby) -"xVI" = ( -/obj/machinery/quantum_server, -/turf/open/floor/catwalk_floor, -/area/station/security/bitden) "xVJ" = ( /obj/effect/turf_decal/box/corners{ dir = 4 @@ -81264,14 +81256,6 @@ /obj/machinery/light/warm/directional/west, /turf/open/floor/iron/dark/smooth_large, /area/station/engineering/atmos) -"xZJ" = ( -/obj/structure/railing{ - dir = 8 - }, -/obj/structure/cable, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/lesser) "xZL" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -81961,6 +81945,23 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/small, /area/station/engineering/atmos/office) +"ykF" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/tile/purple/half{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/turf/open/floor/iron/dark/smooth_half{ + dir = 1 + }, +/area/station/security/bitden) "ykH" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -107599,7 +107600,7 @@ gqh wUI tcl rWp -aHK +gfJ ePv owu lMk @@ -108629,7 +108630,7 @@ sMF dVE soH bWR -aro +hQp pvr nlv uDp @@ -109930,7 +109931,7 @@ xAm vZy xsW dvI -hjz +pux fPA iyO oHE @@ -115593,7 +115594,7 @@ gTt gTt gTt ykB -wnQ +kuQ qbi gWJ fKE @@ -116621,9 +116622,9 @@ xUm aTL kGu hBQ -glr +xrM ffw -cZE +nyK lNk jdG vSA @@ -117134,7 +117135,7 @@ oTb kcf aYJ vbN -lJh +fAL vbN fGw hHf @@ -121285,7 +121286,7 @@ ogC lzn yiW dxe -nkG +sPb nkv pAJ gqN @@ -124065,11 +124066,11 @@ gKl ucv buh ilt -mSw -mSw -mSw -mSw -mSw +qsd +qsd +qsd +qsd +qsd jBY mvw oVX @@ -124322,14 +124323,14 @@ wDi hkU rOy ilt -xLH -oPc -voG -maO -mSw -mSw -mSw -mSw +bbh +rud +twL +uLx +qsd +qsd +qsd +qsd jVI aDk fid @@ -124579,17 +124580,17 @@ ilt pCs mWH ilt -wtv -oPc -ljw -eKa -mSw -maO -piB -mSw -mSw -mSw -mSw +rwC +rud +pXd +rzw +qsd +uLx +jmY +qsd +qsd +qsd +qsd qww qww nzB @@ -124825,7 +124826,7 @@ dFV gUR kFx gBI -veA +vZi qld qld qld @@ -124836,17 +124837,17 @@ ilt tTc noa ilt -vYn -oPc -hAP -lQD -mSw -eKa -pGD -mSw -voG -maO -mSw +gMS +rud +kOW +sRZ +qsd +rzw +lyO +qsd +twL +uLx +qsd kIS qtt gig @@ -125098,12 +125099,12 @@ pOx pZN jOj qld -tJv -xNn -mSw -uqC -eKa -mSw +mpL +gJx +qsd +dad +rzw +qsd qmI poq woY @@ -125358,9 +125359,9 @@ swt vwB tlF qld -oXZ -oYc -mSw +rMl +bXy +qsd qld lgd nRy @@ -125598,7 +125599,7 @@ fHR eqz rwl gFR -tPB +lAE gCL gCL gCL @@ -125855,14 +125856,14 @@ uSh rtl cSd ley -pCv -moL +rLd +joA pLW xyg qvI evU siz -kxn +kno xhf uDe rdU @@ -126113,7 +126114,7 @@ oFW cSd jgJ cSd -sWM +ill rjQ vGA hWS @@ -126373,7 +126374,7 @@ cSd jca tVv ekL -tfp +lsm evU qbx vvF @@ -126629,8 +126630,8 @@ xuB qld oFW oFW -fMP -wBv +hkQ +puO azL xIL uqJ @@ -127658,13 +127659,13 @@ laO laO laO xuB -kJn -ptg -ptg -apB -vuW -ptu -kJn +xnQ +jgb +jgb +lgc +ovR +xfV +xnQ qld qld qld @@ -127915,13 +127916,13 @@ laO laO laO laO -kJn -xsI -gDf -ddq -cMR -qIC -kJn +xnQ +cSt +jch +bjh +lzS +mGq +xnQ laO xuB xuB @@ -128172,13 +128173,13 @@ laO laO laO laO -kJn -oks -oMj -cJe -iME -mlG -kJn +xnQ +ieG +bqN +qNY +ykF +peI +xnQ laO laO xuB @@ -128429,13 +128430,13 @@ laO laO laO laO -kJn -iHA -sNS -sNS -xMJ -xVI -kJn +xnQ +mtz +vcw +vcw +jhw +wAI +xnQ laO laO tzq @@ -128686,13 +128687,13 @@ laO laO laO laO -kJn -kJn -kJn -kJn -kJn -kJn -kJn +xnQ +xnQ +xnQ +xnQ +xnQ +xnQ +xnQ laO laO laO @@ -169842,12 +169843,12 @@ wkF pHs wIF juy -gdb -hUM -hUM -ixQ -bft -gdb +cKK +tjZ +tjZ +vyU +xCl +cKK tio vEH cZr @@ -170099,18 +170100,18 @@ xfC pqB qur qur -gdb -uQN -hvE -wOl -lUq -gdb -gdb -gdb -gdb -gdb -gdb -gdb +cKK +mMK +vqq +bps +szf +cKK +cKK +cKK +cKK +cKK +cKK +cKK ykH vDj izT @@ -170356,18 +170357,18 @@ jgx uXo sBY pHs -gdb -jdT -pYJ -tnM -ePu -idQ -hRK -cHy -wqI -hDF -hnW -gdb +cKK +bXd +bkh +fRo +vTK +nMm +qeT +mmk +cuA +pcp +sNO +cKK xcE esM iTN @@ -170613,18 +170614,18 @@ bdy nCH muk pHs -cpa -bMY -uYG -rCw -anH -oVY -uEB -ikk -qzh -leH -ksQ -gdb +hXA +nGb +dns +eCD +eSR +tsn +mlL +lWK +qwQ +win +oMK +cKK sDQ dAi fqi @@ -170870,18 +170871,18 @@ pHs pHs pHs pHs -gdb -gdb -gdb -sUg -lov -kXq -mWR -vjl -wqI -rGR -iSr -gdb +cKK +cKK +cKK +cNH +oOC +iUW +bNg +lKq +cuA +hao +fUt +cKK hQb lvl eBy @@ -171129,16 +171130,16 @@ gAm jDg aEP cPA -gdb -gdb -gdb -gdb -gdb -gdb -gdb -gdb -gdb -gdb +cKK +cKK +cKK +cKK +cKK +cKK +cKK +cKK +cKK +cKK scu kMZ iFo @@ -171874,7 +171875,7 @@ iNr wEl lpC mMv -xZJ +sAK jiJ xaP eGr @@ -173980,7 +173981,7 @@ oxw dZR gfP jqJ -fNJ +xrc jut rmw tzq @@ -174233,7 +174234,7 @@ wUS gfP qEB oPK -tql +weM uHH gfP gfP @@ -175742,7 +175743,7 @@ klA mRJ rUk eBo -kqS +afa ifB ued nra @@ -176296,7 +176297,7 @@ sah qyI gqd fuQ -tql +weM jNS rmw tzq @@ -184261,7 +184262,7 @@ sRc pHy qgn igS -rjM +iQD pJF wfQ enO @@ -185720,7 +185721,7 @@ wqg tRY gzl cBn -ryj +qrR qcF tRY ikp @@ -187013,7 +187014,7 @@ tRY tRY ugb edi -wBd +vAq xGj roZ fJT @@ -189362,7 +189363,7 @@ eOE pWC wAS ggA -iTM +uXY eol eol eol diff --git a/_maps/map_files/Voidraptor/VoidRaptor.dmm b/_maps/map_files/Voidraptor/VoidRaptor.dmm index d6062d4160e4..a595bbd17597 100644 --- a/_maps/map_files/Voidraptor/VoidRaptor.dmm +++ b/_maps/map_files/Voidraptor/VoidRaptor.dmm @@ -137,13 +137,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/textured_large, /area/station/engineering/atmos) -"acl" = ( -/obj/structure/chair/wood{ - dir = 1; - layer = 2.8 - }, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "acx" = ( /obj/effect/turf_decal/siding/wood{ dir = 9 @@ -1125,17 +1118,6 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron/textured_large, /area/station/hallway/secondary/entry) -"aqf" = ( -/obj/structure/chair/comfy/brown{ - dir = 8 - }, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/service/library/abandoned) "aqg" = ( /obj/structure/table/optable{ name = "Robotics Operating Table" @@ -1370,17 +1352,6 @@ }, /turf/open/floor/wood/large, /area/station/service/theater) -"atd" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/status_display/ai/directional/south, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/chair/comfy/brown{ - color = "#A46106"; - dir = 1 - }, -/obj/effect/landmark/start/quartermaster, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "atf" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/iron/textured_large, @@ -2351,6 +2322,9 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/medical/surgery) +"aIL" = ( +/turf/closed/wall, +/area/station/maintenance/department/bridge) "aIP" = ( /obj/machinery/power/apc/auto_name/directional/north, /obj/effect/turf_decal/trimline/yellow/filled/line{ @@ -2524,6 +2498,12 @@ /obj/machinery/holopad/secure, /turf/open/floor/carpet, /area/station/security/courtroom) +"aLy" = ( +/obj/structure/table, +/obj/effect/turf_decal/tile/dark/opposingcorners, +/obj/machinery/chem_dispenser/drinks/beer, +/turf/open/floor/iron/kitchen, +/area/station/security/prison/mess) "aLz" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -2537,6 +2517,10 @@ }, /turf/open/floor/iron/kitchen, /area/station/service/kitchen) +"aLA" = ( +/obj/machinery/status_display/evac, +/turf/closed/wall/r_wall, +/area/station/cargo/quartermaster) "aLB" = ( /obj/structure/chair/sofa/corp/right, /obj/effect/turf_decal/tile/dark/opposingcorners{ @@ -2932,6 +2916,13 @@ dir = 8 }, /area/station/medical/virology) +"aQv" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Commissary Maintenance" + }, +/obj/effect/mapping_helpers/airlock/access/any/science/maintenance, +/turf/open/floor/catwalk_floor/iron_smooth, +/area/station/maintenance/department/bridge) "aQC" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/trimline/blue/filled/warning{ @@ -3096,6 +3087,13 @@ "aSS" = ( /turf/closed/wall/r_wall, /area/station/engineering/power_room) +"aSU" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/textured, +/area/station/maintenance/port/fore) "aTk" = ( /obj/structure/cable, /obj/machinery/airalarm/directional/east, @@ -3949,6 +3947,10 @@ /obj/structure/cable/layer3, /turf/open/floor/circuit, /area/station/ai_monitored/turret_protected/ai) +"bdS" = ( +/obj/structure/reagent_dispensers/watertank/high, +/turf/open/floor/grass, +/area/station/security/prison/garden) "bdV" = ( /obj/effect/landmark/start/hangover, /turf/open/floor/carpet, @@ -4176,30 +4178,6 @@ }, /turf/open/floor/engine, /area/station/science/xenobiology) -"bif" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/start/gary, -/turf/open/floor/catwalk_floor/iron_smooth, -/area/station/maintenance/starboard/fore) -"bii" = ( -/obj/machinery/power/apc/auto_name/directional/west, -/obj/structure/cable, -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/effect/turf_decal/siding/wood/corner{ - dir = 4 - }, -/obj/machinery/disposal/bin, -/obj/effect/turf_decal/box, -/obj/structure/disposalpipe/trunk{ - dir = 4 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "bik" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/visible, /obj/effect/turf_decal/stripes/line, @@ -4741,14 +4719,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/textured_large, /area/station/cargo/warehouse) -"bsd" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/sepia, -/area/station/service/library) "bsm" = ( /obj/effect/spawner/structure/window/reinforced/plasma, /obj/machinery/atmospherics/pipe/heat_exchanging/junction{ @@ -5002,6 +4972,21 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark/textured_large, /area/station/security/prison/work) +"bvz" = ( +/obj/machinery/door/airlock/highsecurity{ + name = "Blueshield's Equipment Room" + }, +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/iron/dark/textured_large, +/area/station/command/heads_quarters/blueshield) "bvI" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 @@ -5582,6 +5567,14 @@ /obj/machinery/holopad/secure, /turf/open/floor/vault, /area/station/ai_monitored/turret_protected/ai_upload) +"bFr" = ( +/obj/structure/extinguisher_cabinet/directional/east, +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "bFv" = ( /obj/effect/turf_decal/trimline/yellow/filled/warning{ dir = 4 @@ -5646,16 +5639,6 @@ dir = 1 }, /area/station/hallway/primary/fore) -"bGH" = ( -/obj/effect/mapping_helpers/airlock/unres{ - dir = 4 - }, -/obj/effect/mapping_helpers/airlock/access/any/science/maintenance, -/obj/machinery/door/airlock/maintenance{ - name = "Command Hallway Maintenance" - }, -/turf/open/floor/catwalk_floor/iron_smooth, -/area/station/maintenance/department/bridge) "bGJ" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -5835,13 +5818,6 @@ /obj/structure/lattice/catwalk, /turf/open/space/basic, /area/space/nearstation) -"bKt" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/fake_stairs/wood/directional/east, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/wood/large, -/area/station/service/barber) "bKE" = ( /obj/effect/turf_decal/delivery, /obj/machinery/space_heater, @@ -5942,15 +5918,6 @@ }, /turf/open/floor/iron/dark/textured, /area/station/science/xenobiology) -"bLR" = ( -/obj/machinery/status_display/evac/directional/west, -/obj/effect/turf_decal/siding/wood/end{ - dir = 1 - }, -/obj/structure/filingcabinet/chestdrawer, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron/textured_large, -/area/station/cargo/quartermaster) "bLW" = ( /obj/effect/landmark/start/hangover, /turf/open/floor/iron/small, @@ -6081,16 +6048,6 @@ }, /turf/open/floor/wood/large, /area/station/hallway/primary/central/fore) -"bNz" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/textured, -/area/station/maintenance/aft/greater) "bNE" = ( /obj/structure/rack/shelf, /obj/item/reagent_containers/cup/bottle/acidic_buffer{ @@ -6601,16 +6558,6 @@ /obj/effect/turf_decal/siding/wood, /turf/open/floor/wood, /area/station/service/library/abandoned) -"bWx" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/holopad, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "bWK" = ( /obj/machinery/ai_slipper{ uses = 10 @@ -6979,14 +6926,6 @@ }, /turf/open/floor/wood/large, /area/station/hallway/primary/central/fore) -"ccH" = ( -/obj/machinery/computer/cargo{ - dir = 1 - }, -/obj/effect/turf_decal/siding/wood, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "ccV" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /obj/effect/turf_decal/siding/wood/corner{ @@ -7228,6 +7167,15 @@ /obj/machinery/status_display/ai, /turf/closed/wall, /area/station/engineering/atmos) +"cgC" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "cgH" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -7350,32 +7298,6 @@ /obj/effect/spawner/random/maintenance/two, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/aft/greater) -"cix" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/mining{ - name = "Mining Lobby" - }, -/obj/effect/mapping_helpers/airlock/access/all/supply/qm, -/obj/effect/turf_decal/siding/wood/end, -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/effect/turf_decal/siding/wood/corner{ - dir = 1 - }, -/obj/effect/turf_decal/siding/wood/corner{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/iron/textured_large, -/area/station/cargo/quartermaster) "ciL" = ( /obj/structure/railing{ dir = 1 @@ -7936,11 +7858,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/white/textured_large, /area/station/science/auxlab) -"csn" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/maintenance/port/aft) "csp" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -8379,13 +8296,6 @@ /obj/effect/spawner/random/trash/bucket, /turf/open/floor/grass, /area/station/service/hydroponics/garden/abandoned) -"czm" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Commissary Maintenance" - }, -/obj/effect/mapping_helpers/airlock/access/any/science/maintenance, -/turf/open/floor/catwalk_floor/iron_smooth, -/area/station/maintenance/department/bridge) "czo" = ( /obj/machinery/door/airlock/external{ name = "Labor Camp Shuttle Airlock"; @@ -8565,6 +8475,19 @@ }, /turf/open/floor/engine, /area/station/bitrunning/den) +"cBo" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/layer_manifold/scrubbers/hidden, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Atmospherics Maintenance" + }, +/obj/machinery/door/poddoor/preopen{ + id = "atmoslock"; + name = "Atmospherics Lockdown Blast Door" + }, +/obj/effect/mapping_helpers/airlock/access/all/engineering/atmos, +/turf/open/floor/catwalk_floor/iron_smooth, +/area/station/maintenance/port) "cBU" = ( /obj/structure/chair/comfy/beige{ dir = 1 @@ -9516,6 +9439,26 @@ }, /turf/open/floor/circuit, /area/station/ai_monitored/turret_protected/ai) +"cPV" = ( +/obj/structure/table/wood, +/obj/item/folder/yellow{ + pixel_x = 5; + pixel_y = 4 + }, +/obj/item/stamp/head/qm{ + pixel_x = 5; + pixel_y = 4 + }, +/obj/item/stamp/denied{ + pixel_x = -7; + pixel_y = 9 + }, +/obj/item/stamp{ + pixel_x = -7; + pixel_y = 1 + }, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "cQa" = ( /obj/machinery/holopad, /obj/effect/turf_decal/bot, @@ -9624,14 +9567,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/eva_shed/starboard) -"cRE" = ( -/obj/item/radio/intercom/directional/east, -/obj/machinery/light/warm/directional/east, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 8 - }, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "cRT" = ( /obj/machinery/computer/exoscanner_control{ dir = 1 @@ -11185,6 +11120,17 @@ /obj/machinery/status_display/ai/directional/north, /turf/open/floor/pod/dark, /area/station/service/chapel/funeral) +"dom" = ( +/obj/structure/chair/comfy/brown{ + dir = 8 + }, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/service/library/abandoned) "dou" = ( /obj/machinery/airalarm/directional/south, /obj/structure/rack, @@ -11680,6 +11626,14 @@ /obj/effect/mapping_helpers/airlock/access/all/security/brig, /turf/open/floor/iron/dark/textured_large, /area/station/security/execution/transfer) +"dwb" = ( +/obj/effect/spawner/random/trash/mess, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/kitchen, +/area/station/service/kitchen/abandoned) "dwd" = ( /obj/effect/turf_decal/trimline/yellow/filled/warning{ dir = 1 @@ -12293,6 +12247,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/textured_large, /area/station/engineering/storage_shared) +"dER" = ( +/obj/effect/spawner/random/maintenance, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/textured, +/area/station/maintenance/port/fore) "dFa" = ( /obj/structure/mop_bucket/janitorialcart{ dir = 4 @@ -12341,15 +12304,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/aft/lesser) -"dFH" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "dFN" = ( /obj/effect/spawner/random/trash/garbage, /obj/item/storage/box/lights/mixed, @@ -12765,16 +12719,6 @@ /obj/item/seeds/poppy, /turf/open/floor/grass, /area/station/service/chapel) -"dKP" = ( -/obj/structure/chair/comfy/brown{ - color = "#A46106" - }, -/obj/effect/landmark/start/quartermaster, -/obj/machinery/computer/security/telescreen/vault{ - pixel_y = 30 - }, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "dKQ" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -12861,6 +12805,14 @@ /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/floor/iron/dark/textured, /area/station/security/warden) +"dLA" = ( +/obj/structure/sign/calendar/directional/north, +/obj/machinery/status_display/supply{ + pixel_x = -32 + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "dLE" = ( /obj/structure/table/glass, /obj/effect/turf_decal/trimline/purple/filled/line{ @@ -13456,6 +13408,22 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/dark/textured_large, /area/station/command/bridge) +"dTZ" = ( +/obj/machinery/power/apc/auto_name/directional/west, +/obj/structure/cable, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/obj/machinery/disposal/bin, +/obj/effect/turf_decal/box, +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "dUa" = ( /obj/effect/turf_decal/loading_area{ dir = 1 @@ -13928,21 +13896,6 @@ }, /turf/open/floor/iron/white/textured_large, /area/station/medical/medbay/central) -"eag" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/kitchen{ - dir = 1 - }, -/area/station/commons/dorms/laundry) "eai" = ( /obj/machinery/porta_turret/ai, /obj/effect/turf_decal/stripes/white/box, @@ -14046,15 +13999,6 @@ /obj/machinery/newscaster/directional/south, /turf/open/floor/carpet, /area/station/commons/dorms) -"ebE" = ( -/obj/effect/turf_decal/tile/purple/opposingcorners, -/obj/structure/reagent_dispensers/plumbed{ - dir = 1; - name = "science water reservoir" - }, -/obj/effect/turf_decal/delivery/blue, -/turf/open/floor/iron/textured, -/area/station/maintenance/department/bridge) "ebF" = ( /obj/effect/turf_decal/siding/thinplating_new/terracotta/corner, /obj/structure/closet/secure_closet/freezer/kitchen/maintenance, @@ -16111,25 +16055,6 @@ dir = 1 }, /area/station/hallway/secondary/command) -"eFd" = ( -/obj/machinery/door/airlock/highsecurity{ - name = "Blueshield's Equipment Room" - }, -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/poddoor/preopen{ - id = "bridge blast"; - name = "Bridge Blast Door" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/command/heads_quarters/blueshield) "eFg" = ( /obj/structure/chair/comfy/beige{ dir = 1 @@ -16763,6 +16688,11 @@ /obj/structure/reagent_dispensers/fueltank, /turf/open/space/basic, /area/space/nearstation) +"eOK" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "eON" = ( /obj/effect/spawner/random/trash/food_packaging, /obj/effect/decal/cleanable/dirt, @@ -16990,6 +16920,13 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/large, /area/station/commons/vacant_room) +"eSq" = ( +/obj/structure/chair/wood{ + dir = 1; + layer = 2.8 + }, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "eSv" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -17056,21 +16993,6 @@ /obj/machinery/duct, /turf/open/floor/iron/white/textured_large, /area/station/science/xenobiology) -"eUl" = ( -/obj/machinery/door/airlock/highsecurity{ - name = "Blueshield's Equipment Room" - }, -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/command/heads_quarters/blueshield) "eUm" = ( /obj/structure/bed, /obj/item/bedsheet/yellow, @@ -17530,18 +17452,6 @@ /obj/structure/lattice/catwalk, /turf/open/space, /area/station/solars/starboard/fore) -"fbe" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/siding/wood/corner{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "fbg" = ( /obj/effect/turf_decal/bot, /obj/structure/frame/machine, @@ -17752,15 +17662,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/textured_large, /area/station/cargo/miningdock) -"feb" = ( -/obj/machinery/firealarm/directional/north, -/obj/machinery/light_switch/directional/west, -/obj/structure/table/wood, -/obj/item/flashlight/lamp{ - pixel_y = 5 - }, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "feh" = ( /obj/effect/turf_decal/trimline/brown/filled/line{ dir = 1 @@ -18411,6 +18312,10 @@ "fop" = ( /turf/open/floor/grass, /area/station/service/hydroponics/upper) +"for" = ( +/obj/machinery/duct, +/turf/open/floor/catwalk_floor/iron_smooth, +/area/station/maintenance/department/bridge) "fos" = ( /obj/structure/table/glass, /obj/effect/spawner/random/trash/cigbutt, @@ -18605,6 +18510,9 @@ }, /turf/open/floor/iron/textured_large, /area/station/command/heads_quarters/hos) +"frk" = ( +/turf/open/floor/iron/textured, +/area/station/maintenance/department/bridge) "frl" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/trash/garbage, @@ -18759,6 +18667,18 @@ /obj/structure/window/reinforced/plasma/spawner/directional/east, /turf/open/floor/iron/textured, /area/station/maintenance/aft/lesser) +"ftw" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "ftA" = ( /obj/machinery/status_display/evac/directional/south, /obj/effect/turf_decal/siding/wood/end{ @@ -19710,6 +19630,17 @@ }, /turf/open/floor/iron/textured_large, /area/station/cargo/warehouse) +"fLb" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/status_display/ai/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/chair/comfy/brown{ + color = "#A46106"; + dir = 1 + }, +/obj/effect/landmark/start/quartermaster, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "fLd" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -21811,6 +21742,25 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/textured_large, /area/station/cargo/storage) +"gqG" = ( +/obj/machinery/door/airlock/highsecurity{ + name = "Blueshield's Equipment Room" + }, +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/poddoor/preopen{ + id = "bridge blast"; + name = "Bridge Blast Door" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/iron/dark/textured_large, +/area/station/command/heads_quarters/blueshield) "gqN" = ( /obj/effect/turf_decal/trimline/blue/filled/warning{ dir = 4 @@ -22034,6 +21984,10 @@ /obj/effect/turf_decal/trimline/dark_red/arrow_ccw, /turf/open/floor/iron/small, /area/station/hallway/secondary/exit/departure_lounge) +"gtJ" = ( +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "gtM" = ( /obj/effect/turf_decal/trimline/purple/filled/line, /obj/machinery/status_display/evac/directional/south, @@ -23212,18 +23166,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/cafeteria, /area/station/service/cafeteria) -"gKg" = ( -/obj/structure/table/wood/fancy/black, -/obj/effect/turf_decal/siding/wood, -/obj/item/stack/package_wrap{ - pixel_x = -3; - pixel_y = 8 - }, -/obj/item/hand_labeler{ - pixel_y = 3 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "gKl" = ( /obj/structure/chair/wood{ dir = 8 @@ -23827,6 +23769,15 @@ /obj/structure/lattice/catwalk, /turf/open/space/basic, /area/station/solars/port/aft) +"gST" = ( +/obj/machinery/airalarm/directional/south, +/obj/structure/closet/secure_closet/quartermaster, +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "gSW" = ( /obj/machinery/airalarm/directional/north, /obj/effect/turf_decal/loading_area{ @@ -24187,6 +24138,17 @@ }, /turf/open/floor/wood/large, /area/station/service/library) +"gYc" = ( +/obj/machinery/computer/security/qm{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 10 + }, +/obj/structure/sign/calendar/directional/west, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "gYp" = ( /obj/effect/turf_decal/weather/sand, /obj/structure/flora/bush/sparsegrass{ @@ -24604,6 +24566,14 @@ /obj/item/stack/sheet/cardboard, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/starboard/upper) +"hdq" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/sepia, +/area/station/service/library) "hds" = ( /obj/machinery/status_display/evac/directional/west, /turf/open/floor/iron/grimy, @@ -24736,6 +24706,11 @@ "hfU" = ( /turf/closed/wall, /area/station/service/kitchen/coldroom) +"hgd" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/carpet/black, +/area/station/commons/dorms) "hgk" = ( /obj/machinery/door/airlock/grunge{ name = "Chapel Garden" @@ -25055,14 +25030,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/engineering/supermatter/room) -"hko" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/obj/effect/landmark/start/hangover, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/iron/large, -/area/station/commons/vacant_room/commissary) "hkv" = ( /obj/effect/turf_decal/trimline/yellow/filled/warning{ dir = 4 @@ -25346,6 +25313,17 @@ }, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/starboard/aft) +"hpU" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/airlock{ + id_tag = "commissarydoors"; + name = "Vacant Commissary" + }, +/obj/machinery/door/firedoor, +/turf/open/floor/iron/large, +/area/station/commons/vacant_room/commissary) "hqd" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, @@ -25514,6 +25492,15 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron/textured_large, /area/station/cargo/sorting) +"htk" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/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/textured_large, +/area/station/cargo/quartermaster) "htq" = ( /obj/structure/table/wood, /obj/item/book/manual/wiki/security_space_law{ @@ -27608,6 +27595,10 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/dark/textured_edge, /area/station/security/prison) +"hXd" = ( +/obj/machinery/digital_clock, +/turf/closed/wall/r_wall, +/area/station/cargo/quartermaster) "hXj" = ( /obj/machinery/rnd/production/circuit_imprinter, /obj/item/radio/intercom/directional/west, @@ -28343,6 +28334,14 @@ /obj/item/radio, /turf/open/floor/iron/textured, /area/station/security/checkpoint/supply) +"ijg" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet, +/obj/effect/spawner/random/maintenance/four, +/obj/effect/spawner/random/engineering/vending_restock, +/obj/item/storage/box/lights/mixed, +/turf/open/floor/iron/textured, +/area/station/maintenance/department/bridge) "ijj" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, @@ -28531,12 +28530,6 @@ dir = 8 }, /area/station/security/office) -"ilT" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 4 - }, -/turf/open/floor/carpet/cyan, -/area/station/command/heads_quarters/blueshield) "ilY" = ( /obj/effect/turf_decal/trimline/yellow/filled/line, /obj/effect/turf_decal/trimline/blue/filled/line, @@ -28695,6 +28688,13 @@ dir = 8 }, /area/station/cargo/storage) +"inx" = ( +/obj/structure/dresser, +/obj/item/toy/figure/qm{ + pixel_y = 14 + }, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "inB" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 8 @@ -29017,6 +29017,15 @@ /obj/effect/spawner/random/structure/crate, /turf/open/floor/iron/textured, /area/station/maintenance/port/central) +"irl" = ( +/obj/effect/turf_decal/tile/purple/opposingcorners, +/obj/structure/reagent_dispensers/plumbed{ + dir = 1; + name = "science water reservoir" + }, +/obj/effect/turf_decal/delivery/blue, +/turf/open/floor/iron/textured, +/area/station/maintenance/department/bridge) "irm" = ( /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/west, @@ -29244,6 +29253,14 @@ /obj/machinery/light/small/directional/east, /turf/closed/wall/r_wall, /area/station/maintenance/department/science/xenobiology) +"itx" = ( +/obj/item/radio/intercom/directional/east, +/obj/machinery/light/warm/directional/east, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 8 + }, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "ity" = ( /obj/structure/table, /obj/item/clothing/mask/gas, @@ -29410,6 +29427,25 @@ /obj/effect/spawner/random/structure/tank_holder, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/medical/virology) +"ivM" = ( +/obj/structure/table/wood/fancy/black, +/obj/effect/turf_decal/siding/wood{ + dir = 6 + }, +/obj/item/gun_maintenance_supplies{ + pixel_y = 4 + }, +/obj/item/gps/mining{ + gpstag = "QM0"; + pixel_y = 4 + }, +/obj/machinery/light_switch/directional/south, +/obj/item/folder/yellow{ + pixel_x = -15; + pixel_y = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "ivQ" = ( /obj/machinery/computer/order_console/cook, /obj/effect/turf_decal/trimline/brown/filled/line{ @@ -29593,6 +29629,12 @@ "ixX" = ( /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/port/central) +"iyd" = ( +/obj/structure/bed, +/obj/item/bedsheet/qm, +/obj/machinery/newscaster/directional/north, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "iye" = ( /obj/structure/closet, /obj/effect/spawner/random/maintenance/two, @@ -30420,13 +30462,6 @@ dir = 8 }, /area/station/engineering/atmos/hfr_room) -"iLc" = ( -/obj/structure/dresser, -/obj/item/toy/figure/qm{ - pixel_y = 14 - }, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "iLm" = ( /obj/effect/turf_decal/trimline/yellow/filled/warning{ dir = 8 @@ -30491,12 +30526,6 @@ }, /turf/open/floor/catwalk_floor, /area/station/maintenance/department/security/greater) -"iMg" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/dark/opposingcorners, -/obj/machinery/chem_dispenser/drinks/beer, -/turf/open/floor/iron/kitchen, -/area/station/security/prison/mess) "iMh" = ( /obj/effect/turf_decal/trimline/brown/filled/corner{ dir = 1 @@ -31015,6 +31044,12 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/pod, /area/station/service/chapel/office) +"iTX" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/textured, +/area/station/maintenance/starboard/fore) "iUc" = ( /obj/machinery/navbeacon{ codes_txt = "patrol;next_patrol=hall2"; @@ -31068,16 +31103,6 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron/textured, /area/station/maintenance/department/engine/atmos) -"iUP" = ( -/obj/structure/chair/office{ - color = "#A46106" - }, -/obj/effect/landmark/start/quartermaster, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "iVa" = ( /turf/open/floor/engine, /area/station/security/range) @@ -31351,6 +31376,14 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/vault, /area/station/ai_monitored/turret_protected/aisat/foyer) +"iXX" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/trash/popcorn, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/aft/lesser) "iXY" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/effect/turf_decal/tile/blue/opposingcorners{ @@ -31639,6 +31672,17 @@ dir = 8 }, /area/station/science/robotics/lab) +"jbo" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/structure/railing{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/wood/parquet, +/area/station/common/night_club) "jbu" = ( /obj/machinery/vending/boozeomat, /obj/effect/turf_decal/tile/bar/opposingcorners, @@ -32151,6 +32195,9 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating/airless, /area/station/medical/chemistry) +"jjg" = ( +/turf/open/floor/catwalk_floor/iron_smooth, +/area/station/maintenance/department/bridge) "jji" = ( /obj/structure/sign/poster/contraband/crocin_pool/directional/south, /obj/effect/spawner/liquids_spawner, @@ -32204,14 +32251,6 @@ }, /turf/open/floor/iron/textured_edge, /area/station/engineering/atmos/hfr_room) -"jka" = ( -/obj/structure/sign/calendar/directional/north, -/obj/machinery/status_display/supply{ - pixel_x = -32 - }, -/obj/effect/turf_decal/bot, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "jkb" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -32496,6 +32535,30 @@ /obj/effect/decal/cleanable/blood/old, /turf/open/floor/iron/textured, /area/station/maintenance/port/greater) +"jor" = ( +/obj/machinery/door/airlock/corporate{ + name = "Blueshield's Quarters" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/siding/wood/end, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/wood/large, +/area/station/command/heads_quarters/blueshield) "jos" = ( /obj/machinery/vending/coffee{ default_price = 0; @@ -33201,6 +33264,24 @@ }, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/starboard/lesser) +"jwQ" = ( +/obj/structure/table/wood, +/obj/item/flashlight/lamp{ + pixel_x = -4; + pixel_y = 12 + }, +/obj/machinery/firealarm/directional/west, +/obj/item/paper_bin/carbon{ + pixel_x = 12; + pixel_y = 4 + }, +/obj/item/pen/fourcolor{ + pixel_x = 12; + pixel_y = 4 + }, +/obj/machinery/light/directional/west, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "jwV" = ( /obj/effect/spawner/random/structure/grille, /turf/open/floor/iron/textured, @@ -33272,14 +33353,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/textured, /area/station/maintenance/aft/greater) -"jyw" = ( -/obj/effect/decal/cleanable/dirt, -/obj/item/trash/popcorn, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/aft/lesser) "jyD" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -33778,6 +33851,17 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/security/holding_cell) +"jEm" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/obj/effect/turf_decal/siding/dark_blue/end{ + dir = 4 + }, +/obj/effect/turf_decal/tile/dark_blue/full, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/iron/dark/textured_large, +/area/station/command/heads_quarters/blueshield) "jEy" = ( /obj/structure/table/wood, /obj/machinery/status_display/ai/directional/north, @@ -34192,6 +34276,11 @@ /obj/effect/mapping_helpers/airlock/access/all/medical/general, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/port/central) +"jKa" = ( +/obj/effect/spawner/liquids_spawner, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/lowered/iron/pool, +/area/station/common/pool) "jKi" = ( /obj/structure/table/wood, /obj/item/flashlight/lamp/green, @@ -36619,6 +36708,16 @@ /obj/item/clothing/head/cone, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/starboard/fore) +"kvN" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "kvR" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/research/glass{ @@ -37553,15 +37652,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/textured, /area/station/maintenance/starboard/aft) -"kGT" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "kGU" = ( /obj/effect/landmark/start/bartender, /obj/effect/turf_decal/tile/bar/opposingcorners, @@ -37805,9 +37895,6 @@ /obj/structure/grille/broken, /turf/open/floor/iron/textured, /area/station/maintenance/department/science/ordnance_maint) -"kJs" = ( -/turf/open/floor/catwalk_floor/iron_smooth, -/area/station/maintenance/department/bridge) "kJv" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/iron/textured_edge, @@ -38138,6 +38225,12 @@ }, /turf/open/floor/plating, /area/station/security/prison/garden) +"kPk" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/carpet/cyan, +/area/station/command/heads_quarters/blueshield) "kPn" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 1 @@ -39963,12 +40056,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/textured_large, /area/station/hallway/secondary/entry) -"loI" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/textured, -/area/station/maintenance/starboard/fore) "loJ" = ( /obj/effect/turf_decal/tile/purple/diagonal_centre, /obj/structure/disposalpipe/segment{ @@ -40255,6 +40342,26 @@ /obj/effect/turf_decal/siding/thinplating/dark/end, /turf/open/floor/iron/checker, /area/station/medical/virology) +"ltz" = ( +/obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/access/all/supply/qm, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/airlock/mining{ + name = "Mining Lobby" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/iron/textured_large, +/area/station/cargo/quartermaster) "ltB" = ( /obj/structure/lattice/catwalk, /turf/open/space, @@ -43196,10 +43303,6 @@ dir = 8 }, /area/station/engineering/power_room) -"mjo" = ( -/obj/machinery/digital_clock, -/turf/closed/wall/r_wall, -/area/station/cargo/quartermaster) "mjr" = ( /obj/effect/turf_decal/trimline/brown/filled/corner{ dir = 4 @@ -43616,16 +43719,6 @@ dir = 1 }, /area/station/hallway/secondary/entry) -"moT" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "moV" = ( /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ dir = 4 @@ -43936,11 +44029,27 @@ }, /turf/open/floor/iron/textured_large, /area/station/construction/mining/aux_base) -"mvn" = ( -/obj/item/robot_suit, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/science/research/abandoned) +"mvl" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/corporate{ + id_tag = "BSdoor"; + name = "Blueshield's Office" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/iron/dark/textured_large, +/area/station/command/heads_quarters/blueshield) "mvz" = ( /obj/effect/turf_decal/trimline/yellow/filled/warning, /obj/structure/disposalpipe/segment{ @@ -44508,6 +44617,16 @@ }, /turf/open/floor/plating, /area/station/science/robotics/mechbay) +"mEw" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/textured, +/area/station/maintenance/aft/greater) "mEC" = ( /obj/machinery/corral_corner{ mapping_id = "5" @@ -46063,6 +46182,32 @@ /obj/structure/table/wood/fancy/blue, /turf/open/floor/wood/large, /area/station/security/courtroom) +"mZJ" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/mining{ + name = "Mining Lobby" + }, +/obj/effect/mapping_helpers/airlock/access/all/supply/qm, +/obj/effect/turf_decal/siding/wood/end, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/iron/textured_large, +/area/station/cargo/quartermaster) "mZO" = ( /obj/effect/turf_decal/arrows/white{ color = "#00AAFF"; @@ -46270,11 +46415,6 @@ /obj/machinery/atmospherics/pipe/smart/simple/orange/visible, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"ncD" = ( -/obj/effect/spawner/liquids_spawner, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/lowered/iron/pool, -/area/station/common/pool) "ncF" = ( /obj/machinery/light/small/directional/east, /obj/structure/easel, @@ -47319,24 +47459,6 @@ }, /turf/open/floor/iron/white/textured_edge, /area/station/science/research) -"nss" = ( -/obj/structure/table/wood, -/obj/item/flashlight/lamp{ - pixel_x = -4; - pixel_y = 12 - }, -/obj/machinery/firealarm/directional/west, -/obj/item/paper_bin/carbon{ - pixel_x = 12; - pixel_y = 4 - }, -/obj/item/pen/fourcolor{ - pixel_x = 12; - pixel_y = 4 - }, -/obj/machinery/light/directional/west, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "nst" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -47535,25 +47657,6 @@ dir = 1 }, /area/station/medical/medbay/central) -"nui" = ( -/obj/structure/table/wood/fancy/black, -/obj/effect/turf_decal/siding/wood{ - dir = 6 - }, -/obj/item/gun_maintenance_supplies{ - pixel_y = 4 - }, -/obj/item/gps/mining{ - gpstag = "QM0"; - pixel_y = 4 - }, -/obj/machinery/light_switch/directional/south, -/obj/item/folder/yellow{ - pixel_x = -15; - pixel_y = 4 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "nul" = ( /obj/effect/turf_decal/trimline/brown/filled/warning, /obj/effect/turf_decal/arrows, @@ -47597,14 +47700,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/dark/textured, /area/station/security/office) -"nuW" = ( -/obj/effect/spawner/random/trash/mess, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/kitchen, -/area/station/service/kitchen/abandoned) "nvc" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 1 @@ -47995,6 +48090,9 @@ /obj/effect/spawner/random/trash/garbage, /turf/open/floor/plating, /area/station/maintenance/aft/lesser) +"nAt" = ( +/turf/closed/wall/r_wall, +/area/station/cargo/quartermaster) "nAw" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -48726,6 +48824,19 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/port/greater) +"nNa" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/siding/wood{ + dir = 5 + }, +/obj/structure/extinguisher_cabinet/directional/north, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "nNc" = ( /obj/effect/turf_decal/siding/wood, /obj/structure/table{ @@ -48937,16 +49048,6 @@ }, /turf/open/floor/iron/dark/textured_large, /area/station/medical/morgue) -"nPP" = ( -/obj/effect/turf_decal/siding/wood, -/obj/machinery/camera/directional/south{ - c_tag = "Cargo - Quartermaster's Office"; - name = "cargo camera" - }, -/obj/machinery/status_display/ai/directional/south, -/obj/structure/table/wood, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "nPT" = ( /obj/item/radio/intercom/directional/south, /obj/effect/turf_decal/trimline/purple/filled/line, @@ -50198,6 +50299,16 @@ dir = 8 }, /area/station/engineering/storage_shared) +"ohQ" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/requests_console/directional/east{ + department = "Quartermaster's Desk"; + name = "Quartermaster's Requests Console" + }, +/obj/effect/mapping_helpers/requests_console/announcement, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "oia" = ( /obj/effect/turf_decal/tile/green/diagonal_centre, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -51060,6 +51171,9 @@ }, /turf/open/floor/iron/large, /area/station/commons/dorms/laundry) +"out" = ( +/turf/closed/wall, +/area/station/cargo/quartermaster) "ouu" = ( /obj/structure/extinguisher_cabinet/directional/west, /turf/open/floor/light/colour_cycle/dancefloor_b, @@ -51369,15 +51483,6 @@ }, /turf/open/floor/wood/large, /area/station/command/heads_quarters/captain) -"oyB" = ( -/obj/effect/spawner/random/maintenance, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/textured, -/area/station/maintenance/port/fore) "oyG" = ( /obj/machinery/disposal/bin, /obj/effect/turf_decal/box, @@ -51418,6 +51523,15 @@ /obj/effect/turf_decal/vg_decals/numbers/three, /turf/open/floor/iron/dark/textured_large, /area/station/hallway/secondary/command) +"ozs" = ( +/obj/structure/reagent_dispensers/plumbed{ + dir = 1; + name = "science water reservoir" + }, +/obj/effect/turf_decal/tile/purple/opposingcorners, +/obj/effect/turf_decal/delivery/blue, +/turf/open/floor/iron/textured, +/area/station/maintenance/department/bridge) "ozH" = ( /obj/effect/mapping_helpers/airlock/access/all/science/research, /obj/structure/disposalpipe/segment{ @@ -52137,14 +52251,6 @@ }, /turf/open/floor/iron/dark/textured, /area/station/security/prison/mess) -"oKy" = ( -/obj/structure/extinguisher_cabinet/directional/east, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "oKR" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/textured, @@ -54873,15 +54979,6 @@ }, /turf/open/floor/carpet/royalblue, /area/station/command/heads_quarters/captain) -"puB" = ( -/obj/machinery/airalarm/directional/south, -/obj/structure/closet/secure_closet/quartermaster, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "puG" = ( /obj/machinery/power/shuttle_engine/propulsion, /obj/structure/window/reinforced/spawner/directional/west, @@ -55637,13 +55734,6 @@ /obj/machinery/light_switch/directional/east, /turf/open/floor/iron/textured, /area/station/engineering/atmos/storage/gas) -"pFP" = ( -/obj/effect/turf_decal/siding/wood, -/obj/item/radio/intercom/directional/south, -/obj/effect/turf_decal/bot, -/obj/machinery/light/directional/south, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "pGh" = ( /turf/open/floor/iron/white/textured_large, /area/station/hallway/primary/fore) @@ -56548,6 +56638,14 @@ /obj/effect/spawner/random/structure/steam_vent, /turf/open/floor/plating, /area/station/maintenance/aft/greater) +"pSO" = ( +/obj/machinery/computer/cargo{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wood, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "pSX" = ( /obj/machinery/door/firedoor, /obj/structure/disposalpipe/segment{ @@ -56602,17 +56700,6 @@ /obj/structure/table, /turf/open/floor/iron/textured, /area/station/science/research/abandoned) -"pUd" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/airlock{ - id_tag = "commissarydoors"; - name = "Vacant Commissary" - }, -/obj/machinery/door/firedoor, -/turf/open/floor/iron/large, -/area/station/commons/vacant_room/commissary) "pUe" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/pod/dark, @@ -57460,20 +57547,6 @@ }, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/starboard/greater) -"qcg" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/obj/machinery/light/small/directional/south, -/obj/structure/chair/office{ - dir = 4 - }, -/obj/effect/decal/cleanable/blood/old, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/turf_decal/siding/wood, -/obj/effect/landmark/start/gary, -/turf/open/floor/wood, -/area/station/maintenance/department/engine/atmos) "qcj" = ( /obj/item/stack/sheet/plasteel/twenty{ pixel_x = -4 @@ -58106,10 +58179,6 @@ dir = 4 }, /area/station/hallway/primary/aft) -"qkQ" = ( -/obj/structure/reagent_dispensers/watertank/high, -/turf/open/floor/grass, -/area/station/security/prison/garden) "qlA" = ( /obj/effect/turf_decal/stripes/red/full, /turf/open/floor/iron/textured_large, @@ -58268,6 +58337,16 @@ }, /turf/closed/wall, /area/station/maintenance/aft/upper) +"qnt" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/holopad, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "qnC" = ( /obj/structure/table/wood, /obj/item/paper_bin/carbon{ @@ -58501,10 +58580,6 @@ }, /turf/open/floor/iron/textured_edge, /area/station/engineering/main) -"qro" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/station/cargo/quartermaster) "qrF" = ( /obj/effect/landmark/start/prisoner, /turf/open/floor/iron/dark/textured_large, @@ -59343,6 +59418,12 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron/dark/textured, /area/station/security/brig) +"qEh" = ( +/obj/effect/spawner/random/trash/garbage, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/department/crew_quarters/bar) "qEq" = ( /obj/structure/sign/departments/aisat/directional/north, /obj/machinery/light/cold/directional/north, @@ -59581,6 +59662,16 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/freezer, /area/station/security/checkpoint/medical) +"qHw" = ( +/obj/structure/chair/comfy/brown{ + color = "#A46106" + }, +/obj/effect/landmark/start/quartermaster, +/obj/machinery/computer/security/telescreen/vault{ + pixel_y = 30 + }, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "qHx" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -60008,6 +60099,14 @@ /obj/machinery/light_switch/directional/west, /turf/open/floor/iron, /area/station/commons/storage/art) +"qMN" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/effect/landmark/start/hangover, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/iron/large, +/area/station/commons/vacant_room/commissary) "qMR" = ( /obj/effect/turf_decal/siding/wood{ dir = 4 @@ -60111,6 +60210,20 @@ }, /turf/open/floor/iron/dark/textured_edge, /area/station/security/brig) +"qPy" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/machinery/light/small/directional/south, +/obj/structure/chair/office{ + dir = 4 + }, +/obj/effect/decal/cleanable/blood/old, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/turf_decal/siding/wood, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/maintenance/department/engine/atmos) "qPI" = ( /obj/effect/turf_decal/delivery, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/visible, @@ -60462,6 +60575,18 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/wood/large, /area/station/hallway/primary/central/fore) +"qTs" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/machinery/newscaster/directional/west, +/obj/structure/bed/dogbed{ + anchored = 1; + name = "Citrus's bed" + }, +/mob/living/basic/sloth/citrus, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "qTA" = ( /obj/effect/turf_decal/siding/wood{ dir = 5 @@ -62897,27 +63022,6 @@ /obj/effect/landmark/start/chemist, /turf/open/floor/iron/dark/textured, /area/station/medical/break_room) -"rDO" = ( -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/machinery/door/airlock/corporate{ - id_tag = "BSdoor"; - name = "Blueshield's Office" - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/command/heads_quarters/blueshield) "rDP" = ( /obj/machinery/computer/shuttle/mining{ dir = 1; @@ -62939,13 +63043,6 @@ /obj/machinery/atmospherics/components/unary/thermomachine/heater/on, /turf/open/floor/iron/dark/textured_large, /area/station/engineering/atmos) -"rEG" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "rET" = ( /turf/open/floor/iron/textured_edge{ dir = 8 @@ -63251,17 +63348,6 @@ }, /turf/open/floor/engine, /area/station/science/xenobiology) -"rJq" = ( -/obj/machinery/computer/security/qm{ - dir = 1 - }, -/obj/effect/turf_decal/siding/wood{ - dir = 10 - }, -/obj/structure/sign/calendar/directional/west, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "rJK" = ( /obj/structure/flora/ocean/longseaweed, /obj/effect/spawner/liquids_spawner{ @@ -64471,12 +64557,6 @@ }, /turf/open/floor/iron/white/textured_large, /area/station/medical/medbay/lobby) -"sbI" = ( -/obj/effect/spawner/random/trash/garbage, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/department/crew_quarters/bar) "sbU" = ( /obj/machinery/power/smes, /turf/open/floor/catwalk_floor/iron_smooth, @@ -64928,18 +65008,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/wood/large, /area/station/hallway/primary/central/fore) -"siF" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/machinery/newscaster/directional/west, -/obj/structure/bed/dogbed{ - anchored = 1; - name = "Citrus's bed" - }, -/mob/living/basic/sloth/citrus, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "siO" = ( /turf/open/space, /area/space) @@ -65720,6 +65788,16 @@ }, /turf/open/floor/iron/large, /area/station/security/detectives_office) +"sun" = ( +/obj/structure/chair/office{ + color = "#A46106" + }, +/obj/effect/landmark/start/quartermaster, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "sur" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -66193,16 +66271,6 @@ /obj/machinery/portable_atmospherics/canister/air, /turf/open/floor/engine/air, /area/station/engineering/atmos) -"sCm" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 4 - }, -/obj/effect/turf_decal/siding/dark_blue/end{ - dir = 4 - }, -/obj/effect/turf_decal/tile/dark_blue/full, -/turf/open/floor/iron/dark/textured_large, -/area/station/command/heads_quarters/blueshield) "sCw" = ( /obj/machinery/door/airlock/maintenance_hatch, /obj/effect/mapping_helpers/airlock/abandoned, @@ -66287,6 +66355,11 @@ }, /turf/open/floor/iron/textured_large, /area/station/engineering/power_room) +"sDA" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/wood, +/area/station/maintenance/port/aft) "sDB" = ( /obj/structure/dresser, /obj/item/radio/intercom/directional/east, @@ -66944,9 +67017,6 @@ }, /turf/open/floor/iron/kitchen, /area/station/security/prison/mess) -"sKz" = ( -/turf/open/floor/iron/textured, -/area/station/maintenance/department/bridge) "sKA" = ( /obj/machinery/door/airlock/maintenance, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -67079,19 +67149,6 @@ /obj/structure/cable, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/solars/port/aft) -"sLG" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/siding/wood{ - dir = 5 - }, -/obj/structure/extinguisher_cabinet/directional/north, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "sLH" = ( /obj/machinery/door/airlock/maintenance{ name = "Power Station" @@ -67476,15 +67533,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/starboard/upper) -"sPy" = ( -/obj/structure/reagent_dispensers/plumbed{ - dir = 1; - name = "science water reservoir" - }, -/obj/effect/turf_decal/tile/purple/opposingcorners, -/obj/effect/turf_decal/delivery/blue, -/turf/open/floor/iron/textured, -/area/station/maintenance/department/bridge) "sPF" = ( /obj/structure/table/reinforced, /obj/item/clothing/suit/utility/radiation, @@ -68006,17 +68054,6 @@ /obj/item/reagent_containers/cup/glass/shaker, /turf/open/floor/iron, /area/station/service/bar) -"sVZ" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/structure/railing{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/wood/parquet, -/area/station/common/night_club) "sWB" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/tank_holder/extinguisher, @@ -68109,10 +68146,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/wood/large, /area/station/service/theater) -"sXU" = ( -/obj/machinery/status_display/evac, -/turf/closed/wall/r_wall, -/area/station/cargo/quartermaster) "sXX" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -68771,6 +68804,21 @@ }, /turf/open/floor/iron/kitchen, /area/station/service/kitchen) +"tgP" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/kitchen{ + dir = 1 + }, +/area/station/commons/dorms/laundry) "tgQ" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -69458,6 +69506,15 @@ /obj/effect/spawner/random/trash/garbage, /turf/open/floor/iron/textured, /area/station/maintenance/port/aft) +"tqz" = ( +/obj/machinery/status_display/evac/directional/west, +/obj/effect/turf_decal/siding/wood/end{ + dir = 1 + }, +/obj/structure/filingcabinet/chestdrawer, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron/textured_large, +/area/station/cargo/quartermaster) "tqA" = ( /obj/structure/window/spawner/directional/south, /obj/structure/flora/bush/sparsegrass, @@ -70302,14 +70359,6 @@ }, /turf/open/floor/iron/freezer, /area/station/medical/pharmacy) -"tAu" = ( -/obj/machinery/photocopier, -/obj/effect/turf_decal/siding/wood{ - dir = 5 - }, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron/dark/textured_large, -/area/station/cargo/quartermaster) "tAw" = ( /obj/machinery/disposal/bin, /obj/effect/turf_decal/trimline/dark_red/filled/line{ @@ -71072,6 +71121,13 @@ }, /turf/open/floor/iron/textured_large, /area/station/cargo/storage) +"tMp" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/fake_stairs/wood/directional/east, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/wood/large, +/area/station/service/barber) "tMq" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -72816,6 +72872,15 @@ }, /turf/open/floor/iron/white/textured_large, /area/station/medical/surgery) +"unj" = ( +/obj/machinery/firealarm/directional/north, +/obj/machinery/light_switch/directional/west, +/obj/structure/table/wood, +/obj/item/flashlight/lamp{ + pixel_y = 5 + }, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "uno" = ( /obj/machinery/airalarm/directional/north, /obj/machinery/suit_storage_unit/rd, @@ -73879,12 +73944,6 @@ }, /turf/open/floor/carpet/neon/simple/pink, /area/station/science/xenobiology) -"uzO" = ( -/obj/effect/decal/cleanable/blood/old, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/iron/textured, -/area/station/maintenance/port/greater) "uzW" = ( /obj/effect/turf_decal/trimline/dark_red/arrow_ccw, /obj/structure/sign/poster/official/random/directional/south, @@ -74646,9 +74705,6 @@ /obj/structure/window/fulltile, /turf/open/floor/grass, /area/station/hallway/primary/fore) -"uKR" = ( -/turf/closed/wall, -/area/station/maintenance/department/bridge) "uLe" = ( /turf/open/floor/iron/textured_large, /area/station/cargo/office) @@ -74754,10 +74810,6 @@ /obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/incinerator_ordmix, /turf/open/floor/engine, /area/station/science/ordnance/burnchamber) -"uMv" = ( -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "uMy" = ( /obj/effect/landmark/start/hangover, /turf/open/floor/iron/large, @@ -74771,30 +74823,6 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/general, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/solars/port/aft) -"uNm" = ( -/obj/machinery/door/airlock/corporate{ - name = "Blueshield's Quarters" - }, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/siding/wood/end, -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/effect/turf_decal/siding/wood/corner{ - dir = 1 - }, -/obj/effect/turf_decal/siding/wood/corner{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/wood/large, -/area/station/command/heads_quarters/blueshield) "uNu" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -76238,6 +76266,14 @@ /obj/machinery/light/directional/south, /turf/open/floor/iron/small, /area/station/hallway/secondary/exit/departure_lounge) +"vjU" = ( +/obj/machinery/photocopier, +/obj/effect/turf_decal/siding/wood{ + dir = 5 + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "vjY" = ( /obj/structure/training_machine, /obj/item/target, @@ -76260,6 +76296,13 @@ /obj/structure/cable, /turf/open/floor/vault, /area/station/ai_monitored/turret_protected/aisat/foyer) +"vkv" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "vkB" = ( /obj/structure/rack/shelf, /obj/effect/spawner/random/techstorage/service_all, @@ -76530,9 +76573,6 @@ /mob/living/simple_animal/bot/secbot/beepsky/officer, /turf/open/floor/iron/dark/textured_large, /area/station/security/office) -"vnJ" = ( -/turf/closed/wall/r_wall, -/area/station/cargo/quartermaster) "vnQ" = ( /obj/structure/chair/sofa/right/brown{ dir = 4 @@ -76756,6 +76796,10 @@ name = "Holodeck Projector Floor" }, /area/station/holodeck/rec_center) +"vrK" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/station/cargo/quartermaster) "vrU" = ( /obj/machinery/atmospherics/pipe/smart/simple/orange/visible{ dir = 4 @@ -76846,6 +76890,12 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/textured, /area/station/science/research/abandoned) +"vtA" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/iron/textured, +/area/station/maintenance/port/greater) "vtC" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -79154,26 +79204,6 @@ }, /turf/open/floor/engine, /area/station/engineering/main) -"vZG" = ( -/obj/structure/table/wood, -/obj/item/folder/yellow{ - pixel_x = 5; - pixel_y = 4 - }, -/obj/item/stamp/head/qm{ - pixel_x = 5; - pixel_y = 4 - }, -/obj/item/stamp/denied{ - pixel_x = -7; - pixel_y = 9 - }, -/obj/item/stamp{ - pixel_x = -7; - pixel_y = 1 - }, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "vZI" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -79198,16 +79228,6 @@ }, /turf/open/floor/cult, /area/station/service/library) -"vZR" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/requests_console/directional/east{ - department = "Quartermaster's Desk"; - name = "Quartermaster's Requests Console" - }, -/obj/effect/mapping_helpers/requests_console/announcement, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "vZV" = ( /obj/machinery/portable_atmospherics/canister/carbon_dioxide, /obj/effect/turf_decal/box, @@ -79583,12 +79603,6 @@ dir = 8 }, /area/station/cargo/office) -"wfQ" = ( -/obj/machinery/airalarm/directional/north, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/obj/machinery/light_switch/directional/east, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "wfU" = ( /obj/machinery/door/firedoor, /turf/open/floor/iron/stairs/right{ @@ -79918,6 +79932,18 @@ /obj/structure/fluff/beach_umbrella/syndi, /turf/open/floor/iron/white/small, /area/station/common/pool) +"wle" = ( +/obj/structure/table/wood/fancy/black, +/obj/effect/turf_decal/siding/wood, +/obj/item/stack/package_wrap{ + pixel_x = -3; + pixel_y = 8 + }, +/obj/item/hand_labeler{ + pixel_y = 3 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "wlh" = ( /obj/machinery/incident_display/delam, /turf/closed/wall, @@ -80005,6 +80031,14 @@ /obj/structure/window/fulltile, /turf/open/floor/grass, /area/station/commons/fitness/recreation) +"wmE" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/start/gary, +/turf/open/floor/catwalk_floor/iron_smooth, +/area/station/maintenance/starboard/fore) "wmF" = ( /obj/structure/railing{ dir = 8 @@ -80263,14 +80297,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/department/science/ordnance_maint) -"wqs" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/closet, -/obj/effect/spawner/random/maintenance/four, -/obj/effect/spawner/random/engineering/vending_restock, -/obj/item/storage/box/lights/mixed, -/turf/open/floor/iron/textured, -/area/station/maintenance/department/bridge) "wqw" = ( /obj/structure/table/reinforced, /obj/item/clipboard, @@ -80300,11 +80326,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/textured_large, /area/station/cargo/lobby) -"wqS" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/carpet/black, -/area/station/commons/dorms) "wqW" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 @@ -81175,6 +81196,16 @@ /obj/machinery/firealarm/directional/west, /turf/open/floor/iron/stairs/medium, /area/station/hallway/secondary/command) +"wBo" = ( +/obj/effect/turf_decal/siding/wood, +/obj/machinery/camera/directional/south{ + c_tag = "Cargo - Quartermaster's Office"; + name = "cargo camera" + }, +/obj/machinery/status_display/ai/directional/south, +/obj/structure/table/wood, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "wBy" = ( /obj/effect/spawner/random/entertainment/arcade, /obj/structure/sign/poster/contraband/random/directional/north, @@ -81552,6 +81583,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) +"wGn" = ( +/obj/item/robot_suit, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/science/research/abandoned) "wGw" = ( /obj/machinery/holopad, /obj/effect/turf_decal/bot, @@ -81681,13 +81717,6 @@ dir = 1 }, /area/station/cargo/office) -"wJl" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/textured, -/area/station/maintenance/port/fore) "wJx" = ( /obj/structure/window/reinforced/spawner/directional/west{ layer = 2.9 @@ -82192,12 +82221,6 @@ dir = 1 }, /area/station/medical/medbay/lobby) -"wPg" = ( -/obj/structure/bed, -/obj/item/bedsheet/qm, -/obj/machinery/newscaster/directional/north, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "wPp" = ( /obj/item/target, /obj/effect/decal/cleanable/dirt, @@ -82578,6 +82601,12 @@ /mob/living/simple_animal/bot/mulebot, /turf/open/floor/iron/textured_edge, /area/station/cargo/storage) +"wVY" = ( +/obj/machinery/airalarm/directional/north, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/obj/machinery/light_switch/directional/east, +/turf/open/floor/carpet/black, +/area/station/cargo/quartermaster) "wWw" = ( /obj/structure/window/reinforced/spawner/directional/west, /obj/structure/chair/office{ @@ -82862,19 +82891,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/textured_large, /area/station/maintenance/disposal) -"xdK" = ( -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/layer_manifold/scrubbers/hidden, -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Atmospherics Maintenance" - }, -/obj/machinery/door/poddoor/preopen{ - id = "atmoslock"; - name = "Atmospherics Lockdown Blast Door" - }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/atmos, -/turf/open/floor/catwalk_floor/iron_smooth, -/area/station/maintenance/port) "xdT" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 @@ -82964,6 +82980,13 @@ /obj/machinery/light/directional/north, /turf/open/floor/iron/small, /area/station/hallway/secondary/exit/departure_lounge) +"xfD" = ( +/obj/effect/turf_decal/siding/wood, +/obj/item/radio/intercom/directional/south, +/obj/effect/turf_decal/bot, +/obj/machinery/light/directional/south, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "xfM" = ( /turf/open/floor/catwalk_floor/iron_smooth, /area/station/science/robotics/mechbay) @@ -84328,9 +84351,6 @@ /obj/structure/cable, /turf/open/floor/vault, /area/station/ai_monitored/turret_protected/aisat_interior) -"xxR" = ( -/turf/closed/wall, -/area/station/cargo/quartermaster) "xyf" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -84856,6 +84876,15 @@ /obj/effect/spawner/random/trash/garbage, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"xGt" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/cargo/quartermaster) "xGv" = ( /obj/effect/turf_decal/trimline/purple/filled/corner{ dir = 4 @@ -85952,6 +85981,16 @@ /obj/structure/cable, /turf/open/floor/iron/textured_large, /area/station/cargo/miningoffice) +"xXG" = ( +/obj/effect/mapping_helpers/airlock/unres{ + dir = 4 + }, +/obj/effect/mapping_helpers/airlock/access/any/science/maintenance, +/obj/machinery/door/airlock/maintenance{ + name = "Command Hallway Maintenance" + }, +/turf/open/floor/catwalk_floor/iron_smooth, +/area/station/maintenance/department/bridge) "xXU" = ( /obj/effect/turf_decal/stripes/line, /turf/open/floor/engine, @@ -86087,11 +86126,6 @@ dir = 8 }, /area/station/engineering/storage/tcomms) -"xZG" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/carpet/black, -/area/station/cargo/quartermaster) "xZS" = ( /obj/structure/tank_dispenser/oxygen, /obj/effect/turf_decal/bot, @@ -86159,10 +86193,6 @@ /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/floor/iron/dark/textured, /area/station/security/warden) -"yaP" = ( -/obj/machinery/duct, -/turf/open/floor/catwalk_floor/iron_smooth, -/area/station/maintenance/department/bridge) "ybj" = ( /obj/effect/landmark/start/hangover, /turf/open/floor/iron/grimy, @@ -86570,15 +86600,6 @@ /obj/structure/cable, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"yfP" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/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/textured_large, -/area/station/cargo/quartermaster) "yfW" = ( /obj/structure/bed/double, /obj/item/bedsheet/hos/double, @@ -86769,26 +86790,13 @@ /obj/effect/turf_decal/bot, /turf/open/floor/wood/large, /area/station/commons/fitness/recreation) -"ykb" = ( -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/supply/qm, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/airlock/mining{ - name = "Mining Lobby" - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ +"yjY" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/iron/textured_large, -/area/station/cargo/quartermaster) +/obj/effect/landmark/start/blueshield, +/turf/open/floor/carpet/cyan, +/area/station/command/heads_quarters/blueshield) "ykd" = ( /obj/structure/flora/grass/jungle, /obj/structure/flora/bush/grassy, @@ -106935,7 +106943,7 @@ lQt oxA ipJ dwi -csn +sDA rzh uUU jwC @@ -107186,7 +107194,7 @@ sbU xtV dUO lQt -uMv +gtJ oxA oxA oxA @@ -109714,7 +109722,7 @@ lgX gMx wKf ryt -uzO +vtA rLZ wKf lnU @@ -111725,7 +111733,7 @@ ndE uvK uRb fgh -eag +tgP efJ uRb qyR @@ -112039,7 +112047,7 @@ bow pkR iXs jmM -xdK +cBo mMw irQ pzD @@ -112474,7 +112482,7 @@ uvj uvj xmH lQf -sbI +qEh lQf nRd wjI @@ -112952,7 +112960,7 @@ veh veh sRK hrR -wJl +aSU cwH gQh veh @@ -113454,7 +113462,7 @@ ttw veh veh scI -oyB +dER fmR veh veh @@ -114788,7 +114796,7 @@ dje gDL jFt faf -bKt +tMp tJJ wjI vWf @@ -114799,7 +114807,7 @@ mhe mhe mhe xcl -wqS +hgd xir aKT aGK @@ -116435,7 +116443,7 @@ mkr qbr brI hbb -qcg +qPy brI iJi qAD @@ -116801,7 +116809,7 @@ bMb joM cmH iZr -rDO +mvl iuB cmH wxS @@ -116814,9 +116822,9 @@ aEF hER hZN rDu -uKR -bGH -uKR +aIL +xXG +aIL bFO bFO bFO @@ -117071,9 +117079,9 @@ aEF mav xjX sXX -uKR -kJs -wqs +aIL +jjg +ijg vBP dwE gIr @@ -117328,9 +117336,9 @@ uIR srd kuc gMY -uKR -yaP -yaP +aIL +for +for pAw nKV utT @@ -117575,7 +117583,7 @@ uvW uvW wEB kAm -ilT +yjY pGk cmH nVQ @@ -117585,9 +117593,9 @@ xLF tPD xjX kYC -uKR -yaP -sKz +aIL +for +frk vBP mVv exy @@ -117830,8 +117838,8 @@ tuF cmH vEu ohi -imV -uNm +kPk +jor imV uaz cmH @@ -117842,9 +117850,9 @@ xLF tPD rcY qBT -uKR -yaP -sPy +aIL +for +ozs vBP nyh vBI @@ -118099,9 +118107,9 @@ xLF tPD xjX jKG -uKR -yaP -ebE +aIL +for +irl vBP jYI eKU @@ -118344,7 +118352,7 @@ doJ cmH gTg cmH -eUl +bvz cmH cmH cmH @@ -118356,9 +118364,9 @@ aEF xwb xjX sxs -uKR -czm -uKR +aIL +aQv +aIL vBP vBP vBP @@ -118859,7 +118867,7 @@ azd oSL cmH iYy -sCm +jEm pCy cmH skL @@ -119116,7 +119124,7 @@ eip lAb cmH cmH -eFd +gqG cmH cmH agB @@ -123336,7 +123344,7 @@ eYK xud syE syE -pUd +hpU syE syE bTo @@ -123850,7 +123858,7 @@ jEb xud tHN uAc -hko +qMN qDp mhK hYq @@ -124326,7 +124334,7 @@ uuO sSJ mOm oBK -bsd +hdq efP jjw bPq @@ -124866,7 +124874,7 @@ eWh eWh eWh eWh -ncD +jKa aCq lRS oNR @@ -125890,12 +125898,12 @@ xud mdf gZX xVS -vnJ -vnJ -vnJ -vnJ -vnJ -vnJ +nAt +nAt +nAt +nAt +nAt +nAt nAD vwJ wKg @@ -126044,7 +126052,7 @@ ttw ttw xHb vTF -bif +wmE ioM piC ioM @@ -126145,14 +126153,14 @@ ryo vrJ xud mdf -vnJ -vnJ -vnJ -bLR -bii -siF -rJq -vnJ +nAt +nAt +nAt +tqz +dTZ +qTs +gYc +nAt nYU lWY uXx @@ -126402,14 +126410,14 @@ ryo ryo xud cYz -vnJ -jka -nss -acl -moT -iUP -ccH -mjo +nAt +dLA +jwQ +eSq +kvN +sun +pSO +hXd uRm pNh nMh @@ -126659,14 +126667,14 @@ ryo ryo xud cYz -vnJ -dKP -vZG -acl -bWx -kGT -nPP -vnJ +nAt +qHw +cPV +eSq +qnt +cgC +wBo +nAt urc lWY jKT @@ -126916,14 +126924,14 @@ ryo ryo xud cYz -vnJ -wfQ -xZG -vZR -yfP -dFH -pFP -vnJ +nAt +wVY +eOK +ohQ +htk +xGt +xfD +nAt nSV rJf jsz @@ -127173,14 +127181,14 @@ ryo ryo xud dOV -vnJ -xxR -cix -xxR -tAu -fbe -gKg -vnJ +nAt +out +mZJ +out +vjU +ftw +wle +nAt nWh vFv tqu @@ -127430,14 +127438,14 @@ xud xud xud sKs -vnJ -feb -atd -xxR -xxR -sLG -nui -vnJ +nAt +unj +fLb +out +out +nNa +ivM +nAt mCf dtq qxI @@ -127598,7 +127606,7 @@ vwi taf eju dJK -loI +iTX dZd eju taf @@ -127687,14 +127695,14 @@ pMm iGa rWS mdf -vnJ -iLc -rEG -puB -vnJ -ykb -qro -vnJ +nAt +inx +vkv +gST +nAt +ltz +vrK +nAt pqh vCX hTD @@ -127944,11 +127952,11 @@ bOJ iGa rWS mdf -vnJ -wPg -cRE -oKy -sXU +nAt +iyd +itx +bFr +aLA tPA tMq bzZ @@ -128201,11 +128209,11 @@ bOJ oSD oSD cYz -vnJ -vnJ -vnJ -vnJ -vnJ +nAt +nAt +nAt +nAt +nAt bNm oQF qNj @@ -128254,7 +128262,7 @@ ish aVb yiU dJY -bNz +mEw oGI dSV nrb @@ -129032,7 +129040,7 @@ nrb eeF sak xag -aqf +dom bWt sak kFh @@ -129192,7 +129200,7 @@ ePH vNJ vwe xjd -nuW +dwb elo aez vVF @@ -129555,7 +129563,7 @@ jrP unI vWy ehk -sVZ +jbo opW ghP dvO @@ -130053,14 +130061,14 @@ iay dBC kLl kLl -mvn +wGn mPs dNh kLl cQb iay dzC -jyw +iXX uVV xRx wIM @@ -134314,7 +134322,7 @@ kHq exx oKn iXB -iMg +aLy mBM cSZ sKy @@ -135067,7 +135075,7 @@ dKK xbD fkx wpp -qkQ +bdS jDe qhJ dFp diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm index b84faf05a59c..0126a707f6de 100644 --- a/_maps/map_files/debug/runtimestation.dmm +++ b/_maps/map_files/debug/runtimestation.dmm @@ -1734,16 +1734,16 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/science) +"hg" = ( +/obj/structure/tank_dispenser{ + pixel_x = -1 + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "hr" = ( /obj/machinery/electroplater, /turf/open/floor/iron, /area/station/commons/storage/primary) -"hA" = ( -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ - dir = 5 - }, -/turf/open/floor/plating, -/area/station/construction) "hD" = ( /obj/structure/closet/secure_closet/chemical/heisenberg{ locked = 0 @@ -1751,8 +1751,9 @@ /turf/open/floor/iron, /area/station/medical/chemistry) "hJ" = ( -/obj/machinery/atmospherics/pipe/smart/manifold/cyan/visible{ - dir = 1 +/obj/machinery/conveyor{ + dir = 4; + id = "debug" }, /turf/open/floor/plating, /area/station/construction) @@ -1783,9 +1784,7 @@ /turf/open/floor/plating, /area/station/engineering/atmos) "jF" = ( -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ - dir = 6 - }, +/obj/machinery/bouldertech/crusher, /turf/open/floor/plating, /area/station/construction) "jU" = ( @@ -1928,9 +1927,6 @@ dir = 4 }, /obj/machinery/light/directional/west, -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ - dir = 5 - }, /turf/open/floor/iron, /area/station/construction) "oV" = ( @@ -1944,8 +1940,7 @@ /turf/closed/wall/r_wall, /area/station/bitrunning/den) "pt" = ( -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, -/obj/machinery/meter/monitored/distro_loop, +/obj/item/construction/plumbing, /turf/open/floor/plating, /area/station/construction) "pv" = ( @@ -1962,7 +1957,7 @@ }, /obj/machinery/camera/autoname/directional/west, /obj/machinery/light/directional/west, -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, +/obj/structure/test_boulder_spawner, /turf/open/floor/iron, /area/station/construction) "pI" = ( @@ -1976,6 +1971,9 @@ /obj/machinery/door/airlock, /turf/open/floor/plating, /area/station/engineering/atmos) +"qn" = ( +/turf/open/space/basic, +/area/shipbreak) "qF" = ( /obj/machinery/airalarm/directional/north, /obj/effect/mapping_helpers/airalarm/unlocked, @@ -1995,7 +1993,9 @@ /turf/open/floor/iron, /area/station/hallway/secondary/entry) "rr" = ( -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, +/obj/machinery/conveyor_switch/oneway{ + id = "debug" + }, /turf/open/floor/plating, /area/station/construction) "rK" = ( @@ -2010,7 +2010,7 @@ /turf/open/floor/iron, /area/station/hallway/primary/central) "rU" = ( -/obj/machinery/atmospherics/components/binary/circulator, +/obj/item/stack/ducts/fifty, /turf/open/floor/plating, /area/station/construction) "rZ" = ( @@ -2065,7 +2065,10 @@ /turf/open/floor/iron/dark, /area/station/science/explab) "tY" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/freezer/on, +/obj/machinery/conveyor{ + dir = 6; + id = "debug" + }, /turf/open/floor/plating, /area/station/construction) "uf" = ( @@ -2082,10 +2085,6 @@ }, /turf/open/floor/iron, /area/station/cargo/miningoffice) -"uo" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/heater/on, -/turf/open/floor/plating, -/area/station/construction) "ut" = ( /obj/structure/closet/secure_closet/atmospherics{ locked = 0 @@ -2115,8 +2114,10 @@ /turf/open/floor/iron/dark, /area/station/science/explab) "vh" = ( -/obj/machinery/power/thermoelectric_generator, -/obj/structure/cable, +/obj/machinery/conveyor{ + dir = 1; + id = "debug" + }, /turf/open/floor/plating, /area/station/construction) "vm" = ( @@ -2169,16 +2170,14 @@ /turf/open/floor/iron, /area/station/bitrunning/den) "yx" = ( -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ - dir = 4 +/obj/machinery/conveyor{ + dir = 8; + id = "debug" }, /turf/open/floor/plating, /area/station/construction) "yy" = ( -/obj/machinery/atmospherics/components/unary/portables_connector{ - dir = 1 - }, -/obj/machinery/portable_atmospherics/canister/plasma, +/obj/machinery/big_manipulator, /turf/open/floor/plating, /area/station/construction) "yA" = ( @@ -2193,15 +2192,6 @@ /obj/machinery/light/directional/north, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"yJ" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ - dir = 6 - }, -/turf/open/floor/iron, -/area/station/construction) "yK" = ( /obj/structure/fans/tiny/invisible, /obj/effect/turf_decal/stripes/line{ @@ -2215,7 +2205,10 @@ /turf/open/floor/plating/airless, /area/space/nearstation) "yT" = ( -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible, +/obj/machinery/conveyor{ + dir = 2; + id = "debug" + }, /turf/open/floor/plating, /area/station/construction) "zo" = ( @@ -2224,11 +2217,9 @@ /turf/open/floor/iron, /area/station/engineering/atmos) "Aa" = ( -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ - dir = 4 - }, -/turf/open/floor/plating, -/area/station/construction) +/obj/machinery/big_manipulator, +/turf/open/floor/iron, +/area/station/commons/storage/primary) "AP" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 8 @@ -2236,11 +2227,8 @@ /turf/open/floor/iron, /area/station/science) "AR" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, -/turf/open/floor/iron, +/obj/machinery/bouldertech/refinery/smelter, +/turf/open/floor/plating, /area/station/construction) "AY" = ( /obj/effect/landmark/start/assistant, @@ -2275,6 +2263,12 @@ /obj/item/gun/ballistic/automatic/pistol, /turf/open/floor/iron, /area/station/command/bridge) +"BK" = ( +/obj/machinery/computer/shipbreaker{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "BW" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/camera/directional/north, @@ -2282,7 +2276,10 @@ /turf/open/floor/iron, /area/station/construction) "Cc" = ( -/obj/item/wrench, +/obj/machinery/conveyor{ + dir = 9; + id = "debug" + }, /turf/open/floor/plating, /area/station/construction) "Ce" = ( @@ -2320,8 +2317,7 @@ /turf/open/floor/iron, /area/station/bitrunning/den) "DL" = ( -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible, -/obj/machinery/meter/monitored/distro_loop, +/obj/machinery/bouldertech/crystalizer, /turf/open/floor/plating, /area/station/construction) "DW" = ( @@ -2362,7 +2358,10 @@ /turf/open/floor/iron, /area/station/command/bridge) "EN" = ( -/obj/structure/cable, +/obj/machinery/conveyor{ + dir = 5; + id = "debug" + }, /turf/open/floor/plating, /area/station/construction) "ES" = ( @@ -2379,12 +2378,6 @@ }, /turf/open/floor/iron, /area/station/medical/chemistry) -"Fi" = ( -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ - dir = 10 - }, -/turf/open/floor/plating, -/area/station/construction) "GB" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -2410,7 +2403,7 @@ /turf/open/floor/plating, /area/station/commons/storage/primary) "Hr" = ( -/obj/machinery/atmospherics/pipe/smart/manifold/cyan/visible, +/obj/machinery/bouldertech/chemical_injector, /turf/open/floor/plating, /area/station/construction) "Id" = ( @@ -2443,9 +2436,7 @@ /turf/open/floor/iron, /area/station/cargo/miningoffice) "Jn" = ( -/obj/machinery/atmospherics/pipe/smart/manifold/scrubbers/visible{ - dir = 1 - }, +/obj/machinery/bouldertech/purification_chamber, /turf/open/floor/plating, /area/station/construction) "Jp" = ( @@ -2467,17 +2458,16 @@ /turf/open/floor/plating, /area/station/engineering/atmos) "Li" = ( -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ - dir = 9 - }, +/obj/machinery/bouldertech/enricher, /turf/open/floor/plating, /area/station/construction) "Lq" = ( /turf/open/floor/circuit/green, /area/station/bitrunning/den) "Lx" = ( -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ - dir = 9 +/obj/machinery/conveyor{ + dir = 10; + id = "debug" }, /turf/open/floor/plating, /area/station/construction) @@ -2493,14 +2483,6 @@ /obj/machinery/door/airlock/research, /turf/open/floor/iron/dark, /area/station/science/explab) -"LL" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/light_switch/directional/west, -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, -/turf/open/floor/iron, -/area/station/construction) "LW" = ( /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron, @@ -2509,6 +2491,12 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/central) +"Mu" = ( +/obj/machinery/door/airlock/external/ruin{ + name = "Departure Lounge Airlock" + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "ME" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -2542,14 +2530,13 @@ /turf/open/floor/iron, /area/station/science) "Ob" = ( -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ - dir = 10 - }, +/obj/machinery/bouldertech/chemical_washer, /turf/open/floor/plating, /area/station/construction) "Oc" = ( -/obj/machinery/atmospherics/components/binary/volume_pump{ - dir = 4 +/obj/machinery/conveyor/inverted{ + dir = 5; + id = "debug" }, /turf/open/floor/plating, /area/station/construction) @@ -2605,7 +2592,7 @@ /turf/open/floor/iron, /area/station/hallway/secondary/entry) "Rx" = ( -/obj/machinery/atmospherics/components/binary/circulator/cold, +/obj/item/wrench/abductor, /turf/open/floor/plating, /area/station/construction) "RM" = ( @@ -2619,7 +2606,7 @@ /turf/open/floor/iron, /area/station/bitrunning/den) "Sd" = ( -/obj/machinery/atmospherics/pipe/smart/manifold/scrubbers/visible, +/obj/machinery/bouldertech/dissolution_chamber, /turf/open/floor/plating, /area/station/construction) "Sj" = ( @@ -2733,6 +2720,10 @@ }, /turf/open/floor/iron, /area/station/medical/chemistry) +"Xi" = ( +/obj/machinery/suit_storage_unit/ce, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "Xp" = ( /obj/machinery/light/directional/south, /obj/structure/tank_dispenser{ @@ -2745,10 +2736,7 @@ /turf/open/floor/iron, /area/station/science) "XE" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Port to Filter" - }, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/plating, /area/station/construction) "XN" = ( @@ -6160,11 +6148,11 @@ bE cN UK dm -yJ -LL +dy +ii pD -AR -AR +dy +dy oK ii dy @@ -6251,16 +6239,16 @@ ES rL cP cX -uo -Sd dn +Sd +yy dn dn dn Oc -dn -dn -dn +yT +yT +yT dL sr nn @@ -6343,16 +6331,16 @@ bE Mh TV EA -uo -Sd dn +Sd +yy dn dn dn -Jn +yx XE yy -dn +yy dL cN lQ @@ -6435,16 +6423,16 @@ bE bE ef EA -uo -Sd dn dn dn dn -Aa -dn dn +Rx +yx dn +Jn +Jn dL tE ZP @@ -6529,11 +6517,11 @@ cN BW dn Ob -pt +dn rU pt rr -Li +yx dn dn dn @@ -6620,15 +6608,15 @@ bE cN EA EN -EN -EN vh -dn +vh +vh +vh Cc -dn -dn -dn -dn +yx +XE +yy +yy dL cN fI @@ -6711,16 +6699,16 @@ lX bE cN cY -dn -jF +hJ DL -Rx DL -yT -hA -dn -dn +DL +DL +yx +yx dn +jF +jF dZ cN Tt @@ -6804,11 +6792,11 @@ bE cN cY tY -Hr -dn -dn -dn -dn +yT +yT +yT +yT +Lx yx dn dn @@ -6895,16 +6883,16 @@ bE bE cN cY -tY -Hr dn -dn -dn -dn -hJ +yy +yy +yy +yy +yy +yx XE yy -dn +yy dL cN Tt @@ -6987,16 +6975,16 @@ bE bE ef cY -tY -Hr -dn -dn -dn -dn -Oc -dn dn +Hr +Hr +Hr +Hr +Hr +yx dn +Li +Li dL cN Tt @@ -7080,15 +7068,15 @@ bE ef cY dn -Fi +yT yT yT yT yT Lx dn -dn -dn +AR +AR dL cN Tt @@ -7638,7 +7626,7 @@ dJ dI dJ dJ -dJ +Aa dJ dJ ny @@ -7729,9 +7717,9 @@ hr oE dI dJ +Aa dJ -dJ -dJ +Aa dJ dO cS @@ -7822,7 +7810,7 @@ dJ dI dJ dJ -dJ +Aa dJ dJ jU @@ -8932,7 +8920,9 @@ fh fh et ga -ga +fO +fO +fO ga ga ga @@ -8977,8 +8967,6 @@ aa aa aa aa -aa -aa "} (68,1,1) = {" aa @@ -9023,13 +9011,13 @@ ew aa aa aa -aa -aa -aa -aa -aa -aa -aa +ga +fO +fO +fO +Mu +fO +ga aa aa aa @@ -9115,13 +9103,13 @@ fh aa aa aa -aa -aa -aa -aa -aa -aa -aa +ga +hg +fO +fO +ga +fO +ga aa aa aa @@ -9207,13 +9195,13 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa +ga +Xi +BK +fO +ga +fO +ga aa aa aa @@ -9299,13 +9287,13 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa +ga +ga +gf +gf +ga +Mu +ga aa aa aa @@ -9574,25 +9562,25 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn aa aa aa @@ -9666,25 +9654,25 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn aa aa aa @@ -9758,25 +9746,25 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn aa aa aa @@ -9850,25 +9838,25 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn aa aa aa @@ -9942,25 +9930,25 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn aa aa aa @@ -10034,25 +10022,25 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn aa aa aa @@ -10126,25 +10114,25 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn aa aa aa @@ -10218,25 +10206,25 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn aa aa aa @@ -10310,25 +10298,25 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn aa aa aa @@ -10402,25 +10390,25 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn aa aa aa @@ -10494,25 +10482,25 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn +qn aa aa aa diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 3a6be6c7ac17..285de81e4303 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -1743,6 +1743,11 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) +"afJ" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/smooth, +/area/station/maintenance/central/greater) "afN" = ( /obj/structure/lattice/catwalk, /obj/structure/cable, @@ -5500,13 +5505,6 @@ /obj/machinery/duct, /turf/open/floor/iron/white, /area/station/medical/treatment_center) -"aLG" = ( -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 9 - }, -/obj/machinery/computer/records/pathology, -/turf/open/floor/iron/white, -/area/station/medical/storage) "aLH" = ( /obj/effect/turf_decal/loading_area/white{ dir = 1 @@ -6556,11 +6554,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/atmos/pumproom) -"aVx" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/catwalk_floor, -/area/station/maintenance/starboard/central) "aVD" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/trimline/neutral/filled/line, @@ -6623,12 +6616,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/commons/fitness) -"aXq" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/smooth, -/area/station/maintenance/department/crew_quarters/dorms) "aXu" = ( /obj/effect/turf_decal/caution/stand_clear/red{ dir = 4 @@ -6961,11 +6948,6 @@ /obj/machinery/power/apc/auto_name/directional/south, /turf/open/floor/catwalk_floor, /area/station/maintenance/port/aft) -"beN" = ( -/obj/effect/landmark/start/assistant, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/wood/parquet, -/area/station/service/library) "beP" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -7160,6 +7142,11 @@ /obj/item/radio/off, /turf/open/floor/iron/smooth, /area/station/maintenance/starboard/lesser) +"bhR" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/smooth, +/area/station/maintenance/department/crew_quarters/dorms) "bia" = ( /obj/machinery/light/directional/east, /obj/machinery/modular_computer/preset/engineering{ @@ -7501,12 +7488,6 @@ dir = 1 }, /area/station/hallway/secondary/service) -"box" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/smooth, -/area/station/maintenance/department/medical) "boJ" = ( /obj/item/pickaxe, /turf/open/misc/asteroid/airless, @@ -8659,11 +8640,6 @@ }, /turf/open/floor/iron/white, /area/station/science/lower) -"bGG" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/smooth, -/area/station/maintenance/port/aft) "bGI" = ( /obj/structure/chair/comfy/beige{ dir = 1 @@ -9053,6 +9029,11 @@ /obj/machinery/bluespace_beacon, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/foyer) +"bML" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/landmark/start/blueshield, +/turf/open/floor/carpet/neon/simple/blue/nodots, +/area/station/command/heads_quarters/blueshield) "bMX" = ( /obj/effect/turf_decal/trimline/brown/filled/corner{ dir = 1 @@ -9930,15 +9911,6 @@ /obj/machinery/door/airlock/public/glass, /turf/open/floor/iron/smooth, /area/station/hallway/primary/tram/right) -"cav" = ( -/obj/effect/turf_decal/siding/wood/corner{ - dir = 4 - }, -/obj/effect/spawner/random/engineering/tracking_beacon, -/obj/structure/cable, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/wood, -/area/station/commons/vacant_room/office) "cay" = ( /obj/machinery/computer/security{ dir = 1 @@ -11854,14 +11826,6 @@ /obj/machinery/seed_extractor, /turf/open/floor/iron/dark, /area/station/security/prison/garden) -"cFZ" = ( -/obj/structure/table/wood, -/obj/machinery/firealarm/directional/north, -/obj/item/book/bible, -/turf/open/floor/iron/chapel{ - dir = 9 - }, -/area/station/service/chapel) "cGc" = ( /obj/structure/cable, /turf/open/floor/iron, @@ -12442,13 +12406,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/security/office) -"cQN" = ( -/obj/machinery/door/airlock/corporate{ - name = "Blueshield's Quarters" - }, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/turf/open/floor/carpet/neon/simple/blue/nodots, -/area/station/command/heads_quarters/blueshield) "cQQ" = ( /obj/structure/cable, /turf/open/floor/plating, @@ -12582,9 +12539,6 @@ }, /turf/open/floor/iron/smooth, /area/station/maintenance/central/lesser) -"cTK" = ( -/turf/open/floor/carpet/executive, -/area/station/command/heads_quarters/blueshield) "cTM" = ( /obj/effect/turf_decal/trimline/red/filled/line{ dir = 8 @@ -12853,15 +12807,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/tram/center) -"cYx" = ( -/obj/structure/chair{ - dir = 8 - }, -/obj/effect/landmark/event_spawn, -/obj/structure/cable, -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/dark, -/area/station/commons/fitness/recreation/entertainment) "cYA" = ( /obj/docking_port/stationary{ dheight = 4; @@ -17498,6 +17443,11 @@ }, /turf/open/floor/iron/white, /area/station/science/ordnance) +"evs" = ( +/obj/effect/landmark/start/assistant, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/wood/parquet, +/area/station/service/library) "evu" = ( /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 8 @@ -18416,6 +18366,11 @@ "eNx" = ( /turf/open/floor/iron/grimy, /area/station/service/library/lounge) +"eNy" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/catwalk_floor, +/area/station/maintenance/starboard/central) "eNH" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 4 @@ -19206,6 +19161,10 @@ /obj/structure/closet/cardboard, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) +"eZD" = ( +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/grimy, +/area/station/service/library/lounge) "eZS" = ( /obj/machinery/door/airlock/grunge{ name = "Entertainment Center" @@ -20182,10 +20141,6 @@ }, /turf/open/floor/plating, /area/station/cargo/sorting) -"fqe" = ( -/obj/effect/landmark/start/gary/rare, -/turf/open/floor/iron/grimy, -/area/station/service/library/lounge) "fqn" = ( /obj/effect/turf_decal/trimline/red/filled/corner{ dir = 1 @@ -20234,6 +20189,11 @@ /obj/structure/industrial_lift/public, /turf/open/floor/plating/elevatorshaft, /area/station/hallway/secondary/service) +"frQ" = ( +/obj/structure/flora/bush/flowers_yw/style_random, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/grass, +/area/station/asteroid) "frT" = ( /obj/machinery/atmospherics/pipe/layer_manifold/supply/hidden, /turf/closed/wall/r_wall, @@ -21841,6 +21801,14 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/construction/engineering) +"fRR" = ( +/obj/structure/table/wood, +/obj/machinery/firealarm/directional/north, +/obj/item/book/bible, +/turf/open/floor/iron/chapel{ + dir = 9 + }, +/area/station/service/chapel) "fRW" = ( /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 5 @@ -22453,10 +22421,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"gfj" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/carpet/neon/simple/blue/nodots, -/area/station/command/heads_quarters/blueshield) "gfu" = ( /obj/effect/turf_decal/siding/thinplating_new{ dir = 4 @@ -22466,6 +22430,10 @@ }, /turf/open/floor/iron, /area/station/science/lower) +"gfH" = ( +/obj/effect/landmark/start/blueshield, +/turf/open/floor/carpet/executive, +/area/station/command/heads_quarters/blueshield) "gfK" = ( /turf/closed/wall/r_wall, /area/station/security/execution/education) @@ -24305,11 +24273,6 @@ dir = 4 }, /area/station/command/teleporter) -"gKm" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/smooth, -/area/station/maintenance/port/central) "gKr" = ( /obj/effect/turf_decal/siding/thinplating, /obj/structure/cable, @@ -25053,6 +25016,22 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/medical/break_room) +"gWb" = ( +/obj/structure/rack, +/obj/structure/window/spawner/directional/east, +/obj/item/book/bible{ + pixel_x = -4; + pixel_y = -4 + }, +/obj/item/book/bible, +/obj/item/book/bible{ + pixel_x = 4; + pixel_y = 4 + }, +/obj/structure/window/spawner/directional/south, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/smooth, +/area/station/maintenance/department/crew_quarters/dorms) "gWc" = ( /mob/living/carbon/human/species/monkey, /turf/open/misc/grass/jungle, @@ -26162,6 +26141,12 @@ }, /turf/open/floor/iron/dark, /area/station/science/lower) +"hqL" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/smooth, +/area/station/maintenance/department/medical) "hqN" = ( /obj/structure/weightmachine/weightlifter, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -27900,6 +27885,11 @@ /obj/structure/cable/layer1, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/hallway) +"hVC" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/smooth, +/area/station/maintenance/port/central) "hVD" = ( /obj/machinery/computer/teleporter{ dir = 1 @@ -30306,11 +30296,6 @@ /obj/effect/landmark/navigate_destination/tram/bankofcargo, /turf/open/floor/iron/dark, /area/station/cargo/miningdock/oresilo) -"iIT" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/smooth, -/area/station/maintenance/starboard/central) "iJd" = ( /obj/effect/turf_decal/trimline/neutral/filled/corner{ dir = 4 @@ -31049,6 +31034,21 @@ /obj/structure/cable, /turf/open/floor/iron/dark/textured, /area/station/engineering/main) +"iUf" = ( +/obj/machinery/door/airlock/grunge{ + name = "Morgue" + }, +/obj/machinery/door/firedoor, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/any/medical/general, +/obj/effect/mapping_helpers/airlock/access/any/medical/morgue, +/turf/open/floor/iron/dark, +/area/station/medical/morgue) "iUh" = ( /turf/closed/wall, /area/station/security/warden) @@ -31239,11 +31239,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/commons/fitness/recreation) -"iWn" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron, -/area/station/maintenance/starboard/central) "iWz" = ( /obj/machinery/door/airlock/external/glass{ name = "Supply Door Airlock" @@ -37995,11 +37990,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) -"lau" = ( -/obj/item/book/bible, -/obj/structure/altar_of_gods, -/turf/open/floor/iron/dark, -/area/station/service/chapel) "lav" = ( /obj/machinery/holopad, /obj/effect/turf_decal/trimline/neutral/corner{ @@ -38322,6 +38312,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/catwalk_floor, /area/station/maintenance/tram/mid) +"lfe" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/dark, +/area/station/commons/vacant_room/commissary) "lfq" = ( /obj/effect/turf_decal/trimline/white/warning{ dir = 4 @@ -40874,6 +40869,15 @@ /obj/item/pen, /turf/open/floor/iron, /area/station/security/checkpoint/supply) +"lXC" = ( +/obj/effect/turf_decal/trimline/green/filled/line{ + dir = 1 + }, +/obj/machinery/airalarm/directional/north, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/machinery/computer/records/pathology, +/turf/open/floor/iron/dark, +/area/station/medical/pathology) "lXH" = ( /obj/machinery/atmospherics/pipe/smart/manifold/yellow/visible{ dir = 1 @@ -41134,11 +41138,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/showroomfloor, /area/station/security/warden) -"mcb" = ( -/obj/structure/flora/bush/flowers_yw/style_random, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/grass, -/area/station/asteroid) "mcf" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, @@ -41308,6 +41307,12 @@ /obj/item/queen_bee/bought, /turf/open/floor/iron/dark, /area/station/service/hydroponics) +"met" = ( +/obj/structure/chair/stool/bar/directional/east, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/smooth, +/area/station/maintenance/starboard/greater) "meu" = ( /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 8 @@ -43403,6 +43408,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/service/hydroponics/garden) +"mNI" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/smooth, +/area/station/maintenance/department/crew_quarters/dorms) "mNN" = ( /obj/structure/chair/comfy/brown{ dir = 1 @@ -43551,6 +43562,13 @@ /obj/effect/spawner/random/engineering/canister, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"mPr" = ( +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 9 + }, +/obj/machinery/computer/records/pathology, +/turf/open/floor/iron/white, +/area/station/medical/storage) "mPA" = ( /obj/structure/cable, /obj/effect/turf_decal/sand/plating, @@ -44236,17 +44254,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/dark, /area/station/security/courtroom) -"ncX" = ( -/obj/machinery/door/airlock/corporate{ - id_tag = "BSdoor"; - name = "Blueshield's Office" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/airlock/access/all/command/captain, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/turf/open/floor/carpet/neon/simple/blue/nodots, -/area/station/command/heads_quarters/blueshield) "ndb" = ( /turf/open/floor/engine{ name = "Holodeck Projector Floor" @@ -45055,6 +45062,31 @@ /obj/machinery/cassette/adv_cassette_deck, /turf/open/floor/wood/large, /area/station/service/library) +"noG" = ( +/obj/machinery/button/door/directional/east{ + id = "armory"; + name = "Armory Shutters"; + req_access = list("armory") + }, +/obj/machinery/status_display/ai/directional/north, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/rack, +/obj/item/ammo_box/magazine/m35, +/obj/item/ammo_box/magazine/m35, +/obj/item/ammo_box/magazine/m35, +/obj/item/ammo_box/magazine/m35, +/obj/item/ammo_box/magazine/m35, +/obj/item/ammo_box/magazine/m35, +/obj/item/ammo_box/magazine/m35, +/obj/item/ammo_box/magazine/m35, +/obj/item/ammo_box/magazine/m35, +/obj/item/ammo_box/magazine/m35, +/obj/item/gun/ballistic/automatic/pistol/paco/no_mag, +/obj/item/gun/ballistic/automatic/pistol/paco/no_mag{ + pixel_y = 6 + }, +/turf/open/floor/iron/dark, +/area/station/ai_monitored/security/armory) "noI" = ( /obj/effect/turf_decal/trimline/red/filled/line{ dir = 1 @@ -45248,22 +45280,6 @@ }, /turf/open/floor/iron/white, /area/station/science/lower) -"nrt" = ( -/obj/structure/rack, -/obj/structure/window/spawner/directional/east, -/obj/item/book/bible{ - pixel_x = -4; - pixel_y = -4 - }, -/obj/item/book/bible, -/obj/item/book/bible{ - pixel_x = 4; - pixel_y = 4 - }, -/obj/structure/window/spawner/directional/south, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/iron/smooth, -/area/station/maintenance/department/crew_quarters/dorms) "nrM" = ( /obj/machinery/door/airlock/mining/glass{ name = "Cargo Office" @@ -46446,6 +46462,11 @@ /obj/structure/sign/directions/ptl/directional/west, /turf/open/floor/iron, /area/station/engineering/main) +"nMn" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/smooth, +/area/station/maintenance/central/lesser) "nMr" = ( /obj/effect/turf_decal/trimline/dark_red/warning{ dir = 10 @@ -47745,6 +47766,15 @@ }, /turf/open/floor/iron/dark/textured, /area/station/engineering/main) +"oht" = ( +/obj/structure/chair{ + dir = 8 + }, +/obj/effect/landmark/event_spawn, +/obj/structure/cable, +/obj/effect/landmark/start/gary/rare, +/turf/open/floor/iron/dark, +/area/station/commons/fitness/recreation/entertainment) "ohw" = ( /obj/structure/flora/bush/flowers_pp, /obj/structure/chair/sofa/bench/right{ @@ -48980,6 +49010,11 @@ /obj/effect/spawner/random/trash/food_packaging, /turf/open/floor/catwalk_floor, /area/station/maintenance/starboard/central) +"oDc" = ( +/obj/item/book/bible, +/obj/structure/altar_of_gods, +/turf/open/floor/iron/dark, +/area/station/service/chapel) "oDd" = ( /obj/effect/turf_decal/siding/white{ dir = 1 @@ -51519,6 +51554,12 @@ /obj/machinery/light/small/directional/south, /turf/open/floor/engine/air, /area/station/engineering/atmos) +"pww" = ( +/obj/structure/table/wood, +/obj/machinery/light/dim/directional/north, +/obj/item/book/bible, +/turf/open/floor/carpet, +/area/station/service/chapel/monastery) "pwx" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 1 @@ -51652,13 +51693,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/command) -"pys" = ( -/obj/machinery/plumbing/ooze_sucker{ - mapping_id = "6" - }, -/obj/machinery/light/floor/has_bulb, -/turf/open/floor/engine, -/area/station/science/xenobiology) "pyu" = ( /obj/effect/turf_decal/siding/thinplating/corner{ dir = 1 @@ -52157,6 +52191,11 @@ }, /turf/open/space/openspace, /area/space) +"pEE" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/smooth, +/area/station/maintenance/starboard/central) "pEL" = ( /obj/machinery/atmospherics/pipe/bridge_pipe/dark/visible{ dir = 8 @@ -52803,11 +52842,6 @@ /obj/structure/spider/passage, /turf/open/floor/iron/smooth, /area/station/maintenance/starboard/lesser) -"pNr" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/smooth, -/area/station/maintenance/central/greater) "pNz" = ( /obj/effect/landmark/navigate_destination/chapel, /turf/open/floor/carpet, @@ -54244,6 +54278,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/brig) +"qml" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/smooth, +/area/station/maintenance/port/aft) "qmp" = ( /obj/machinery/light/small/directional/east, /turf/open/floor/engine/n2o, @@ -54349,6 +54388,13 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/science/robotics/mechbay) +"qoq" = ( +/obj/machinery/door/airlock/corporate{ + name = "Blueshield's Quarters" + }, +/obj/effect/mapping_helpers/airlock/access/all/admin/general, +/turf/open/floor/carpet/neon/simple/blue/nodots, +/area/station/command/heads_quarters/blueshield) "qos" = ( /obj/machinery/exodrone_launcher, /obj/effect/decal/cleanable/dirt, @@ -54968,6 +55014,13 @@ /obj/effect/turf_decal/trimline/neutral/filled/corner, /turf/open/floor/iron, /area/station/security/courtroom) +"qyA" = ( +/obj/machinery/plumbing/ooze_sucker{ + mapping_id = "6" + }, +/obj/machinery/light/floor/has_bulb, +/turf/open/floor/engine, +/area/station/science/xenobiology) "qyI" = ( /obj/effect/landmark/tram/tramstation/east, /turf/open/floor/noslip/tram_plate, @@ -55405,6 +55458,13 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) +"qFc" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/stone, +/area/station/smithing) "qFf" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 8 @@ -56757,12 +56817,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/gravity_generator) -"qZQ" = ( -/obj/structure/chair/stool/bar/directional/east, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/smooth, -/area/station/maintenance/starboard/greater) "raf" = ( /obj/machinery/light/directional/west, /obj/structure/cable, @@ -56881,21 +56935,6 @@ /obj/effect/turf_decal/stripes/white/line, /turf/open/floor/iron, /area/station/hallway/primary/tram/left) -"rbg" = ( -/obj/machinery/door/airlock/grunge{ - name = "Morgue" - }, -/obj/machinery/door/firedoor, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/mapping_helpers/airlock/access/any/medical/general, -/obj/effect/mapping_helpers/airlock/access/any/medical/morgue, -/turf/open/floor/iron/dark, -/area/station/medical/morgue) "rbj" = ( /obj/machinery/requests_console/directional/east{ assistance_requestable = 1; @@ -57131,6 +57170,12 @@ }, /turf/open/floor/iron/white, /area/station/medical/surgery/aft) +"rfs" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/blobstart, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/smooth, +/area/station/maintenance/department/medical) "rfP" = ( /obj/structure/cable, /turf/open/floor/wood, @@ -60105,13 +60150,6 @@ /obj/structure/railing, /turf/open/openspace, /area/station/solars/port) -"sgm" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/effect/landmark/start/gary/uncommon, -/turf/open/floor/stone, -/area/station/smithing) "sgo" = ( /mob/living/basic/butterfly, /turf/open/floor/grass, @@ -60702,16 +60740,6 @@ }, /turf/open/floor/iron/white, /area/station/science/research) -"sqm" = ( -/obj/machinery/door/airlock/grunge{ - name = "Morgue External Access" - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/mapping_helpers/airlock/access/all/medical/morgue, -/turf/open/floor/iron/dark, -/area/station/medical/morgue) "sqq" = ( /obj/effect/mob_spawn/corpse/human/charredskeleton, /obj/effect/decal/cleanable/blood/splatter, @@ -60727,11 +60755,6 @@ /obj/structure/extinguisher_cabinet/directional/west, /turf/open/floor/iron, /area/station/security/courtroom) -"sqC" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/smooth, -/area/station/maintenance/starboard/greater) "sqF" = ( /obj/effect/turf_decal/trimline/green/corner{ dir = 8 @@ -60755,6 +60778,17 @@ }, /turf/open/floor/iron/white, /area/station/science/lower) +"sqP" = ( +/obj/machinery/door/airlock/corporate{ + id_tag = "BSdoor"; + name = "Blueshield's Office" + }, +/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/all/admin/general, +/turf/open/floor/carpet/neon/simple/blue/nodots, +/area/station/command/heads_quarters/blueshield) "sqQ" = ( /obj/machinery/door/airlock/medical{ name = "Surgery B" @@ -61112,15 +61146,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/medical/pathology) -"svP" = ( -/obj/effect/turf_decal/trimline/green/filled/line{ - dir = 1 - }, -/obj/machinery/airalarm/directional/north, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/machinery/computer/records/pathology, -/turf/open/floor/iron/dark, -/area/station/medical/pathology) "svZ" = ( /obj/effect/turf_decal/trimline/red/filled/line, /obj/machinery/light/directional/south, @@ -62474,11 +62499,6 @@ "sQZ" = ( /turf/closed/wall/r_wall, /area/station/science/explab) -"sRa" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/smooth, -/area/station/maintenance/department/crew_quarters/dorms) "sRh" = ( /obj/structure/showcase/cyborg/old{ pixel_y = 20 @@ -63997,11 +64017,6 @@ }, /turf/open/floor/noslip/tram_plate, /area/station/hallway/primary/tram/right) -"toN" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/plating, -/area/station/maintenance/starboard/greater) "toY" = ( /obj/structure/table/wood, /obj/structure/reagent_dispensers/wall/peppertank/directional/east, @@ -64933,11 +64948,6 @@ "tDT" = ( /turf/open/openspace, /area/station/commons/fitness/recreation) -"tEd" = ( -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/dark, -/area/station/commons/vacant_room/commissary) "tEe" = ( /obj/structure/flora/bush/sparsegrass/style_random, /obj/structure/flora/bush/grassy/style_random, @@ -65822,6 +65832,11 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) +"tUc" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/plating, +/area/station/maintenance/starboard/greater) "tUH" = ( /obj/structure/rack, /obj/item/clothing/under/color/blue, @@ -66972,12 +66987,6 @@ /obj/effect/turf_decal/trimline/neutral/filled/warning, /turf/open/floor/iron, /area/station/hallway/primary/tram/left) -"unN" = ( -/obj/structure/table/wood, -/obj/machinery/light/dim/directional/north, -/obj/item/book/bible, -/turf/open/floor/carpet, -/area/station/service/chapel/monastery) "unS" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -69016,6 +69025,11 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/maint) +"uTq" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron, +/area/station/maintenance/starboard/central) "uTz" = ( /obj/structure/railing{ dir = 8 @@ -71251,31 +71265,6 @@ /obj/effect/spawner/random/engineering/tank, /turf/open/floor/iron/smooth, /area/station/maintenance/department/crew_quarters/dorms) -"vzg" = ( -/obj/machinery/button/door/directional/east{ - id = "armory"; - name = "Armory Shutters"; - req_access = list("armory") - }, -/obj/machinery/status_display/ai/directional/north, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/structure/rack, -/obj/item/ammo_box/magazine/m35, -/obj/item/ammo_box/magazine/m35, -/obj/item/ammo_box/magazine/m35, -/obj/item/ammo_box/magazine/m35, -/obj/item/ammo_box/magazine/m35, -/obj/item/ammo_box/magazine/m35, -/obj/item/ammo_box/magazine/m35, -/obj/item/ammo_box/magazine/m35, -/obj/item/ammo_box/magazine/m35, -/obj/item/ammo_box/magazine/m35, -/obj/item/gun/ballistic/automatic/pistol/paco/no_mag, -/obj/item/gun/ballistic/automatic/pistol/paco/no_mag{ - pixel_y = 6 - }, -/turf/open/floor/iron/dark, -/area/station/ai_monitored/security/armory) "vzl" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/trash/garbage, @@ -72853,6 +72842,15 @@ }, /turf/open/floor/carpet, /area/station/command/bridge) +"vZW" = ( +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/obj/effect/spawner/random/engineering/tracking_beacon, +/obj/structure/cable, +/obj/effect/landmark/start/gary/uncommon, +/turf/open/floor/wood, +/area/station/commons/vacant_room/office) "vZX" = ( /obj/structure/lattice/catwalk, /obj/structure/railing{ @@ -74050,6 +74048,21 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/freezer, /area/station/commons/toilet) +"wtJ" = ( +/obj/machinery/door/airlock/grunge{ + name = "Morgue External Access" + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/medical/morgue, +/turf/open/floor/iron/dark, +/area/station/medical/morgue) +"wtN" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/gary, +/turf/open/floor/iron/smooth, +/area/station/maintenance/starboard/greater) "wtP" = ( /obj/structure/closet{ name = "Evidence Closet 2" @@ -77916,11 +77929,6 @@ /obj/machinery/vending/wallmed/directional/north, /turf/open/floor/iron/white, /area/station/medical/medbay/central) -"xKz" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/smooth, -/area/station/maintenance/central/lesser) "xKD" = ( /obj/structure/dresser, /turf/open/floor/carpet/executive, @@ -79214,12 +79222,6 @@ /obj/machinery/airalarm/directional/south, /turf/open/floor/iron/dark, /area/station/medical/storage) -"yeR" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/start/gary, -/turf/open/floor/iron/smooth, -/area/station/maintenance/department/medical) "yeX" = ( /obj/machinery/computer/telecomms/monitor{ dir = 1; @@ -92495,7 +92497,7 @@ apC jXf yah jfs -sRa +bhR lOR yah aac @@ -94038,7 +94040,7 @@ cAY apC lgu lgu -sRa +bhR lgu apC aaa @@ -98365,7 +98367,7 @@ pZW pVD jAk jAk -gKm +hVC jAk jAk ahU @@ -98869,7 +98871,7 @@ rUR rUR rUR uzS -ncX +sqP pnp bJM lQM @@ -99636,9 +99638,9 @@ kLz kLz kLz lRF -cTK -cQN -gfj +gfH +qoq +bML lyI iUN lQM @@ -99955,7 +99957,7 @@ snM xJZ lgu lgu -sRa +bhR lgu apC aac @@ -101239,7 +101241,7 @@ jnq vqn jnq lgu -sRa +bhR gsE apC ncE @@ -102506,7 +102508,7 @@ qOf amu rtp kWN -cYx +oht byx kWN rtp @@ -105772,7 +105774,7 @@ vXM aac qLK lnY -pNr +afJ nMu jcq nMu @@ -106054,7 +106056,7 @@ hFr hFr hFr aTT -pNr +afJ nMu nMu hFr @@ -106101,7 +106103,7 @@ aaa jnq cRa juN -xKz +nMn sAK pmz dzp @@ -106554,7 +106556,7 @@ eSk jbH iXh nMu -pNr +afJ nMu hFr qxf @@ -115829,7 +115831,7 @@ quF wfU quF quF -sqC +wtN quF iRL gbF @@ -117366,7 +117368,7 @@ aac siI iRB fIA -toN +tUc fIA iRL wkE @@ -121233,7 +121235,7 @@ iRL pWy iRL vqz -qZQ +met kOI quF aaS @@ -121484,7 +121486,7 @@ aaa aaa iRL quF -sqC +wtN mAF cOx pWy @@ -123312,7 +123314,7 @@ ejC ePU qxm ryO -iIT +pEE gDw qxm nZX @@ -124337,7 +124339,7 @@ gBw sIW whZ bvT -sgm +qFc glO hxW qxm @@ -126680,7 +126682,7 @@ vmk qVr bfH bfH -pys +qyA xQh cim kTh @@ -128967,7 +128969,7 @@ oys oys pom cwB -iWn +uTq oys iix xYf @@ -130755,7 +130757,7 @@ ecO kDR oNd kDR -aVx +eNy hiJ pAf oAw @@ -155152,7 +155154,7 @@ aaa iyc fCO kMf -cav +vZW mpa sQe iyc @@ -157514,7 +157516,7 @@ tdx mQa mQa mQa -bGG +qml mQa mQa mQa @@ -158277,7 +158279,7 @@ hnH gFt cSr gCQ -beN +evs dyx tdx tVH @@ -159568,7 +159570,7 @@ kgd rAS iMy eNx -fqe +eZD eNx apO tdx @@ -162918,7 +162920,7 @@ gHe gHe hYh vCZ -unN +pww skw kkg buB @@ -163685,7 +163687,7 @@ jkt jkt aPg piE -lau +oDc aQx kUo tXn @@ -164191,7 +164193,7 @@ tDT ylF srN pUw -cFZ +fRR qOi oqS mEs @@ -164633,7 +164635,7 @@ rmB rmB dEv dEv -vzg +noG mcU eka dEv @@ -167538,7 +167540,7 @@ jPK bpr bcG fmS -sRa +bhR apC aaa aaa @@ -168559,7 +168561,7 @@ ndb fsC hSE lgu -aXq +mNI lgu apC jPK @@ -169071,7 +169073,7 @@ fsC whz whz whz -nrt +gWb lgu lgu fas @@ -171121,7 +171123,7 @@ acm abW abW abW -mcb +frQ abW abS abW @@ -172163,7 +172165,7 @@ apC jPK apC lgu -sRa +bhR lgu apC xOk @@ -173176,7 +173178,7 @@ xBk pMh drn bdq -aLG +mPr vcv odH kRL @@ -180371,7 +180373,7 @@ oXP xOM oIa oIa -rbg +iUf oIa bFq bFq @@ -181666,7 +181668,7 @@ whz rXK srX ugt -svP +lXC txh sAd ykV @@ -182684,7 +182686,7 @@ vNN whz whz whz -sqm +wtJ whz whz whz @@ -182951,7 +182953,7 @@ vNN mHl kSi cyX -yeR +rfs srC rZZ rNg @@ -184232,7 +184234,7 @@ xTG xTG xip obu -box +hqL vlE kSi kSi @@ -193727,7 +193729,7 @@ ptZ nSI axt eRb -tEd +lfe rMB gAQ eoX diff --git a/_maps/ouroboros.json b/_maps/ouroboros.json index 69c071ccb13d..68f4554cb407 100644 --- a/_maps/ouroboros.json +++ b/_maps/ouroboros.json @@ -3,6 +3,7 @@ "map_name": "Ouroboros", "map_path": "map_files/Ouroboros", "map_file": "Ouroboros.dmm", + "space_ruin_levels": 3, "shuttles": { "emergency": "emergency_nova", "ferry": "ferry_fancy", diff --git a/_maps/tramstation.json b/_maps/tramstation.json index 4968e18e41b6..8a9468229ea0 100644 --- a/_maps/tramstation.json +++ b/_maps/tramstation.json @@ -3,6 +3,7 @@ "map_name": "Tramstation", "map_path": "map_files/tramstation", "map_file": "tramstation.dmm", + "space_ruin_levels": 3, "shuttles": { "cargo": "cargo_box", "ferry": "ferry_fancy", diff --git a/code/__DEFINES/explosions.dm b/code/__DEFINES/explosions.dm index a1645b659d1c..79b9baff89c0 100644 --- a/code/__DEFINES/explosions.dm +++ b/code/__DEFINES/explosions.dm @@ -52,6 +52,7 @@ #define EXARG_KEY_SILENT STRINGIFY(silent) /// Whether or not the explosion should produce smoke if it is large enough to warrant it. #define EXARG_KEY_SMOKE STRINGIFY(smoke) +#define EXARG_KEY_AREA_LOCK STRINGIFY(area_lock) // Explodable component deletion values /// Makes the explodable component queue to reset its exploding status when it detonates. diff --git a/code/__DEFINES/jobs.dm b/code/__DEFINES/jobs.dm index 8ba1bd9d5788..88005dacbd4a 100644 --- a/code/__DEFINES/jobs.dm +++ b/code/__DEFINES/jobs.dm @@ -185,6 +185,9 @@ #define DEPARTMENT_BITFLAG_SPOOKTOBER (1<<10) #define DEPARTMENT_SPOOKTOBER "Spooktober" +#define DEPARTMENT_BITFLAG_CENTRAL_COMMAND (1<<11) +#define DEPARTMENT_CENTRAL_COMMAND "Central Command" + /* Job datum job_flags */ /// Whether the mob is announced on arrival. #define JOB_ANNOUNCE_ARRIVAL (1<<0) diff --git a/code/__DEFINES/materials.dm b/code/__DEFINES/materials.dm index 6ffcc733928a..100435408602 100644 --- a/code/__DEFINES/materials.dm +++ b/code/__DEFINES/materials.dm @@ -68,3 +68,15 @@ #define MATERIAL_SLOWDOWN_PLASTEEL (0.05) /// The slowdown value of one [SHEET_MATERIAL_AMOUNT] of alien alloy. #define MATERIAL_SLOWDOWN_ALIEN_ALLOY (0.1) + +// The number of ore vents that will spawn boulders with this material. +/// Is this material going to spawn often in ore vents? (80% of vents on lavaland) +#define MATERIAL_RARITY_COMMON 12 +/// Is this material going to spawn often in ore vents? (53% of vents on lavaland) +#define MATERIAL_RARITY_SEMIPRECIOUS 8 +/// Is this material going to spawn uncommonly in ore vents? (33% of vents on lavaland) +#define MATERIAL_RARITY_PRECIOUS 5 +/// Is this material going to spawn rarely in ore vents? (20% of vents on lavaland) +#define MATERIAL_RARITY_RARE 3 +/// Is this material only going to spawn once in ore vents? (6% of vents on lavaland) +#define MATERIAL_RARITY_UNDISCOVERED 1 diff --git a/code/__DEFINES/mining.dm b/code/__DEFINES/mining.dm new file mode 100644 index 000000000000..11d150a453db --- /dev/null +++ b/code/__DEFINES/mining.dm @@ -0,0 +1,49 @@ +// Defines related to the mining rework circa June 2023 +/// Durability of a large size boulder from a large size vent. +#define BOULDER_SIZE_LARGE 15 +/// Durability of a medium size boulder from a medium size vent. +#define BOULDER_SIZE_MEDIUM 10 +/// Durability of a small size boulder from a small size vent. +#define BOULDER_SIZE_SMALL 5 +/// How many boulders can a single ore vent have on it's tile before it stops producing more? +#define MAX_BOULDERS_PER_VENT 10 +/// Time multiplier +#define INATE_BOULDER_SPEED_MULTIPLIER 3 +// Vent type +/// Large vents, giving large boulders. +#define LARGE_VENT_TYPE "large" +/// Medium vents, giving medium boulders. +#define MEDIUM_VENT_TYPE "medium" +/// Small vents, giving small boulders. +#define SMALL_VENT_TYPE "small" + +/// Proximity to a vent that a wall ore needs to be for 5 ore to be mined. +#define VENT_PROX_VERY_HIGH 3 +/// Proximity to a vent that a wall ore needs to be for 4 ore to be mined. +#define VENT_PROX_HIGH 6 +/// Proximity to a vent that a wall ore needs to be for 3 ore to be mined. +#define VENT_PROX_MEDIUM 15 +/// Proximity to a vent that a wall ore needs to be for 2 ore to be mined. +#define VENT_PROX_LOW 32 +/// Proximity to a vent that a wall ore needs to be for 1 ore to be mined. +#define VENT_PROX_FAR 64 + +/// The chance of ore spawning in a wall that is VENT_PROX_VERY_HIGH tiles to a vent. +#define VENT_CHANCE_VERY_HIGH 75 +/// The chance of ore spawning in a wall that is VENT_PROX_HIGH tiles to a vent. +#define VENT_CHANCE_HIGH 18 +/// The chance of ore spawning in a wall that is VENT_PROX_MEDIUM tiles to a vent. +#define VENT_CHANCE_MEDIUM 9 +/// The chance of ore spawning in a wall that is VENT_PROX_LOW tiles to a vent. +#define VENT_CHANCE_LOW 5 +/// The chance of ore spawning in a wall that is VENT_PROX_FAR tiles to a vent. +#define VENT_CHANCE_FAR 1 + +/// The number of points a miner gets for discovering a vent, multiplied by BOULDER_SIZE when completing a wave defense minus the discovery bonus. +#define MINER_POINT_MULTIPLIER 100 +/// The multiplier that gets applied for automatically generated mining points. +#define MINING_POINT_MACHINE_MULTIPLIER 0.8 + +//String defines to use with CaveGenerator presets for what ore breakdown to use. +#define OREGEN_PRESET_LAVALAND "lavaland" +#define OREGEN_PRESET_TRIPLE_Z "triple_z" diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index e0947d2d420a..24e14b06fa7c 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -60,6 +60,7 @@ // Playtime tracking system, see jobs_exp.dm #define EXP_TYPE_LIVING "Living" #define EXP_TYPE_CREW "Crew" +#define EXP_TYPE_CENTRAL_COMMAND "Central Command" #define EXP_TYPE_COMMAND "Command" #define EXP_TYPE_ENGINEERING "Engineering" #define EXP_TYPE_MEDICAL "Medical" diff --git a/code/__DEFINES/screentips.dm b/code/__DEFINES/screentips.dm index 9d56e8cf36e5..f99443752a69 100644 --- a/code/__DEFINES/screentips.dm +++ b/code/__DEFINES/screentips.dm @@ -30,3 +30,5 @@ /// Screentips are only enabled when they have context #define SCREENTIP_PREFERENCE_CONTEXT_ONLY "Only with tips" + +#define SCREENTIP_CONTEXT_MISC "Misc" diff --git a/code/__DEFINES/skills.dm b/code/__DEFINES/skills.dm index 26e66eee1f54..722293b1a431 100644 --- a/code/__DEFINES/skills.dm +++ b/code/__DEFINES/skills.dm @@ -42,6 +42,9 @@ ///The multiplier of the extra experience given by the fishing minigame based on difficulty. At the default difficulty of 15, the bonus will be of 21%. #define FISHING_SKILL_DIFFIULTY_EXP_MULT 0.015 ///How much exp one would gain per spent playing the fishing minigame at minimum difficulty. -#define FISHING_SKILL_EXP_PER_SECOND (SKILL_EXP_LEGENDARY / (22 MINUTES)) +#define FISHING_SKILL_EXP_PER_SECOND (SKILL_EXP_LEGENDARY / (15 MINUTES * 0.1)) ///The maximum amount of experience one can get per fishing minigame. I appreciate the effort though. #define FISHING_SKILL_EXP_CAP_PER_GAME (SKILL_EXP_LEGENDARY / 5) + +///The base modifier a boulder's size grants to the mining skill. +#define MINING_SKILL_BOULDER_SIZE_XP 10 diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 9b75f5352410..6f5d4e3e78a3 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -169,7 +169,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// This carbon doesn't bleed #define TRAIT_NOBLOOD "noblood" /// This just means that the carbon will always have functional liverless metabolism -/* #define TRAIT_LIVERLESS_METABOLISM "liverless_metabolism" */ +#define TRAIT_LIVERLESS_METABOLISM "liverless_metabolism" /// This carbon can't be overdosed by chems /* #define TRAIT_OVERDOSEIMMUNE "overdose_immune" */ /// Humans with this trait cannot be turned into zombies @@ -1220,12 +1220,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Trait which means whatever has this is dancing by a dance machine /* #define TRAIT_DISCO_DANCER "disco_dancer" */ -/// Trait which allows mobs to instantly break down boulders. -/* #define TRAIT_INSTANTLY_PROCESSES_BOULDERS "instantly_processes_boulders" */ - -/// Trait applied to objects and mobs that can attack a boulder and break it down. (See /obj/item/boulder/manual_process()) -/* #define TRAIT_BOULDER_BREAKER "boulder_breaker" */ - /// Trait given to anything linked to, not necessarily allied to, the mansus /* #define TRAIT_MANSUS_TOUCHED "mansus_touched" */ @@ -1273,4 +1267,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai ///Trait which allows mobs to parry mining mob projectiles /* #define TRAIT_MINING_PARRYING "mining_parrying" */ +/// That which allows mobs to instantly break down boulders. +#define TRAIT_INSTANTLY_PROCESSES_BOULDERS "instantly_processes_boulders" + +/// Trait applied to objects and mobs that can attack a boulder and break it down. (See /obj/item/boulder/manual_process()) +#define TRAIT_BOULDER_BREAKER "boulder_breaker" + // END TRAIT DEFINES diff --git a/code/__DEFINES/traits/monkestation/sources.dm b/code/__DEFINES/traits/monkestation/sources.dm index b8f958ee987f..057086421db2 100644 --- a/code/__DEFINES/traits/monkestation/sources.dm +++ b/code/__DEFINES/traits/monkestation/sources.dm @@ -30,3 +30,5 @@ #define FEED_TRAIT "feed_trait" /// Source trait during a Frenzy #define FRENZY_TRAIT "frenzy_trait" +/// Source trait for slashers. +#define TRAIT_SLASHER "slasher_trait" diff --git a/code/__DEFINES/~monkestation/_patreon.dm b/code/__DEFINES/~monkestation/_patreon.dm index 3517dc8c4612..6e8bec50c4ae 100644 --- a/code/__DEFINES/~monkestation/_patreon.dm +++ b/code/__DEFINES/~monkestation/_patreon.dm @@ -6,6 +6,7 @@ #define TRAITOR_RANK "9641531" //muh defines #define NUKIE_RANK "10901851" #define OLD_NUKIE_RANK "9641543" +#define REALLY_ANOTHER_FUCKING_NUKIE_RANK "23202435" #define ACCESS_THANKS_RANK 1 #define ACCESS_ASSISTANT_RANK 2 diff --git a/code/__DEFINES/~monkestation/blueshift.dm b/code/__DEFINES/~monkestation/blueshift.dm index ae8559e4b71e..c327e4e56a0f 100644 --- a/code/__DEFINES/~monkestation/blueshift.dm +++ b/code/__DEFINES/~monkestation/blueshift.dm @@ -329,4 +329,4 @@ GLOBAL_LIST_INIT(antag_opt_in_colors, list( #define OPT_IN_DEFAULT_LEVEL OPT_IN_YES_KILL /// If the player has any non-ghost role antags enabled, they are forced to use a minimum of this. -#define OPT_IN_ANTAG_ENABLED_LEVEL OPT_IN_YES_TEMP +#define OPT_IN_ANTAG_ENABLED_LEVEL OPT_IN_YES_KILL diff --git a/code/__DEFINES/~monkestation/cargo.dm b/code/__DEFINES/~monkestation/cargo.dm new file mode 100644 index 000000000000..0747a6ea33e1 --- /dev/null +++ b/code/__DEFINES/~monkestation/cargo.dm @@ -0,0 +1 @@ +#define COMSIG_FILTER_CHECK "filter_check" diff --git a/code/__DEFINES/~monkestation/chewin.dm b/code/__DEFINES/~monkestation/chewin.dm new file mode 100644 index 000000000000..980bcb76b964 --- /dev/null +++ b/code/__DEFINES/~monkestation/chewin.dm @@ -0,0 +1,120 @@ + +#define sequential_id(key) GLOB.uniqueness_repository.Generate(/datum/uniqueness_generator/id_sequential, key) +#define random_id(key,min_id,max_id) GLOB.uniqueness_repository.Generate(/datum/uniqueness_generator/id_random, key, min_id, max_id) + +//#define CHEWIN_DEBUG 1 + +//Step classifications, for easy reference later. +//If something falls outside these classifications, why would it? +#define CHEWIN_START 1 //Default step to construct the list. +#define CHEWIN_ADD_ITEM 2 //Adding an item to a recipe (Ex- adding a slice of bread) +#define CHEWIN_ADD_REAGENT 3 //Adding a reagent to a recipe (Ex- Adding salt) +#define CHEWIN_USE_ITEM 4 //Using an item in a recipe (Ex- cutting bread with a knife) +#define CHEWIN_USE_TOOL 5 +#define CHEWIN_ADD_PRODUCE 6 //Adding Produce to a recipe +#define CHEWIN_USE_STOVE 7 //Using a stove in a recipe +#define CHEWIN_USE_GRILL 8 //Using a stove in a recipe +#define CHEWIN_USE_OVEN 9 //Using a stove in a recipe +#define CHEWIN_USE_FRYER 10 +#define CHEWIN_ADD_REAGENT_CHOICE 11 +#define CHEWIN_ADD_PRODUCE_CHOICE 12 +#define CHEWIN_USE_OTHER 13 //Custom Command flag, will take in argument lists. + +//Optional flags +#define CHEWIN_ADD_ITEM_OPTIONAL 200 +#define CHEWIN_ADD_REAGENT_OPTIONAL 300 +#define CHEWIN_USE_ITEM_OPTIONAL 400 +#define CHEWIN_USE_TOOL_OPTIONAL 500 +#define CHEWIN_ADD_PRODUCE_OPTIONAL 600 +#define CHEWIN_USE_STOVE_OPTIONAL 700 +#define CHEWIN_USE_GRILL_OPTIONAL 800 +#define CHEWIN_USE_OVEN_OPTIONAL 900 +#define CHEWIN_ADD_REAGENT_CHOICE_OPTIONAL 1000 +#define CHEWIN_ADD_PRODUCE_CHOICE_OPTIONAL 1100 +#define CHEWIN_OTHER_OPTIONAL 1200 + + +#define CHEWIN_BEGIN_EXCLUSIVE_OPTIONS 10000 //Beginning an exclusive option list +#define CHEWIN_END_EXCLUSIVE_OPTIONS 20000 //Ending an exclusive option list +#define CHEWIN_BEGIN_OPTION_CHAIN 30000 //Beginning an option chain +#define CHEWIN_END_OPTION_CHAIN 40000 //Ending an option chain + +//Recipe state flags +#define CHEWIN_IS_LAST_STEP 1 //If the step in the recipe is marked as the last step +#define CHEWIN_IS_OPTIONAL 2 //If the step in the recipe is marked as 'Optional' +#define CHEWIN_IS_OPTION_CHAIN 4 //If the step in the recipe is marked to be part of an option chain. +#define CHEWIN_IS_EXCLUSIVE 8 //If the step in the recipe is marked to exclude other options when followed. +#define CHEWIN_BASE_QUALITY_ENABLED 16 +#define CHEWIN_MAX_QUALITY_ENABLED 32 + +//Check item use flags +#define CHEWIN_NO_STEPS 1 //The used object has no valid recipe uses +#define CHEWIN_CHOICE_CANCEL 2 //The user opted to cancel when given a choice +#define CHEWIN_SUCCESS 3 //The user decided to use the item and the step was followed +#define CHEWIN_PARTIAL_SUCCESS 4 //The user decided to use the item but the qualifications for the step was not fulfilled +#define CHEWIN_COMPLETE 5 //The meal has been completed! +#define CHEWIN_LOCKOUT 6 //Someone tried starting the function while a prompt was running. Jerk. +#define CHEWIN_BURNT 7 //The meal was ruined by burning the food somehow. + +#define CHEWIN_CHECK_INVALID 0 +#define CHEWIN_CHECK_VALID 1 +#define CHEWIN_CHECK_FULL 2 //For reagents, nothing can be added to + +//Cooking container types +#define PLATE "plate" +#define CUTTING_BOARD "cutting board" +#define PAN "pan" +#define POT "pot" +#define BOWL "bowl" +#define DF_BASKET "deep fryer basket" +#define AF_BASKET "air fryer basket" +#define OVEN "oven" +#define GRILL "grill" + +//Stove temp settings. +#define J_LO "Low" +#define J_MED "Medium" +#define J_HI "High" + +//Just a catalog for the cooking catalog +#define CATALOG_COOKING "cooking" + +//Burn times for cooking things on a stove. +//Anything put on a stove for this long becomes a burned mess. +#define CHEWIN_BURN_TIME_LOW 15 MINUTES +#define CHEWIN_BURN_TIME_MEDIUM 10 MINUTES +#define CHEWIN_BURN_TIME_HIGH 5 MINUTES + +//Ignite times for reagents interacting with a stove. +//The stove will catch fire if left on too long with flammable reagents in any of its holders. +#define CHEWIN_IGNITE_TIME_LOW 1 HOUR +#define CHEWIN_IGNITE_TIME_MEDIUM 30 MINUTES +#define CHEWIN_IGNITE_TIME_HIGH 15 MINUTES + +//Determines how much quality is taken from a food each tick when a 'no recipe' response is made. +#define CHEWIN_BASE_QUAL_REDUCTION 5 + +//A dictionary of unique step ids that point to other step IDs that should be EXCLUDED if it is present in a recipe_pointer's list of possible steps. +GLOBAL_LIST_EMPTY(chewin_optional_step_exclusion_dictionary) + +//A dictionary of all recipes by the basic ingredient +//Format: {base_ingedient_type:{unique_id:recipe}} +GLOBAL_LIST_EMPTY(chewin_recipe_dictionary) + +//A dictionary of all recipes full_stop. Used later for assembling the HTML list. +//Format: {recipe_type:{unique_id:recipe}} +GLOBAL_LIST_EMPTY(chewin_recipe_list) + +//A dictionary of all steps held within all recipes +//Format: {unique_id:step} +GLOBAL_LIST_EMPTY(chewin_step_dictionary) + +//An organized heap of recipes by class and grouping. +//Format: {class_of_step:{step_group_identifier:{unique_id:step}}} +GLOBAL_LIST_EMPTY(chewin_step_dictionary_ordered) + +#define COMSIG_STOVE_PROCESS "comsig_stove_process" + +#define CAT_BULK "Bulk Recipes" +#define CAT_STOVETOP "Stovetop Recipes" +#define CAT_OVEN "Oven Recipes" diff --git a/code/__DEFINES/~monkestation/dcs/signals/signals_item.dm b/code/__DEFINES/~monkestation/dcs/signals/signals_item.dm index 0e6c854dca47..b913dd94bfe1 100644 --- a/code/__DEFINES/~monkestation/dcs/signals/signals_item.dm +++ b/code/__DEFINES/~monkestation/dcs/signals/signals_item.dm @@ -16,3 +16,5 @@ /// the comsig for clockwork items checking turf #define COMSIG_CHECK_TURF_CLOCKWORK "check_turf_clockwork" + +#define COMSIG_ITEM_DAMAGE_MULTIPLIER "damage_multi_item" diff --git a/code/__DEFINES/~monkestation/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/~monkestation/dcs/signals/signals_mob/signals_mob_main.dm index 780dcf78e57e..bfc0f361e4f4 100644 --- a/code/__DEFINES/~monkestation/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/~monkestation/dcs/signals/signals_mob/signals_mob_main.dm @@ -28,3 +28,8 @@ #define COMSIG_MOB_PICKED_UP "mob_picked_up" #define COMSIG_MOB_DROPPED "mob_dropped" + +#define COMSIG_DRANK_REAGENT "drank_reagent" + +#define COMSIG_LIVING_TRACKER_REMOVED "tracker_removed" +#define COMSIG_CLEAR_SEE "clear_see" diff --git a/code/__DEFINES/~monkestation/pain.dm b/code/__DEFINES/~monkestation/pain.dm new file mode 100644 index 000000000000..d28ed424b326 --- /dev/null +++ b/code/__DEFINES/~monkestation/pain.dm @@ -0,0 +1,51 @@ +/// If the mob enters shock, they will have +1 cure condition (helps cure it faster) +#define TRAIT_ABATES_SHOCK "shock_abated" +/// Pain effects, such as stuttering or feedback messages ("Everything hurts") are disabled. +#define TRAIT_NO_PAIN_EFFECTS "no_pain_effects" +/// Shock buildup does not increase, only decrease. No effect if already in shock (unlike abates_shock) +#define TRAIT_NO_SHOCK_BUILDUP "no_shock_buildup" +/// Don't get slowed down by aggro grabbing (or above) +#define TRAIT_NO_GRAB_SPEED_PENALTY "no_grab_speed_penalty" +/// Doesn't let a mob shift this atom around with move_pulled +#define TRAIT_NO_MOVE_PULL "no_move_pull" + +/// Sent when a carbon gains pain. (source = mob/living/carbon/human, obj/item/bodypart/affected_bodypart, amount, type) +#define COMSIG_CARBON_PAIN_GAINED "pain_gain" +/// Sent when a carbon loses pain. (source = mob/living/carbon/human, obj/item/bodypart/affected_bodypart, amount, type) +#define COMSIG_CARBON_PAIN_LOST "pain_loss" +/// Sent when a temperature pack runs out of juice. (source = obj/item/temperature_pack) +#define COMSIG_TEMPERATURE_PACK_EXPIRED "temp_pack_expired" + +/// Various lists of body zones affected by pain. +#define BODY_ZONES_ALL list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) +#define BODY_ZONES_MINUS_HEAD list(BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) +#define BODY_ZONES_LIMBS list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) +#define BODY_ZONES_MINUS_CHEST list(BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + +/// List of some emotes that convey pain. +#define PAIN_EMOTES list("wince", "gasp", "grimace", "shiver", "sway", "twitch_s", "whimper", "inhale_s", "exhale_s", "groan") + +/// Amount of pain gained (to chest) from dismembered limb +#define PAIN_LIMB_DISMEMBERED 90 +/// Amount of pain gained (to chest) from surgically removed limb +#define PAIN_LIMB_REMOVED 30 + +/// Soft max pains for bodyparts, adds up to 500 +#define PAIN_LIMB_MAX 70 +#define PAIN_CHEST_MAX 120 +#define PAIN_HEAD_MAX 100 + +// Keys for pain modifiers +#define PAIN_MOD_CHEMS "chems" +#define PAIN_MOD_LYING "lying" +#define PAIN_MOD_NEAR_DEATH "near-death" +#define PAIN_MOD_KOD "ko-d" +#define PAIN_MOD_RECENT_SHOCK "recently-shocked" +#define PAIN_MOD_QUIRK "quirk" +#define PAIN_MOD_SPECIES "species" +#define PAIN_MOD_OFF_STATION "off-station-pain-resistance" + +// ID for traits and modifiers gained by pain +#define PAIN_LIMB_PARALYSIS "pain_paralysis" +#define MOVESPEED_ID_PAIN "pain_movespeed" +#define ACTIONSPEED_ID_PAIN "pain_actionspeed" diff --git a/code/__DEFINES/~monkestation/virology.dm b/code/__DEFINES/~monkestation/virology.dm index 7b63db744b22..8b3008d78218 100644 --- a/code/__DEFINES/~monkestation/virology.dm +++ b/code/__DEFINES/~monkestation/virology.dm @@ -47,6 +47,7 @@ #define DISEASE_TRAUMA "trauma" #define DISEASE_DECLONING "decloning" #define DISEASE_ANXIETY "anxiety" +#define DISEASE_SHOCK "shock" #define DISEASE_DORMANT (1 << 3) #define DISEASE_COPYSTAGE (1<<4) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 0da14e44a19b..2b82cbc7383d 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -281,6 +281,7 @@ GLOBAL_LIST_INIT(round_end_images, world.file2list("data/image_urls.txt")) // MO //stop collecting feedback during grifftime SSblackbox.Seal() + save_datums() // we care about this for now // monkestation start: token backups, monkecoin rewards, challenges, and roundend webhook save_tokens() diff --git a/code/_globalvars/lists/ores_spawned.dm b/code/_globalvars/lists/ores_spawned.dm new file mode 100644 index 000000000000..227e06061ad7 --- /dev/null +++ b/code/_globalvars/lists/ores_spawned.dm @@ -0,0 +1,35 @@ +/** + * Sets of global lists breaking down the base spawning distributions for various maps and stations. + * + * Currently used for ore vents on roundstart when the map is generated. (See ore_vent.dm, seedRuins() and ore_generation.dm) + * Ore vent lists here are copied to ore_vent_minerals on ruin seeding, + * in order to dynamically adjust the spawn rates as materials are picked and set a global ore distribution from vents. + * + * By default vents pull 4 unique materials each, but this can vary with subtypes. + */ + +GLOBAL_LIST_INIT(ore_vent_minerals_lavaland, list( + /datum/material/iron = 13, + /datum/material/glass = 12, + /datum/material/plasma = 9, + /datum/material/titanium = 6, + /datum/material/silver = 5, + /datum/material/gold = 5, + /datum/material/diamond = 3, + /datum/material/uranium = 3, + /datum/material/bluespace = 3, + /datum/material/plastic = 1, + )) + +GLOBAL_LIST_INIT(ore_vent_minerals_triple_z, list( + /datum/material/iron = 24, + /datum/material/glass = 23, + /datum/material/plasma = 16, + /datum/material/titanium = 10, + /datum/material/silver = 8, + /datum/material/gold = 7, + /datum/material/diamond = 4, + /datum/material/uranium = 4, + /datum/material/bluespace = 3, + /datum/material/plastic = 1, + )) diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 91495683b763..334565ba7dad 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -295,6 +295,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_LIGHT_STEP" = TRAIT_LIGHT_STEP, "TRAIT_LIMBATTACHMENT" = TRAIT_LIMBATTACHMENT, "TRAIT_LITERATE" = TRAIT_LITERATE, + "TRAIT_LIVERLESS_METABOLISM" = TRAIT_LIVERLESS_METABOLISM, "TRAIT_LOUD_ASS" = TRAIT_LOUD_ASS, "TRAIT_MADNESS_IMMUNE" = TRAIT_MADNESS_IMMUNE, "TRAIT_MAGICALLY_GIFTED" = TRAIT_MAGICALLY_GIFTED, @@ -538,7 +539,6 @@ GLOBAL_LIST_INIT(traits_by_type, list( /* "TRAIT_INVISIMIN" = TRAIT_INVISIMIN, */ /* "TRAIT_IN_CALL" = TRAIT_IN_CALL, */ /* "TRAIT_IWASBATONED" = TRAIT_IWASBATONED, */ - /* "TRAIT_LIVERLESS_METABOLISM" = TRAIT_LIVERLESS_METABOLISM, */ /* "TRAIT_MAFIAINITIATE" = TRAIT_MAFIAINITIATE, */ /* "TRAIT_MANSUS_TOUCHED" = TRAIT_MANSUS_TOUCHED, */ /* "TRAIT_MEDIBOTCOMINGTHROUGH" = TRAIT_MEDIBOTCOMINGTHROUGH, */ @@ -632,7 +632,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( /* "TRAIT_BYPASS_RANGED_ARMOR" = TRAIT_BYPASS_RANGED_ARMOR, */ /* "TRAIT_CONTRABAND_BLOCKER" = TRAIT_CONTRABAND_BLOCKER, */ /* "TRAIT_GERM_SENSITIVE" = TRAIT_GERM_SENSITIVE, */ - /* "TRAIT_INSTANTLY_PROCESSES_BOULDERS" = TRAIT_INSTANTLY_PROCESSES_BOULDERS, */ + "TRAIT_INSTANTLY_PROCESSES_BOULDERS" = TRAIT_INSTANTLY_PROCESSES_BOULDERS, /* "TRAIT_ITEM_OBJECTIVE_BLOCKED" = TRAIT_ITEM_OBJECTIVE_BLOCKED, */ /* "TRAIT_NO_SIDE_KICK" = TRAIT_NO_SIDE_KICK, */ ), diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 3980bffac060..f5b2a314a961 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -185,7 +185,7 @@ else if(ismob(A)) changeNext_move(CLICK_CD_MELEE) - UnarmedAttack(A,1) + UnarmedAttack(A,1, modifiers) else if(W) if((istate & ISTATE_SECONDARY)) @@ -311,7 +311,7 @@ * used for figuring out different properties of the click, mostly right vs left and such. */ -/mob/proc/UnarmedAttack(atom/A, proximity_flag) +/mob/proc/UnarmedAttack(atom/A, proximity_flag, list/params) if(ismob(A)) changeNext_move(CLICK_CD_MELEE) return diff --git a/code/_onclick/hud/new_player.dm b/code/_onclick/hud/new_player.dm index 44a20e485c3e..a6e139dad084 100644 --- a/code/_onclick/hud/new_player.dm +++ b/code/_onclick/hud/new_player.dm @@ -190,6 +190,11 @@ to_chat(hud.mymob, span_boldwarning("The round is either not ready, or has already finished...")) return + if(hud.mymob.client?.check_overwatch()) + to_chat(hud.mymob, span_warning("Kindly wait until your connection has been authenticated before joining")) + message_admins("[hud.mymob.key] tried to use the Join button but failed the overwatch check.") + return + //Determines Relevent Population Cap var/relevant_cap var/hard_popcap = CONFIG_GET(number/hard_popcap) diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index 76e19620194b..7f0e772bede8 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -19,7 +19,7 @@ Otherwise pretty standard. */ -/mob/living/carbon/human/UnarmedAttack(atom/A, proximity_flag) +/mob/living/carbon/human/UnarmedAttack(atom/A, proximity_flag, list/params) if(HAS_TRAIT(src, TRAIT_HANDS_BLOCKED) && stat < SOFT_CRIT) if(src == A) check_self_for_injuries() @@ -40,7 +40,7 @@ if(!right_click_attack_chain(A) && !dna?.species?.spec_unarmedattack(src, A)) //Because species like monkeys dont use attack hand //monkestation edit - . = A.attack_hand(src) + . = A.attack_hand(src, params) if(.) animate_interact(A, INTERACT_GENERIC) //monkestation edit end @@ -49,7 +49,7 @@ return target.attack_hand_secondary(src, modifiers) /// Return TRUE to cancel other attack hand effects that respect it. Modifiers is the assoc list for click info such as if it was a right click. -/atom/proc/attack_hand(mob/user) +/atom/proc/attack_hand(mob/user, list/params) . = FALSE if(!(interaction_flags_atom & INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND)) add_fingerprint(user) diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 511f7b9d7450..5634f11b172c 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -234,6 +234,13 @@ GLOBAL_REAL(Master, /datum/controller/master) // Initialize subsystems. for (var/datum/controller/subsystem/subsystem in stage_sorted_subsystems[current_init_stage]) init_subsystem(subsystem) + if(world.system_type == MS_WINDOWS) + var/ss_name = "[subsystem.name]" + var/memory_summary = call_ext("memorystats", "get_memory_stats")() + var/file = file("data/mem_stat/[GLOB.round_id]-memstat.txt") + + var/string = "[ss_name] [memory_summary]" + WRITE_FILE(file, string) CHECK_TICK current_initializing_subsystem = null @@ -250,6 +257,9 @@ GLOBAL_REAL(Master, /datum/controller/master) var/msg = "Initializations complete within [time] second[time == 1 ? "" : "s"]!" + + initialize_cooking_recipes() + to_chat(world, span_boldannounce("[msg]")) log_world(msg) diff --git a/code/controllers/subsystem/explosions.dm b/code/controllers/subsystem/explosions.dm index ace4e3177f49..5d11d479dd26 100644 --- a/code/controllers/subsystem/explosions.dm +++ b/code/controllers/subsystem/explosions.dm @@ -224,7 +224,7 @@ SUBSYSTEM_DEF(explosions) * - smoke: Whether to generate a smoke cloud provided the explosion is powerful enough to warrant it. * - explosion_cause: [Optional] The atom that caused the explosion, when different to the origin. Used for logging. */ -/datum/controller/subsystem/explosions/proc/explode(atom/origin, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 0, flame_range = 0, flash_range = 0, adminlog = TRUE, ignorecap = FALSE, silent = FALSE, smoke = FALSE, atom/explosion_cause = null) +/datum/controller/subsystem/explosions/proc/explode(atom/origin, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 0, flame_range = 0, flash_range = 0, adminlog = TRUE, ignorecap = FALSE, silent = FALSE, smoke = FALSE, atom/explosion_cause = null, area/area_lock) var/list/arguments = list( EXARG_KEY_ORIGIN = origin, EXARG_KEY_DEV_RANGE = devastation_range, @@ -237,6 +237,7 @@ SUBSYSTEM_DEF(explosions) EXARG_KEY_SILENT = silent, EXARG_KEY_SMOKE = smoke, EXARG_KEY_EXPLOSION_CAUSE = explosion_cause ? explosion_cause : origin, + EXARG_KEY_AREA_LOCK = area_lock, ) var/atom/location = isturf(origin) ? origin : origin.loc if(SEND_SIGNAL(origin, COMSIG_ATOM_EXPLODE, arguments) & COMSIG_CANCEL_EXPLOSION) @@ -282,7 +283,7 @@ SUBSYSTEM_DEF(explosions) * - smoke: Whether to generate a smoke cloud provided the explosion is powerful enough to warrant it. * - explosion_cause: The atom that caused the explosion. Used for logging. */ -/datum/controller/subsystem/explosions/proc/propagate_blastwave(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flame_range, flash_range, adminlog, ignorecap, silent, smoke, atom/explosion_cause) +/datum/controller/subsystem/explosions/proc/propagate_blastwave(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flame_range, flash_range, adminlog, ignorecap, silent, smoke, atom/explosion_cause, area/area_lock) epicenter = get_turf(epicenter) var/area/checking = get_area(epicenter) @@ -400,6 +401,9 @@ SUBSYSTEM_DEF(explosions) //lists are guaranteed to contain at least 1 turf at this point //we presuppose that we'll be iterating away from the epicenter for(var/turf/explode as anything in affected_turfs) + if(area_lock && !(explode in area_lock)) + continue + var/our_x = explode.x var/our_y = explode.y var/dist = CHEAP_HYPOTENUSE(our_x, our_y, x0, y0) diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index be4a804b1ff8..6fa3c952c07a 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -260,16 +260,16 @@ SUBSYSTEM_DEF(mapping) var/list/ice_ruins = levels_by_trait(ZTRAIT_ICE_RUINS) if (ice_ruins.len) // needs to be whitelisted for underground too so place_below ruins work - seedRuins(ice_ruins, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/surface/outdoors/unexplored), themed_ruins[ZTRAIT_ICE_RUINS], clear_below = TRUE) + seedRuins(ice_ruins, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/surface/outdoors/unexplored), themed_ruins[ZTRAIT_ICE_RUINS], clear_below = TRUE, mineral_budget = 4) var/list/ice_ruins_underground = levels_by_trait(ZTRAIT_ICE_RUINS_UNDERGROUND) if (ice_ruins_underground.len) - seedRuins(ice_ruins_underground, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/underground/unexplored), themed_ruins[ZTRAIT_ICE_RUINS_UNDERGROUND], clear_below = TRUE) + seedRuins(ice_ruins_underground, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/underground/unexplored), themed_ruins[ZTRAIT_ICE_RUINS_UNDERGROUND], clear_below = TRUE, mineral_budget = 21) // Generate deep space ruins var/list/space_ruins = levels_by_trait(ZTRAIT_SPACE_RUINS) if (space_ruins.len) - seedRuins(space_ruins, CONFIG_GET(number/space_budget), list(/area/space), themed_ruins[ZTRAIT_SPACE_RUINS]) + seedRuins(space_ruins, CONFIG_GET(number/space_budget), list(/area/space), themed_ruins[ZTRAIT_SPACE_RUINS], mineral_budget = 0) /// Sets up rivers, and things that behave like rivers. So lava/plasma rivers, and chasms /// It is important that this happens AFTER generating mineral walls and such, since we rely on them for river logic diff --git a/code/datums/brain_damage/magic.dm b/code/datums/brain_damage/magic.dm index ac27ca655550..051ce4cbe588 100644 --- a/code/datums/brain_damage/magic.dm +++ b/code/datums/brain_damage/magic.dm @@ -124,3 +124,9 @@ desc = "It's coming closer..." image_icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' image_state = "curseblob" + var/datum/brain_trauma/magic/stalker_multiple/host + +/obj/effect/client_image_holder/stalker_phantom/Destroy(force) + . = ..() + host.stalkers -= src + host = null diff --git a/code/datums/components/fullauto.dm b/code/datums/components/fullauto.dm index 044619d594aa..e52ac35e186b 100644 --- a/code/datums/components/fullauto.dm +++ b/code/datums/components/fullauto.dm @@ -279,8 +279,9 @@ return FALSE var/obj/item/bodypart/other_hand = shooter.has_hand_for_held_index(shooter.get_inactive_hand_index()) if(weapon_weight == WEAPON_HEAVY && (shooter.get_inactive_held_item() || !other_hand)) - balloon_alert(shooter, "use both hands!") - return FALSE + if(!istype(shooter.get_inactive_held_item(), /obj/item/offhand)) + balloon_alert(shooter, "use both hands!") + return FALSE return TRUE diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index 5afc69b3dd78..603d966862d4 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -316,8 +316,10 @@ for(var/mob/living/rider in robot_parent.buckled_mobs) rider.setDir(dir) if(istype(robot_parent.model)) - rider.pixel_x = robot_parent.model.ride_offset_x[dir2text(dir)] - rider.pixel_y = robot_parent.model.ride_offset_y[dir2text(dir)] + if(dir2text(dir) in robot_parent.model.ride_offset_x) + rider.pixel_x = robot_parent.model.ride_offset_x[dir2text(dir)] + if(dir2text(dir) in robot_parent.model.ride_offset_y) + rider.pixel_y = robot_parent.model.ride_offset_y[dir2text(dir)] //now onto every other ridable mob// diff --git a/code/datums/components/twohanded.dm b/code/datums/components/twohanded.dm index 86b312610b95..4362835ad070 100644 --- a/code/datums/components/twohanded.dm +++ b/code/datums/components/twohanded.dm @@ -94,6 +94,7 @@ RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip)) RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_drop)) RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(on_attack_self)) + RegisterSignal(parent, COMSIG_CLICK_CTRL, PROC_REF(on_attack_self)) RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(on_attack)) RegisterSignal(parent, COMSIG_ATOM_UPDATE_ICON, PROC_REF(on_update_icon)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) diff --git a/code/datums/datum.dm b/code/datums/datum.dm index 5daabc063048..68b894b1e6a9 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -60,6 +60,7 @@ var/list/filter_data #ifdef REFERENCE_TRACKING + var/running_find_references /// When was this datum last touched by a reftracker? /// If this value doesn't match with the start of the search /// We know this datum has never been seen before, and we should check it diff --git a/code/datums/elements/deliver_first.dm b/code/datums/elements/deliver_first.dm index 7587c437b769..7e525e61849c 100644 --- a/code/datums/elements/deliver_first.dm +++ b/code/datums/elements/deliver_first.dm @@ -28,6 +28,7 @@ RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) RegisterSignal(target, COMSIG_ATOM_EMAG_ACT, PROC_REF(on_emag)) RegisterSignal(target, COMSIG_CLOSET_POST_OPEN, PROC_REF(on_post_open)) + RegisterSignal(target, COMSIG_FILTER_CHECK, PROC_REF(on_filter_check)) ADD_TRAIT(target, TRAIT_BANNED_FROM_CARGO_SHUTTLE, REF(src)) //registers pre_open when appropriate area_check(target) @@ -102,4 +103,9 @@ playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) target.RemoveElement(/datum/element/deliver_first, goal_area_type, payment) +/datum/element/deliver_first/proc/on_filter_check(obj/structure/closet/target, list/filter_locations) + var/name = departmental_destination_to_tag(goal_area_type) + if(name in filter_locations) + return TRUE + return FALSE #undef DENY_SOUND_COOLDOWN diff --git a/code/datums/greyscale/config_types/greyscale_configs.dm b/code/datums/greyscale/config_types/greyscale_configs.dm index 1d7e0be945c3..5feff2c8bd24 100644 --- a/code/datums/greyscale/config_types/greyscale_configs.dm +++ b/code/datums/greyscale/config_types/greyscale_configs.dm @@ -1289,3 +1289,13 @@ name = "Worn Playbunny Ears" icon_file = 'monkestation/icons/mob/clothing/head_32x48.dmi' json_config = 'code/datums/greyscale/json_configs/playbunny_ears_worn.json' + +/datum/greyscale_config/big_manipulator + name = "Big Manipulator" + icon_file = 'monkestation/code/modules/factory_type_beat/icons/big_manipulator_core.dmi' + json_config = 'code/datums/greyscale/json_configs/big_manipulator.json' + +/datum/greyscale_config/manipulator_hand + name = "Manipulator Hand" + icon_file = 'monkestation/code/modules/factory_type_beat/icons/big_manipulator_hand.dmi' + json_config = 'code/datums/greyscale/json_configs/manipulator_hand.json' diff --git a/code/datums/greyscale/json_configs/big_manipulator.json b/code/datums/greyscale/json_configs/big_manipulator.json new file mode 100644 index 000000000000..c7f96bac2aba --- /dev/null +++ b/code/datums/greyscale/json_configs/big_manipulator.json @@ -0,0 +1,15 @@ +{ + "core": [ + { + "type": "icon_state", + "icon_state": "core", + "blend_mode": "overlay" + }, + { + "type": "icon_state", + "icon_state": "core_colour", + "blend_mode": "overlay", + "color_ids": [ 1 ] + } + ] +} diff --git a/code/datums/greyscale/json_configs/manipulator_hand.json b/code/datums/greyscale/json_configs/manipulator_hand.json new file mode 100644 index 000000000000..be7c96df62b6 --- /dev/null +++ b/code/datums/greyscale/json_configs/manipulator_hand.json @@ -0,0 +1,15 @@ +{ + "hand": [ + { + "type": "icon_state", + "icon_state": "hand", + "blend_mode": "overlay" + }, + { + "type": "icon_state", + "icon_state": "hand_colour", + "blend_mode": "overlay", + "color_ids": [ 1 ] + } + ] +} diff --git a/code/datums/id_trim/jobs.dm b/code/datums/id_trim/jobs.dm index cb3be26cc835..358a0c5540e6 100644 --- a/code/datums/id_trim/jobs.dm +++ b/code/datums/id_trim/jobs.dm @@ -179,32 +179,6 @@ ) job = /datum/job/bitrunner -/datum/id_trim/job/blueshield - assignment = "Blueshield" - trim_state = "trim_blueshield" - department_color = COLOR_COMMAND_BLUE - subdepartment_color = COLOR_SECURITY_RED - sechud_icon_state = SECHUD_BLUESHIELD - minimal_access = list( - ACCESS_MEDICAL, - ACCESS_SCIENCE, - ACCESS_SERVICE, - ACCESS_CONSTRUCTION, - ACCESS_SECURITY, - ACCESS_BRIG_ENTRANCE, - ACCESS_COMMAND, - ACCESS_MAINT_TUNNELS, - ACCESS_MINERAL_STOREROOM, - ACCESS_WEAPONS, - ) - extra_access = list( - ) - template_access = list( - ACCESS_CAPTAIN, - ACCESS_CHANGE_IDS - ) - job = /datum/job/blueshield - /datum/id_trim/job/botanist assignment = "Botanist" trim_state = "trim_botanist" diff --git a/code/datums/mapgen/CaveGenerator.dm b/code/datums/mapgen/CaveGenerator.dm index ad27001ff7a9..4005427637ec 100644 --- a/code/datums/mapgen/CaveGenerator.dm +++ b/code/datums/mapgen/CaveGenerator.dm @@ -95,6 +95,7 @@ if(!weighted_feature_spawn_list) weighted_feature_spawn_list = list( /obj/structure/geyser/random = 1, + /obj/structure/ore_vent/random = 1, ) feature_spawn_list = expand_weights(weighted_feature_spawn_list) open_turf_types = expand_weights(weighted_open_turf_types) @@ -217,6 +218,7 @@ var/megas_allowed = (generate_in.area_flags & MEGAFAUNA_SPAWN_ALLOWED) && length(megafauna_spawn_list) var/start_time = REALTIMEOFDAY + SSore_generation.ore_vent_minerals = (SSore_generation.ore_vent_minerals_default).Copy() for(var/turf/target_turf as anything in turfs) if(!(target_turf.type in open_turf_types)) //only put stuff on open turfs we generated, so closed walls and rivers and stuff are skipped diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index ec6920edf310..df8369a707e1 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -8,6 +8,7 @@ allow_temp_override = FALSE help_verb = /mob/living/proc/sleeping_carp_help display_combos = TRUE + COOLDOWN_DECLARE(block_cooldown) var/list/scarp_traits = list(TRAIT_NOGUNS, TRAIT_HARDLY_WOUNDED, TRAIT_NODISMEMBER, TRAIT_HEAVY_SLEEPER) /datum/martial_art/the_sleeping_carp/teach(mob/living/target, make_temporary = FALSE) @@ -160,6 +161,9 @@ return ..() /datum/martial_art/the_sleeping_carp/proc/can_deflect(mob/living/carp_user) + if(!COOLDOWN_FINISHED(src, block_cooldown)) + if(prob(70)) + return FALSE if(!can_use(carp_user)) return FALSE if(!(carp_user.istate & ISTATE_HARM)) // monke edit: istates/intents @@ -185,7 +189,9 @@ span_danger("[carp_user] effortlessly swats [hitting_projectile] aside! [carp_user.p_They()] can block bullets with [carp_user.p_their()] bare hands!"), span_userdanger("You deflect [hitting_projectile]!"), ) + COOLDOWN_START(src, block_cooldown, 3 SECONDS) playsound(carp_user, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), vol = 75, vary = TRUE) + carp_user.stamina?.adjust(-50) hitting_projectile.firer = carp_user hitting_projectile.set_angle(rand(0, 360))//SHING return COMPONENT_BULLET_PIERCED diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index b062651b8936..aea7332fb184 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -29,6 +29,8 @@ Simple datum which is instanced once per type and is used for every object of sa var/list/categories = list() ///The type of sheet this material creates. This should be replaced as soon as possible by greyscale sheets var/sheet_type + /// What type of ore is this material associated with? Used for mining, and not every material has one. + var/obj/item/ore_type ///This is a modifier for force, and resembles the strength of the material var/strength_modifier = 1 ///This is a modifier for integrity, and resembles the strength of the material @@ -51,6 +53,10 @@ Simple datum which is instanced once per type and is used for every object of sa var/obj/item/shard_type ///What type of debris the tile will leave behind when shattered. var/obj/effect/decal/debris_type + /// How likely this mineral is to be found in a boulder during mining. + var/mineral_rarity = MATERIAL_RARITY_COMMON + /// How many points per units of ore does this grant? + var/points_per_unit = 1 / SHEET_MATERIAL_AMOUNT /** Handles initializing the material. * diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index 0760d493ed19..a0139337015a 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -7,6 +7,9 @@ categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/iron value_per_unit = 0.0025 + ore_type = /obj/item/stack/ore/iron + mineral_rarity = MATERIAL_RARITY_COMMON + points_per_unit = 1 / SHEET_MATERIAL_AMOUNT /datum/material/iron/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5) @@ -28,6 +31,9 @@ value_per_unit = 0.0025 beauty_modifier = 0.05 armor_modifiers = list(MELEE = 0.2, BULLET = 0.2, ENERGY = 1, BIO = 0.2, FIRE = 1, ACID = 0.2) + ore_type = /obj/item/stack/ore/glass + mineral_rarity = MATERIAL_RARITY_COMMON + points_per_unit = 1 / SHEET_MATERIAL_AMOUNT /datum/material/glass/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5, sharpness = TRUE) //cronch @@ -48,6 +54,9 @@ Unless you know what you're doing, only use the first three numbers. They're in sheet_type = /obj/item/stack/sheet/mineral/silver value_per_unit = 0.025 beauty_modifier = 0.075 + ore_type = /obj/item/stack/ore/silver + mineral_rarity = MATERIAL_RARITY_SEMIPRECIOUS + points_per_unit = 16 / SHEET_MATERIAL_AMOUNT /datum/material/silver/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5) @@ -65,6 +74,9 @@ Unless you know what you're doing, only use the first three numbers. They're in value_per_unit = 0.0625 beauty_modifier = 0.15 armor_modifiers = list(MELEE = 1.1, BULLET = 1.1, LASER = 1.15, ENERGY = 1.15, BOMB = 1, BIO = 1, FIRE = 0.7, ACID = 1.1) + ore_type = /obj/item/stack/ore/gold + mineral_rarity = MATERIAL_RARITY_PRECIOUS + points_per_unit = 18 / SHEET_MATERIAL_AMOUNT /datum/material/gold/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5) @@ -83,6 +95,9 @@ Unless you know what you're doing, only use the first three numbers. They're in value_per_unit = 0.25 beauty_modifier = 0.3 armor_modifiers = list(MELEE = 1.3, BULLET = 1.3, LASER = 0.6, ENERGY = 1, BOMB = 1.2, BIO = 1, FIRE = 1, ACID = 1) + ore_type = /obj/item/stack/ore/diamond + mineral_rarity = MATERIAL_RARITY_RARE + points_per_unit = 50 / SHEET_MATERIAL_AMOUNT /datum/material/diamond/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(15, BRUTE, BODY_ZONE_HEAD, wound_bonus = 7) @@ -99,6 +114,9 @@ Unless you know what you're doing, only use the first three numbers. They're in value_per_unit = 0.05 beauty_modifier = 0.3 //It shines so beautiful armor_modifiers = list(MELEE = 1.5, BULLET = 1.4, LASER = 0.5, ENERGY = 0.5, FIRE = 1, ACID = 1) + ore_type = /obj/item/stack/ore/uranium + mineral_rarity = MATERIAL_RARITY_SEMIPRECIOUS + points_per_unit = 30 / SHEET_MATERIAL_AMOUNT /datum/material/uranium/on_applied(atom/source, amount, material_flags) . = ..() @@ -134,6 +152,9 @@ Unless you know what you're doing, only use the first three numbers. They're in value_per_unit = 0.1 beauty_modifier = 0.15 armor_modifiers = list(MELEE = 1.4, BULLET = 0.7, ENERGY = 1.2, BIO = 1.2, ACID = 0.5) + ore_type = /obj/item/stack/ore/plasma + mineral_rarity = MATERIAL_RARITY_PRECIOUS + points_per_unit = 15 / SHEET_MATERIAL_AMOUNT /datum/material/plasma/on_applied(atom/source, amount, material_flags) . = ..() @@ -166,6 +187,9 @@ Unless you know what you're doing, only use the first three numbers. They're in beauty_modifier = 0.5 sheet_type = /obj/item/stack/sheet/bluespace_crystal value_per_unit = 0.15 + ore_type = /obj/item/stack/ore/bluespace_crystal + mineral_rarity = MATERIAL_RARITY_RARE + points_per_unit = 50 / SHEET_MATERIAL_AMOUNT /datum/material/bluespace/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.reagents.add_reagent(/datum/reagent/bluespace, rand(5, 8)) @@ -183,6 +207,9 @@ Unless you know what you're doing, only use the first three numbers. They're in value_per_unit = 0.5 beauty_modifier = 0.5 armor_modifiers = list(BOMB = 100, FIRE = 10) //Clowns cant be blown away. + ore_type = /obj/item/stack/ore/bananium + mineral_rarity = MATERIAL_RARITY_UNDISCOVERED + points_per_unit = 60 / SHEET_MATERIAL_AMOUNT /datum/material/bananium/on_applied(atom/source, amount, material_flags) . = ..() @@ -211,6 +238,8 @@ Unless you know what you're doing, only use the first three numbers. They're in value_per_unit = 0.0625 beauty_modifier = 0.05 armor_modifiers = list(MELEE = 1.35, BULLET = 1.3, LASER = 1.3, ENERGY = 1.25, BOMB = 1.25, BIO = 1, FIRE = 0.7, ACID = 1) + ore_type = /obj/item/stack/ore/titanium + mineral_rarity = MATERIAL_RARITY_SEMIPRECIOUS /datum/material/titanium/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(15, BRUTE, BODY_ZONE_HEAD, wound_bonus = 7) @@ -227,6 +256,8 @@ Unless you know what you're doing, only use the first three numbers. They're in value_per_unit = 0.3 beauty_modifier = 0.5 armor_modifiers = list(MELEE = 1.35, BULLET = 2, LASER = 0.5, ENERGY = 1.25, BOMB = 1.25, BIO = 1, FIRE = 1.4, ACID = 1) //rune is weak against magic lasers but strong against bullets. This is the combat triangle. + mineral_rarity = MATERIAL_RARITY_UNDISCOVERED + points_per_unit = 100 / SHEET_MATERIAL_AMOUNT /datum/material/runite/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(20, BRUTE, BODY_ZONE_HEAD, wound_bonus = 10) @@ -244,6 +275,9 @@ Unless you know what you're doing, only use the first three numbers. They're in value_per_unit = 0.0125 beauty_modifier = -0.01 armor_modifiers = list(MELEE = 1.5, BULLET = 1.1, LASER = 0.3, ENERGY = 0.5, BOMB = 1, BIO = 1, FIRE = 1.1, ACID = 1) + ore_type = /obj/item/stack/ore/slag + mineral_rarity = MATERIAL_RARITY_UNDISCOVERED //Nobody's found oil on lavaland yet. + points_per_unit = 4 / SHEET_MATERIAL_AMOUNT /datum/material/plastic/on_accidental_mat_consumption(mob/living/carbon/eater, obj/item/food) eater.reagents.add_reagent(/datum/reagent/plastic_polymers, rand(6, 8)) @@ -303,6 +337,8 @@ Unless you know what you're doing, only use the first three numbers. They're in value_per_unit = 0.25 beauty_modifier = 0.4 armor_modifiers = list(MELEE = 1.5, BULLET = 1.5, LASER = 1.3, ENERGY = 1.3, BOMB = 1, BIO = 1, FIRE = 2.5, ACID = 1) + mineral_rarity = MATERIAL_RARITY_UNDISCOVERED //Doesn't naturally spawn on lavaland. + points_per_unit = 100 / SHEET_MATERIAL_AMOUNT /datum/material/adamantine/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(20, BRUTE, BODY_ZONE_HEAD, wound_bonus = 10) @@ -320,6 +356,8 @@ Unless you know what you're doing, only use the first three numbers. They're in strength_modifier = 1.2 armor_modifiers = list(MELEE = 1.5, BULLET = 1.5, LASER = 1.5, ENERGY = 1.5, BOMB = 1.5, BIO = 1.5, FIRE = 1.5, ACID = 1.5) beauty_modifier = 0.5 + mineral_rarity = MATERIAL_RARITY_UNDISCOVERED //Doesn't naturally spawn on lavaland. + points_per_unit = 100 / SHEET_MATERIAL_AMOUNT /* monkestation edit: this is given anyways by [/datum/material_trait/magical] /datum/material/mythril/on_applied_obj(atom/source, amount, material_flags) diff --git a/code/datums/quirks/negative_quirks.dm b/code/datums/quirks/negative_quirks.dm index 08393519a5dc..a2528c8c9d92 100644 --- a/code/datums/quirks/negative_quirks.dm +++ b/code/datums/quirks/negative_quirks.dm @@ -592,7 +592,7 @@ if(BODY_ZONE_R_LEG) prosthetic = new /obj/item/bodypart/leg/right/robot/surplus slot_string = "right leg" - human_holder.del_and_replace_bodypart(prosthetic) + human_holder.del_and_replace_bodypart(prosthetic, TRUE) /datum/quirk/prosthetic_limb/post_add() to_chat(quirk_holder, span_boldannounce("Your [slot_string] has been replaced with a surplus prosthetic. It is fragile and will easily come apart under duress. Additionally, \ @@ -609,10 +609,10 @@ /datum/quirk/quadruple_amputee/add_unique(client/client_source) var/mob/living/carbon/human/human_holder = quirk_holder - human_holder.del_and_replace_bodypart(new /obj/item/bodypart/arm/left/robot/surplus) - human_holder.del_and_replace_bodypart(new /obj/item/bodypart/arm/right/robot/surplus) - human_holder.del_and_replace_bodypart(new /obj/item/bodypart/leg/left/robot/surplus) - human_holder.del_and_replace_bodypart(new /obj/item/bodypart/leg/right/robot/surplus) + human_holder.del_and_replace_bodypart(new /obj/item/bodypart/arm/left/robot/surplus, TRUE) + human_holder.del_and_replace_bodypart(new /obj/item/bodypart/arm/right/robot/surplus, TRUE) + human_holder.del_and_replace_bodypart(new /obj/item/bodypart/leg/left/robot/surplus, TRUE) + human_holder.del_and_replace_bodypart(new /obj/item/bodypart/leg/right/robot/surplus, TRUE) /datum/quirk/quadruple_amputee/post_add() to_chat(quirk_holder, span_boldannounce("All your limbs have been replaced with surplus prosthetics. They are fragile and will easily come apart under duress. Additionally, \ @@ -799,7 +799,7 @@ hardcore_value = 4 quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_PROCESSES mail_goodies = list(/obj/effect/spawner/random/contraband/narcotics) - var/drug_list = list(/datum/reagent/drug/blastoff, /datum/reagent/drug/krokodil, /datum/reagent/medicine/morphine, /datum/reagent/drug/happiness, /datum/reagent/drug/methamphetamine) //List of possible IDs + var/drug_list = list(/datum/reagent/drug/blastoff, /datum/reagent/drug/krokodil, /datum/reagent/medicine/painkiller/morphine, /datum/reagent/drug/happiness, /datum/reagent/drug/methamphetamine) //List of possible IDs var/datum/reagent/reagent_type //!If this is defined, reagent_id will be unused and the defined reagent type will be instead. var/datum/reagent/reagent_instance //! actual instanced version of the reagent var/where_drug //! Where the drug spawned diff --git a/code/datums/ruins.dm b/code/datums/ruins.dm index 2a7b73d1f7e8..703991f596e9 100644 --- a/code/datums/ruins.dm +++ b/code/datums/ruins.dm @@ -6,17 +6,27 @@ How is there a wooden container filled with 18th century coinage in the middle of a lavawracked hellscape? \ It is clearly a mystery." - var/unpickable = FALSE //If TRUE these won't be placed automatically (can still be forced or loaded with another ruin) - var/always_place = FALSE //Will skip the whole weighting process and just plop this down, ideally you want the ruins of this kind to have no cost. - var/placement_weight = 1 //How often should this ruin appear - var/cost = 0 //Cost in ruin budget placement system + ///If TRUE these won't be placed automatically (can still be forced or loaded with another ruin) + var/unpickable = FALSE + ///Will skip the whole weighting process and just plop this down, ideally you want the ruins of this kind to have no cost. + var/always_place = FALSE + ///How often should this ruin appear + var/placement_weight = 1 + ///Cost in ruin budget placement system + var/cost = 0 + /// Cost in the ruin budget placement system associated with mineral spawning. We use a different budget for mineral sources like ore vents. For practical use see seedRuins + var/mineral_cost = 0 + /// If TRUE, this ruin can be placed multiple times in the same map var/allow_duplicates = TRUE - var/list/always_spawn_with = null //These ruin types will be spawned along with it (where dependent on the flag) eg list(/datum/map_template/ruin/space/teleporter_space = SPACERUIN_Z) - var/list/never_spawn_with = null //If this ruin is spawned these will not eg list(/datum/map_template/ruin/base_alternate) - + ///These ruin types will be spawned along with it (where dependent on the flag) eg list(/datum/map_template/ruin/space/teleporter_space = SPACERUIN_Z) + var/list/always_spawn_with = null + ///If this ruin is spawned these will not eg list(/datum/map_template/ruin/base_alternate) + var/list/never_spawn_with = null + ///Static part of the ruin path eg "_maps\RandomRuins\LavaRuins\" var/prefix = null + ///The dynamic part of the ruin path eg "lavaland_surface_ruinfile.dmm" var/suffix = null - + ///What flavor or ruin is this? eg ZTRAIT_SPACE_RUINS var/ruin_type = null /datum/map_template/ruin/New() diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index fade934c438c..1b63e5a4a2a4 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -152,11 +152,13 @@ victim.visible_message("Blood spews out of [victim]'s mouth from the blow to [victim.p_their()] chest!", span_danger("You spit out a string of blood from the blow to your chest!"), vision_distance=COMBAT_MESSAGE_RANGE) new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir, COLOR_DARK_RED) victim.bleed(blood_bled) + victim.blood_particles(amount = 1) if(20 to INFINITY) victim.visible_message(span_danger("Blood spurts out of [victim]'s mouth from the blow to [victim.p_their()] chest!"), span_danger("You choke up on a spray of blood from the blow to your chest!"), vision_distance=COMBAT_MESSAGE_RANGE) victim.bleed(blood_bled) new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir, COLOR_DARK_RED) victim.add_splatter_floor(get_step(victim.loc, victim.dir)) + victim.blood_particles(amount = 3) /datum/wound/blunt/bone/modify_desc_before_span(desc) . = ..() diff --git a/code/datums/wounds/loss.dm b/code/datums/wounds/loss.dm index 479656a8a429..bcad804eba68 100644 --- a/code/datums/wounds/loss.dm +++ b/code/datums/wounds/loss.dm @@ -50,6 +50,7 @@ log_wound(victim, src) if(dismembered_part.can_bleed() && wounding_type != WOUND_BURN && victim.blood_volume) victim.spray_blood(attack_direction, severity) + victim.blood_particles(amount = rand(3, 6), angle = 0, min_deviation = 0, max_deviation = 360) dismembered_part.dismember(wounding_type == WOUND_BURN ? BURN : BRUTE, wounding_type = wounding_type) qdel(src) return TRUE diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index 238e28001738..4deb88361768 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -30,6 +30,7 @@ set_blood_flow(initial_flow) if(limb.can_bleed() && attack_direction && victim.blood_volume > BLOOD_VOLUME_OKAY) victim.spray_blood(attack_direction, severity) + victim.blood_particles(amount = rand(3, 6), angle = 0, min_deviation = 0, max_deviation = 360) return ..() diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm index e297849e61a3..b0edc7f25074 100644 --- a/code/datums/wounds/slash.dm +++ b/code/datums/wounds/slash.dm @@ -57,6 +57,7 @@ set_blood_flow(initial_flow) if(limb.can_bleed() && attack_direction && victim.blood_volume > BLOOD_VOLUME_OKAY) victim.spray_blood(attack_direction, severity) + victim.blood_particles(amount = rand(3, 6), angle = 0, min_deviation = 0, max_deviation = 360) if(!highest_scar) var/datum/scar/new_scar = new diff --git a/code/game/atoms.dm b/code/game/atoms.dm index cc8b96345131..95ba030e198a 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -2115,6 +2115,7 @@ var/shift_lmb_ctrl_shift_lmb_line = "" var/extra_lines = 0 var/extra_context = "" + var/misc_context = "" if(isliving(user) || isovermind(user) || isaicamera(user) || (ghost_screentips && isobserver(user))) var/obj/item/held_item = user.get_active_held_item() @@ -2176,8 +2177,17 @@ if (shift_lmb_ctrl_shift_lmb_line != "") extra_lines++ + if(SCREENTIP_CONTEXT_MISC in context) + misc_context += context[SCREENTIP_CONTEXT_MISC] + + if (misc_context != "") + 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]" + if(misc_context != "") + extra_context = "
[misc_context]\n[lmb_rmb_line][ctrl_lmb_ctrl_rmb_line][alt_lmb_alt_rmb_line][shift_lmb_ctrl_shift_lmb_line]" + else + 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 diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 1b41d2f33170..453e9fe19940 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -372,7 +372,7 @@ ) required_enemies = list(3,3,3,3,3,2,1,1,0,0) required_candidates = 5 - weight = 5 + weight = 0 cost = 7 minimum_round_time = 70 MINUTES requirements = REQUIREMENTS_VERY_HIGH_THREAT_NEEDED diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index a8f502efe013..728df8ba25cc 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -821,12 +821,23 @@ spawn_frame(disassembled) for(var/part in component_parts) + var/area/shipbreak/A = get_area(src) if(istype(part, /datum/stock_part)) var/datum/stock_part/datum_part = part - new datum_part.physical_object_type(loc) + var/obj/item/item = new datum_part.physical_object_type(loc) + if(istype(A) && item.get_shipbreaking_reward()) //shipbreaking + var/obj/item/reward = item.get_shipbreaking_reward() + if(reward) + new reward(loc) + qdel(item) else var/obj/item/obj_part = part obj_part.forceMove(loc) + if(istype(A) && obj_part.get_shipbreaking_reward()) //shipbreaking + var/obj/item/reward = obj_part.get_shipbreaking_reward() + if(reward) + new reward(loc) + qdel(obj_part) if(istype(obj_part, /obj/item/circuitboard/machine)) var/obj/item/circuitboard/machine/board = obj_part for(var/component in board.req_components) //loop through all stack components and spawn them diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index e151967a1c7f..11aab499f5cc 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -155,6 +155,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) JOB_ERT_CHAPLAIN = 225, JOB_ERT_JANITOR = 226, JOB_ERT_DEATHSQUAD = 227, + JOB_BLUESHIELD = 231, // ANYTHING ELSE = UNKNOWN_JOB_ID, Unknowns/custom jobs will appear after civilians, and before assistants JOB_ASSISTANT = 999, diff --git a/code/game/machinery/prisongate.dm b/code/game/machinery/prisongate.dm index 0b7529cbb79e..4a932b2258c5 100644 --- a/code/game/machinery/prisongate.dm +++ b/code/game/machinery/prisongate.dm @@ -45,6 +45,14 @@ /obj/machinery/prisongate/CanAllowThrough(atom/movable/gate_toucher, border_dir) . = ..() if(!iscarbon(gate_toucher)) + if(isvehicle(gate_toucher)) + var/obj/vehicle/toucher = gate_toucher + for(var/mob/living/carbon/human in toucher.occupants) + if(COOLDOWN_FINISHED(src, spam_cooldown_time)) + say("Please dismount your vehicles before trying to enter.") + playsound(src, 'sound/machines/buzz-two.ogg', 50, FALSE) + COOLDOWN_START(src, spam_cooldown_time, SPAM_CD) + return FALSE if(!isstructure(gate_toucher)) return TRUE var/obj/structure/cargobay = gate_toucher diff --git a/code/game/machinery/sleepers.dm b/code/game/machinery/sleepers.dm index b6d2e886b1cb..42c13632d1da 100644 --- a/code/game/machinery/sleepers.dm +++ b/code/game/machinery/sleepers.dm @@ -29,7 +29,7 @@ var/list/possible_chems = list( list( /datum/reagent/medicine/epinephrine, - /datum/reagent/medicine/morphine, + /datum/reagent/medicine/painkiller/morphine, /datum/reagent/medicine/c2/convermol, /datum/reagent/medicine/c2/libital, /datum/reagent/medicine/c2/aiuri, diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 83d905882447..08715536511e 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -365,6 +365,8 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) var/splatter_strength = 3 /// Insurance so that we don't keep moving once we hit a stoppoint var/hit_endpoint = FALSE + /// Type of squirt decals we should try to create when moving + var/line_type = /obj/effect/decal/cleanable/blood/line /obj/effect/decal/cleanable/blood/hitsplatter/Initialize(mapload, splatter_strength) . = ..() @@ -413,6 +415,17 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) splatter_strength-- if(splatter_strength <= 0) // we used all the puff so we delete it. qdel(src) + return + if(line_type && isturf(loc)) + var/obj/effect/decal/cleanable/line = locate(line_type) in loc + if(line) + line.add_blood_DNA(blood_dna_info) + else + line = new line_type(loc, get_dir(prev_loc, loc)) + line.add_blood_DNA(blood_dna_info) + line.alpha = 0 + animate(line, alpha = initial(line.alpha), time = 2) + /obj/effect/decal/cleanable/blood/hitsplatter/proc/loop_done(datum/source) SIGNAL_HANDLER @@ -454,3 +467,4 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) the_window.vis_contents += final_splatter the_window.bloodied = TRUE qdel(src) + diff --git a/code/game/objects/items/food/meatslab.dm b/code/game/objects/items/food/meatslab.dm index 1392be355916..4d4cf0bbac0b 100644 --- a/code/game/objects/items/food/meatslab.dm +++ b/code/game/objects/items/food/meatslab.dm @@ -227,7 +227,7 @@ icon_state = "bearmeat" food_reagents = list( /datum/reagent/consumable/nutriment/protein = 16, - /datum/reagent/medicine/morphine = 5, + /datum/reagent/medicine/painkiller/morphine = 5, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/cooking_oil = 6, ) diff --git a/code/game/objects/items/food/spaghetti.dm b/code/game/objects/items/food/spaghetti.dm index 6cf2bbc81d1d..893fa08d7d0f 100644 --- a/code/game/objects/items/food/spaghetti.dm +++ b/code/game/objects/items/food/spaghetti.dm @@ -60,7 +60,7 @@ // where the soul comes from /datum/reagent/pax = 5, /datum/reagent/medicine/psicodine = 10, - /datum/reagent/medicine/morphine = 5, + /datum/reagent/medicine/painkiller/morphine = 5, ) tastes = list("nostalgia" = 1, "happiness" = 1) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index ae9a980d989b..3df9763ddde7 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -20,7 +20,8 @@ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' flags_1 = CONDUCT_1 slot_flags = ITEM_SLOT_BELT - force = 10 + force = 1 + pain_damage = 12 throwforce = 7 demolition_mod = 0.25 wound_bonus = 15 diff --git a/code/game/objects/items/robot/items/hypo.dm b/code/game/objects/items/robot/items/hypo.dm index 389d10175196..d02f110fae79 100644 --- a/code/game/objects/items/robot/items/hypo.dm +++ b/code/game/objects/items/robot/items/hypo.dm @@ -47,7 +47,7 @@ ) #define BASE_SYNDICATE_REAGENTS list(\ /datum/reagent/medicine/inacusiate,\ - /datum/reagent/medicine/morphine,\ + /datum/reagent/medicine/painkiller/morphine,\ /datum/reagent/medicine/potass_iodide,\ /datum/reagent/medicine/syndicate_nanites\ ) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index cf1d76bab1f0..517a05a58ee7 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -321,6 +321,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ 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), \ new/datum/stack_recipe("wooden barrel", /obj/structure/fermenting_barrel, 8, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_CONTAINERS), \ + new/datum/stack_recipe("fermenting keg", /obj/structure/fermentation_keg, 8, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_CONTAINERS), \ new/datum/stack_recipe("dog bed", /obj/structure/bed/dogbed, 10, time = 1 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ new/datum/stack_recipe("dresser", /obj/structure/dresser, 10, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ new/datum/stack_recipe("picture frame", /obj/item/wallframe/picture, 1, time = 1 SECONDS, check_density = FALSE, category = CAT_ENTERTAINMENT),\ diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index f299eea303dc..0b2abb6bd53d 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -206,35 +206,33 @@ . = (amount) /** - * Builds all recipes in a given recipe list and returns an association list containing them - * - * Arguments: - * * recipe_to_iterate - The list of recipes we are using to build recipes + * Recursively builds the recipes data for the given list of recipes, iterating through each recipe. + * If recipe is of type /datum/stack_recipe, it adds the recipe data to the recipes_data list with the title as the key. + * If recipe is of type /datum/stack_recipe_list, it recursively calls itself, scanning the entire list and adding each recipe to its category. */ -/obj/item/stack/proc/recursively_build_recipes(list/recipe_to_iterate) - var/list/L = list() - for(var/recipe in recipe_to_iterate) - if(istype(recipe, /datum/stack_recipe_list)) - var/datum/stack_recipe_list/R = recipe - L["[R.title]"] = recursively_build_recipes(R.recipes) +/obj/item/stack/proc/recursively_build_recipes(list/recipes_to_iterate) + var/list/recipes_data = list() + for(var/recipe in recipes_to_iterate) if(istype(recipe, /datum/stack_recipe)) - var/datum/stack_recipe/R = recipe - L["[R.title]"] = build_recipe(R) - return L + var/datum/stack_recipe/single_recipe = recipe + recipes_data["[single_recipe.title]"] = build_recipe_data(single_recipe) -/** - * Returns a list of properties of a given recipe - * - * Arguments: - * * R - The stack recipe we are using to get a list of properties - */ -/obj/item/stack/proc/build_recipe(datum/stack_recipe/R) - return list( - "res_amount" = R.res_amount, - "max_res_amount" = R.max_res_amount, - "req_amount" = R.req_amount, - "ref" = text_ref(R), - ) + else if(istype(recipe, /datum/stack_recipe_list)) + var/datum/stack_recipe_list/recipe_list = recipe + recipes_data["[recipe_list.title]"] = recursively_build_recipes(recipe_list.recipes) + + return recipes_data + +/obj/item/stack/proc/build_recipe_data(datum/stack_recipe/recipe) + var/list/data = list() + + data["ref"] = text_ref(recipe) + data["required_amount"] = recipe.req_amount + data["result_amount"] = recipe.res_amount + data["max_result_amount"] = recipe.max_res_amount + data["image"] = recipe.image + + return data /** * Checks if the recipe is valid to be used @@ -265,7 +263,8 @@ /obj/item/stack/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, "StackCrafting", name) + ui = new(user, src, "StackCraft", name) + ui.set_autoupdate(FALSE) ui.open() /obj/item/stack/ui_data(mob/user) @@ -278,16 +277,14 @@ data["recipes"] = recursively_build_recipes(recipes) return data -/obj/item/stack/ui_act(action, params) - . = ..() - if(.) - return +/obj/item/stack/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + if(..()) + return FALSE switch(action) if("make") var/datum/stack_recipe/recipe = locate(params["ref"]) var/multiplier = text2num(params["multiplier"]) - return make_item(usr, recipe, multiplier) /// The key / title for a radial option that shows the entire list of buildables (uses the old menu) diff --git a/code/game/objects/items/stacks/stack_recipe.dm b/code/game/objects/items/stacks/stack_recipe.dm index a065a4916b39..a6e5cdf395f5 100644 --- a/code/game/objects/items/stacks/stack_recipe.dm +++ b/code/game/objects/items/stacks/stack_recipe.dm @@ -38,6 +38,8 @@ var/trait_modifier = 1 /// Category for general crafting menu var/category + /// Cached recipe result base64 image + var/image /datum/stack_recipe/New( title, @@ -77,6 +79,16 @@ src.trait_modifier = trait_modifier src.category = src.category || category || CAT_MISC + var/obj/item/result = result_type + var/icon/result_icon = icon(result::icon, result::icon_state, SOUTH, 1) + var/paint = result::color + + result_icon.Scale(32, 32) + if(!isnull(paint) && paint != COLOR_WHITE) + result_icon.Blend(paint, ICON_MULTIPLY) + + src.image = "[icon2base64(result_icon)]" + /datum/stack_recipe/radial /// Optional info to be shown on the radial option for this item var/desc diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 76f728432d44..47582a860ad3 100755 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -328,7 +328,7 @@ /obj/structure/closet/secure_closet/tac name = "armory tac locker" - req_access = list(ACCESS_ARMORY) + req_access = list(ACCESS_CENT_GENERAL) icon_state = "tac" /obj/structure/closet/secure_closet/tac/PopulateContents() diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 99317dd61aed..da3c3635ed97 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -371,6 +371,9 @@ /obj/structure/girder/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) var/remains = pick(/obj/item/stack/rods, /obj/item/stack/sheet/iron) + var/area/shipbreak/A = get_area(src) + if(istype(A)) //shipbreaking + remains = /obj/item/stack/scrap/framing new remains(loc) qdel(src) diff --git a/code/game/sound.dm b/code/game/sound.dm index 856c49c975c5..52281543f36f 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -263,15 +263,14 @@ GLOBAL_LIST_EMPTY(cached_mixer_channels) S.status = SOUND_UPDATE SEND_SOUND(src, S) -/client/proc/playtitlemusic(vol = 0.85) +/client/proc/playtitlemusic(vol = 85) set waitfor = FALSE UNTIL(SSticker.login_music_done) //wait for SSticker init to set the login music // monkestation edit: fix-lobby-music UNTIL(fully_created) if("[CHANNEL_LOBBYMUSIC]" in prefs.channel_volume) if(prefs.channel_volume["[CHANNEL_LOBBYMUSIC]"] != 0) - vol *= prefs.channel_volume["[CHANNEL_LOBBYMUSIC]"] * 0.01 + vol = prefs.channel_volume["[CHANNEL_LOBBYMUSIC]"] vol *= prefs.channel_volume["[CHANNEL_MASTER_VOLUME]"] * 0.01 - if((prefs && (!prefs.read_preference(/datum/preference/toggle/sound_lobby))) || CONFIG_GET(flag/disallow_title_music)) return @@ -279,6 +278,7 @@ GLOBAL_LIST_EMPTY(cached_mixer_channels) media = new /datum/media_manager(src) media.open() media.update_music() + media.lobby_music = TRUE if(!length(SSmedia_tracks.lobby_tracks)) return @@ -293,7 +293,8 @@ GLOBAL_LIST_EMPTY(cached_mixer_channels) SSmedia_tracks.first_lobby_play = FALSE var/datum/media_track/T = SSmedia_tracks.current_lobby_track - media.push_music(T.url, world.time, vol) + media.push_music(T.url, world.time, 1) + media.update_volume(vol) // this makes it easier if we modify volume later on to_chat(src,"Lobby music: [T.title] by [T.artist].") /proc/get_rand_frequency() diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index baf7cd488086..793447312b94 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -27,6 +27,7 @@ var/hardness = 40 var/slicing_duration = 100 //default time taken to slice the wall var/sheet_type = /obj/item/stack/sheet/iron + var/scrap_type = /obj/item/stack/scrap/plating var/sheet_amount = 2 var/girder_type = /obj/structure/girder /// A turf that will replace this turf when this turf is destroyed @@ -138,12 +139,20 @@ QUEUE_SMOOTH_NEIGHBORS(src) /turf/closed/wall/proc/break_wall() - new sheet_type(src, sheet_amount) + var/area/shipbreak/A = get_area(src) + if(istype(A)) //if we are actually in the shipbreaking zone... + new scrap_type(src, sheet_amount) + else + new sheet_type(src, sheet_amount) if(girder_type) return new girder_type(src) /turf/closed/wall/proc/devastate_wall() - new sheet_type(src, sheet_amount) + var/area/shipbreak/A = get_area(src) + if(istype(A)) + new scrap_type(src, sheet_amount) + else + new sheet_type(src, sheet_amount) if(girder_type) new /obj/item/stack/sheet/iron(src) diff --git a/code/modules/actionspeed/_actionspeed_modifier.dm b/code/modules/actionspeed/_actionspeed_modifier.dm index 761bfc3ff74a..07fce1f52f2d 100644 --- a/code/modules/actionspeed/_actionspeed_modifier.dm +++ b/code/modules/actionspeed/_actionspeed_modifier.dm @@ -40,8 +40,6 @@ can next move /datum/actionspeed_modifier/New(init_id) . = ..() - id = init_id - if(!id) id = "[type]" //We turn the path into a string. diff --git a/code/modules/admin/view_variables/reference_tracking.dm b/code/modules/admin/view_variables/reference_tracking.dm index b9fd0e6d2ad6..645467bf0fe0 100644 --- a/code/modules/admin/view_variables/reference_tracking.dm +++ b/code/modules/admin/view_variables/reference_tracking.dm @@ -1,29 +1,36 @@ #ifdef REFERENCE_TRACKING -#define REFSEARCH_RECURSE_LIMIT 64 -/datum/proc/find_references(references_to_clear = INFINITY) +/datum/proc/find_references(skip_alert) + running_find_references = type if(usr?.client) - if(tgui_alert(usr,"Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", list("Yes", "No")) != "Yes") + if(usr.client.running_find_references) + log_reftracker("CANCELLED search for references to a [usr.client.running_find_references].") + usr.client.running_find_references = null + running_find_references = null + //restart the garbage collector + SSgarbage.can_fire = TRUE + SSgarbage.update_nextfire(reset_time = TRUE) + return + + if(!skip_alert && tgui_alert(usr,"Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", list("Yes", "No")) != "Yes") + running_find_references = null return - src.references_to_clear = references_to_clear //this keeps the garbage collector from failing to collect objects being searched for in here SSgarbage.can_fire = FALSE - _search_references() - //restart the garbage collector - SSgarbage.can_fire = TRUE - SSgarbage.update_nextfire(reset_time = TRUE) + if(usr?.client) + usr.client.running_find_references = type -/datum/proc/_search_references() - log_reftracker("Beginning search for references to a [type], looking for [references_to_clear] refs.") + log_reftracker("Beginning search for references to a [type].") var/starting_time = world.time + + log_reftracker("Refcount for [type]: [refcount(src)]") + //Time to search the whole game for our ref - DoSearchVar(GLOB, "GLOB", starting_time) //globals + DoSearchVar(GLOB, "GLOB", search_time = starting_time) //globals log_reftracker("Finished searching globals") - if(src.references_to_clear == 0) - return //Yes we do actually need to do this. The searcher refuses to read weird lists //And global.vars is a really weird list @@ -31,46 +38,45 @@ for(var/key in global.vars) global_vars[key] = global.vars[key] - DoSearchVar(global_vars, "Native Global", starting_time) + DoSearchVar(global_vars, "Native Global", search_time = starting_time) log_reftracker("Finished searching native globals") - if(src.references_to_clear == 0) - return for(var/datum/thing in world) //atoms (don't beleive its lies) - DoSearchVar(thing, "World -> [thing.type]", starting_time) - if(src.references_to_clear == 0) - break + DoSearchVar(thing, "World -> [thing.type]", search_time = starting_time) log_reftracker("Finished searching atoms") - if(src.references_to_clear == 0) - return for(var/datum/thing) //datums - DoSearchVar(thing, "Datums -> [thing.type]", starting_time) - if(src.references_to_clear == 0) - break + DoSearchVar(thing, "Datums -> [thing.type]", search_time = starting_time) log_reftracker("Finished searching datums") - if(src.references_to_clear == 0) - return //Warning, attempting to search clients like this will cause crashes if done on live. Watch yourself #ifndef REFERENCE_DOING_IT_LIVE for(var/client/thing) //clients - DoSearchVar(thing, "Clients -> [thing.type]", starting_time) - if(src.references_to_clear == 0) - break + DoSearchVar(thing, "Clients -> [thing.type]", search_time = starting_time) log_reftracker("Finished searching clients") - if(src.references_to_clear == 0) - return #endif log_reftracker("Completed search for references to a [type].") -/datum/proc/DoSearchVar(potential_container, container_name, search_time, recursion_count, is_special_list) - if(recursion_count >= REFSEARCH_RECURSE_LIMIT) - log_reftracker("Recursion limit reached. [container_name]") + if(usr?.client) + usr.client.running_find_references = null + running_find_references = null + + //restart the garbage collector + SSgarbage.can_fire = TRUE + SSgarbage.update_nextfire(reset_time = TRUE) + +/datum/proc/DoSearchVar(potential_container, container_name, recursive_limit = 64, search_time = world.time) + #ifdef REFERENCE_TRACKING_DEBUG + if(SSgarbage.should_save_refs && !found_refs) + found_refs = list() + #endif + + if(usr?.client && !usr.client.running_find_references) return - if(references_to_clear == 0) + if(!recursive_limit) + log_reftracker("Recursion limit reached. [container_name]") return //Check each time you go down a layer. This makes it a bit slow, but it won't effect the rest of the game at all @@ -84,116 +90,73 @@ return datum_container.last_find_references = search_time + var/container_print = datum_container.ref_search_details() var/list/vars_list = datum_container.vars - var/is_atom = FALSE - var/is_area = FALSE - if(isatom(datum_container)) - is_atom = TRUE - if(isarea(datum_container)) - is_area = TRUE for(var/varname in vars_list) + #ifndef FIND_REF_NO_CHECK_TICK + CHECK_TICK + #endif + if (varname == "vars" || varname == "vis_locs") //Fun fact, vis_locs don't count for references + continue var/variable = vars_list[varname] - if(islist(variable)) - //Fun fact, vis_locs don't count for references - if(varname == "vars" || (is_atom && (varname == "vis_locs" || varname == "overlays" || varname == "underlays" || varname == "filters" || varname == "verbs" || (is_area && varname == "contents")))) - continue - // We do this after the varname check to avoid area contents (reading it incures a world loop's worth of cost) - if(!length(variable)) - continue - DoSearchVar(variable,\ - "[container_name] [datum_container.ref_search_details()] -> [varname] (list)",\ - search_time,\ - recursion_count + 1,\ - /*is_special_list = */ is_atom && (varname == "contents" || varname == "vis_contents" || varname == "locs")) - else if(variable == src) + + if(variable == src) #ifdef REFERENCE_TRACKING_DEBUG if(SSgarbage.should_save_refs) - if(!found_refs) - found_refs = list() found_refs[varname] = TRUE continue //End early, don't want these logging - else - log_reftracker("Found [type] [text_ref(src)] in [datum_container.type]'s [datum_container.ref_search_details()] [varname] var. [container_name]") - #else - log_reftracker("Found [type] [text_ref(src)] in [datum_container.type]'s [datum_container.ref_search_details()] [varname] var. [container_name]") #endif - references_to_clear -= 1 - if(references_to_clear == 0) - log_reftracker("All references to [type] [text_ref(src)] found, exiting.") - return + log_reftracker("Found [type] [text_ref(src)] in [datum_container.type]'s [container_print] [varname] var. [container_name]") continue + if(islist(variable)) + DoSearchVar(variable, "[container_name] [container_print] -> [varname] (list)", recursive_limit - 1, search_time) + else if(islist(potential_container)) + var/normal = IS_NORMAL_LIST(potential_container) var/list/potential_cache = potential_container for(var/element_in_list in potential_cache) - //Check normal sublists - if(islist(element_in_list)) - if(length(element_in_list)) - DoSearchVar(element_in_list, "[container_name] -> [element_in_list] (list)", search_time, recursion_count + 1) + #ifndef FIND_REF_NO_CHECK_TICK + CHECK_TICK + #endif //Check normal entrys - else if(element_in_list == src) + if(element_in_list == src) #ifdef REFERENCE_TRACKING_DEBUG if(SSgarbage.should_save_refs) - if(!found_refs) - found_refs = list() found_refs[potential_cache] = TRUE - continue - else - log_reftracker("Found [type] [text_ref(src)] in list [container_name].") - #else + continue //End early, don't want these logging + #endif log_reftracker("Found [type] [text_ref(src)] in list [container_name].") + continue + + var/assoc_val = null + if(!isnum(element_in_list) && normal) + assoc_val = potential_cache[element_in_list] + //Check assoc entrys + if(assoc_val == src) + #ifdef REFERENCE_TRACKING_DEBUG + if(SSgarbage.should_save_refs) + found_refs[potential_cache] = TRUE + continue //End early, don't want these logging #endif + log_reftracker("Found [type] [text_ref(src)] in list [container_name]\[[element_in_list]\]") + continue + //We need to run both of these checks, since our object could be hiding in either of them + //Check normal sublists + if(islist(element_in_list)) + DoSearchVar(element_in_list, "[container_name] -> [element_in_list] (list)", recursive_limit - 1, search_time) + //Check assoc sublists + if(islist(assoc_val)) + DoSearchVar(potential_container[element_in_list], "[container_name]\[[element_in_list]\] -> [assoc_val] (list)", recursive_limit - 1, search_time) + +/proc/qdel_and_find_ref_if_fail(datum/thing_to_del, force = FALSE) + thing_to_del.qdel_and_find_ref_if_fail(force) + +/datum/proc/qdel_and_find_ref_if_fail(force = FALSE) + SSgarbage.reference_find_on_fail[text_ref(src)] = TRUE + qdel(src, force) - // This is dumb as hell I'm sorry - // I don't want the garbage subsystem to count as a ref for the purposes of this number - // If we find all other refs before it I want to early exit, and if we don't I want to keep searching past it - var/ignore_ref = FALSE - var/list/queues = SSgarbage.queues - for(var/list/queue in queues) - if(potential_cache in queue) - ignore_ref = TRUE - break - if(ignore_ref) - log_reftracker("[container_name] does not count as a ref for our count") - else - references_to_clear -= 1 - if(references_to_clear == 0) - log_reftracker("All references to [type] [text_ref(src)] found, exiting.") - return - - if(!isnum(element_in_list) && !is_special_list) - // This exists to catch an error that throws when we access a special list - // is_special_list is a hint, it can be wrong - try - var/assoc_val = potential_cache[element_in_list] - //Check assoc sublists - if(islist(assoc_val)) - if(length(assoc_val)) - DoSearchVar(potential_container[element_in_list], "[container_name]\[[element_in_list]\] -> [assoc_val] (list)", search_time, recursion_count + 1) - //Check assoc entry - else if(assoc_val == src) - #ifdef REFERENCE_TRACKING_DEBUG - if(SSgarbage.should_save_refs) - if(!found_refs) - found_refs = list() - found_refs[potential_cache] = TRUE - continue - else - log_reftracker("Found [type] [text_ref(src)] in list [container_name]\[[element_in_list]\]") - #else - log_reftracker("Found [type] [text_ref(src)] in list [container_name]\[[element_in_list]\]") - #endif - references_to_clear -= 1 - if(references_to_clear == 0) - log_reftracker("All references to [type] [text_ref(src)] found, exiting.") - return - catch - // So if it goes wrong we kill it - is_special_list = TRUE - log_reftracker("Curiosity: [container_name] lead to an error when acessing [element_in_list], what is it?") - -#undef REFSEARCH_RECURSE_LIMIT #endif // Kept outside the ifdef so overrides are easy to implement diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 733bb4b63c0b..01d0b5819806 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -966,6 +966,10 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if(failed && !(ckey in GLOB.interviews.approved_ckeys)) message_admins(span_adminnotice("Proxy Detection: [key_name_admin(src)] Overwatch detected this is a [string]")) interviewee = TRUE + + if(ckey in GLOB.interviews.approved_ckeys) + return FALSE + return failed /client/Click(atom/object, atom/location, control, params) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index b3d105951f61..0dfff4d73fe8 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -399,10 +399,15 @@ GLOBAL_LIST_EMPTY(preferences_datums) QDEL_NULL(body) body = new + RegisterSignal(body, COMSIG_QDELETING, PROC_REF(clear_body)) // Without this, it doesn't show up in the menu body.appearance_flags &= ~TILE_BOUND +/atom/movable/screen/map_view/char_preview/proc/clear_body(atom/movable/deletee) + if(body == deletee) + body = null + /datum/preferences/proc/create_character_profiles() var/list/profiles = list() diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm index 89f430232789..84254ef615b7 100644 --- a/code/modules/error_handler/error_handler.dm +++ b/code/modules/error_handler/error_handler.dm @@ -34,6 +34,9 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0) if(!error_last_seen) // A runtime is occurring too early in start-up initialization return ..() + if(!islist(error_last_seen)) + return ..() //how the fuck? + if(stack_workaround.Find(E.name)) var/list/data = json_decode(stack_workaround.group[1]) E.file = data[1] diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index 91b3c0f99431..da8c6409c43e 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -24,7 +24,9 @@ typepath = /datum/round_event/disease_outbreak max_occurrences = 1 min_players = 10 - weight = 4 + weight = 0 + track = EVENT_TRACK_MAJOR + earliest_start = 55 MINUTES category = EVENT_CATEGORY_HEALTH description = "A 'classic' virus will infect some members of the crew." min_wizard_trigger_potency = 2 @@ -143,9 +145,9 @@ name = "Disease Outbreak: Advanced" typepath = /datum/round_event/disease_outbreak/advanced category = EVENT_CATEGORY_HEALTH - weight = 5 //monkestation change 15 ==> 5 + weight = 0 //monkestation change 15 ==> 5 min_players = 35 // To avoid shafting lowpop - earliest_start = 15 MINUTES // give the chemist a chance + earliest_start = 55 MINUTES // give the chemist a chance description = "An 'advanced' disease will infect some members of the crew." min_wizard_trigger_potency = 2 max_wizard_trigger_potency = 6 diff --git a/code/modules/events/ghost_role/alien_infestation.dm b/code/modules/events/ghost_role/alien_infestation.dm index 04aaad6999c5..9b35b2145dcf 100644 --- a/code/modules/events/ghost_role/alien_infestation.dm +++ b/code/modules/events/ghost_role/alien_infestation.dm @@ -1,11 +1,12 @@ /datum/round_event_control/antagonist/solo/from_ghosts/alien_infestation name = "Alien Infestation" typepath = /datum/round_event/antagonist/solo/ghost/alien_infestation - weight = 5 + weight = 3 + max_occurrences = 1 min_players = 35 //monkie edit: 10 to 35 (tg what the fuck) - earliest_start = 45 MINUTES //monkie edit: 20 to 90 + earliest_start = 60 MINUTES //monkie edit: 20 to 90 //dynamic_should_hijack = TRUE category = EVENT_CATEGORY_ENTITIES description = "A xenomorph larva spawns on a random vent." @@ -22,7 +23,6 @@ JOB_SECURITY_ASSISTANT, ) required_enemies = 5 - max_occurrences = 1 prompted_picking = TRUE /datum/round_event_control/antagonist/solo/from_ghosts/alien_infestation/can_spawn_event(players_amt, allow_magic = FALSE, fake_check = FALSE) //MONKESTATION ADDITION: fake_check = FALSE diff --git a/code/modules/food_and_drinks/machinery/deep_fryer.dm b/code/modules/food_and_drinks/machinery/deep_fryer.dm index be5c84fa7f79..6eeba5c25e84 100644 --- a/code/modules/food_and_drinks/machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/machinery/deep_fryer.dm @@ -25,7 +25,7 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list( circuit = /obj/item/circuitboard/machine/deep_fryer /// What's being fried RIGHT NOW? - var/obj/item/frying + var/frying = FALSE /// How long the current object has been cooking for var/cook_time = 0 /// How much cooking oil is used per process @@ -51,19 +51,13 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list( /obj/machinery/deepfryer/Initialize(mapload) . = ..() + basket = new(src) create_reagents(50, OPENCONTAINER) reagents.add_reagent(/datum/reagent/consumable/cooking_oil, 25) fry_loop = new(src, FALSE) /obj/machinery/deepfryer/Destroy() QDEL_NULL(fry_loop) - QDEL_NULL(frying) - return ..() - -/obj/machinery/deepfryer/deconstruct(disassembled) - // This handles nulling out frying via exited - if(frying) - frying.forceMove(drop_location()) return ..() /obj/machinery/deepfryer/RefreshParts() @@ -76,8 +70,6 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list( /obj/machinery/deepfryer/examine(mob/user) . = ..() - if(frying) - . += "You can make out \a [frying] in the oil." if(in_range(user, src) || isobserver(user)) . += span_notice("The status display reads: Frying at [fry_speed*100]% speed.
Using [oil_use] units of oil per second.") @@ -109,7 +101,10 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list( to_chat(user, span_userdanger("Your cooking skills are not up to the legendary Doublefry technique.")) return // Handle opening up the fryer with tools - if(default_deconstruction_screwdriver(user, "fryer_off", "fryer_off", weapon)) //where's the open maint panel icon?! + var/fryer_icon = "fryer_off" + if(!basket) + fryer_icon = "fryer" + if(default_deconstruction_screwdriver(user, fryer_icon, fryer_icon, weapon)) //where's the open maint panel icon?! return else // So we skip the attack animation @@ -122,13 +117,10 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list( || HAS_TRAIT(weapon, TRAIT_NODROP) \ || (weapon.item_flags & (ABSTRACT|DROPDEL|HAND_ITEM))) return ..() - // Do the frying. - else if(!frying && user.transferItemToLoc(weapon, src)) - start_fry(weapon, user) - return return ..() +/* /obj/machinery/deepfryer/process(seconds_per_tick) ..() var/datum/reagent/consumable/cooking_oil/frying_oil = reagents.has_reagent(/datum/reagent/consumable/cooking_oil) @@ -149,47 +141,7 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list( visible_message(span_warning("[src] emits an acrid smell!")) use_power(active_power_usage) - -/obj/machinery/deepfryer/Exited(atom/movable/gone, direction) - . = ..() - if(gone == frying) - reset_frying() - -/obj/machinery/deepfryer/handle_atom_del(atom/deleting_atom) - . = ..() - if(deleting_atom == frying) - reset_frying() - -/obj/machinery/deepfryer/proc/reset_frying() - if(!QDELETED(frying)) - frying.AddElement(/datum/element/fried_item, cook_time) - - frying = null - frying_fried = FALSE - frying_burnt = FALSE - fry_loop.stop() - cook_time = 0 - icon_state = "fryer_off" - -/obj/machinery/deepfryer/proc/start_fry(obj/item/frying_item, mob/user) - to_chat(user, span_notice("You put [frying_item] into [src].")) - if(istype(frying_item, /obj/item/freeze_cube)) - log_bomber(user, "put a freeze cube in a", src) - visible_message(span_userdanger("[src] starts glowing... Oh no...")) - playsound(src, 'sound/effects/pray_chaplain.ogg', 100) - add_filter("entropic_ray", 10, list("type" = "rays", "size" = 35, "color" = COLOR_VIVID_YELLOW)) - addtimer(CALLBACK(src, PROC_REF(blow_up)), 5 SECONDS) - - frying = frying_item - // Give them reagents to put frying oil in - if(isnull(frying.reagents)) - frying.create_reagents(50, INJECTABLE) - if(user.mind) - ADD_TRAIT(frying, TRAIT_FOOD_CHEF_MADE, REF(user.mind)) - SEND_SIGNAL(frying, COMSIG_ITEM_ENTERED_FRYER) - - icon_state = "fryer_on" - fry_loop.start() +*/ /obj/machinery/deepfryer/proc/blow_up() visible_message(span_userdanger("[src] blows up from the entropic reaction!")) @@ -201,10 +153,12 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list( /obj/machinery/deepfryer/attack_hand(mob/living/user, list/modifiers) if(frying) - to_chat(user, span_notice("You eject [frying] from [src].")) - frying.forceMove(drop_location()) - if(Adjacent(user) && !issilicon(user)) - user.put_in_hands(frying) + frying = FALSE + reset_frying(user) + if(Adjacent(user) && !issilicon(user) && basket) + user.put_in_hands(basket) + basket = null + icon_state = "fryer" return else if(user.pulling && iscarbon(user.pulling) && reagents.total_volume) @@ -232,6 +186,11 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list( reagents.remove_all((reagents.total_volume/2)) dunking_target.Paralyze(60) user.changeNext_move(CLICK_CD_MELEE) + if(Adjacent(user) && !issilicon(user) && basket) + user.put_in_hands(basket) + basket = null + icon_state = "fryer" + return ..() #undef DEEPFRYER_COOKTIME diff --git a/code/modules/food_and_drinks/machinery/oven.dm b/code/modules/food_and_drinks/machinery/oven.dm index 077d775a4428..130a78142397 100644 --- a/code/modules/food_and_drinks/machinery/oven.dm +++ b/code/modules/food_and_drinks/machinery/oven.dm @@ -139,6 +139,17 @@ . = ..() open = !open if(open) + timer_duration = world.time - timer_laststart + deltimer(oven_timer) + oven_timer = null + if(used_tray) + var/obj/item/reagent_containers/cooking_container/located = locate(/obj/item/reagent_containers/cooking_container) in used_tray.contents + if(located) + if(user && user.Adjacent(src)) + located.process_item(src, user, lower_quality_on_fail=CHEWIN_BASE_QUAL_REDUCTION, send_message=TRUE) + else + located.process_item(src, user, lower_quality_on_fail=CHEWIN_BASE_QUAL_REDUCTION) + playsound(src, 'sound/machines/oven/oven_open.ogg', 75, TRUE) set_smoke_state(OVEN_SMOKE_STATE_NONE) to_chat(user, span_notice("You open [src].")) @@ -146,6 +157,8 @@ if(used_tray) used_tray.vis_flags &= ~VIS_HIDE else + timer_laststart = world.time + oven_timer = addtimer(CALLBACK(src, PROC_REF(go_off_queen)), timer_duration, TIMER_UNIQUE | TIMER_STOPPABLE) playsound(src, 'sound/machines/oven/oven_close.ogg', 75, TRUE) to_chat(user, span_notice("You close [src].")) if(used_tray) diff --git a/code/modules/food_and_drinks/machinery/stove_component.dm b/code/modules/food_and_drinks/machinery/stove_component.dm index b148e27f01b0..9ccdf8fc2302 100644 --- a/code/modules/food_and_drinks/machinery/stove_component.dm +++ b/code/modules/food_and_drinks/machinery/stove_component.dm @@ -23,6 +23,12 @@ var/container_y = 8 /// Modifies how much temperature is exposed to the reagents, and in turn modifies how fast the reagents are heated. var/heat_coefficient = 0.033 + ///our stove temperature + var/temperature = J_LO + ///list of temperatures + var/list/temperatures = list(J_LO, J_MED, J_HI) + ///our temp index + var/temp_index = 1 /datum/component/stove/Initialize(container_x = 0, container_y = 8, obj/item/spawn_container) if(!ismachinery(parent)) @@ -37,6 +43,7 @@ add_container(spawn_container) /datum/component/stove/RegisterWithParent() + RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(switch_temp)) RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND_SECONDARY, PROC_REF(on_attack_hand_secondary)) RegisterSignal(parent, COMSIG_ATOM_EXITED, PROC_REF(on_exited)) @@ -73,6 +80,7 @@ turn_off() return + SEND_SIGNAL(container, COMSIG_STOVE_PROCESS, temperature, seconds_per_tick, parent) container?.reagents.expose_temperature(SOUP_BURN_TEMP + 80, heat_coefficient) real_parent.use_power(real_parent.active_power_usage) @@ -165,6 +173,7 @@ /datum/component/stove/proc/on_requesting_context(obj/machinery/source, list/context, obj/item/held_item) SIGNAL_HANDLER + context[SCREENTIP_CONTEXT_ALT_LMB] = "Change Temperature" if(isnull(held_item)) context[SCREENTIP_CONTEXT_RMB] = "Turn [on ? "off":"on"] burner" return CONTEXTUAL_SCREENTIP_SET @@ -173,6 +182,14 @@ context[SCREENTIP_CONTEXT_LMB] = "Place container" return CONTEXTUAL_SCREENTIP_SET +/datum/component/stove/proc/switch_temp(datum/source, atom/target) + temp_index++ + if(temp_index > length(temperatures)) + temp_index = 1 + temperature = temperatures[temp_index] + var/atom/movable/parent_atom = parent + parent_atom.visible_message("Temperature set to [temperature]") + /datum/component/stove/proc/on_examine(obj/machinery/source, mob/user, list/examine_list) SIGNAL_HANDLER diff --git a/code/modules/food_and_drinks/plate.dm b/code/modules/food_and_drinks/plate.dm index 083a9c5236e1..46c24742512d 100644 --- a/code/modules/food_and_drinks/plate.dm +++ b/code/modules/food_and_drinks/plate.dm @@ -14,7 +14,7 @@ var/placement_offset = -15 /obj/item/plate/attackby(obj/item/I, mob/user, params) - if(!IS_EDIBLE(I)) + if(!IS_EDIBLE(I) && !istype(I, /obj/item/reagent_containers/cooking_container)) to_chat(user, span_notice("[src] is made for food, and food alone!")) return if(contents.len >= max_items) diff --git a/code/modules/food_and_drinks/recipes/drinks/drinks_alcoholic.dm b/code/modules/food_and_drinks/recipes/drinks/drinks_alcoholic.dm index 116982d597c2..ab21e0043156 100644 --- a/code/modules/food_and_drinks/recipes/drinks/drinks_alcoholic.dm +++ b/code/modules/food_and_drinks/recipes/drinks/drinks_alcoholic.dm @@ -290,7 +290,7 @@ /datum/chemical_reaction/drink/neurotoxin results = list(/datum/reagent/consumable/ethanol/neurotoxin = 2) - required_reagents = list(/datum/reagent/consumable/ethanol/gargle_blaster = 1, /datum/reagent/medicine/morphine = 1) + required_reagents = list(/datum/reagent/consumable/ethanol/gargle_blaster = 1, /datum/reagent/medicine/painkiller/morphine = 1) reaction_tags = REACTION_TAG_DRINK | REACTION_TAG_EASY | REACTION_TAG_OTHER /datum/chemical_reaction/drink/snowwhite @@ -558,7 +558,7 @@ /datum/chemical_reaction/drink/the_juice results = list(/datum/reagent/consumable/ethanol/the_juice = 5) - required_reagents = list(/datum/reagent/consumable/mushroom_tea = 1, /datum/reagent/bluespace = 1, /datum/reagent/toxin/mindbreaker = 1, /datum/reagent/consumable/ethanol/neurotoxin = 1, /datum/reagent/medicine/morphine = 1) + required_reagents = list(/datum/reagent/consumable/mushroom_tea = 1, /datum/reagent/bluespace = 1, /datum/reagent/toxin/mindbreaker = 1, /datum/reagent/consumable/ethanol/neurotoxin = 1, /datum/reagent/medicine/painkiller/morphine = 1) mix_message = "The liquids all swirl together into a deep purple." /datum/chemical_reaction/drink/helianthus diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_guide.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_guide.dm index 707d199cba8f..4076cffd109b 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_guide.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_guide.dm @@ -37,7 +37,6 @@ non_craftable = TRUE /datum/crafting_recipe/food/reaction/New() - . = ..() if(!ispath(reaction, /datum/chemical_reaction)) return diff --git a/code/modules/hydroponics/grown/mushrooms.dm b/code/modules/hydroponics/grown/mushrooms.dm index 3b94cebeab6a..8d88dba452f6 100644 --- a/code/modules/hydroponics/grown/mushrooms.dm +++ b/code/modules/hydroponics/grown/mushrooms.dm @@ -23,7 +23,7 @@ growthstages = 4 genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism) growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi' - reagents_add = list(/datum/reagent/medicine/morphine = 0.35, /datum/reagent/medicine/c2/multiver = 0.35, /datum/reagent/consumable/nutriment = 0) + reagents_add = list(/datum/reagent/medicine/painkiller/morphine = 0.35, /datum/reagent/medicine/c2/multiver = 0.35, /datum/reagent/consumable/nutriment = 0) graft_gene = /datum/plant_gene/trait/plant_type/fungal_metabolism /obj/item/food/grown/mushroom/reishi diff --git a/code/modules/hydroponics/grown/tea_coffee.dm b/code/modules/hydroponics/grown/tea_coffee.dm index 9231102097f4..1f816c79360e 100644 --- a/code/modules/hydroponics/grown/tea_coffee.dm +++ b/code/modules/hydroponics/grown/tea_coffee.dm @@ -89,4 +89,4 @@ name = "coffee robusta beans" desc = "Increases robustness by 37 percent!" icon_state = "coffee_robusta" - grind_results = list(/datum/reagent/toxin/coffeepowder = 0, /datum/reagent/medicine/morphine = 0) + grind_results = list(/datum/reagent/toxin/coffeepowder = 0, /datum/reagent/medicine/painkiller/morphine = 0) diff --git a/code/modules/mapping/ruins.dm b/code/modules/mapping/ruins.dm index a7b9480a34e4..ff87057796bc 100644 --- a/code/modules/mapping/ruins.dm +++ b/code/modules/mapping/ruins.dm @@ -64,7 +64,16 @@ return center -/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = list(/area/space), list/potentialRuins, clear_below = FALSE) +/** + * Loads the ruins for a given z level. + * @param z_levels The z levels to load ruins on. + * @param budget The budget to spend on ruins. Compare against the cost of the ruins in /datum/map_template/ruin. + * @param whitelist A list of areas to allow ruins to be placed in. + * @param potentialRuins A list of ruins to choose from. + * @param clear_below Whether to clear the area below the ruin. Used for multiz ruins. + * @param mineral_budget The budget to spend on ruins that spawn ore vents. Map templates with vents have that defined by mineral_cost. + */ +/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = list(/area/space), list/potentialRuins, clear_below = FALSE, mineral_budget = 15) if(!z_levels || !z_levels.len) WARNING("No Z levels provided - Not generating ruins") return @@ -93,14 +102,14 @@ R.allow_duplicates = FALSE // no multiples for testing R.always_place = !R.unpickable // unpickable ruin means it spawns as a set with another ruin - if(R.cost > budget) //Why would you do that + if(R.cost > budget || R.mineral_cost > mineral_budget) //Why would you do that continue if(R.always_place) forced_ruins[R] = -1 if(R.unpickable) continue ruins_available[R] = R.placement_weight - while(budget > 0 && (ruins_available.len || forced_ruins.len)) + while((budget > 0 || mineral_budget > 0) && (ruins_available.len || forced_ruins.len)) var/datum/map_template/ruin/current_pick var/forced = FALSE var/forced_z //If set we won't pick z level and use this one instead. @@ -159,6 +168,7 @@ log_world("Failed to place [current_pick.name] ruin.") else budget -= current_pick.cost + mineral_budget -= current_pick.mineral_cost if(!current_pick.allow_duplicates) for(var/datum/map_template/ruin/R in ruins_available) if(R.id == current_pick.id) @@ -189,7 +199,7 @@ //Update the available list for(var/datum/map_template/ruin/R in ruins_available) - if(R.cost > budget) + if(R.cost > budget || R.mineral_cost > mineral_budget) ruins_available -= R log_world("Ruin loader finished with [budget] left to spend.") diff --git a/code/modules/mining/equipment/mineral_scanner.dm b/code/modules/mining/equipment/mineral_scanner.dm index 46b6d407e38a..1011e8af2ff2 100644 --- a/code/modules/mining/equipment/mineral_scanner.dm +++ b/code/modules/mining/equipment/mineral_scanner.dm @@ -82,7 +82,9 @@ duration = 35 pixel_x = -224 pixel_y = -224 + /// What animation easing to use when we create the ore overlay on rock walls/ore vents. + var/easing_style = EASE_IN /obj/effect/temp_visual/mining_overlay/Initialize(mapload) . = ..() - animate(src, alpha = 0, time = duration, easing = EASE_IN) + animate(src, alpha = 0, time = duration, easing = easing_style) diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index ed00c93095fd..18a4e63e6eda 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -299,6 +299,10 @@ return new_character.key = key //Manually transfer the key to log them in, new_character.stop_sound_channel(CHANNEL_LOBBYMUSIC) + if(new_character?.client?.media) + new_character.client.media.lobby_music = FALSE + new_character.client.media.stop_music() + var/area/joined_area = get_area(new_character.loc) if(joined_area) joined_area.on_joining_game(new_character) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 5d3d80745a3d..d6a9075abf80 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -285,7 +285,7 @@ * * Will pass FALSE if the item can not be dropped due to TRAIT_NODROP via doUnEquip() * If the item can be dropped, it will be forceMove()'d to the ground and the turf's Entered() will be called. */ -/mob/proc/dropItemToGround(obj/item/I, force = FALSE, silent = FALSE, invdrop = TRUE) +/mob/proc/dropItemToGround(obj/item/I, force = FALSE, silent = FALSE, invdrop = TRUE, violent = FALSE) if (isnull(I)) return TRUE @@ -300,6 +300,11 @@ I.pixel_y = I.base_pixel_y + rand(-6, 6) I.do_drop_animation(src) + if(violent) + var/turf/drop = drop_location() + I.launch_item(drop) + + //for when the item will be immediately placed in a loc other than the ground /mob/proc/transferItemToLoc(obj/item/I, newloc = null, force = FALSE, silent = TRUE) . = doUnEquip(I, force, newloc, FALSE, silent = silent) 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 0f90a8b2ed02..2bcee4a6d55f 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 @@ -105,7 +105,7 @@ if (LAZYLEN(SSmobs.cheeserats) >= rat_cap) to_chat(owner,span_warning("There's too many mice on this station to beckon a new one! Find them first!")) return - new /mob/living/basic/mouse(owner.loc) + new /mob/living/basic/mouse/ratking(owner.loc) owner.visible_message(span_warning("[owner] commands a rat to their side!")) /// Makes a passed mob into our minion diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 246e539d3985..4c9635ef9742 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -79,7 +79,7 @@ if(iter_part.generic_bleedstacks) // If you don't have any bleedstacks, don't try and heal them if(HAS_TRAIT(src, TRAIT_HEAVY_BLEEDER)) - iter_part.adjustBleedStacks(-1, 0) /// we basically double up on bleedstacks + iter_part.adjustBleedStacks(-1, minimum = 0) /// we basically double up on bleedstacks iter_part.adjustBleedStacks(-1, 0) if(temp_bleed) @@ -92,24 +92,23 @@ iter_part.update_part_wound_overlay() //Makes a blood drop, leaking amt units of blood from the mob -/mob/living/carbon/proc/bleed(amt) - if(!blood_volume || (status_flags & GODMODE)) +/mob/living/carbon/proc/bleed(amt, no_visual = FALSE) + if(!blood_volume || (status_flags & GODMODE) || HAS_TRAIT(src, TRAIT_NOBLOOD)) return blood_volume = max(blood_volume - amt, 0) //Blood loss still happens in locker, floor stays clean - if(isturf(loc) && prob(sqrt(amt)*BLOOD_DRIP_RATE_MOD)) - add_splatter_floor(loc, (amt <= 10)) + if(!no_visual && isturf(loc) && prob(sqrt(amt) * 80)) + add_splatter_floor(loc, small_drip = (amt < 10)) -/mob/living/carbon/human/bleed(amt) +/mob/living/carbon/human/bleed(amt, no_visual = FALSE) amt *= physiology.bleed_mod - if(!HAS_TRAIT(src, TRAIT_NOBLOOD)) - ..() + return ..() /// A helper to see how much blood we're losing per tick /mob/living/carbon/proc/get_bleed_rate() - if(!blood_volume) - return + if(!blood_volume || HAS_TRAIT(src, TRAIT_NOBLOOD)) + return 0 var/bleed_amt = 0 for(var/X in bodyparts) var/obj/item/bodypart/iter_bodypart = X @@ -117,10 +116,7 @@ return bleed_amt /mob/living/carbon/human/get_bleed_rate() - if(HAS_TRAIT(src, TRAIT_NOBLOOD)) - return - . = ..() - . *= physiology.bleed_mod + return ..() * physiology.bleed_mod /** * bleed_warn() is used to for carbons with an active client to occasionally receive messages warning them about their bleeding status (if applicable) @@ -324,26 +320,26 @@ . = safe //to add a splatter of blood or other mob liquid. -/mob/living/proc/add_splatter_floor(turf/T, small_drip) - if(get_blood_id() != /datum/reagent/blood) +/mob/living/proc/add_splatter_floor(turf/splattered, small_drip) + if((get_blood_id() != /datum/reagent/blood) || HAS_TRAIT(src, TRAIT_NOBLOOD)) return - if(!QDELETED(T)) - T = get_turf(src) - if(QDELETED(T) || isclosedturf(T) || (isgroundlessturf(T) && !GET_TURF_BELOW(T))) + if(!splattered) + splattered = get_turf(src) + if(isclosedturf(splattered) || (isgroundlessturf(splattered) && !GET_TURF_BELOW(splattered))) return var/datum/reagent/blood_type = get_blood_id() var/list/temp_blood_DNA if(small_drip) - if(!QDELETED(T.liquids)) + if(!QDELETED(splattered.liquids)) var/list/blood_drop = list(get_blood_id() = 0.1) - T.add_liquid_list(blood_drop, FALSE, 300) + splattered.add_liquid_list(blood_drop, FALSE, 300) return // Only a certain number of drips (or one large splatter) can be on a given turf. - var/obj/effect/decal/cleanable/blood/drip/drop = locate() in T + var/obj/effect/decal/cleanable/blood/drip/drop = locate() in splattered if(drop) if(drop.drips < 5) - T?.pollute_turf(/datum/pollutant/metallic_scent, 5) + splattered?.pollute_turf(/datum/pollutant/metallic_scent, 5) drop.drips++ drop.add_overlay(pick(drop.random_icon_states)) drop.transfer_mob_blood_dna(src) @@ -352,18 +348,18 @@ temp_blood_DNA = GET_ATOM_BLOOD_DNA(drop) //we transfer the dna from the drip to the splatter qdel(drop)//the drip is replaced by a bigger splatter else - T?.pollute_turf(/datum/pollutant/metallic_scent, 5) - drop = new(T, get_static_viruses()) + splattered?.pollute_turf(/datum/pollutant/metallic_scent, 5) + drop = new(splattered, get_static_viruses()) drop.transfer_mob_blood_dna(src) return // Create a bit of metallic pollution, as that's how blood smells - T.pollute_turf(/datum/pollutant/metallic_scent, 30) + splattered.pollute_turf(/datum/pollutant/metallic_scent, 30) // Find a blood decal or create a new one. - var/obj/effect/decal/cleanable/blood/B = locate() in T + var/obj/effect/decal/cleanable/blood/B = locate() in splattered if(!B) - B = new /obj/effect/decal/cleanable/blood/splatter(T, get_static_viruses()) + B = new /obj/effect/decal/cleanable/blood/splatter(splattered, get_static_viruses()) if(QDELETED(B)) //Give it up return B.bloodiness = min((B.bloodiness + BLOOD_AMOUNT_PER_DECAL), BLOOD_POOL_MAX) @@ -383,7 +379,7 @@ if(B.count > 9) qdel(B) var/list/blood_large = list(get_blood_id() = 20) - T.add_liquid_list(blood_large, FALSE, 300) + splattered.add_liquid_list(blood_large, FALSE, 300) /mob/living/carbon/human/add_splatter_floor(turf/T, small_drip) if(!HAS_TRAIT(src, TRAIT_NOBLOOD)) @@ -404,4 +400,33 @@ if(!B) B = new(T) +/** + * This proc is a helper for spraying blood for things like slashing/piercing wounds and dismemberment. + * + * The strength of the splatter in the second argument determines how much it can dirty and how far it can go + * + * Arguments: + * * splatter_direction: Which direction the blood is flying + * * splatter_strength: How many tiles it can go, and how many items it can pass over and dirty + */ +/mob/living/proc/spray_blood(splatter_direction, splatter_strength = 3) + if(!isturf(loc) || !blood_volume || HAS_TRAIT(src, TRAIT_NOBLOOD)) + return + var/obj/effect/decal/cleanable/blood/hitsplatter/our_splatter = new(loc) + our_splatter.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + var/turf/targ = get_ranged_target_turf(src, splatter_direction, splatter_strength) + our_splatter.fly_towards(targ, splatter_strength) + +/** + * Helper proc for throwing blood particles around, similar to the spray_blood proc. + */ +/mob/living/proc/blood_particles(amount = rand(1, 3), angle = rand(0,360), min_deviation = -30, max_deviation = 30, min_pixel_z = 0, max_pixel_z = 6) + if(!isturf(loc) || !blood_volume ||HAS_TRAIT(src, TRAIT_NOBLOOD)) + return + for(var/i in 1 to amount) + var/obj/effect/decal/cleanable/blood/particle/droplet = new(loc) + droplet.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + droplet.pixel_z = rand(min_pixel_z, max_pixel_z) + droplet.start_movement(angle + rand(min_deviation, max_deviation)) + #undef BLOOD_DRIP_RATE_MOD diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index a9e876648fa6..8ed56358f71e 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1376,24 +1376,6 @@ log_combat(shover, target, "shoved", addition = "into [name]") return COMSIG_CARBON_SHOVE_HANDLED -/** - * This proc is a helper for spraying blood for things like slashing/piercing wounds and dismemberment. - * - * The strength of the splatter in the second argument determines how much it can dirty and how far it can go - * - * Arguments: - * * splatter_direction: Which direction the blood is flying - * * splatter_strength: How many tiles it can go, and how many items it can pass over and dirty - */ -/mob/living/carbon/proc/spray_blood(splatter_direction, splatter_strength = 3) - if(!isturf(loc)) - return - var/obj/effect/decal/cleanable/blood/hitsplatter/our_splatter = new(loc) - our_splatter.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) - our_splatter.blood_dna_info = get_blood_dna_list() - var/turf/targ = get_ranged_target_turf(src, splatter_direction, splatter_strength) - our_splatter.fly_towards(targ, splatter_strength) - /mob/living/carbon/ominous_nosebleed() var/obj/item/bodypart/head = get_bodypart(BODY_ZONE_HEAD) if(isnull(head)) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 488e04eee515..73dad7af793c 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -103,8 +103,7 @@ if(I.damtype == BRUTE && affecting.can_bleed()) if(prob(33)) I.add_mob_blood(src) - var/turf/location = get_turf(src) - add_splatter_floor(location) + blood_particles(amount = rand(1, 1 + round(I.force/15, 1)), angle = (user == src ? rand(0, 360): get_angle(user, src))) if(get_dist(user, src) <= 1) //people with TK won't get smeared with blood user.add_mob_blood(src) if(affecting.body_zone == BODY_ZONE_HEAD) diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index a0edf5431b62..ba629ae60144 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -26,11 +26,11 @@ /mob/living/carbon/gib(no_brain, no_organs, no_bodyparts, safe_gib = FALSE) add_memory_in_range(src, 7, /datum/memory/witness_gib, protagonist = src) - if(safe_gib) // If you want to keep all the mob's items and not have them deleted - for(var/obj/item/W in src) - dropItemToGround(W) - if(prob(50)) - step(W, pick(GLOB.alldirs)) + // if(safe_gib) // If you want to keep all the mob's items and not have them deleted MONKESTATION EDIT + for(var/obj/item/W in src) + dropItemToGround(W, violent = TRUE) + if(prob(50)) + step(W, pick(GLOB.alldirs)) var/atom/Tsec = drop_location() for(var/mob/M in src) M.forceMove(Tsec) @@ -50,10 +50,11 @@ qdel(organs) //so the brain isn't transfered to the head when the head drops. continue var/org_zone = check_zone(organs.zone) //both groin and chest organs. - if(org_zone == BODY_ZONE_CHEST) - organs.Remove(src) - organs.forceMove(Tsec) - organs.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5) + if(org_zone != BODY_ZONE_CHEST) + continue + organs.Remove(src) + organs.forceMove(Tsec) + organs.fly_away(Tsec, horizontal_multiplier = 2, vertical_multiplier = 1.2) else for(var/obj/item/organ/organs as anything in organs) if(no_brain && istype(organs, /obj/item/organ/internal/brain)) @@ -64,17 +65,18 @@ continue organs.Remove(src) organs.forceMove(Tsec) - organs.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5) + organs.fly_away(Tsec, horizontal_multiplier = 2, vertical_multiplier = 1.2) /// Launches all bodyparts away from the mob. skip_head will keep the head attached. -/mob/living/carbon/spread_bodyparts(skip_head = FALSE) +/mob/living/carbon/spread_bodyparts(skip_head = FALSE, skip_organ = FALSE, violent = FALSE) + var/atom/Tsec = drop_location() for(var/obj/item/bodypart/part as anything in bodyparts) if(skip_head && part.body_zone == BODY_ZONE_HEAD) continue else if(part.body_zone == BODY_ZONE_CHEST) continue - part.drop_limb() - part.throw_at(get_edge_target_turf(src, pick(GLOB.alldirs)), rand(1,3), 5) + part.drop_limb(violent = violent) + part.fly_away(Tsec, horizontal_multiplier = 2, vertical_multiplier = 1.2) /mob/living/carbon/set_suicide(suicide_state) //you thought that box trick was pretty clever, didn't you? well now hardmode is on, boyo. . = ..() diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index 895a80e4ac80..fb6762f4863f 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -213,3 +213,7 @@ GLOBAL_LIST_EMPTY(dummy_mob_list) bound_height = 64 var/list/extra_bodyparts = list() + +/mob/living/carbon/human/dummy/extra_tall/Destroy() + . = ..() + extra_bodyparts = null diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index f82259bf5f22..a51504d92cd9 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -173,6 +173,8 @@ I.disease_contact(src, check_zone(user.zone_selected)) SSblackbox.record_feedback("nested tally", "item_used_for_combat", 1, list("[I.force]", "[initial(I.name)]")) SSblackbox.record_feedback("tally", "zone_targeted", 1, target_area) + if(I.pain_damage) + cause_pain(target_area, I.pain_damage, I.damtype) // the attacked_by code varies among species return dna.species.spec_attacked_by(I, user, affecting, src) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 833e435b58a3..9793371343fa 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -34,13 +34,18 @@ bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, - attacking_item, + obj/item/attacking_item, ) SHOULD_CALL_PARENT(TRUE) var/damage_amount = damage if(!forced) damage_amount *= ((100 - blocked) / 100) damage_amount *= get_incoming_damage_modifier(damage_amount, damagetype, def_zone, sharpness, attack_direction, attacking_item) + if(attacking_item) + if(!SEND_SIGNAL(attacking_item, COMSIG_ITEM_DAMAGE_MULTIPLIER, src, def_zone)) + attacking_item.last_multi = 1 + damage_amount *= attacking_item.last_multi + if(damage_amount <= 0) return 0 diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 957839645d92..a82cacfaf960 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -18,9 +18,17 @@ spill_organs(no_brain, no_organs, no_bodyparts) if(!no_bodyparts) - spread_bodyparts(no_brain, no_organs) + spread_bodyparts(no_brain, no_organs, TRUE) spawn_gibs(no_bodyparts) + ///lol I want it to be bloody as fuck + blood_particles(5, min_deviation = 70, max_deviation = 120, min_pixel_z = 4, max_pixel_z = 11) + blood_particles(6, min_deviation = -70, max_deviation = -30, min_pixel_z = 5, max_pixel_z = 7) + blood_particles(4, min_deviation = -190, max_deviation = -80, min_pixel_z = 0, max_pixel_z = 9) + blood_particles(7, min_deviation = 130, max_deviation = 160, min_pixel_z = 12, max_pixel_z = 16) + blood_particles(4, min_deviation = -200, max_deviation = -220, min_pixel_z = 4, max_pixel_z = 6) + blood_particles(2, min_deviation = 161, max_deviation = 200, min_pixel_z = 2, max_pixel_z = 12) + ///lol SEND_SIGNAL(src, COMSIG_LIVING_GIBBED, no_brain, no_organs, no_bodyparts) qdel(src) @@ -33,7 +41,7 @@ /mob/living/proc/spill_organs() return -/mob/living/proc/spread_bodyparts() +/mob/living/proc/spread_bodyparts(skip_head, skip_organs, violent) return /** diff --git a/code/modules/plumbing/ducts.dm b/code/modules/plumbing/ducts.dm index 9e91221ea8a5..33c4c5e300c7 100644 --- a/code/modules/plumbing/ducts.dm +++ b/code/modules/plumbing/ducts.dm @@ -19,7 +19,7 @@ All the important duct code: ///our ductnet, wich tracks what we're connected to var/datum/ductnet/duct ///amount we can transfer per process. note that the ductnet can carry as much as the lowest capacity duct - var/capacity = 100 + var/capacity = 1000 ///the color of our duct var/duct_color = COLOR_VERY_LIGHT_GRAY diff --git a/code/modules/plumbing/plumbers/synthesizer.dm b/code/modules/plumbing/plumbers/synthesizer.dm index 4f9f3672ecba..479af8c800a7 100644 --- a/code/modules/plumbing/plumbers/synthesizer.dm +++ b/code/modules/plumbing/plumbers/synthesizer.dm @@ -20,6 +20,7 @@ var/list/dispensable_reagents = list( /datum/reagent/aluminium, /datum/reagent/bromine, + /datum/reagent/brine, /datum/reagent/carbon, /datum/reagent/chlorine, /datum/reagent/copper, diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index bd12ddd9a4fa..bc0f0ea385ce 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -172,8 +172,11 @@ playsound(src, fire_sound, fire_sound_volume, vary_fire_sound) /obj/item/gun/proc/shoot_live_shot(mob/living/user, pointblank = 0, atom/pbtarget = null, message = 1) + var/angle = get_angle(user, pbtarget)+rand(-recoil_deviation, recoil_deviation) + 180 + if(angle > 360) + angle -= 360 if(recoil && !tk_firing(user)) - shake_camera(user, recoil + 1, recoil) + recoil_camera(user, recoil+1, (recoil*recoil_backtime_multiplier) + 1, recoil, angle) fire_sounds() if(!suppressed) if(message) @@ -278,8 +281,9 @@ var/obj/item/bodypart/other_hand = user.has_hand_for_held_index(user.get_inactive_hand_index()) //returns non-disabled inactive hands if(weapon_weight == WEAPON_HEAVY && (user.get_inactive_held_item() || !other_hand)) - balloon_alert(user, "use both hands!") - return + if(!istype(user.get_inactive_held_item(), /obj/item/offhand)) + balloon_alert(user, "use both hands!") + return //DUAL (or more!) WIELDING var/bonus_spread = 0 var/loop_counter = 0 diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index f5eb4bb7c71f..134980255e35 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -127,8 +127,11 @@ ///What is the cap on our misfire probability? Do not set this to 100. var/misfire_probability_cap = 25 + var/wield_recoil = 0 + /obj/item/gun/ballistic/Initialize(mapload) . = ..() + AddComponent(/datum/component/two_handed, wield_callback = CALLBACK(src, PROC_REF(on_wield)), unwield_callback = CALLBACK(src, PROC_REF(on_unwield))) if(!spawn_magazine_type) spawn_magazine_type = accepted_magazine_type if (!spawnwithmagazine) @@ -143,6 +146,12 @@ chamber_round(replace_new_round = TRUE) update_appearance() RegisterSignal(src, COMSIG_ITEM_RECHARGED, PROC_REF(instant_reload)) + register_context() + +/obj/item/gun/ballistic/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + context[SCREENTIP_CONTEXT_CTRL_LMB] = "Toggle Bracing" + return CONTEXTUAL_SCREENTIP_SET /obj/item/gun/ballistic/Destroy() QDEL_NULL(magazine) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 4b668f80fef0..28166514b241 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -8,6 +8,7 @@ icon_state = "bullet" density = FALSE anchored = TRUE + animate_movement = NO_STEPS //Use SLIDE_STEPS in conjunction with legacy mouse_opacity = MOUSE_OPACITY_TRANSPARENT movement_type = FLYING wound_bonus = CANT_WOUND // can't wound by default @@ -314,8 +315,9 @@ new /obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter(target_turf, splatter_dir) else new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_turf, splatter_dir) - if(prob(33)) - living_target.add_splatter_floor(target_turf) + if(prob(damage)) + living_target.blood_particles(amount = rand(1, 1 + round(damage/20, 1)), angle = src.Angle) + else if (!isnull(hit_bodypart) && (hit_bodypart.biological_state & (BIO_METAL|BIO_WIRED))) var/random_damage_mult = RANDOM_DECIMAL(0.85, 1.15) // SOMETIMES you can get more or less sparks var/damage_dealt = ((damage / (1 - (blocked / 100))) * random_damage_mult) diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index b4198caeafd1..98e2f150d65d 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -13,6 +13,12 @@ wound_falloff_tile = -5 embed_falloff_tile = -3 + light_system = OVERLAY_LIGHT + light_outer_range = 1.25 + light_power = 1 + light_color = COLOR_VERY_SOFT_YELLOW + light_on = TRUE + speed = 0.4 //twice as fast /obj/projectile/bullet/smite diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 3f5c833c11b5..a897c80dc6ec 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -230,6 +230,8 @@ //add the reagent to the existing if it exists for(var/datum/reagent/iter_reagent as anything in cached_reagents) if(iter_reagent.type == reagent) + if(!iter_reagent.can_merge) + return if(override_base_ph) added_ph = iter_reagent.ph iter_reagent.purity = ((iter_reagent.creation_purity * iter_reagent.volume) + (added_purity * amount)) /(iter_reagent.volume + amount) //This should add the purity to the product @@ -2040,6 +2042,7 @@ monkestation end */ qdel(reagents) reagents = new /datum/reagents(max_vol, flags) reagents.my_atom = src + return reagents /atom/movable/chem_holder name = "This atom exists to hold chems. If you can see this, make an issue report" diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index e017d291a67c..fbc515d8bec4 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -87,7 +87,7 @@ var/list/emagged_reagents = list( /datum/reagent/toxin/carpotoxin, /datum/reagent/medicine/mine_salve, - /datum/reagent/medicine/morphine, + /datum/reagent/medicine/painkiller/morphine, /datum/reagent/drug/space_drugs, /datum/reagent/australium ) @@ -710,7 +710,7 @@ /datum/reagent/fuel/oil, /datum/reagent/saltpetre, /datum/reagent/medicine/mine_salve, - /datum/reagent/medicine/morphine, + /datum/reagent/medicine/painkiller/morphine, /datum/reagent/drug/space_drugs, /datum/reagent/toxin, /datum/reagent/toxin/plasma, diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index aa3d15916aa0..69929561ee18 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -126,6 +126,8 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) var/list/metabolized_traits /// A list of traits to apply while the reagent is in a mob. var/list/added_traits + ///are we able to merge + var/can_merge = TRUE /datum/reagent/New() SHOULD_CALL_PARENT(TRUE) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index da8cf6bf8e26..f7dd0808abba 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -595,7 +595,7 @@ holder.remove_reagent(/datum/reagent/toxin/histamine, 3 * REM * seconds_per_tick) ..() -/datum/reagent/medicine/morphine +/datum/reagent/medicine/painkiller/morphine name = "Morphine" description = "A painkiller that allows the patient to move at full speed even when injured. Causes drowsiness and eventually unconsciousness in high doses. Overdose will cause a variety of effects, ranging from minor to lethal." reagent_state = LIQUID @@ -607,28 +607,20 @@ addiction_types = list(/datum/addiction/opioids = 10) metabolized_traits = list(TRAIT_ANALGESIA) -/datum/reagent/medicine/morphine/on_mob_metabolize(mob/living/affected_mob) +/datum/reagent/medicine/painkiller/morphine/on_mob_metabolize(mob/living/affected_mob) ..() affected_mob.add_movespeed_mod_immunities(type, /datum/movespeed_modifier/damage_slowdown) -/datum/reagent/medicine/morphine/on_mob_end_metabolize(mob/living/affected_mob) +/datum/reagent/medicine/painkiller/morphine/on_mob_end_metabolize(mob/living/affected_mob) affected_mob.remove_movespeed_mod_immunities(type, /datum/movespeed_modifier/damage_slowdown) ..() -/datum/reagent/medicine/morphine/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) +/datum/reagent/medicine/painkiller/morphine/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) if(current_cycle >= 5) affected_mob.add_mood_event("numb", /datum/mood_event/narcotic_medium, name) - switch(current_cycle) - if(11) - to_chat(affected_mob, span_warning("You start to feel tired...") ) - if(12 to 24) - affected_mob.adjust_drowsiness(2 SECONDS * REM * seconds_per_tick) - if(24 to INFINITY) - affected_mob.Sleeping(40 * REM * seconds_per_tick) - . = TRUE ..() -/datum/reagent/medicine/morphine/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired) +/datum/reagent/medicine/painkiller/morphine/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired) if(SPT_PROB(18, seconds_per_tick)) affected_mob.drop_all_held_items() affected_mob.set_dizzy_if_lower(4 SECONDS) diff --git a/code/modules/reagents/chemistry/recipes/drugs.dm b/code/modules/reagents/chemistry/recipes/drugs.dm index b692d22b516e..a60e74c9d044 100644 --- a/code/modules/reagents/chemistry/recipes/drugs.dm +++ b/code/modules/reagents/chemistry/recipes/drugs.dm @@ -5,7 +5,7 @@ /datum/chemical_reaction/krokodil results = list(/datum/reagent/drug/krokodil = 6) - required_reagents = list(/datum/reagent/medicine/diphenhydramine = 1, /datum/reagent/medicine/morphine = 1, /datum/reagent/space_cleaner = 1, /datum/reagent/potassium = 1, /datum/reagent/phosphorus = 1, /datum/reagent/fuel = 1) + required_reagents = list(/datum/reagent/medicine/diphenhydramine = 1, /datum/reagent/medicine/painkiller/morphine = 1, /datum/reagent/space_cleaner = 1, /datum/reagent/potassium = 1, /datum/reagent/phosphorus = 1, /datum/reagent/fuel = 1) mix_message = "The mixture dries into a pale blue powder." required_temp = 380 reaction_tags = REACTION_TAG_EASY | REACTION_TAG_DRUG @@ -84,7 +84,7 @@ /datum/chemical_reaction/aranesp results = list(/datum/reagent/drug/aranesp = 3) - required_reagents = list(/datum/reagent/medicine/epinephrine = 1, /datum/reagent/medicine/atropine = 1, /datum/reagent/medicine/morphine = 1) + required_reagents = list(/datum/reagent/medicine/epinephrine = 1, /datum/reagent/medicine/atropine = 1, /datum/reagent/medicine/painkiller/morphine = 1) reaction_tags = REACTION_TAG_EASY | REACTION_TAG_DRUG | REACTION_TAG_TOXIN | REACTION_TAG_DAMAGING /datum/chemical_reaction/happiness diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm index 8edab30eee11..582f3cf11a5a 100644 --- a/code/modules/reagents/chemistry/recipes/medicine.dm +++ b/code/modules/reagents/chemistry/recipes/medicine.dm @@ -328,7 +328,7 @@ reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_ORGAN /datum/chemical_reaction/medicine/morphine - results = list(/datum/reagent/medicine/morphine = 2) + results = list(/datum/reagent/medicine/painkiller/morphine = 2) required_reagents = list(/datum/reagent/carbon = 2, /datum/reagent/hydrogen = 2, /datum/reagent/consumable/ethanol = 1, /datum/reagent/oxygen = 1) required_temp = 480 reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_OTHER | REACTION_TAG_DRUG diff --git a/code/modules/reagents/chemistry/recipes/toxins.dm b/code/modules/reagents/chemistry/recipes/toxins.dm index 2bc8aa303138..4011a8142b9f 100644 --- a/code/modules/reagents/chemistry/recipes/toxins.dm +++ b/code/modules/reagents/chemistry/recipes/toxins.dm @@ -248,7 +248,7 @@ /datum/chemical_reaction/zombiepowder results = list(/datum/reagent/toxin/zombiepowder = 2) - required_reagents = list(/datum/reagent/toxin/carpotoxin = 5, /datum/reagent/medicine/morphine = 5, /datum/reagent/copper = 5) + required_reagents = list(/datum/reagent/toxin/carpotoxin = 5, /datum/reagent/medicine/painkiller/morphine = 5, /datum/reagent/copper = 5) mix_message = "The mixture turns into a strange green powder." is_cold_recipe = FALSE required_temp = 100 diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 0da5d92aa3c0..c9ef536d8ded 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -346,3 +346,9 @@ filling.color = mix_color_from_reagents(reagents.reagent_list) . += filling + +/obj/item/reagent_containers/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + after_attack_pour(user, target) + +/obj/item/reagent_containers/proc/after_attack_pour(mob/user, atom/target) diff --git a/code/modules/reagents/reagent_containers/cups/_cup.dm b/code/modules/reagents/reagent_containers/cups/_cup.dm index 72ad62edda93..a51fa5bac242 100644 --- a/code/modules/reagents/reagent_containers/cups/_cup.dm +++ b/code/modules/reagents/reagent_containers/cups/_cup.dm @@ -89,6 +89,7 @@ checkLiked(fraction, target_mob) ////playsound(target_mob.loc,'sound/items/drink.ogg', rand(10,50), TRUE) // monkestation edit original playsound(target_mob.loc,get_drink_sound(target_mob), rand(10,50), TRUE) // monkestation edit: synthesized drink sounds + SEND_SIGNAL(target_mob.reagents, COMSIG_DRANK_REAGENT, reagents, gulp_size) if(!iscarbon(target_mob)) return var/mob/living/carbon/carbon_drinker = target_mob @@ -136,6 +137,7 @@ reagents.trans_to(chugger, gulp_size, transfered_by = chugger, methods = INGEST) checkLiked(fraction, chugger) playsound(chugger.loc,get_drink_sound(chugger), rand(10,50), TRUE) + SEND_SIGNAL(chugger.reagents, COMSIG_DRANK_REAGENT, reagents, gulp_size) if(!iscarbon(chugger)) continue var/mob/living/carbon/carbon_drinker = chugger diff --git a/code/modules/reagents/reagent_containers/cups/bottle.dm b/code/modules/reagents/reagent_containers/cups/bottle.dm index 9394124c9d2a..8aeb4118c8a6 100644 --- a/code/modules/reagents/reagent_containers/cups/bottle.dm +++ b/code/modules/reagents/reagent_containers/cups/bottle.dm @@ -41,7 +41,7 @@ name = "morphine bottle" desc = "A small bottle of morphine." icon = 'icons/obj/medical/chemical.dmi' - list_reagents = list(/datum/reagent/medicine/morphine = 30) + list_reagents = list(/datum/reagent/medicine/painkiller/morphine = 30) /obj/item/reagent_containers/cup/bottle/chloralhydrate name = "chloral hydrate bottle" diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index ea56463d1fba..c7f9cf6c65be 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -188,7 +188,7 @@ icon_state = "morphen" inhand_icon_state = "morphen" base_icon_state = "morphen" - list_reagents = list(/datum/reagent/medicine/morphine = 10) + list_reagents = list(/datum/reagent/medicine/painkiller/morphine = 10) /obj/item/reagent_containers/hypospray/medipen/oxandrolone name = "oxandrolone medipen" @@ -245,9 +245,9 @@ icon_state = "stimpen" inhand_icon_state = "stimpen" base_icon_state = "stimpen" - volume = 30 - amount_per_transfer_from_this = 30 - list_reagents = list( /datum/reagent/medicine/epinephrine = 8, /datum/reagent/medicine/c2/aiuri = 8, /datum/reagent/medicine/c2/libital = 8, /datum/reagent/medicine/leporazine = 6) + volume = 35 + amount_per_transfer_from_this = 35 + list_reagents = list( /datum/reagent/medicine/epinephrine = 8, /datum/reagent/medicine/c2/aiuri = 8, /datum/reagent/medicine/c2/libital = 8, /datum/reagent/medicine/leporazine = 6, /datum/reagent/medicine/painkiller/hydromorphone = 5) /obj/item/reagent_containers/hypospray/medipen/survival/inject(mob/living/affected_mob, mob/user) if(lavaland_equipment_pressure_check(get_turf(user))) @@ -272,9 +272,9 @@ icon_state = "luxpen" inhand_icon_state = "atropen" base_icon_state = "luxpen" - volume = 60 - amount_per_transfer_from_this = 60 - list_reagents = list(/datum/reagent/medicine/salbutamol = 10, /datum/reagent/medicine/c2/penthrite = 10, /datum/reagent/medicine/oxandrolone = 10, /datum/reagent/medicine/sal_acid = 10 ,/datum/reagent/medicine/omnizine = 10 ,/datum/reagent/medicine/leporazine = 10) + volume = 70 + amount_per_transfer_from_this = 70 + list_reagents = list(/datum/reagent/medicine/salbutamol = 10, /datum/reagent/medicine/c2/penthrite = 10, /datum/reagent/medicine/oxandrolone = 10, /datum/reagent/medicine/sal_acid = 10 ,/datum/reagent/medicine/omnizine = 10 ,/datum/reagent/medicine/leporazine = 10, /datum/reagent/medicine/painkiller/hydromorphone = 10) /obj/item/reagent_containers/hypospray/medipen/atropine name = "atropine autoinjector" diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index 28d259d6cd8b..85f2baa58a4a 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -110,7 +110,7 @@ name = "morphine pill" desc = "Commonly used to treat insomnia." icon_state = "pill8" - list_reagents = list(/datum/reagent/medicine/morphine = 30) + list_reagents = list(/datum/reagent/medicine/painkiller/morphine = 30) rename_with_volume = TRUE /obj/item/reagent_containers/pill/stimulant diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index c9535ddff580..c4746b9cacfa 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -312,4 +312,4 @@ list_reagents = list(/datum/reagent/toxin/fentanyl = 15) /obj/item/reagent_containers/syringe/contraband/morphine - list_reagents = list(/datum/reagent/medicine/morphine = 15) + list_reagents = list(/datum/reagent/medicine/painkiller/morphine = 15) diff --git a/code/modules/religion/burdened/psyker.dm b/code/modules/religion/burdened/psyker.dm index 4c31e56ac899..e913584081cd 100644 --- a/code/modules/religion/burdened/psyker.dm +++ b/code/modules/religion/burdened/psyker.dm @@ -44,7 +44,7 @@ return new_head_owner.become_blind(limb_id) -/obj/item/bodypart/head/psyker/drop_limb(special, dismembered) +/obj/item/bodypart/head/psyker/drop_limb(special, dismembered, violent) owner.cure_blind(limb_id) return ..() diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index bd68bed5b46c..4a818a53e8dc 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -15,6 +15,11 @@ "basic_micro_laser", "basic_scanning", "blast", + "big_manipulator", + "assembler", + "manipulator_filter", + "manipulator_filter_cargo", + "manipulator_filter_internal", "bodybag", "bounced_radio", "bowl", @@ -63,6 +68,8 @@ "infrared_emitter", "intercom_frame", "kitchen_knife", + "recipe_card", + "bottling_kit", "laptop", "light_bulb", "light_replacer", @@ -1429,6 +1436,9 @@ "borg_upgrade_damagemod", "borg_upgrade_rangemod", "cargoexpress", + "b_smelter", + "b_refinery", + "brm", "cooldownmod", "damagemod", "drill", diff --git a/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm b/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm index f22e6109fb35..97ce1219d682 100644 --- a/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm +++ b/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm @@ -158,7 +158,7 @@ supplementary_reagents = list( /datum/reagent/consumable/honey = 8, //Hunny. /datum/reagent/growthserum = 5, - /datum/reagent/medicine/morphine = 4, //morphine is a vital nutrient for space bears, but it is better as a supplemental for gameplay reasons. + /datum/reagent/medicine/painkiller/morphine = 4, //morphine is a vital nutrient for space bears, but it is better as a supplemental for gameplay reasons. /datum/reagent/consumable/nutriment/vitamin = 3) suppressive_reagents = list( @@ -245,7 +245,7 @@ suppressive_reagents = list( /datum/reagent/consumable/frostoil = -4, /datum/reagent/cryostylane = -4, - /datum/reagent/medicine/morphine = -2, + /datum/reagent/medicine/painkiller/morphine = -2, /datum/reagent/consumable/ice = -2) //Brrr! virus_suspectibility = 0 diff --git a/code/modules/spells/spell_types/touch/scream_for_me.dm b/code/modules/spells/spell_types/touch/scream_for_me.dm index 231b6927e504..f12ab5ce7eff 100644 --- a/code/modules/spells/spell_types/touch/scream_for_me.dm +++ b/code/modules/spells/spell_types/touch/scream_for_me.dm @@ -21,6 +21,7 @@ span_userdanger("The spell bounces from [victim]'s skin back into your arm!"), ) var/obj/item/bodypart/to_wound = caster.get_holding_bodypart_of_item(hand) + victim.cause_pain(BODY_ZONE_EVERYTHING, 50, BRUTE) caster.cause_wound_of_type_and_severity(WOUND_SLASH, to_wound, WOUND_SEVERITY_MODERATE, WOUND_SEVERITY_CRITICAL) /datum/action/cooldown/spell/touch/scream_for_me/cast_on_hand_hit(obj/item/melee/touch_attack/hand, mob/living/victim, mob/living/carbon/caster) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 5e082c0d323e..5178752d63af 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -406,18 +406,27 @@ SHOULD_CALL_PARENT(TRUE) var/atom/drop_loc = drop_location() - if(IS_ORGANIC_LIMB(src)) + if(IS_ORGANIC_LIMB(src) && violent_removal) playsound(drop_loc, 'sound/misc/splort.ogg', 50, TRUE, -1) seep_gauze(9999) // destroy any existing gauze if any exists - for(var/obj/item/organ/bodypart_organ in get_organs()) - bodypart_organ.transfer_to_limb(src, owner) - for(var/obj/item/organ/external/external in external_organs) - external.remove_from_limb() - external.forceMove(drop_loc) + for(var/obj/item/organ/organ as anything in get_organs()) + if(owner) + organ.Remove(owner) + else + organ.remove_from_limb(src) + organ.forceMove(drop_loc) + if(violent_removal) + organ.fly_away(drop_loc) for(var/obj/item/item_in_bodypart in src) item_in_bodypart.forceMove(drop_loc) + if(violent_removal && owner) + item_in_bodypart.transfer_mob_blood_dna(owner) + + if(owner) + owner.update_body() + else + update_icon_dropped() - update_icon_dropped() ///since organs aren't actually stored in the bodypart themselves while attached to a person, we have to query the owner for what we should have /obj/item/bodypart/proc/get_organs() diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 9f4d54e86d61..6991a2bdd46a 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -51,48 +51,27 @@ target_turf = new_turf if(new_turf.density) break - throw_at(target_turf, throw_range, throw_speed) + fly_away(limb_owner.drop_location()) return TRUE /obj/item/bodypart/chest/dismember(dam_type = BRUTE, silent=TRUE, wounding_type) - if(!owner) + if(!owner || (bodypart_flags & BODYPART_UNREMOVABLE)) return FALSE - var/mob/living/carbon/chest_owner = owner - if(bodypart_flags & BODYPART_UNREMOVABLE) + if(owner.status_flags & GODMODE) return FALSE - if(HAS_TRAIT(chest_owner, TRAIT_NODISMEMBER)) + if(HAS_TRAIT(owner, TRAIT_NODISMEMBER)) return FALSE - . = list() - if(wounding_type != WOUND_BURN && isturf(chest_owner.loc) && can_bleed()) - chest_owner.add_splatter_floor(chest_owner.loc) - playsound(get_turf(chest_owner), 'sound/misc/splort.ogg', 80, TRUE) - for(var/obj/item/organ/organ as anything in chest_owner.organs) - var/org_zone = check_zone(organ.zone) - if(org_zone != BODY_ZONE_CHEST) - continue - organ.Remove(chest_owner) - organ.forceMove(chest_owner.loc) - . += organ - - for(var/obj/item/organ/external/ext_organ as anything in src.external_organs) - if(!(ext_organ.organ_flags & ORGAN_UNREMOVABLE)) - ext_organ.Remove(chest_owner) - ext_organ.forceMove(chest_owner.loc) - . += ext_organ + return drop_organs(violent_removal = TRUE) - if(cavity_item) - cavity_item.forceMove(chest_owner.loc) - . += cavity_item - cavity_item = null ///limb removal. The "special" argument is used for swapping a limb with a new one without the effects of losing a limb kicking in. -/obj/item/bodypart/proc/drop_limb(special, dismembered) +/obj/item/bodypart/proc/drop_limb(special, dismembered, violent = FALSE) if(!owner) return var/atom/drop_loc = owner.drop_location() - SEND_SIGNAL(owner, COMSIG_CARBON_REMOVE_LIMB, src, dismembered) + SEND_SIGNAL(owner, COMSIG_CARBON_REMOVE_LIMB, src, dismembered, special) SEND_SIGNAL(src, COMSIG_BODYPART_REMOVED, owner, dismembered) update_limb(dropping_limb = TRUE) //limb is out and about, it can't really be considered an implant @@ -154,7 +133,7 @@ qdel(src) return - if(limb_id == SPECIES_OOZELING) + if((limb_id == SPECIES_OOZELING) && !special) to_chat(phantom_owner, span_warning("Your [src] splatters with an unnerving squelch!")) playsound(phantom_owner, 'sound/effects/blobattack.ogg', 60, TRUE) phantom_owner.blood_volume -= 60 //Makes for 120 when you regenerate it. @@ -246,11 +225,11 @@ head.tongue = src ..() -/obj/item/bodypart/chest/drop_limb(special) +/obj/item/bodypart/chest/drop_limb(special, dismembered, violent) if(special) return ..() -/obj/item/bodypart/arm/drop_limb(special) +/obj/item/bodypart/arm/drop_limb(special, dismembered, violent) var/mob/living/carbon/arm_owner = owner . = ..() @@ -260,7 +239,7 @@ if(arm_owner.hand_bodyparts[held_index] == src) // We only want to do this if the limb being removed is the active hand part. // This catches situations where limbs are "hot-swapped" such as augmentations and roundstart prosthetics. - arm_owner.dropItemToGround(arm_owner.get_item_for_held_index(held_index), 1) + arm_owner.dropItemToGround(arm_owner.get_item_for_held_index(held_index), 1, violent = violent) arm_owner.hand_bodyparts[held_index] = null if(arm_owner.handcuffed) arm_owner.handcuffed.forceMove(drop_location()) @@ -271,10 +250,10 @@ var/atom/movable/screen/inventory/hand/associated_hand = arm_owner.hud_used.hand_slots["[held_index]"] associated_hand?.update_appearance() if(arm_owner.gloves) - arm_owner.dropItemToGround(arm_owner.gloves, TRUE) + arm_owner.dropItemToGround(arm_owner.gloves, TRUE, violent = violent) arm_owner.update_worn_gloves() //to remove the bloody hands overlay -/obj/item/bodypart/leg/drop_limb(special) +/obj/item/bodypart/leg/drop_limb(special, dismembered, violent) if(owner && !special) if(owner.legcuffed) owner.legcuffed.forceMove(owner.drop_location()) //At this point bodypart is still in nullspace @@ -282,14 +261,14 @@ owner.legcuffed = null owner.update_worn_legcuffs() if(owner.shoes) - owner.dropItemToGround(owner.shoes, TRUE) + owner.dropItemToGround(owner.shoes, TRUE, violent = violent) return ..() -/obj/item/bodypart/head/drop_limb(special) +/obj/item/bodypart/head/drop_limb(special, dismembered, violent) if(!special) //Drop all worn head items for(var/obj/item/head_item as anything in list(owner.glasses, owner.ears, owner.wear_mask, owner.head)) - owner.dropItemToGround(head_item, force = TRUE) + owner.dropItemToGround(head_item, force = TRUE, violent = violent) qdel(owner.GetComponent(/datum/component/creamed)) //clean creampie overlay flushed emoji diff --git a/code/modules/unit_tests/mapload_space_verification.dm b/code/modules/unit_tests/mapload_space_verification.dm index 6ff32145efa1..ff93799281e3 100644 --- a/code/modules/unit_tests/mapload_space_verification.dm +++ b/code/modules/unit_tests/mapload_space_verification.dm @@ -25,6 +25,7 @@ /area/station/solars, // magnet area is designed specifically to hold the asteroid /area/station/cargo/mining/asteroid_magnet, + /area/shipbreak, )) // We aren't planetary, so let's check area placements and ensure stuff lines up. diff --git a/code/modules/vending/drinnerware.dm b/code/modules/vending/drinnerware.dm index 6b8d2e75d1a8..2e57c0f53063 100644 --- a/code/modules/vending/drinnerware.dm +++ b/code/modules/vending/drinnerware.dm @@ -9,6 +9,12 @@ "name" = "Kitchen Utensils", "icon" = FA_ICON_KITCHEN_SET, "products" = list( + /obj/item/reagent_containers/cooking_container/deep_basket = 10, + /obj/item/reagent_containers/cooking_container/pan = 10, + /obj/item/reagent_containers/cooking_container/pot = 10, + /obj/item/reagent_containers/cooking_container/bowl = 10, + /obj/item/reagent_containers/cooking_container/oven = 10, + /obj/item/reagent_containers/cooking_container/board = 10, /obj/item/storage/bag/tray = 8, /obj/item/reagent_containers/cup/soup_pot = 3, /obj/item/kitchen/spoon/soup_ladle = 3, diff --git a/icons/effects/blood.dmi b/icons/effects/blood.dmi index 36f30f74f1ff..9bf25b8de2bb 100644 Binary files a/icons/effects/blood.dmi and b/icons/effects/blood.dmi differ diff --git a/icons/obj/weapons/guns/projectiles.dmi b/icons/obj/weapons/guns/projectiles.dmi index 6830a4ac5bdf..4e57ac40c940 100644 Binary files a/icons/obj/weapons/guns/projectiles.dmi and b/icons/obj/weapons/guns/projectiles.dmi differ diff --git a/interface/skin.dmf b/interface/skin.dmf index 9f3d8ccdb7a8..a07ed21500f6 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -10,21 +10,21 @@ macro "default" menu "menu" - elem + elem name = "&File" command = "" saved-params = "is-checked" - elem + elem name = "&Quick screenshot\tF2" command = ".screenshot auto" category = "&File" saved-params = "is-checked" - elem + elem name = "&Save screenshot as...\tShift+F2" command = ".screenshot" category = "&File" saved-params = "is-checked" - elem + elem name = "" command = "" category = "&File" @@ -34,7 +34,7 @@ menu "menu" command = ".reconnect" category = "&File" saved-params = "is-checked" - elem + elem name = "&Quit\tAlt-F4" command = ".quit" category = "&File" @@ -43,22 +43,22 @@ menu "menu" name = "&Help" command = "" saved-params = "is-checked" - elem + elem name = "&Admin Help\tF1" command = "adminhelp" category = "&Help" saved-params = "is-checked" - elem + elem name = "&Hotkeys" command = "Hotkeys-Help" category = "&Help" saved-params = "is-checked" - elem + elem name = "Refresh TGUI" command = "refresh-tgui" category = "&Help" saved-params = "is-checked" - elem + elem name = "Fix Chat" command = "fix-chat" category = "&Help" @@ -277,6 +277,14 @@ window "outputwindow" command = ".winset \"mebutton.is-checked=true ? input.command=\"!me \\\"\" : input.command=\"\"mebutton.is-checked=true ? saybutton.is-checked=false\"\"mebutton.is-checked=true ? oocbutton.is-checked=false\"" is-flat = true button-type = pushbox + elem "mediapanel" + type = BROWSER + pos = 599,460 + size = 1x1 + anchor1 = 100,100 + anchor2 = -1,-1 + is-visible = false + saved-params = "" elem "browseroutput" type = BROWSER pos = 0,0 @@ -350,14 +358,6 @@ window "statwindow" anchor2 = 100,100 is-visible = false saved-params = "" - elem "mediapanel" - type = BROWSER - pos = 392,25 - size = 1x1 - anchor1 = -1,-1 - anchor2 = -1,-1 - is-visible = false - saved-params = "" window "tgui_say" elem "tgui_say" diff --git a/memorystats.dll b/memorystats.dll new file mode 100644 index 000000000000..1d81a2450731 Binary files /dev/null and b/memorystats.dll differ diff --git a/monkestation/code/datums/brain_damage/magic.dm b/monkestation/code/datums/brain_damage/magic.dm index bda553113ebf..2ced19ca79ca 100644 --- a/monkestation/code/datums/brain_damage/magic.dm +++ b/monkestation/code/datums/brain_damage/magic.dm @@ -11,7 +11,8 @@ /datum/brain_trauma/magic/stalker_multiple/Destroy() for (var/stalker in stalkers) - QDEL_NULL(stalker) + stalkers -= stalker + qdel(stalker) return ..() /datum/brain_trauma/magic/stalker_multiple/on_gain() @@ -22,6 +23,7 @@ var/turf/stalker_source = locate(owner.x + pick(-12, 12), owner.y + pick(-12, -6, 0, 6, 12), owner.z) //random corner var/obj/effect/client_image_holder/stalker_phantom/stalker = new(stalker_source, owner) stalkers += stalker + stalker.host = src /datum/brain_trauma/magic/stalker_multiple/proc/create_stalker_multiple(count) var/turf/stalker_source = locate(owner.x + pick(-12, 12), owner.y + pick(-12, -6, 0, 6, 12), owner.z) //random corner @@ -29,10 +31,12 @@ for (var/x = 0; x < count; x++) var/obj/effect/client_image_holder/stalker_phantom/stalker = new(stalker_source, owner) stalkers += stalker + stalker.host = src /datum/brain_trauma/magic/stalker_multiple/on_lose() for (var/stalker in stalkers) - QDEL_NULL(stalker) + stalkers -= stalker + qdel(stalker) return ..() /datum/brain_trauma/magic/stalker_multiple/on_life(seconds_per_tick, times_fired) diff --git a/monkestation/code/datums/patreon_data.dm b/monkestation/code/datums/patreon_data.dm index 1e9e664fa787..c1ee4bc83ed4 100644 --- a/monkestation/code/datums/patreon_data.dm +++ b/monkestation/code/datums/patreon_data.dm @@ -59,7 +59,7 @@ access_rank = ACCESS_COMMAND_RANK if(TRAITOR_RANK) access_rank = ACCESS_TRAITOR_RANK - if(NUKIE_RANK, OLD_NUKIE_RANK) + if(NUKIE_RANK, OLD_NUKIE_RANK, REALLY_ANOTHER_FUCKING_NUKIE_RANK) access_rank = ACCESS_NUKIE_RANK /datum/patreon_data/proc/has_access(rank) @@ -70,6 +70,6 @@ return FALSE /datum/patreon_data/proc/is_donator() - if((owned_rank != NO_RANK) && (owned_rank != UNSUBBED)) - return TRUE - return FALSE + if((owned_rank == NO_RANK) || !owned_rank || (owned_rank == UNSUBBED)) + return FALSE + return TRUE diff --git a/monkestation/code/datums/status_effects/food_buffs.dm b/monkestation/code/datums/status_effects/food_buffs.dm index 16ea5135f204..45f79a5edf3f 100644 --- a/monkestation/code/datums/status_effects/food_buffs.dm +++ b/monkestation/code/datums/status_effects/food_buffs.dm @@ -2,6 +2,7 @@ duration = 10 MINUTES status_type = STATUS_EFFECT_REPLACE show_duration = TRUE + var/quality_modifier = 1 /datum/status_effect/food/on_apply() if(HAS_TRAIT(owner, TRAIT_GOURMAND)) diff --git a/monkestation/code/game/sound.dm b/monkestation/code/game/sound.dm index 54efc47f10d7..3505ea2e567d 100644 --- a/monkestation/code/game/sound.dm +++ b/monkestation/code/game/sound.dm @@ -69,7 +69,7 @@ /datum/ui_module/volume_mixer/proc/set_channel_volume(channel, vol, mob/user) if((channel == CHANNEL_LOBBYMUSIC) || (channel == CHANNEL_MASTER_VOLUME)) if(isnewplayer(user)) - user.client.media.update_volume(0.5 + (vol * 0.05)) + user.client.media.update_volume((vol)) var/sound/S = sound(null, channel = channel, volume = vol) S.status = SOUND_UPDATE diff --git a/monkestation/code/modules/a_ship_in_need_of_breaking/area.dm b/monkestation/code/modules/a_ship_in_need_of_breaking/area.dm new file mode 100644 index 000000000000..e2a2cba4fd74 --- /dev/null +++ b/monkestation/code/modules/a_ship_in_need_of_breaking/area.dm @@ -0,0 +1,4 @@ + +/area/shipbreak + name = "Shipbreak Zone" + icon_state = "escape" diff --git a/monkestation/code/modules/a_ship_in_need_of_breaking/icons/shipbreaking.dmi b/monkestation/code/modules/a_ship_in_need_of_breaking/icons/shipbreaking.dmi new file mode 100644 index 000000000000..93f4b56f0d28 Binary files /dev/null and b/monkestation/code/modules/a_ship_in_need_of_breaking/icons/shipbreaking.dmi differ diff --git a/monkestation/code/modules/a_ship_in_need_of_breaking/machines/console.dm b/monkestation/code/modules/a_ship_in_need_of_breaking/machines/console.dm new file mode 100644 index 000000000000..a4cd775f721f --- /dev/null +++ b/monkestation/code/modules/a_ship_in_need_of_breaking/machines/console.dm @@ -0,0 +1,125 @@ +/obj/machinery/computer/shipbreaker + name = "Shipbreaking Shuttle Console" + desc = "A computer console used to call a ship for breaking, how original!" + icon_screen = "holocontrol" + + + var/turf/bottom_left + +///what area type this holodeck loads into. linked turns into the nearest instance of this area + var/area/mapped_start_area = /area/shipbreak + +///the currently used map template + var/datum/map_template/shipbreaker/template + +///List of ships to spawn. + var/list/possible_ships = list() + +///subtypes of this (but not this itself) are loadable programs + var/ship_type = /datum/map_template/shipbreaker + +///links the shipbreaker zone to the computer + var/area/shipbreak/linked +///cool variablw + var/spawn_area_clear = TRUE + + ///our overall ship health + var/ship_health = 0 + ///our initial turf count + var/turf_count = 0 + +/obj/machinery/computer/shipbreaker/Initialize(mapload) + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/computer/shipbreaker/LateInitialize() + linked = GLOB.areas_by_type[mapped_start_area] + if(!linked) + return + bottom_left = locate(linked.x, linked.y, src.z) + for(var/ship in subtypesof(ship_type)) + var/datum/map_template/shipbreaker/s = new ship + possible_ships+= s + +/obj/machinery/computer/shipbreaker/proc/spawn_ship() + area_clear_check() + if(!spawn_area_clear) + say("ERROR: SHIPBREAKING ZONE NOT CLEAR, PLEASE REMOVE ALL REMAINING SHIP PARTS") + return + var/datum/map_template/shipbreaker/ship_to_spawn = pick(possible_ships) + + ship_to_spawn.load(bottom_left) + + setup_health_tracker() + damage_ship() + +/obj/machinery/computer/shipbreaker/proc/area_clear_check() + for(var/turf/t in linked) + if(!isspaceturf(t)) + spawn_area_clear = FALSE + return + for(var/obj/s in linked) + if(isstructure(s) || ismachinery(s)) + spawn_area_clear = FALSE + return + + spawn_area_clear = TRUE + +/obj/machinery/computer/shipbreaker/proc/clear_floor_plating() + for(var/turf/t in linked) + if(isfloorturf(t)) + t.ScrapeAway() + + +/obj/machinery/computer/shipbreaker/ui_interact(mob/user, datum/tgui/ui) + . = ..() + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ShipbreakerConsole", name) + ui.open() + +/obj/machinery/computer/shipbreaker/ui_data(mob/user) + . = ..() + var/list/data = list() + data["health"] = ship_health + + return data + +/obj/machinery/computer/shipbreaker/ui_act(action, params) + . = ..() + if(.) + return + . = TRUE + + switch(action) + if("spawn_ship") + turf_count = 0 + spawn_ship() + return + if("clear_floor_plating") + clear_floor_plating() + return + +/obj/machinery/computer/shipbreaker/proc/setup_health_tracker() + for(var/turf/turf in linked) + turf_count++ + RegisterSignal(turf, COMSIG_TURF_DESTROY, PROC_REF(modify_health)) + ship_health = 100 + +/obj/machinery/computer/shipbreaker/proc/modify_health(turf/source) + ship_health -= (1 / turf_count) + ship_health = max(ship_health, 0) + + +/obj/machinery/computer/shipbreaker/proc/damage_ship() + var/list/turfs = list() + for(var/turf/turf in linked) + turfs += turf + + var/prob_chance_explode = 100 + if(prob(0)) + prob_chance_explode = 0 + while(prob(prob_chance_explode)) + prob_chance_explode -= 33 + var/turf/picked_turf = pick(turfs) + explosion(picked_turf, rand(0, 4), rand(0, 4), rand(0, 6), 0, 0 , FALSE, FALSE, TRUE, FALSE, linked) diff --git a/monkestation/code/modules/a_ship_in_need_of_breaking/machines/recycler.dm b/monkestation/code/modules/a_ship_in_need_of_breaking/machines/recycler.dm new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/monkestation/code/modules/a_ship_in_need_of_breaking/scrap.dm b/monkestation/code/modules/a_ship_in_need_of_breaking/scrap.dm new file mode 100644 index 000000000000..3d611a949879 --- /dev/null +++ b/monkestation/code/modules/a_ship_in_need_of_breaking/scrap.dm @@ -0,0 +1,78 @@ +/obj/item/proc/get_shipbreaking_reward() + return null + +/obj/item/stock_parts/get_shipbreaking_reward() + if(prob(rating * 10)) //more chance to get better things if you have a higher rating + switch(rand(1,10)) + if(1 to 6) + return /obj/item/stack/scrap/electronics + if(6 to 9) + return /obj/item/stack/scrap/plasma + if(10) + return /obj/item/stack/scrap/crystalline_matrix + return /obj/item/stack/scrap/electronics + +/obj/item/circuitboard/machine/get_shipbreaking_reward() + return /obj/item/stack/scrap/electronics + +/obj/item/stack/scrap + name = "scrap" + singular_name = "scrap" + merge_type = /obj/item/stack/scrap + desc = "get some help if you see this" + icon = 'monkestation/code/modules/a_ship_in_need_of_breaking/icons/shipbreaking.dmi' + icon_state = "ship_plating" + var/point_value = 0 //how many shipbreaking points these give from recycling + +/obj/item/stack/scrap/plating + name = "ship plating" + singular_name = "ship plating" + merge_type = /obj/item/stack/scrap/plating + desc = "Rigid sheet plating used in the construction of ships." + custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT) + point_value = 10 + +/obj/item/stack/scrap/electronics + name = "scrap electronics" + singular_name = "scrap electronic" + merge_type = /obj/item/stack/scrap/electronics + icon_state = "scrap_electronics" + desc = "Piles of scrap electronics crowbarred out of ships. You can't seem to find the gibber board in this mess." + custom_materials = list(/datum/material/glass = SHEET_MATERIAL_AMOUNT, /datum/material/gold = 100) + point_value = 20 + +/obj/item/stack/scrap/framing + name = "ship framing" + singular_name = "ship framing" + merge_type = /obj/item/stack/scrap/framing + icon_state = "ship_framing" + desc = "Silver-Titanium alloy I-beams used in the construction of ships. Whoever designed this must have owned a silver mining planet." + custom_materials = list(/datum/material/silver = SHEET_MATERIAL_AMOUNT, /datum/material/titanium = 100) + point_value = 30 + +/obj/item/stack/scrap/plasma + name = "congealed plasma" + singular_name = "congealed plasma" + merge_type = /obj/item/stack/scrap/plasma + icon_state = "congealed_plasma" + desc = "A nasty bundle of congealed plasma gathered from ship innards. Nice and sticky!" + custom_materials = list(/datum/material/plasma = SHEET_MATERIAL_AMOUNT) + point_value = 50 + +/obj/item/stack/scrap/core + name = "ship core" + singular_name = "ship core" + merge_type = /obj/item/stack/scrap/core + icon_state = "ship_core" + desc = "A radioactive core of a nuclear thruster. Make sure there's no assistants under your ship with a reciprocating saw." + custom_materials = list(/datum/material/uranium = SHEET_MATERIAL_AMOUNT, /datum/material/iron = 100) + point_value = 45 + +/obj/item/stack/scrap/crystalline_matrix + name = "crystalline matrix" + singular_name = "crystalline matrix" + merge_type = /obj/item/stack/scrap/crystalline_matrix + icon_state = "crystalline_matrix" + desc = "A crystalline matrix used in immense calculations to sheer ships. AGI by 2520!" + custom_materials = list(/datum/material/diamond = SHEET_MATERIAL_AMOUNT, /datum/material/bluespace = 100) + point_value = 100 diff --git a/monkestation/code/modules/a_ship_in_need_of_breaking/ship_maps/robotics.dmm b/monkestation/code/modules/a_ship_in_need_of_breaking/ship_maps/robotics.dmm new file mode 100644 index 000000000000..5c6948c25990 --- /dev/null +++ b/monkestation/code/modules/a_ship_in_need_of_breaking/ship_maps/robotics.dmm @@ -0,0 +1,667 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"bo" = ( +/obj/machinery/rnd/production/protolathe/offstation, +/obj/machinery/conveyor{ + dir = 4; + id = "mothership_right" + }, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"bG" = ( +/turf/closed/wall/mineral/titanium, +/area/shipbreak) +"cE" = ( +/obj/machinery/conveyor_switch/oneway{ + id = "mothership_right" + }, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"cH" = ( +/obj/machinery/status_display/ai, +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/shipbreak) +"dk" = ( +/obj/machinery/door/airlock/external/ruin, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/turf/open/floor/plating, +/area/shipbreak) +"dB" = ( +/obj/machinery/power/shuttle_engine/heater, +/obj/structure/window/reinforced/spawner/directional/north{ + layer = 2.9 + }, +/turf/template_noop, +/area/shipbreak) +"ev" = ( +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/shipbreak) +"fi" = ( +/obj/machinery/light/cold/no_nightlight/directional/west, +/obj/machinery/button/door/directional/west{ + id = "mothership_left" + }, +/obj/structure/cable, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"fA" = ( +/obj/item/stack/sheet/mineral/titanium, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/plating/airless, +/area/shipbreak) +"ht" = ( +/obj/structure/lattice, +/obj/item/stack/sheet/mineral/titanium, +/turf/template_noop, +/area/shipbreak) +"hQ" = ( +/obj/structure/spacevine, +/obj/machinery/conveyor{ + id = "mothership_main"; + dir = 10 + }, +/obj/structure/cable, +/turf/open/floor/plating/airless, +/area/shipbreak) +"hZ" = ( +/obj/structure/cable, +/turf/open/floor/plating, +/area/shipbreak) +"ib" = ( +/turf/open/floor/circuit/airless, +/area/shipbreak) +"jp" = ( +/obj/structure/sign/warning/vacuum/external/directional/west, +/obj/structure/closet/emcloset/anchored, +/obj/machinery/light/small/directional/west, +/turf/open/floor/plating, +/area/shipbreak) +"jH" = ( +/obj/machinery/power/shuttle_engine/heater, +/obj/structure/window/reinforced/spawner/directional/north{ + layer = 2.9 + }, +/obj/structure/window/reinforced/spawner/directional/east, +/turf/template_noop, +/area/shipbreak) +"ka" = ( +/obj/structure/lattice, +/turf/template_noop, +/area/shipbreak) +"mj" = ( +/obj/effect/spawner/structure/window/reinforced/shuttle, +/obj/structure/cable, +/turf/open/floor/plating, +/area/shipbreak) +"mC" = ( +/obj/machinery/power/shuttle_engine/propulsion, +/turf/template_noop, +/area/shipbreak) +"nJ" = ( +/obj/item/radio/intercom/directional/south, +/obj/structure/ai_core, +/turf/open/floor/circuit/green/airless, +/area/shipbreak) +"pL" = ( +/obj/machinery/light/small/directional/south, +/obj/machinery/conveyor{ + dir = 8; + id = "mothership_main" + }, +/obj/structure/cable, +/turf/open/floor/plating/airless, +/area/shipbreak) +"qg" = ( +/obj/item/organ/internal/brain, +/obj/structure/cable, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"qN" = ( +/obj/machinery/conveyor/inverted{ + dir = 5; + id = "mothership_main" + }, +/turf/open/floor/plating/airless, +/area/shipbreak) +"rI" = ( +/turf/template_noop, +/area/shipbreak) +"we" = ( +/obj/machinery/power/smes, +/obj/structure/cable, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"wg" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"wB" = ( +/obj/machinery/computer/camera_advanced/shuttle_docker/cyborg_mothership{ + dir = 1 + }, +/turf/open/floor/circuit/green/airless, +/area/shipbreak) +"xg" = ( +/obj/machinery/mineral/stacking_machine{ + input_dir = 2 + }, +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/shipbreak) +"xX" = ( +/obj/machinery/conveyor_switch/oneway{ + id = "mothership_left" + }, +/obj/structure/cable, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"ys" = ( +/obj/machinery/light/cold/no_nightlight/directional/east, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"yL" = ( +/obj/machinery/conveyor/inverted{ + dir = 6; + id = "mothership_main" + }, +/turf/open/floor/plating/airless, +/area/shipbreak) +"zp" = ( +/obj/machinery/space_heater{ + anchored = 1 + }, +/obj/machinery/camera/directional/west, +/obj/item/pipe_dispenser, +/obj/machinery/airalarm/directional/west, +/obj/effect/mapping_helpers/airalarm/all_access, +/obj/item/wrench, +/turf/open/floor/plating, +/area/shipbreak) +"AL" = ( +/obj/machinery/mecha_part_fabricator/maint{ + name = "forgotten exosuit fabricator"; + dir = 8 + }, +/obj/machinery/conveyor{ + dir = 8; + id = "mothership_left" + }, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"AY" = ( +/obj/machinery/computer/shuttle/cyborg_mothership{ + dir = 1 + }, +/turf/open/floor/circuit/green/airless, +/area/shipbreak) +"BI" = ( +/obj/machinery/power/shuttle_engine/heater, +/obj/structure/window/reinforced/spawner/directional/north{ + layer = 2.9 + }, +/obj/structure/window/reinforced/spawner/directional/west, +/turf/template_noop, +/area/shipbreak) +"Cj" = ( +/obj/machinery/door/airlock/hatch, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/turf/open/floor/plating, +/area/shipbreak) +"DF" = ( +/obj/item/stack/rods, +/obj/machinery/light/broken/directional/east, +/obj/machinery/button/door/directional/east{ + id = "mothership_right" + }, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"Ea" = ( +/obj/machinery/recharge_station, +/obj/structure/sign/warning/vacuum/external/directional/east, +/obj/machinery/camera/directional/east, +/turf/open/floor/plating, +/area/shipbreak) +"FK" = ( +/obj/machinery/conveyor{ + id = "Recycler" + }, +/obj/structure/cable, +/turf/open/floor/plating/airless, +/area/shipbreak) +"FL" = ( +/obj/structure/lattice, +/obj/structure/marker_beacon/cerulean, +/turf/template_noop, +/area/shipbreak) +"Ga" = ( +/obj/structure/spacevine, +/obj/machinery/conveyor{ + dir = 1; + id = "mothership_main" + }, +/obj/structure/cable, +/turf/open/floor/plating/airless, +/area/shipbreak) +"Hr" = ( +/obj/item/mmi, +/turf/open/floor/circuit/green/airless, +/area/shipbreak) +"HO" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/power/tracker, +/obj/structure/cable, +/turf/template_noop, +/area/shipbreak) +"Ja" = ( +/obj/structure/girder, +/turf/open/floor/plating/airless, +/area/shipbreak) +"Jk" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/conveyor_switch{ + id = "Recycler"; + name = "Recycler" + }, +/turf/template_noop, +/area/shipbreak) +"Jn" = ( +/obj/item/circuitboard/aicore, +/obj/structure/cable, +/turf/open/floor/circuit/green/airless, +/area/shipbreak) +"Js" = ( +/obj/machinery/holopad/secure, +/obj/structure/cable, +/turf/open/floor/circuit/green/airless, +/area/shipbreak) +"JW" = ( +/obj/structure/cable, +/obj/machinery/power/terminal{ + dir = 4 + }, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"LS" = ( +/obj/item/stack/sheet/rglass{ + amount = 2 + }, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"Mf" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/machinery/door/airlock/external/ruin{ + id_tag = "caravanpirate_bolt_port" + }, +/obj/effect/turf_decal/stripes/asteroid/line, +/turf/open/floor/plating, +/area/shipbreak) +"NY" = ( +/obj/machinery/mineral/ore_redemption{ + input_dir = 4 + }, +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/shipbreak) +"OR" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/camera/directional/north, +/obj/machinery/ore_silo, +/turf/template_noop, +/area/shipbreak) +"Pc" = ( +/obj/machinery/conveyor/inverted{ + dir = 6; + id = "mothership_main" + }, +/obj/structure/cable, +/turf/template_noop, +/area/shipbreak) +"Qd" = ( +/obj/machinery/conveyor{ + dir = 8; + id = "mothership_main" + }, +/turf/template_noop, +/area/shipbreak) +"Qm" = ( +/obj/machinery/conveyor{ + id = "mothership_main"; + dir = 9 + }, +/obj/structure/cable, +/turf/open/floor/plating/airless, +/area/shipbreak) +"RU" = ( +/obj/item/disk/holodisk/ruin/cyborg_mothership, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"Th" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/shipbreak) +"UU" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/conveyor_switch/oneway{ + id = "mothership_main" + }, +/turf/template_noop, +/area/shipbreak) +"Vf" = ( +/obj/machinery/conveyor{ + dir = 8; + id = "mothership_main" + }, +/obj/structure/cable, +/turf/open/floor/plating/airless, +/area/shipbreak) +"VU" = ( +/obj/structure/table, +/obj/item/toy/talking/ai{ + pixel_x = 7; + pixel_y = 10 + }, +/obj/machinery/cell_charger, +/obj/item/stock_parts/cell/high, +/turf/open/floor/circuit/green/airless, +/area/shipbreak) +"VW" = ( +/obj/machinery/camera/directional/south, +/obj/structure/cable, +/obj/machinery/power/apc/auto_name/directional/south{ + environ = 0; + equipment = 0; + lighting = 0 + }, +/obj/effect/mapping_helpers/apc/unlocked, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"Wf" = ( +/obj/machinery/conveyor/inverted{ + dir = 5; + id = "mothership_main" + }, +/obj/structure/cable, +/turf/template_noop, +/area/shipbreak) +"WC" = ( +/obj/structure/cable, +/obj/structure/table_frame, +/obj/item/aicard, +/obj/item/ai_module/core/full/overlord, +/turf/open/floor/circuit/green/airless, +/area/shipbreak) +"WH" = ( +/obj/machinery/conveyor{ + dir = 8; + id = "mothership_main" + }, +/obj/machinery/recycler{ + dir = 1; + eat_dir = 4 + }, +/turf/open/floor/plating/airless, +/area/shipbreak) +"XU" = ( +/obj/structure/spacevine, +/obj/machinery/conveyor{ + id = "mothership_main" + }, +/obj/structure/cable, +/turf/open/floor/plating/airless, +/area/shipbreak) +"Ya" = ( +/obj/machinery/light/small/directional/east, +/obj/machinery/portable_atmospherics/canister/air, +/turf/open/floor/plating, +/area/shipbreak) +"Yj" = ( +/obj/machinery/light/cold/no_nightlight/directional/west, +/turf/open/floor/circuit/airless, +/area/shipbreak) +"ZL" = ( +/obj/machinery/conveyor{ + id = "mothership_main"; + dir = 10 + }, +/obj/structure/cable, +/turf/open/floor/plating/airless, +/area/shipbreak) + +(1,1,1) = {" +rI +rI +rI +ev +ev +ev +ev +ev +ev +ev +ev +ev +rI +Qd +rI +rI +rI +rI +rI +"} +(2,1,1) = {" +rI +rI +ev +ev +rI +rI +rI +rI +rI +rI +rI +rI +ev +Qd +ev +ev +rI +rI +rI +"} +(3,1,1) = {" +ev +ev +bG +rI +ka +bG +ev +AL +ev +ev +bG +ka +rI +Pc +Ga +Qm +dB +mC +rI +"} +(4,1,1) = {" +bG +ev +ev +bG +bG +ev +fi +xX +wg +Yj +ev +bG +rI +rI +xg +Vf +jH +mC +rI +"} +(5,1,1) = {" +cH +jp +ev +zp +cH +LS +Jn +wB +WC +JW +ib +cH +ka +FL +qN +Vf +Qm +jH +mC +"} +(6,1,1) = {" +dk +Th +Mf +hZ +Cj +qg +Js +nJ +ev +we +VW +ev +OR +UU +WH +Jk +pL +mj +HO +"} +(7,1,1) = {" +cH +Ea +ev +Ya +cH +RU +Hr +AY +VU +ib +ib +cH +ka +FL +yL +FK +ZL +BI +mC +"} +(8,1,1) = {" +bG +ev +ev +bG +Ja +fA +DF +cE +ib +ys +ev +bG +rI +rI +NY +Vf +BI +mC +rI +"} +(9,1,1) = {" +ev +ev +bG +rI +ht +fA +ev +bo +ev +ev +bG +ka +rI +Wf +XU +hQ +dB +mC +rI +"} +(10,1,1) = {" +rI +rI +ev +ev +rI +rI +rI +rI +rI +rI +rI +rI +ev +Qd +ev +ev +rI +rI +rI +"} +(11,1,1) = {" +rI +rI +rI +ev +ev +ev +ev +ev +ev +ev +ev +ev +rI +Qd +rI +rI +rI +rI +rI +"} diff --git a/monkestation/code/modules/a_ship_in_need_of_breaking/ships/_base_ship.dm b/monkestation/code/modules/a_ship_in_need_of_breaking/ships/_base_ship.dm new file mode 100644 index 000000000000..d0bb8f483343 --- /dev/null +++ b/monkestation/code/modules/a_ship_in_need_of_breaking/ships/_base_ship.dm @@ -0,0 +1,10 @@ + +/datum/map_template/shipbreaker + should_place_on_top = TRUE + returns_created_atoms = TRUE + keep_cached_map = TRUE + + var/template_id + var/description + var/datum/parsed_map/lastparsed + var/tied_faction = DONK_CO_NAME diff --git a/monkestation/code/modules/a_ship_in_need_of_breaking/ships/robotics.dm b/monkestation/code/modules/a_ship_in_need_of_breaking/ships/robotics.dm new file mode 100644 index 000000000000..3ea3f176c3f3 --- /dev/null +++ b/monkestation/code/modules/a_ship_in_need_of_breaking/ships/robotics.dm @@ -0,0 +1,5 @@ +/datum/map_template/shipbreaker/robotics + name = "Old Robotics Cruiser" + template_id = "robotics" + description = "robotics" + mappath = "monkestation/code/modules/a_ship_in_need_of_breaking/ship_maps/robotics.dmm" diff --git a/monkestation/code/modules/abberant_organs/components/abberant_organ.dm b/monkestation/code/modules/abberant_organs/components/abberant_organ.dm index aa3fa24c65bc..1666f8834fda 100644 --- a/monkestation/code/modules/abberant_organs/components/abberant_organ.dm +++ b/monkestation/code/modules/abberant_organs/components/abberant_organ.dm @@ -49,11 +49,11 @@ host = null SEND_SIGNAL(parent, COMSIG_ABBERANT_HOST_CLEARED) -/datum/component/abberant_organ/proc/trigger() +/datum/component/abberant_organ/proc/trigger(datum/source, trigger_value, list/extra_data) SIGNAL_HANDLER for(var/datum/organ_process/process as anything in processors) - process.trigger(host, stability) - SEND_SIGNAL(parent, COMSIG_ABBERANT_OUTCOME) + process.trigger(host, stability, trigger_value, extra_data) + SEND_SIGNAL(parent, COMSIG_ABBERANT_OUTCOME, trigger_value, extra_data) /datum/component/abberant_organ/proc/add_trait(datum/source, /datum/organ_trait) //TODO diff --git a/monkestation/code/modules/abberant_organs/processes/_base.dm b/monkestation/code/modules/abberant_organs/processes/_base.dm index 801bcfb81d25..d095b155ab6e 100644 --- a/monkestation/code/modules/abberant_organs/processes/_base.dm +++ b/monkestation/code/modules/abberant_organs/processes/_base.dm @@ -5,4 +5,4 @@ var/complexity_cost = 0 var/process_flags = NONE -/datum/organ_process/proc/trigger(datum/weakref/host, stability) +/datum/organ_process/proc/trigger(datum/weakref/host, stability, trigger_value, list/extra_data) diff --git a/monkestation/code/modules/abberant_organs/processes/liver/reagent_conversion.dm b/monkestation/code/modules/abberant_organs/processes/liver/reagent_conversion.dm index 0e470d30f1c7..72e246600b2f 100644 --- a/monkestation/code/modules/abberant_organs/processes/liver/reagent_conversion.dm +++ b/monkestation/code/modules/abberant_organs/processes/liver/reagent_conversion.dm @@ -10,12 +10,18 @@ . = ..() converted_reagent = /datum/reagent/consumable/ethanol -/datum/organ_process/reagent_conversion/trigger(datum/weakref/host, stability) +/datum/organ_process/reagent_conversion/trigger(datum/weakref/host, stability, trigger_value, list/extra_data) if(!host) return var/mob/living/mob = host.resolve() if(!mob.reagents) return - var/volume_to_use = mob.reagents.total_volume * conversion_precent - mob.reagents.remove_all(volume_to_use) + var/volume_to_use = trigger_value * conversion_precent + if(extra_data) + if("reagent" in extra_data) + mob.reagents.remove_all_type(extra_data["reagent"], volume_to_use) + else + mob.reagents.remove_all(volume_to_use) + else + mob.reagents.remove_all(volume_to_use) mob.reagents.add_reagent(converted_reagent, volume_to_use) diff --git a/monkestation/code/modules/abberant_organs/triggers/_base_trigger.dm b/monkestation/code/modules/abberant_organs/triggers/_base_trigger.dm index ea6f12372b8e..8c62623fa96b 100644 --- a/monkestation/code/modules/abberant_organs/triggers/_base_trigger.dm +++ b/monkestation/code/modules/abberant_organs/triggers/_base_trigger.dm @@ -15,11 +15,11 @@ RegisterSignal(parent, COMSIG_ABBERANT_HOST_SET, PROC_REF(set_host)) RegisterSignal(parent, COMSIG_ABBERANT_HOST_CLEARED, PROC_REF(remove_host)) -/datum/organ_trigger/proc/trigger() +/datum/organ_trigger/proc/trigger(trigger_value = 0, list/extra_data) SIGNAL_HANDLER SHOULD_CALL_PARENT(TRUE) - SEND_SIGNAL(parent, COMSIG_ABBERANT_TRIGGER, trigger_cost) + SEND_SIGNAL(parent, COMSIG_ABBERANT_TRIGGER, trigger_value, extra_data) /datum/organ_trigger/proc/set_host(atom/parent, atom/movable/incoming) SIGNAL_HANDLER diff --git a/monkestation/code/modules/abberant_organs/triggers/liver/chemical_consumption.dm b/monkestation/code/modules/abberant_organs/triggers/liver/chemical_consumption.dm index a18fc9767509..fed768e780fe 100644 --- a/monkestation/code/modules/abberant_organs/triggers/liver/chemical_consumption.dm +++ b/monkestation/code/modules/abberant_organs/triggers/liver/chemical_consumption.dm @@ -13,7 +13,7 @@ . = ..() if(!incoming.reagents) return - RegisterSignal(incoming.reagents, COMSIG_REAGENTS_ADD_REAGENT, PROC_REF(check_trigger)) + RegisterSignal(incoming.reagents, COMSIG_DRANK_REAGENT, PROC_REF(check_trigger)) /datum/organ_trigger/chemical_consume/remove_host() var/mob/living/resolved = host.resolve() @@ -21,6 +21,7 @@ UnregisterSignal(resolved.reagents, COMSIG_REAGENTS_ADD_REAGENT) . = ..() -/datum/organ_trigger/chemical_consume/proc/check_trigger(datum/source, datum/reagent/reagent, amount, reagtemp, data, no_react) - if(reagent.type == consumed_chemical) - trigger() +/datum/organ_trigger/chemical_consume/proc/check_trigger(datum/source, datum/reagents/reagent, amount) + for(var/datum/reagent/listed as anything in reagent.reagent_list) + if(listed.type == consumed_chemical) + trigger(amount / length(reagent.reagent_list), list("reagent" = consumed_chemical)) diff --git a/monkestation/code/modules/antagonists/borers/code/mobs/cortical_borer.dm b/monkestation/code/modules/antagonists/borers/code/mobs/cortical_borer.dm index 2b907b0f6e2f..b3d5b2cbc666 100644 --- a/monkestation/code/modules/antagonists/borers/code/mobs/cortical_borer.dm +++ b/monkestation/code/modules/antagonists/borers/code/mobs/cortical_borer.dm @@ -122,7 +122,7 @@ GLOBAL_LIST_INIT(borer_second_name, world.file2list("monkestation/code/modules/a /datum/reagent/medicine/haloperidol, /datum/reagent/medicine/inacusiate, /datum/reagent/medicine/mannitol, - /datum/reagent/medicine/morphine, + /datum/reagent/medicine/painkiller/morphine, /datum/reagent/medicine/mutadone, /datum/reagent/medicine/oculine, /datum/reagent/medicine/potass_iodide, diff --git a/monkestation/code/modules/antagonists/slasher/abilities/incorporealize.dm b/monkestation/code/modules/antagonists/slasher/abilities/incorporealize.dm deleted file mode 100644 index 1fa4f0e73c56..000000000000 --- a/monkestation/code/modules/antagonists/slasher/abilities/incorporealize.dm +++ /dev/null @@ -1,148 +0,0 @@ -/datum/action/cooldown/slasher/incorporealize - name = "Incorporealize" - desc = "Become incorporeal, capable of moving through walls and being completely invisible, but unable to interact with the world. Can only be used when corporeal and when not in view of any human being." - button_icon_state = "incorporealize" - cooldown_time = 20 SECONDS - - var/jaunt_type = /obj/effect/dummy/phased_mob - -/datum/action/cooldown/slasher/incorporealize/Activate(atom/target) - var/datum/antagonist/slasher/slasherdatum = owner.mind.has_antag_datum(/datum/antagonist/slasher) - var/area/owner_area = get_area(owner) - var/turf/owner_turf = get_turf(owner) - - /** - * Here we start our checks - * We cant do it in PreActivate() since that for some reason does not work - */ - - // Standard jaunt checks - - if(!owner_area || !owner_turf) - return // nullspaced? - - if(owner_area.area_flags & NOTELEPORT) - to_chat(owner, span_danger("Some dull, universal force is stopping you from going incorporeal here.")) - return - - if(owner_turf?.turf_flags & NOJAUNT) - to_chat(owner, span_danger("An otherwordly force is preventing you from going incorporeal here.")) - return - - // Unique slasher checks - - if(!slasherdatum) - to_chat(owner, span_warning("You should not have this ability or your slasher antagonist datum was deleted, please contact coders")) - return - - if(slasherdatum.soul_punishment >= 2) - to_chat(owner, span_boldwarning("The souls you have stolen are preventing you from going incorporeal!")) - return - - for(var/mob/living/watcher in viewers(9, target)) - if(watcher == target) - continue - - if(!watcher.mind) //only mobs with minds stop you from jaunting - continue - - if(isdead(watcher)) - continue - - if(isaicamera(watcher)) - var/mob/camera/ai_eye/ai_eye = watcher - var/mob/living/silicon/ai/true_ai = ai_eye.ai - true_ai.disconnect_shell() // should never happen, lets try it anyway - true_ai.view_core() - to_chat(true_ai, span_warning("UNEXPECTED ENERGY SURGE -- RETURNING TO THE CORE")) - do_sparks(3, FALSE, true_ai) - true_ai.adjustBruteLoss(30) // same as a light explosion, to dis-encurage the AI always watching the slasher and telling their location - continue - - target.balloon_alert(owner, "you can only vanish unseen.") - return - - . = ..() - - if(is_jaunting(target)) - . = exit_jaunt(target) - else - . = enter_jaunt(target) - -/datum/action/cooldown/slasher/incorporealize/proc/enter_jaunt(mob/living/jaunter) - var/datum/antagonist/slasher/slasherdatum = owner.mind.has_antag_datum(/datum/antagonist/slasher) - - update_the_button(jaunter) - - animate(jaunter, alpha = 0, time = 1.5 SECONDS) - SLEEP_CHECK_DEATH(1.5 SECONDS, src) - - var/obj/effect/dummy/phased_mob/jaunt = new jaunt_type(get_turf(jaunter), jaunter) - - RegisterSignal(jaunt, COMSIG_MOB_EJECTED_FROM_JAUNT, PROC_REF(on_jaunt_exited)) - jaunter.add_traits(list(TRAIT_MAGICALLY_PHASED, TRAIT_RUNECHAT_HIDDEN), REF(src)) - jaunter.drop_all_held_items() - ADD_TRAIT(jaunter, TRAIT_NO_TRANSFORM, INNATE_TRAIT) - - // Give them some bloody hands to prevent them from doing things - var/obj/item/bloodcrawl/left_hand = new(jaunter) - var/obj/item/bloodcrawl/right_hand = new(jaunter) - left_hand.icon_state = "bloodhand_right" // Icons swapped intentionally.. - right_hand.icon_state = "bloodhand_left" // ..because perspective, or something - jaunter.put_in_hands(left_hand) - jaunter.put_in_hands(right_hand) - - // Make sure they wont be burning for 20 seconds - jaunter.extinguish_mob() - REMOVE_TRAIT(jaunter, TRAIT_NO_TRANSFORM, INNATE_TRAIT) - - slasherdatum.corporeal = FALSE - ADD_TRAIT(jaunter, TRAIT_NOBREATH, REF(src)) - - // This needs to happen at the end, after all the traits and stuff is handled - SEND_SIGNAL(jaunter, COMSIG_MOB_ENTER_JAUNT, src, jaunt) - return jaunt - -/datum/action/cooldown/slasher/incorporealize/proc/exit_jaunt(mob/living/unjaunter) - var/datum/antagonist/slasher/slasherdatum = owner.mind.has_antag_datum(/datum/antagonist/slasher) - var/obj/effect/dummy/phased_mob/jaunt = unjaunter.loc - - update_the_button(unjaunter) - - jaunt.eject_jaunter() - - animate(unjaunter, alpha = 255, time = 1.5 SECONDS) - SLEEP_CHECK_DEATH(1.5 SECONDS, src) - - for(var/obj/item/bloodcrawl/blood_hand in unjaunter.held_items) - unjaunter.temporarilyRemoveItemFromInventory(blood_hand, force = TRUE) - qdel(blood_hand) - - slasherdatum.corporeal = TRUE - REMOVE_TRAIT(unjaunter, TRAIT_NOBREATH, REF(src)) - - return TRUE - -/datum/action/cooldown/slasher/incorporealize/proc/update_the_button(atom/target) - if(is_jaunting(target)) - name = "Incorporealize" - desc = "Become incorporeal, capable of moving through walls and being completely invisible, but unable to interact with the world. Can only be used when corporeal and when not in view of any human being. " - button_icon_state = "incorporealize" - else - name = "Corporealize" - desc = "Manifest your being from your incorporeal state." - button_icon_state = "corporealize" - build_all_button_icons(UPDATE_BUTTON_NAME|UPDATE_BUTTON_ICON) - -/datum/action/cooldown/slasher/incorporealize/proc/on_jaunt_exited(obj/effect/dummy/phased_mob/jaunt, mob/living/unjaunter) - unjaunter.remove_traits(list(TRAIT_MAGICALLY_PHASED, TRAIT_RUNECHAT_HIDDEN), REF(src)) - // This needs to happen at the end, after all the traits and stuff is handled - SEND_SIGNAL(unjaunter, COMSIG_MOB_AFTER_EXIT_JAUNT, src) - -/datum/action/cooldown/slasher/incorporealize/Remove(mob/living/remove_from) - exit_jaunt(remove_from) - if(!is_jaunting(remove_from)) // In case you have made exit_jaunt conditional, as in mirror walk - return ..() - var/obj/effect/dummy/phased_mob/jaunt = remove_from.loc - jaunt.eject_jaunter() - return ..() diff --git a/monkestation/code/modules/antagonists/slasher/slasher_datum.dm b/monkestation/code/modules/antagonists/slasher/slasher_datum.dm deleted file mode 100644 index ca39a5a59a85..000000000000 --- a/monkestation/code/modules/antagonists/slasher/slasher_datum.dm +++ /dev/null @@ -1,168 +0,0 @@ -/datum/outfit/slasher - name = "Slasher Outfit" - suit = /obj/item/clothing/suit/apron/slasher - uniform = /obj/item/clothing/under/color/random/slasher - shoes = /obj/item/clothing/shoes/slasher_shoes - mask = /obj/item/clothing/mask/gas/slasher - -/datum/antagonist/slasher - name = "\improper Slasher" - show_in_antagpanel = TRUE - roundend_category = "slashers" - antagpanel_category = "Slasher" - job_rank = ROLE_SLASHER - antag_hud_name = "slasher" - show_name_in_check_antagonists = TRUE - hud_icon = 'monkestation/icons/mob/slasher.dmi' - preview_outfit = /datum/outfit/slasher - show_to_ghosts = TRUE - - ///the linked machette that the slasher can summon even if destroyed and is unique to them - var/obj/item/slasher_machette/linked_machette - ///toggles false/true if we are visible in order to breathe out or in - var/breath_out = FALSE - ///rallys the amount of souls effects are based on this - var/souls_sucked = 0 - ///when we sucked our last soul in world time - var/last_soul_sucked = 0 - ///cooldown we should have for soul sucking without downside - var/soul_digestion = 5 MINUTES - ///our current soul punishment state - var/soul_punishment = 0 - ///our cached brute_mod - var/cached_brute_mod = 0 - ///processes to heartbeat - var/heartbeat_processes = 0 - ///processes until wail if above punishment threshold - var/wailing_processes = 0 - ///our breath processes - var/breath_processes = 0 - ///list of mobs that have been given a overlay so we can remove later - var/list/mobs_with_fullscreens = list() - ///this is needed because it double fires sometimes before finishing - var/is_hudchecking = FALSE - /// the mob we are stalking - var/mob/living/carbon/human/stalked_human - /// how close we are in % to finishing stalking - var/stalk_precent = 0 - /// are we corporeal - var/corporeal = TRUE - ///ALL Powers currently owned - var/list/datum/action/cooldown/slasher/powers = list() - -/datum/antagonist/slasher/apply_innate_effects(mob/living/mob_override) - . = ..() - var/mob/living/current_mob = mob_override || owner.current - - ADD_TRAIT(current_mob, TRAIT_BATON_RESISTANCE, "slasher") - ADD_TRAIT(current_mob, TRAIT_CLUMSY, "slasher") - ADD_TRAIT(current_mob, TRAIT_DUMB, "slasher") - ADD_TRAIT(current_mob, TRAIT_NODEATH, "slasher") - ADD_TRAIT(current_mob, TRAIT_LIMBATTACHMENT, "slasher") - - var/mob/living/carbon/carbon = current_mob - var/obj/item/organ/internal/eyes/shadow/shadow = new - shadow.Insert(carbon, drop_if_replaced = FALSE) - - RegisterSignal(current_mob, COMSIG_LIVING_LIFE, PROC_REF(LifeTick)) - - ///abilities galore - for(var/datum/action/cooldown/slasher/listed_slasher as anything in subtypesof(/datum/action/cooldown/slasher)) - var/datum/action/cooldown/slasher/new_ability = new listed_slasher - new_ability.Grant(current_mob) - powers |= new_ability - - var/mob/living/carbon/human/human = current_mob - if(istype(human)) - human.equipOutfit(/datum/outfit/slasher) - cached_brute_mod = human.dna.species.brutemod - - -/datum/antagonist/slasher/on_removal() - . = ..() - owner.current.remove_traits(list(TRAIT_BATON_RESISTANCE, TRAIT_CLUMSY, TRAIT_NODEATH, TRAIT_DUMB, TRAIT_LIMBATTACHMENT), "slasher") - for(var/datum/action/cooldown/slasher/listed_slasher as anything in powers) - listed_slasher.Remove(owner.current) - -/datum/antagonist/slasher/proc/LifeTick(mob/living/source, seconds_per_tick, times_fired) - if(corporeal) - breath_processes++ - if(breath_processes >= 2) - breath_processes = 0 - if(breath_out) - source.emote("exhale") - breath_out = FALSE - else - source.emote("inhale") - breath_out = TRUE - - heartbeat_processes++ - if(heartbeat_processes >= 4) - heartbeat_processes = 0 - for(var/mob/living/carbon/human in view(7, source)) - if(human == source) - continue - human.playsound_local(human, 'sound/health/slowbeat.ogg', 40, FALSE, channel = CHANNEL_HEARTBEAT, use_reverb = FALSE) - - if(stalked_human) - for(var/mob/living/carbon/human in view(7, source)) - if(stalked_human != human) - continue - if(stalked_human.stat == DEAD) - failed_stalking() - stalk_precent += (1 / 1.8) - if(stalk_precent >= 100) - finish_stalking() - - if(!is_hudchecking) - is_hudchecking = TRUE - var/list/starting_humans = list() - starting_humans += mobs_with_fullscreens - for(var/mob/living/carbon/human in view(7, source)) - if(!(human in mobs_with_fullscreens)) - mobs_with_fullscreens += human - human.overlay_fullscreen("slasher_prox", /atom/movable/screen/fullscreen/nearby, 1) - else - starting_humans -= human - - if(length(starting_humans)) - for(var/mob/living/carbon/human in starting_humans) - human.clear_fullscreen("slasher_prox", 15) - mobs_with_fullscreens -= human - is_hudchecking = FALSE - - for(var/obj/machinery/light/listed_light in view(3, source)) - if(prob(10)) - listed_light.break_light_tube() - - var/turf/TT = get_turf(source) - var/turf/T = pick(RANGE_TURFS(4,TT)) - - if(prob(5)) - new /obj/effect/gibspawner/generic(T) - - if(soul_punishment >= 2) - wailing_processes++ - if(wailing_processes >= 8) - wailing_processes = 0 - playsound(owner.current, 'monkestation/sound/voice/terror-cry.ogg', 50, falloff_exponent = 0, use_reverb = FALSE) - owner.current.emote("wails") - var/mob/living/carbon/human/human = owner.current - human.blood_volume -= 10 - var/turf/turf = get_turf(human) - var/list/blood_drop = list(human.get_blood_id() = 10) - turf.add_liquid_list(blood_drop, FALSE, 300) - -/datum/antagonist/slasher/proc/finish_stalking() - to_chat(owner, span_boldwarning("You have finished spooking your victim, and have harvested part of their soul!")) - if(linked_machette) - linked_machette.force += 2.5 - linked_machette.throwforce += 2.5 - stalked_human = null - -/datum/antagonist/slasher/proc/failed_stalking() - to_chat(owner, span_boldwarning("You let your victim be taken before it was time!")) - if(linked_machette) - linked_machette.force -= 5 - linked_machette.throwforce -= 5 - stalked_human = null diff --git a/monkestation/code/modules/antagonists/slasher/slasher_outfit/slasher_footwear.dm b/monkestation/code/modules/antagonists/slasher/slasher_outfit/slasher_footwear.dm deleted file mode 100644 index 854969079328..000000000000 --- a/monkestation/code/modules/antagonists/slasher/slasher_outfit/slasher_footwear.dm +++ /dev/null @@ -1,10 +0,0 @@ -/obj/item/clothing/shoes/slasher_shoes - name = "Industrial Boots" - icon_state = "jackboots" - inhand_icon_state = "jackboots" - clothing_traits = list(TRAIT_NO_SLIP_ALL) - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - -/obj/item/clothing/shoes/slasher_shoes/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, "slasher") diff --git a/monkestation/code/modules/antagonists/slasher/slasher_outfit/slasher_headgear.dm b/monkestation/code/modules/antagonists/slasher/slasher_outfit/slasher_headgear.dm deleted file mode 100644 index 790d0f430f64..000000000000 --- a/monkestation/code/modules/antagonists/slasher/slasher_outfit/slasher_headgear.dm +++ /dev/null @@ -1,17 +0,0 @@ -/obj/item/clothing/mask/gas/slasher - name = "slasher's gas mask" - desc = "A close-fitting sealed gas mask, this one seems to be protruding some kind of dark aura." - - icon = 'icons/obj/clothing/head/utility.dmi' - worn_icon = 'icons/mob/clothing/head/utility.dmi' - icon_state = "welding" - inhand_icon_state = "welding" - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - slowdown = 1 - -/obj/item/clothing/mask/gas/slasher/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, "slasher") - -/obj/item/clothing/mask/gas/slasher/adjustmask() - return diff --git a/monkestation/code/modules/antagonists/slasher/slasher_outfit/slasher_middlewear.dm b/monkestation/code/modules/antagonists/slasher/slasher_outfit/slasher_middlewear.dm deleted file mode 100644 index 54e41adb4d2d..000000000000 --- a/monkestation/code/modules/antagonists/slasher/slasher_outfit/slasher_middlewear.dm +++ /dev/null @@ -1,17 +0,0 @@ -/obj/item/clothing/suit/apron/slasher - name = "butcher's apron" - desc = "A brown butcher's apron, you can feel an aura of something dark radiating off of it." - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - - icon_state = "slasher" - inhand_icon_state = null - -/obj/item/clothing/suit/apron/slasher/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, "slasher") - -/obj/item/clothing/under/color/random/slasher - name = "butcher's jumpsuit" - clothing_traits = list(TRAIT_NODROP) - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - diff --git a/monkestation/code/modules/antagonists/slasher/slasher_punishment.dm b/monkestation/code/modules/antagonists/slasher/slasher_punishment.dm deleted file mode 100644 index 5a7049729e69..000000000000 --- a/monkestation/code/modules/antagonists/slasher/slasher_punishment.dm +++ /dev/null @@ -1,8 +0,0 @@ -/datum/antagonist/slasher/proc/check_soul_punishment() - if(last_soul_sucked + soul_digestion < world.time) - return - soul_punishment++ - addtimer(CALLBACK(src, PROC_REF(remove_punishment_layer)), 5 MINUTES) - -/datum/antagonist/slasher/proc/remove_punishment_layer() - soul_punishment-- diff --git a/monkestation/code/modules/assault_ops/code/assault_op_vendor.dm b/monkestation/code/modules/assault_ops/code/assault_op_vendor.dm index 10b37fa61dc6..2b9d3c9e9dd0 100644 --- a/monkestation/code/modules/assault_ops/code/assault_op_vendor.dm +++ b/monkestation/code/modules/assault_ops/code/assault_op_vendor.dm @@ -10,6 +10,8 @@ /obj/item/armament_points_card/assaultops points = 50 + armament_type = /datum/armament_entry/assault_operatives + access = list(ACCESS_SYNDICATE) // ARMAMENT ENTRIES diff --git a/monkestation/code/modules/blood_for_the_blood_gods/fly_away.dm b/monkestation/code/modules/blood_for_the_blood_gods/fly_away.dm new file mode 100644 index 000000000000..f9d4a5678eda --- /dev/null +++ b/monkestation/code/modules/blood_for_the_blood_gods/fly_away.dm @@ -0,0 +1,50 @@ +/// Called on drop_organs for the organ to "fly away" using movable physics +/obj/item/organ/proc/fly_away(turf/open/owner_location, fly_angle = rand(0, 360), horizontal_multiplier = 1, vertical_multiplier = 1) + if(!istype(owner_location)) + return + return AddComponent(/datum/component/movable_physics, \ + physics_flags = MPHYSICS_QDEL_WHEN_NO_MOVEMENT, \ + angle = fly_angle, \ + horizontal_velocity = rand(2.5 * 100, 6 * 100) * horizontal_multiplier * 0.01, \ + vertical_velocity = rand(4 * 100, 4.5 * 100) * vertical_multiplier * 0.01, \ + horizontal_friction = rand(0.24 * 100, 0.3 * 100) * 0.01, \ + vertical_friction = 10 * 0.05, \ + horizontal_conservation_of_momentum = 0.5, \ + vertical_conservation_of_momentum = 0.5, \ + z_floor = 0, \ +) + +/// Proc called to initialize movable physics when a bodypart gets dismembered +/obj/item/bodypart/proc/fly_away(turf/open/owner_location, fly_angle = rand(0, 360), horizontal_multiplier = 1, vertical_multiplier = 1) + if(!istype(owner_location)) + return + pixel_x = -px_x + pixel_y = -px_y + forceMove(owner_location) + return AddComponent(/datum/component/movable_physics, \ + physics_flags = MPHYSICS_QDEL_WHEN_NO_MOVEMENT, \ + angle = fly_angle, \ + horizontal_velocity = rand(2.5 * 100, 6 * 100) * horizontal_multiplier * 0.01, \ + vertical_velocity = rand(4 * 100, 4.5 * 100) * vertical_multiplier * 0.01, \ + horizontal_friction = rand(0.24 * 100, 0.3 * 100) * 0.01, \ + vertical_friction = 10 * 0.05, \ + horizontal_conservation_of_momentum = 0.5, \ + vertical_conservation_of_momentum = 0.5, \ + z_floor = 0, \ + ) + +/obj/item/proc/launch_item(turf/open/owner_location, fly_angle = rand(0, 360), horizontal_multiplier = 1, vertical_multiplier = 1) + if(!istype(owner_location)) + return + forceMove(owner_location) + return AddComponent(/datum/component/movable_physics, \ + physics_flags = MPHYSICS_QDEL_WHEN_NO_MOVEMENT, \ + angle = fly_angle, \ + horizontal_velocity = rand(2.5 * 100, 6 * 100) * horizontal_multiplier * 0.01, \ + vertical_velocity = rand(4 * 100, 4.5 * 100) * vertical_multiplier * 0.01, \ + horizontal_friction = rand(0.24 * 100, 0.3 * 100) * 0.01, \ + vertical_friction = 10 * 0.05, \ + horizontal_conservation_of_momentum = 0.5, \ + vertical_conservation_of_momentum = 0.5, \ + z_floor = 0, \ + ) diff --git a/monkestation/code/modules/blood_for_the_blood_gods/icons/slasher_ui.dmi b/monkestation/code/modules/blood_for_the_blood_gods/icons/slasher_ui.dmi new file mode 100644 index 000000000000..4cd55f751e65 Binary files /dev/null and b/monkestation/code/modules/blood_for_the_blood_gods/icons/slasher_ui.dmi differ diff --git a/monkestation/code/modules/blood_for_the_blood_gods/particle.dm b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm new file mode 100644 index 000000000000..a74415bfeb8a --- /dev/null +++ b/monkestation/code/modules/blood_for_the_blood_gods/particle.dm @@ -0,0 +1,158 @@ +/// Blood drip subtype meant to be thrown around as a particle +/obj/effect/decal/cleanable/blood/particle + name = "blood droplet" + icon_state = "drip5" //using drip5 since the others tend to blend in with pipes & wires. + random_icon_states = list("drip1","drip2","drip3","drip4","drip5") + plane = GAME_PLANE + layer = BELOW_MOB_LAYER + should_dry = FALSE + bloodiness = BLOOD_AMOUNT_PER_DECAL * 0.2 + mergeable_decal = FALSE + /// Splatter type we create when we bounce on the floor + var/obj/effect/decal/cleanable/splatter_type_floor = /obj/effect/decal/cleanable/blood/splatter/stacking + /// Splatter type we create when we bump on a wall + var/obj/effect/decal/cleanable/splatter_type_wall = /obj/effect/decal/cleanable/blood/splatter/over_window + /// Whether or not we transfer our pixel_x and pixel_y to the splatter, only works for floor splatters though + var/messy_splatter = TRUE + +/obj/effect/decal/cleanable/blood/particle/can_bloodcrawl_in() + return FALSE + +/obj/effect/decal/cleanable/blood/particle/proc/start_movement(movement_angle) + var/datum/component/movable_physics/movable_physics = GetComponent(/datum/component/movable_physics) + if(!movable_physics) + movable_physics = initialize_physics() + if(!isnull(movement_angle)) + movable_physics.set_angle(movement_angle) + +/obj/effect/decal/cleanable/blood/particle/proc/initialize_physics() + return AddComponent(/datum/component/movable_physics, \ + horizontal_velocity = rand(3 * 100, 5.5 * 100) * 0.01, \ + vertical_velocity = rand(4 * 100, 4.5 * 100) * 0.01, \ + horizontal_friction = rand(0.05 * 100, 0.1 * 100) * 0.01, \ + vertical_friction = 10 * 0.05, \ + vertical_conservation_of_momentum = 0.1, \ + z_floor = 0, \ + bounce_callback = CALLBACK(src, PROC_REF(on_bounce)), \ + bump_callback = CALLBACK(src, PROC_REF(on_bump)), \ + ) + +/obj/effect/decal/cleanable/blood/particle/proc/on_bounce() + if(!isturf(loc) || !splatter_type_floor) + qdel(src) + return + var/obj/effect/decal/cleanable/splatter + if(!ispath(splatter_type_floor, /obj/effect/decal/cleanable/blood/splatter/stacking)) + splatter = new splatter_type_floor(loc) + if(messy_splatter) + splatter.pixel_x = src.pixel_x + splatter.pixel_y = src.pixel_y + else + var/obj/effect/decal/cleanable/blood/splatter/stacking/stacker = locate(splatter_type_floor) in loc + if(!stacker) + stacker = new splatter_type_floor(loc) + if(messy_splatter && length(stacker.splat_overlays)) + var/mutable_appearance/existing_appearance = stacker.splat_overlays[1] + existing_appearance.pixel_x = src.pixel_x + existing_appearance.pixel_y = src.pixel_y + stacker.bloodiness = src.bloodiness + stacker.update_appearance(UPDATE_ICON) + else + var/obj/effect/decal/cleanable/blood/splatter/stacking/other_splatter = new splatter_type_floor() + if(messy_splatter && length(other_splatter.splat_overlays)) + var/mutable_appearance/existing_appearance = other_splatter.splat_overlays[1] + existing_appearance.pixel_x = src.pixel_x + existing_appearance.pixel_y = src.pixel_y + other_splatter.bloodiness = src.bloodiness + other_splatter.handle_merge_decal(stacker) + qdel(other_splatter) + splatter = stacker + var/list/blood_dna = GET_ATOM_BLOOD_DNA(src) + if(blood_dna) + splatter.add_blood_DNA(blood_dna) + qdel(src) + +/obj/effect/decal/cleanable/blood/particle/proc/on_bump(atom/bumped_atom) + if(!isturf(loc) || !splatter_type_wall) + return + if(iswallturf(bumped_atom)) + //Adjust pixel offset to make splatters appear on the wall + var/obj/effect/decal/cleanable/blood/splatter/over_window/final_splatter = new splatter_type_wall(loc) + var/dir_to_wall = get_dir(src, bumped_atom) + final_splatter.pixel_x = (dir_to_wall & EAST ? world.icon_size : (dir_to_wall & WEST ? -world.icon_size : 0)) + final_splatter.pixel_y = (dir_to_wall & NORTH ? world.icon_size : (dir_to_wall & SOUTH ? -world.icon_size : 0)) + var/list/blood_dna = GET_ATOM_BLOOD_DNA(src) + if(blood_dna) + final_splatter.add_blood_DNA(blood_dna) + qdel(src) + else if(istype(bumped_atom, /obj/structure/window)) + var/obj/structure/window/the_window = bumped_atom + if(!the_window.fulltile) + return + if(the_window.bloodied) + qdel(src) + return + var/obj/effect/decal/cleanable/blood/splatter/over_window/final_splatter = new splatter_type_wall() + final_splatter.forceMove(the_window) + the_window.vis_contents += final_splatter + the_window.bloodied = TRUE + qdel(src) + +/// subtype of splatter capable of doing proper "stacking" behavior +/obj/effect/decal/cleanable/blood/splatter/stacking + /// Maximum amount of blood overlays we can have visually + var/maximum_splats = 50 + /// Listing containing overlays of all the splatters we've merged with + var/list/splat_overlays = list() + +/obj/effect/decal/cleanable/blood/splatter/stacking/Initialize(mapload) + . = ..() + var/mutable_appearance/our_appearance = mutable_appearance(src.icon, src.icon_state) + our_appearance.color = src.color + our_appearance.pixel_x = src.pixel_x + our_appearance.pixel_y = src.pixel_y + icon_state = null + color = null + pixel_x = 0 + pixel_y = 0 + splat_overlays += our_appearance + update_appearance(UPDATE_ICON) + +/obj/effect/decal/cleanable/blood/splatter/stacking/Destroy() + . = ..() + splat_overlays = null + +/obj/effect/decal/cleanable/blood/splatter/stacking/update_overlays() + . = ..() + var/splat_length = length(splat_overlays) + if(splat_length > maximum_splats) + splat_overlays = splat_overlays.Splice(splat_length - maximum_splats, splat_length) + . += splat_overlays + +/obj/effect/decal/cleanable/blood/splatter/stacking/handle_merge_decal(obj/effect/decal/cleanable/blood/splatter/stacking/merger) + . = ..() + merger.splat_overlays |= splat_overlays + merger.update_appearance(UPDATE_ICON) + +/obj/effect/decal/cleanable/blood/line + name = "blood line" + desc = "Raining blood, from a lacerated sky, bleeding its horror!" + icon_state = "line" + random_icon_states = null + dryname = "dried blood line" + drydesc = "Creating my structure - Now I shall reign in blood!" + +/obj/effect/decal/cleanable/blood/line/Initialize(mapload, direction) + if(!isnull(direction)) + //has to be done before we call replace_decal() + setDir(direction) + return ..() + +/obj/effect/decal/cleanable/blood/line/replace_decal(obj/effect/decal/cleanable/merger) + . = ..() + if(!.) + return + //squirts of the same dir are redundant, but not if they're different + if(merger.dir != src.dir) + return FALSE + diff --git a/monkestation/code/modules/antagonists/slasher/__base_slasher_additions.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/__base_slasher_additions.dm similarity index 100% rename from monkestation/code/modules/antagonists/slasher/__base_slasher_additions.dm rename to monkestation/code/modules/blood_for_the_blood_gods/slasher/__base_slasher_additions.dm diff --git a/monkestation/code/modules/antagonists/slasher/abilities/_slasher_base.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/_slasher_base.dm similarity index 100% rename from monkestation/code/modules/antagonists/slasher/abilities/_slasher_base.dm rename to monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/_slasher_base.dm diff --git a/monkestation/code/modules/antagonists/slasher/abilities/blood_walk.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/blood_walk.dm similarity index 100% rename from monkestation/code/modules/antagonists/slasher/abilities/blood_walk.dm rename to monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/blood_walk.dm diff --git a/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/envelope_darkness.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/envelope_darkness.dm new file mode 100644 index 000000000000..4316cb8ac304 --- /dev/null +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/envelope_darkness.dm @@ -0,0 +1,40 @@ +/datum/action/cooldown/slasher/envelope_darkness + name = "Darkness Shroud" + desc = "Become masked in the light and visible in the dark." + button_icon_state = "incorporealize" + cooldown_time = 20 SECONDS + + +/datum/action/cooldown/slasher/envelope_darkness/Activate(atom/target) + var/offset = GET_Z_PLANE_OFFSET(owner.z) + var/render = OFFSET_RENDER_TARGET(O_LIGHTING_VISUAL_RENDER_TARGET, offset) + owner.add_filter("envelope", 1, alpha_mask_filter(render, flags = MASK_INVERSE)) + RegisterSignal(owner, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(break_envelope)) + RegisterSignal(owner, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(bullet_impact)) + +/datum/action/cooldown/slasher/envelope_darkness/Remove(mob/living/remove_from) + . = ..() + UnregisterSignal(owner, COMSIG_MOB_AFTER_APPLY_DAMAGE) + UnregisterSignal(owner, COMSIG_ATOM_PRE_BULLET_ACT) + owner.remove_filter("envelope") + +/datum/action/cooldown/slasher/envelope_darkness/proc/break_envelope(datum/source, damage, damagetype) + SIGNAL_HANDLER + UnregisterSignal(owner, COMSIG_MOB_AFTER_APPLY_DAMAGE) + UnregisterSignal(owner, COMSIG_ATOM_PRE_BULLET_ACT) + if(damage < 5) + return + + var/mob/living/owner_mob = owner + for(var/i = 1 to 4) + owner_mob.blood_particles(2, max_deviation = rand(-120, 120), min_pixel_z = rand(-4, 12), max_pixel_z = rand(-4, 12)) + + + var/datum/antagonist/slasher/slasher = owner_mob.mind?.has_antag_datum(/datum/antagonist/slasher) + + slasher?.reduce_fear_area(15, 4) + owner.remove_filter("envelope") + +/datum/action/cooldown/slasher/envelope_darkness/proc/bullet_impact(mob/living/carbon/human/source, obj/projectile/hitting_projectile, def_zone) + SIGNAL_HANDLER + return COMPONENT_BULLET_PIERCED diff --git a/monkestation/code/modules/antagonists/slasher/abilities/recall_machette.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/recall_machette.dm similarity index 97% rename from monkestation/code/modules/antagonists/slasher/abilities/recall_machette.dm rename to monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/recall_machette.dm index 49dc0aba9e70..f5c53dfdbf66 100644 --- a/monkestation/code/modules/antagonists/slasher/abilities/recall_machette.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/recall_machette.dm @@ -24,6 +24,8 @@ if(!owner.put_in_hands(stored_machette)) stored_machette.forceMove(get_turf(owner)) + else + SEND_SIGNAL(owner, COMSIG_LIVING_PICKED_UP_ITEM, stored_machette) /obj/item/slasher_machette name = "slasher's machete" diff --git a/monkestation/code/modules/antagonists/slasher/abilities/slasher_regenerate.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/slasher_regenerate.dm similarity index 100% rename from monkestation/code/modules/antagonists/slasher/abilities/slasher_regenerate.dm rename to monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/slasher_regenerate.dm diff --git a/monkestation/code/modules/antagonists/slasher/abilities/soul_steal.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/soul_steal.dm similarity index 91% rename from monkestation/code/modules/antagonists/slasher/abilities/soul_steal.dm rename to monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/soul_steal.dm index 63dd1c195655..272978a07a84 100644 --- a/monkestation/code/modules/antagonists/slasher/abilities/soul_steal.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/soul_steal.dm @@ -37,15 +37,8 @@ if(human_owner == human_target) // you cant suck yourself, no comment return - if(slasherdatum.last_soul_sucked + slasherdatum.soul_digestion > world.time) // they are a speedrunner, mark them as such - quick_eater = TRUE - // After this point, give chat messages about failures - if(!slasherdatum.corporeal) - to_chat(owner, span_warning("You cannot suck souls whilst incorporeal!")) - return - if(!ishuman(target)) // are they trying to suck a corgi? to_chat(owner, span_warning("You can only suck the souls of humans")) return @@ -95,8 +88,6 @@ human_target.update_body(is_creating = TRUE) slasherdatum.souls_sucked++ - slasherdatum.check_soul_punishment() - slasherdatum.last_soul_sucked = world.time // lets make their machette stronger slasherdatum.linked_machette.force += 2.5 diff --git a/monkestation/code/modules/antagonists/slasher/abilities/stalk_target.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/stalk_target.dm similarity index 96% rename from monkestation/code/modules/antagonists/slasher/abilities/stalk_target.dm rename to monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/stalk_target.dm index 1606f1c43ebd..169cffb75306 100644 --- a/monkestation/code/modules/antagonists/slasher/abilities/stalk_target.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/stalk_target.dm @@ -10,8 +10,8 @@ . = ..() var/list/possible_targets = list() for(var/datum/mind/possible_target as anything in get_crewmember_minds()) - if(possible_target == owner.mind) - continue + //if(possible_target == owner.mind) + //continue if(!ishuman(possible_target.current)) continue if(possible_target.current.stat == DEAD) diff --git a/monkestation/code/modules/antagonists/slasher/abilities/terror_screech.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/terror_screech.dm similarity index 55% rename from monkestation/code/modules/antagonists/slasher/abilities/terror_screech.dm rename to monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/terror_screech.dm index d27fae7f1866..02d9dabd447d 100644 --- a/monkestation/code/modules/antagonists/slasher/abilities/terror_screech.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/abilities/terror_screech.dm @@ -1,6 +1,6 @@ /datum/action/cooldown/slasher/terror name = "Screech of Terror" - desc = "Inflict near paralyzing fear to those around you." + desc = "Inflict near paralyzing fear to those already scared of you." button_icon_state = "stagger_group" cooldown_time = 45 SECONDS @@ -10,21 +10,10 @@ . = ..() var/datum/antagonist/slasher/slasherdatum = owner.mind.has_antag_datum(/datum/antagonist/slasher) - if(!slasherdatum) - to_chat(owner, span_warning("You should not have this ability or your slasher antagonist datum was deleted, please contact coders")) - return - - if(!slasherdatum.corporeal) // if he is incorporeal, dont stun people - playsound(owner, 'monkestation/sound/voice/terror.ogg', 20, falloff_exponent = 0, use_reverb = FALSE) - for(var/mob/living/carbon/human/human in view(7, owner)) - if(human == owner) - continue - to_chat(human, span_warning("You hear a distant screech... this cant possibly be good")) - human.Shake(duration = 1 SECONDS) - return + var/list/mobs = slasherdatum.return_feared_people(7, 50) playsound(owner, 'monkestation/sound/voice/terror.ogg', 100, falloff_exponent = 0, use_reverb = FALSE) - for(var/mob/living/carbon/human/human in view(7, owner)) + for(var/mob/living/carbon/human/human in mobs) if(human == owner) continue human.overlay_fullscreen("terror", /atom/movable/screen/fullscreen/curse, 1) @@ -32,6 +21,8 @@ human.stamina.adjust(-60) human.emote("scream") human.SetParalyzed(1.5 SECONDS) + var/fear_amount = (15 - get_dist(owner, human)) + slasherdatum.increase_fear(human, fear_amount) addtimer(CALLBACK(src, PROC_REF(remove_overlay), human), 5 SECONDS) /datum/action/cooldown/slasher/terror/proc/remove_overlay(mob/living/carbon/human/remover) diff --git a/monkestation/code/modules/blood_for_the_blood_gods/slasher/components/see_as_something.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/components/see_as_something.dm new file mode 100644 index 000000000000..5b861bdeb49f --- /dev/null +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/components/see_as_something.dm @@ -0,0 +1,48 @@ +/datum/component/see_as_something + var/datum/weakref/creature + var/image_icon_state + var/image_icon + var/image/funny_image + var/delusion_name + +/datum/component/see_as_something/Initialize(atom/movable/seer, image_icon_state, image_icon, create_name) + . = ..() + if(!seer) + return + creature = WEAKREF(seer) + src.image_icon_state = image_icon_state + src.image_icon = image_icon + delusion_name = create_name + + setup_image() + +/datum/component/see_as_something/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_CLEAR_SEE, PROC_REF(remove)) + +/datum/component/see_as_something/UnregisterFromParent() + . = ..() + UnregisterSignal(parent, COMSIG_CLEAR_SEE) + +/datum/component/see_as_something/Destroy(force, silent) + . = ..() + remove_image() + + +/datum/component/see_as_something/proc/setup_image() + var/atom/movable/resolved = creature.resolve() + + funny_image = image(image_icon, resolved, image_icon_state) + funny_image.name = delusion_name + funny_image.override = TRUE + + var/mob/parent_mob = parent + + parent_mob.client?.images += funny_image + +/datum/component/see_as_something/proc/remove() + qdel(src) + +/datum/component/see_as_something/proc/remove_image() + var/mob/parent_mob = parent + parent_mob.client?.images -= funny_image diff --git a/monkestation/code/modules/antagonists/slasher/components/team_monitor.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/components/team_monitor.dm similarity index 99% rename from monkestation/code/modules/antagonists/slasher/components/team_monitor.dm rename to monkestation/code/modules/blood_for_the_blood_gods/slasher/components/team_monitor.dm index ed40ecbcd77d..6e30712a9f9c 100644 --- a/monkestation/code/modules/antagonists/slasher/components/team_monitor.dm +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/components/team_monitor.dm @@ -102,7 +102,8 @@ GLOBAL_LIST_EMPTY(tracker_beacons) if(frequency) team_frequency = "[frequency_key][frequency]" else - team_frequency = null + team_frequency = team_freq_key + attached_beacon = _attached_beacon @@ -113,6 +114,8 @@ GLOBAL_LIST_EMPTY(tracker_beacons) if(team_frequency) GLOB.tracker_huds[team_frequency] -= src + SEND_SIGNAL(parent, COMSIG_LIVING_TRACKER_REMOVED, team_frequency) + //Stop processing STOP_PROCESSING(SSprocessing, src) @@ -415,7 +418,7 @@ GLOBAL_LIST_EMPTY(tracker_beacons) else if(_frequency) team_frequency = "[_frequency_key][_frequency]" else - team_frequency = null + team_frequency = team_freq_key //Add ourselves to the tracking network add_tracker_beacon(team_frequency, src) diff --git a/monkestation/code/modules/antagonists/slasher/ghost_role.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/ghost_role.dm similarity index 100% rename from monkestation/code/modules/antagonists/slasher/ghost_role.dm rename to monkestation/code/modules/blood_for_the_blood_gods/slasher/ghost_role.dm diff --git a/monkestation/code/modules/blood_for_the_blood_gods/slasher/slasher_datum.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/slasher_datum.dm new file mode 100644 index 000000000000..6e9245150587 --- /dev/null +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/slasher_datum.dm @@ -0,0 +1,316 @@ +/datum/outfit/slasher + name = "Slasher Outfit" + suit = /obj/item/clothing/suit/apron/slasher + uniform = /obj/item/clothing/under/color/random/slasher + shoes = /obj/item/clothing/shoes/slasher_shoes + mask = /obj/item/clothing/mask/gas/slasher + +/datum/antagonist/slasher + name = "\improper Slasher" + show_in_antagpanel = TRUE + roundend_category = "slashers" + antagpanel_category = "Slasher" + job_rank = ROLE_SLASHER + antag_hud_name = "slasher" + show_name_in_check_antagonists = TRUE + hud_icon = 'monkestation/icons/mob/slasher.dmi' + preview_outfit = /datum/outfit/slasher + show_to_ghosts = TRUE + + ///the linked machette that the slasher can summon even if destroyed and is unique to them + var/obj/item/slasher_machette/linked_machette + ///rallys the amount of souls effects are based on this + var/souls_sucked = 0 + ///our cached brute_mod + var/cached_brute_mod = 0 + /// the mob we are stalking + var/mob/living/carbon/human/stalked_human + /// how close we are in % to finishing stalking + var/stalk_precent = 0 + ///ALL Powers currently owned + var/list/datum/action/cooldown/slasher/powers = list() + + ///this is our team monitor + var/datum/component/team_monitor/slasher_monitor + ///this is our tracker component + var/datum/component/tracking_beacon + var/monitor_key = "slasher_key" + + ///weakref list of mobs and their fear + var/list/fears = list() + ///weakref list of mobs and last fear attempt to stop fear maxxing + var/list/fear_cooldowns = list() + ///weakref list of mobs and last fear stages + var/list/fear_stages = list() + ///this is a list of all heartbeaters + var/list/heartbeats = list() + //this is a list of all statics + var/list/mobs_with_fullscreens = list() + ///this is our list of refs over 100 fear + var/list/total_fear = list() + ///this is our list of tracked people + var/list/tracked = list() + ///this is our list of seers + var/list/seers = list() + +/datum/antagonist/slasher/apply_innate_effects(mob/living/mob_override) + . = ..() + var/mob/living/current_mob = mob_override || owner.current + current_mob.overlay_fullscreen("slasher_prox", /atom/movable/screen/fullscreen/nearby, 1) + + monitor_key = "slasher_monitor_[current_mob.ckey]" + tracking_beacon = current_mob.AddComponent(/datum/component/tracking_beacon, monitor_key, null, null, TRUE, "#f3d594") + slasher_monitor = current_mob.AddComponent(/datum/component/team_monitor, monitor_key, null, tracking_beacon) + slasher_monitor.show_hud(owner.current) + + ADD_TRAIT(current_mob, TRAIT_BATON_RESISTANCE, "slasher") + ADD_TRAIT(current_mob, TRAIT_CLUMSY, "slasher") + ADD_TRAIT(current_mob, TRAIT_DUMB, "slasher") + ADD_TRAIT(current_mob, TRAIT_NODEATH, "slasher") + ADD_TRAIT(current_mob, TRAIT_LIMBATTACHMENT, "slasher") + ADD_TRAIT(current_mob, TRAIT_SLASHER, "slasher") + + var/mob/living/carbon/carbon = current_mob + var/obj/item/organ/internal/eyes/shadow/shadow = new + shadow.Insert(carbon, drop_if_replaced = FALSE) + + RegisterSignal(current_mob, COMSIG_LIVING_LIFE, PROC_REF(LifeTick)) + RegisterSignal(current_mob, COMSIG_LIVING_PICKED_UP_ITEM, PROC_REF(item_pickup)) + RegisterSignal(current_mob, COMSIG_MOB_DROPPING_ITEM, PROC_REF(item_drop)) + RegisterSignal(current_mob, COMSIG_MOB_ITEM_ATTACK, PROC_REF(check_attack)) + + ///abilities galore + for(var/datum/action/cooldown/slasher/listed_slasher as anything in subtypesof(/datum/action/cooldown/slasher)) + var/datum/action/cooldown/slasher/new_ability = new listed_slasher + new_ability.Grant(current_mob) + powers |= new_ability + + var/mob/living/carbon/human/human = current_mob + if(istype(human)) + human.equipOutfit(/datum/outfit/slasher) + cached_brute_mod = human.dna.species.brutemod + + +/datum/antagonist/slasher/on_removal() + . = ..() + owner.current.clear_fullscreen("slasher_prox", 15) + owner.current.remove_traits(list(TRAIT_BATON_RESISTANCE, TRAIT_CLUMSY, TRAIT_NODEATH, TRAIT_DUMB, TRAIT_LIMBATTACHMENT), "slasher") + for(var/datum/action/cooldown/slasher/listed_slasher as anything in powers) + listed_slasher.Remove(owner.current) + +/datum/antagonist/slasher/proc/LifeTick(mob/living/source, seconds_per_tick, times_fired) + + var/list/currently_beating = list() + var/list/current_statics = list() + for(var/datum/weakref/held as anything in fear_stages) + var/stage = fear_stages[held] + var/mob/living/carbon/human/human = held.resolve() + + if(stage >= 1) + currently_beating |= held + if(!(held in heartbeats)) + heartbeats |= held + human.playsound_local(human, 'sound/health/slowbeat.ogg', 40, FALSE, channel = CHANNEL_HEARTBEAT, use_reverb = FALSE) + + if(stage >= 2) + current_statics |= held + if(!(held in mobs_with_fullscreens)) + human.overlay_fullscreen("slasher_prox", /atom/movable/screen/fullscreen/nearby, 1) + mobs_with_fullscreens |= held + + + for(var/datum/weakref/held_ref as anything in (heartbeats - currently_beating)) + var/mob/living/carbon/human/human = held_ref.resolve() + human.stop_sound_channel(CHANNEL_HEARTBEAT) + heartbeats -= held_ref + + for(var/datum/weakref/held_ref as anything in (mobs_with_fullscreens - current_statics)) + var/mob/living/carbon/human/human = held_ref.resolve() + human.clear_fullscreen("slasher_prox", 15) + mobs_with_fullscreens -= held_ref + + if(stalked_human) + for(var/mob/living/carbon/human in view(7, source)) + if(stalked_human != human) + continue + if(stalked_human.stat == DEAD) + failed_stalking() + stalk_precent += (1 / 1.8) + if(stalk_precent >= 100) + finish_stalking() + +/datum/antagonist/slasher/proc/finish_stalking() + to_chat(owner, span_boldwarning("You have finished spooking your victim, and have harvested part of their soul!")) + if(linked_machette) + linked_machette.force += 2.5 + linked_machette.throwforce += 2.5 + stalked_human = null + +/datum/antagonist/slasher/proc/failed_stalking() + to_chat(owner, span_boldwarning("You let your victim be taken before it was time!")) + if(linked_machette) + linked_machette.force -= 5 + linked_machette.throwforce -= 5 + stalked_human = null + +/datum/antagonist/slasher/proc/check_attack(mob/living/attacking_person, mob/living/attacked_mob) + var/obj/item/held_item = attacking_person.get_active_held_item() + + var/held_force = 3 + if(held_item) + held_force = held_item.force + + increase_fear(attacked_mob, held_force / 3) + + for(var/i = 1 to (held_force / 3)) + attacked_mob.blood_particles(2, max_deviation = rand(-120, 120), min_pixel_z = rand(-4, 12), max_pixel_z = rand(-4, 12)) + +/datum/antagonist/slasher/proc/item_pickup(datum/input_source, obj/item/source) + RegisterSignal(source, COMSIG_ITEM_DAMAGE_MULTIPLIER, PROC_REF(damage_multiplier)) + +/datum/antagonist/slasher/proc/item_drop(datum/input_source, obj/item/source) + UnregisterSignal(source, COMSIG_ITEM_DAMAGE_MULTIPLIER) + +/obj/item/var/last_multi = 1 + +/datum/antagonist/slasher/proc/damage_multiplier(obj/item/source, mob/living/attacked, def_zone) + var/health_left = max(0, attacked.health) * 0.01 + + attacked.cause_pain(def_zone, source.force) + + source.last_multi = health_left + + return TRUE + +/datum/antagonist/slasher/proc/increase_fear(atom/movable/target, amount) + var/datum/weakref/weak = WEAKREF(target) + if(!(weak in fear_cooldowns)) + target.AddComponent(/datum/component/hovering_information, /datum/hover_data/slasher_fear, TRAIT_SLASHER) + fear_cooldowns |= weak + fear_cooldowns[weak] = 0 + + if(fear_cooldowns[weak] > world.time + 10 SECONDS) + return + + if(!(weak in fears)) + fears |= weak + fears[weak] += amount + + fear_cooldowns[weak] = world.time + fear_stage_check(weak) + +/datum/antagonist/slasher/proc/reduce_fear_area(amount, area) + for(var/mob/living/carbon/human/human in range(area, get_turf(owner))) + var/datum/weakref/weak = WEAKREF(human) + if(!(weak in fears)) + continue + fears[weak] -= amount + fears[weak] = max(fears[weak], 0) + fear_stage_check(weak) + +/datum/antagonist/slasher/proc/reduce_fear(atom/target, amount) + var/datum/weakref/weak = WEAKREF(target) + if(!(weak in fears)) + return + fears[weak] -= amount + fears[weak] = max(fears[weak], 0) + fear_stage_check(weak) + +/datum/antagonist/slasher/proc/fear_stage_check(datum/weakref/weak) + var/fear_number = fears[weak] + var/old_stage = fear_stages[weak] + var/stage = 0 + switch(fear_number) + if(0 to 25) + stage = 0 + if(26 to 50) + stage = 1 + if(51 to 75) + stage = 2 + if(76 to 100) + stage = 3 + else + stage = 4 + + if((weak in fear_stages)) + if(fear_stages[weak] == stage) + return + stage_change(weak, stage, old_stage) + + +/datum/antagonist/slasher/proc/stage_change(datum/weakref/weak, new_stage, last_stage) + fear_stages[weak] = new_stage + + if(new_stage >= 3) + try_add_tracker(weak) + if(new_stage >= 4) + try_add_seer(weak) + + +/datum/antagonist/slasher/proc/return_feared_people(range, value) + var/list/mobs = list() + for(var/datum/weakref/weak_ref as anything in fears) + if(fears[weak_ref] < value) + continue + var/mob/living/mob = weak_ref.resolve() + if(get_dist(owner.current, mob) > range) + continue + mobs += mob + return mobs + +/datum/antagonist/slasher/proc/try_add_tracker(datum/weakref/weak) + if(weak in tracked) + return + tracked += weak + + var/mob/living/living = weak.resolve() + + var/datum/component/tracking_beacon/beacon = living.AddComponent(/datum/component/tracking_beacon, monitor_key, null, null, TRUE, "#f3d594") + slasher_monitor.add_to_tracking_network(beacon) + + RegisterSignal(living, COMSIG_LIVING_TRACKER_REMOVED, PROC_REF(remove_tracker)) + +/datum/antagonist/slasher/proc/remove_tracker(mob/living/source, frequency) + if(frequency != monitor_key) + return + + tracked -= WEAKREF(source) + slasher_monitor.update_all_directions() + +/datum/antagonist/slasher/proc/try_add_seer(datum/weakref/weak) + if(weak in seers) + return + seers += weak + + var/mob/living/living = weak.resolve() + living.AddComponent(/datum/component/see_as_something, owner.current, "wendigo", 'icons/mob/simple/icemoon/64x64megafauna.dmi', "?????") + +/datum/hover_data/slasher_fear/setup_data(atom/source, mob/enterer) + if(!enterer.mind?.has_antag_datum(/datum/antagonist/slasher)) + return + var/datum/antagonist/slasher/slasher = enterer.mind.has_antag_datum(/datum/antagonist/slasher) + + var/datum/weakref/weak = WEAKREF(source) + if(!(weak in slasher.fear_stages)) + return + var/fear_stage = slasher.fear_stages[weak] + + var/image/new_image = new + new_image.icon = 'monkestation/code/modules/blood_for_the_blood_gods/icons/slasher_ui.dmi' + new_image.pixel_x = 10 + new_image.plane = GAME_PLANE_UPPER + switch(fear_stage) + if(2) + new_image.icon_state = "they_fear" + if(3) + new_image.icon_state = "they_see_no_evil" + if(4) + new_image.icon_state = "they_see" + else + new_image.icon_state = null + + if(!isturf(source.loc)) + new_image.loc = source.loc + else + new_image.loc = source + add_client_image(new_image, enterer.client) diff --git a/monkestation/code/modules/blood_for_the_blood_gods/slasher/slasher_outfit/slasher_clothing.dm b/monkestation/code/modules/blood_for_the_blood_gods/slasher/slasher_outfit/slasher_clothing.dm new file mode 100644 index 000000000000..9a84c3caa952 --- /dev/null +++ b/monkestation/code/modules/blood_for_the_blood_gods/slasher/slasher_outfit/slasher_clothing.dm @@ -0,0 +1,46 @@ +/obj/item/clothing/shoes/slasher_shoes + name = "Industrial Boots" + icon_state = "jackboots" + inhand_icon_state = "jackboots" + clothing_traits = list(TRAIT_NO_SLIP_ALL) + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + +/obj/item/clothing/shoes/slasher_shoes/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_NODROP, "slasher") + +/obj/item/clothing/mask/gas/slasher + name = "slasher's gas mask" + desc = "A close-fitting sealed gas mask, this one seems to be protruding some kind of dark aura." + + icon = 'icons/obj/clothing/head/utility.dmi' + worn_icon = 'icons/mob/clothing/head/utility.dmi' + icon_state = "welding" + inhand_icon_state = "welding" + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + slowdown = 1 + +/obj/item/clothing/mask/gas/slasher/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_NODROP, "slasher") + +/obj/item/clothing/mask/gas/slasher/adjustmask() + return + +/obj/item/clothing/suit/apron/slasher + name = "butcher's apron" + desc = "A brown butcher's apron, you can feel an aura of something dark radiating off of it." + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + + icon_state = "slasher" + inhand_icon_state = null + +/obj/item/clothing/suit/apron/slasher/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_NODROP, "slasher") + +/obj/item/clothing/under/color/random/slasher + name = "butcher's jumpsuit" + clothing_traits = list(TRAIT_NODROP) + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + diff --git a/monkestation/code/modules/bloodsuckers/powers/fortitude.dm b/monkestation/code/modules/bloodsuckers/powers/fortitude.dm index 2577ad14ed3a..617dd765b3ee 100644 --- a/monkestation/code/modules/bloodsuckers/powers/fortitude.dm +++ b/monkestation/code/modules/bloodsuckers/powers/fortitude.dm @@ -22,7 +22,7 @@ owner.balloon_alert(owner, "fortitude turned on.") to_chat(owner, span_notice("Your flesh, skin, and muscles become as steel.")) // Traits & Effects - owner.add_traits(list(TRAIT_PIERCEIMMUNE, TRAIT_NODISMEMBER, TRAIT_PUSHIMMUNE, TRAIT_NO_SPRINT), FORTITUDE_TRAIT) + owner.add_traits(list(TRAIT_PIERCEIMMUNE, TRAIT_ANALGESIA, TRAIT_NODISMEMBER, TRAIT_PUSHIMMUNE, TRAIT_NO_SPRINT), FORTITUDE_TRAIT) if(level_current >= 4) owner.add_traits(list(TRAIT_STUNIMMUNE, TRAIT_CANT_STAMCRIT), FORTITUDE_TRAIT) // They'll get stun resistance + this, who cares. var/mob/living/carbon/human/bloodsucker_user = owner @@ -61,7 +61,7 @@ if(!HAS_TRAIT_FROM(bloodsucker_user, TRAIT_STUNIMMUNE, FORTITUDE_TRAIT)) bloodsucker_user.physiology.stamina_mod /= fortitude_resist // Remove Traits & Effects - owner.remove_traits(list(TRAIT_PIERCEIMMUNE, TRAIT_NODISMEMBER, TRAIT_PUSHIMMUNE, TRAIT_NO_SPRINT, TRAIT_STUNIMMUNE, TRAIT_CANT_STAMCRIT), FORTITUDE_TRAIT) + owner.remove_traits(list(TRAIT_PIERCEIMMUNE, TRAIT_ANALGESIA, TRAIT_NODISMEMBER, TRAIT_PUSHIMMUNE, TRAIT_NO_SPRINT, TRAIT_STUNIMMUNE, TRAIT_CANT_STAMCRIT), FORTITUDE_TRAIT) if(was_running && bloodsucker_user.m_intent == MOVE_INTENT_WALK) bloodsucker_user.set_move_intent(MOVE_INTENT_RUN) diff --git a/monkestation/code/modules/bloodsuckers/structures/bloodsucker_recipes.dm b/monkestation/code/modules/bloodsuckers/structures/bloodsucker_recipes.dm index 0b0aa55a2ab5..e065a7d2ebd3 100644 --- a/monkestation/code/modules/bloodsuckers/structures/bloodsucker_recipes.dm +++ b/monkestation/code/modules/bloodsuckers/structures/bloodsucker_recipes.dm @@ -112,3 +112,12 @@ time = 8 SECONDS category = CAT_WEAPON_MELEE always_available = FALSE + +/datum/crafting_recipe/coffin + name = "Coffin" + result = /obj/structure/closet/crate/coffin + reqs = list( + /obj/item/stack/sheet/mineral/wood = 5, + ) + time = 15 SECONDS + category = CAT_STRUCTURE diff --git a/monkestation/code/modules/blueshield/areas.dm b/monkestation/code/modules/blueshield/areas.dm new file mode 100644 index 000000000000..84e75acd3d5e --- /dev/null +++ b/monkestation/code/modules/blueshield/areas.dm @@ -0,0 +1,5 @@ +// Blueshield area +/area/station/command/heads_quarters/blueshield + name = "Blueshield's Office" + icon = 'monkestation/code/modules/blueshift/icons/areas/areas_station.dmi' + icon_state = "blueshield" diff --git a/monkestation/code/modules/blueshield/closet.dm b/monkestation/code/modules/blueshield/closet.dm new file mode 100644 index 000000000000..5402f2db276f --- /dev/null +++ b/monkestation/code/modules/blueshield/closet.dm @@ -0,0 +1,34 @@ +/obj/item/storage/bag/garment/blueshield + name = "blueshield's garment bag" + desc = "A bag for storing extra clothes and shoes. This one belongs to the blueshield." + +/obj/item/storage/bag/garment/blueshield/PopulateContents() + new /obj/item/clothing/suit/hooded/wintercoat/nova/blueshield(src) + new /obj/item/clothing/head/beret/blueshield(src) + new /obj/item/clothing/head/beret/blueshield/navy(src) + new /obj/item/clothing/under/rank/blueshield(src) + new /obj/item/clothing/under/rank/blueshield/skirt(src) + new /obj/item/clothing/under/rank/blueshield/turtleneck(src) + new /obj/item/clothing/under/rank/blueshield/turtleneck/skirt(src) + new /obj/item/clothing/suit/armor/vest/blueshield(src) + new /obj/item/clothing/suit/armor/vest/blueshield/jacket(src) + new /obj/item/clothing/neck/mantle/bsmantle(src) + +/obj/structure/closet/secure_closet/blueshield + name = "blueshield's locker" + icon_state = "bs" + icon = 'monkestation/code/modules/blueshift/icons/obj/closet.dmi' + req_access = list(ACCESS_CENT_GENERAL) + +/obj/structure/closet/secure_closet/blueshield/New() + ..() + new /obj/item/storage/briefcase/secure(src) + new /obj/item/storage/belt/security/full(src) + new /obj/item/grenade/flashbang(src) + new /obj/item/assembly/flash/handheld(src) + new /obj/item/restraints/handcuffs(src) + new /obj/item/clothing/glasses/hud/security/sunglasses(src) + new /obj/item/storage/medkit/frontier/stocked(src) + new /obj/item/storage/bag/garment/blueshield(src) + new /obj/item/mod/control/pre_equipped/blueshield(src) + new /obj/item/sensor_device/blueshield(src) diff --git a/monkestation/code/modules/blueshift/clothing/blueshield.dm b/monkestation/code/modules/blueshield/clothing.dm similarity index 68% rename from monkestation/code/modules/blueshift/clothing/blueshield.dm rename to monkestation/code/modules/blueshield/clothing.dm index 3c44a9c7c8e0..0bb05426e1fd 100644 --- a/monkestation/code/modules/blueshift/clothing/blueshield.dm +++ b/monkestation/code/modules/blueshield/clothing.dm @@ -139,3 +139,79 @@ worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/suits/wintercoat.dmi' icon_state = "coataformal" hoodtype = /obj/item/clothing/head/hooded/winterhood/nova + +/* +* BLUESHIELD +*/ +//Why is this in command.dm? Simple: Centcom.dmi will already be packed with CC/NTNavy/AD/LL/SOL/FTU - all of them more event-based clothes, while this will appear +//on-station often. + +/obj/item/clothing/under/rank/blueshield + icon = 'monkestation/code/modules/blueshift/icons/obj/clothing/under/command.dmi' + worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/under/command.dmi' + worn_icon_digitigrade = 'monkestation/code/modules/blueshift/icons/mob/clothing/under/command_digi.dmi' + name = "blueshield's suit" + desc = "A classic bodyguard's suit, with custom-fitted Blueshield-Blue cuffs and a Nanotrasen insignia over one of the pockets." + icon_state = "blueshield" + strip_delay = 50 + armor_type = /datum/armor/clothing_under/rank_blueshield + sensor_mode = SENSOR_COORDS + random_sensor = FALSE + alt_covers_chest = TRUE + +/datum/armor/clothing_under/rank_blueshield + melee = 10 + bullet = 5 + laser = 5 + energy = 10 + bomb = 10 + fire = 50 + acid = 50 + +/obj/item/clothing/under/rank/blueshield/skirt + name = "blueshield's suitskirt" + desc = "A classic bodyguard's suitskirt, with custom-fitted Blueshield-Blue cuffs and a Nanotrasen insignia over one of the pockets." + icon_state = "blueshieldskirt" + body_parts_covered = CHEST|GROIN|ARMS + dying_key = DYE_REGISTRY_JUMPSKIRT + female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON + + +/obj/item/clothing/under/rank/blueshield/turtleneck + name = "blueshield's turtleneck" + desc = "A tactical jumper fit for only the best of bodyguards, with plenty of tactical pockets for your tactical needs." + icon_state = "bs_turtleneck" + +/obj/item/clothing/under/rank/blueshield/turtleneck/skirt + name = "blueshield's skirtleneck" + desc = "A tactical jumper fit for only the best of bodyguards - instead of tactical pockets, this one has a tactical lack of leg protection." + icon_state = "bs_skirtleneck" + body_parts_covered = CHEST|GROIN|ARMS + dying_key = DYE_REGISTRY_JUMPSKIRT + female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON + +/obj/item/clothing/neck/mantle/bsmantle + name = "\proper the blueshield's mantle" + desc = "A plated mantle with command colors. Suitable for the one assigned to making sure they're still breathing." + icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/neck.dmi' + worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/neck.dmi' + icon_state = "bsmantle" + +/obj/item/radio/headset/headset_bs + name = "\proper the blueshield's headset" + icon = 'monkestation/code/modules/blueshield/icons/radio.dmi' + worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/ears.dmi' + icon_state = "bshield_headset" + worn_icon_state = "bshield_headset" + keyslot = /obj/item/encryptionkey/heads/blueshield + keyslot2 = /obj/item/encryptionkey/headset_cent + +/obj/item/radio/headset/headset_bs/alt + icon_state = "bshield_headset_alt" + worn_icon_state = "bshield_headset_alt" + +/obj/item/radio/headset/headset_bs/alt/Initialize(mapload) + . = ..() + AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS)) diff --git a/monkestation/code/modules/blueshield/devices/crew_monitor.dm b/monkestation/code/modules/blueshield/devices/crew_monitor.dm new file mode 100644 index 000000000000..63549cfc312a --- /dev/null +++ b/monkestation/code/modules/blueshield/devices/crew_monitor.dm @@ -0,0 +1,133 @@ +/* +* Trimmed and modified copy of ".../machinery/computer/crew.dm" +* for the sake of modularity. (Blueshield Monitor Console soon?) +*/ + +#define SENSORS_UPDATE_PERIOD (10 SECONDS) + +GLOBAL_DATUM_INIT(blueshield_crewmonitor, /datum/crewmonitor/blueshield, new) + +//list of all Command/CC jobs +/datum/crewmonitor/blueshield + var/list/jobs_command = list( + JOB_CAPTAIN = 00, + JOB_HEAD_OF_SECURITY = 10, + JOB_CHIEF_MEDICAL_OFFICER = 20, + JOB_RESEARCH_DIRECTOR = 30, + JOB_CHIEF_ENGINEER = 40, + JOB_QUARTERMASTER = 50, + JOB_HEAD_OF_PERSONNEL = 60, + JOB_CENTCOM_ADMIRAL = 200, + JOB_CENTCOM = 201, + JOB_CENTCOM_OFFICIAL = 210, + JOB_CENTCOM_COMMANDER = 211, + JOB_CENTCOM_BARTENDER = 212, + JOB_CENTCOM_CUSTODIAN = 213, + JOB_CENTCOM_MEDICAL_DOCTOR = 214, + JOB_CENTCOM_RESEARCH_OFFICER = 215, + JOB_ERT_COMMANDER = 220, + JOB_ERT_OFFICER = 221, + JOB_ERT_ENGINEER = 222, + JOB_ERT_MEDICAL_DOCTOR = 223, + JOB_ERT_CLOWN = 224, + JOB_ERT_CHAPLAIN = 225, + JOB_ERT_JANITOR = 226, + JOB_ERT_DEATHSQUAD = 227, + JOB_NT_REP = 230, + JOB_BLUESHIELD = 231, + ) + +/datum/crewmonitor/blueshield/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if (!ui) + ui = new(user, src, "CrewConsoleNovaBlueshield") + ui.open() + +/* +* Override of crewmonitor/update_data(z) +* - "trim_assignment" is now iterated for command-only jobs +* - "if (id_card)" now encapsulates all the remaining checks to avoid showing unknowns +*/ +/datum/crewmonitor/blueshield/update_data(z) + if(data_by_z["[z]"] && last_update["[z]"] && world.time <= last_update["[z]"] + SENSORS_UPDATE_PERIOD) + return data_by_z["[z]"] + + var/list/results = list() + for(var/tracked_mob in GLOB.suit_sensors_list) + if(!tracked_mob) + stack_trace("Null entry in suit sensors list.") + continue + + var/mob/living/tracked_living_mob = tracked_mob + + var/turf/pos = get_turf(tracked_living_mob) + + if(!pos) + stack_trace("Tracked mob has no loc and is likely in nullspace: [tracked_living_mob] ([tracked_living_mob.type])") + continue + + if(pos.z != z && (!is_station_level(pos.z) || !is_station_level(z)) && !HAS_TRAIT(tracked_living_mob, TRAIT_MULTIZ_SUIT_SENSORS)) + continue + + var/mob/living/carbon/human/tracked_human = tracked_living_mob + + if(!ishuman(tracked_human)) + stack_trace("Non-human mob is in suit_sensors_list: [tracked_living_mob] ([tracked_living_mob.type])") + continue + + var/obj/item/clothing/under/uniform = tracked_human.w_uniform + if (!istype(uniform)) + stack_trace("Human without a suit sensors compatible uniform is in suit_sensors_list: [tracked_human] ([tracked_human.type]) ([uniform?.type])") + continue + + if((uniform.has_sensor <= NO_SENSORS) || !uniform.sensor_mode) + stack_trace("Human without active suit sensors is in suit_sensors_list: [tracked_human] ([tracked_human.type]) ([uniform.type])") + continue + + var/sensor_mode = uniform.sensor_mode + var/list/entry = list() + + var/obj/item/card/id/id_card = tracked_living_mob.get_idcard(hand_first = FALSE) + if (id_card) + + entry["name"] = id_card.registered_name + entry["assignment"] = id_card.assignment + var/trim_assignment = id_card.get_trim_assignment() + + //Check if they are command + if (jobs_command[trim_assignment] != null) + entry["ijob"] = jobs_command[trim_assignment] + else + continue + + if (isipc(tracked_human)) + entry["is_robot"] = TRUE + + if (sensor_mode >= SENSOR_LIVING) + entry["life_status"] = (tracked_living_mob.stat != DEAD) + + if (sensor_mode >= SENSOR_VITALS) + entry += list( + "oxydam" = round(tracked_living_mob.getOxyLoss(), 1), + "toxdam" = round(tracked_living_mob.getToxLoss(), 1), + "burndam" = round(tracked_living_mob.getFireLoss(), 1), + "brutedam" = round(tracked_living_mob.getBruteLoss(), 1), + "health" = round(tracked_living_mob.health, 1), + ) + + if (sensor_mode >= SENSOR_COORDS) + entry["area"] = get_area_name(tracked_living_mob, format_text = TRUE) + + entry["can_track"] = tracked_living_mob.can_track() + + else + continue + + results[++results.len] = entry + + data_by_z["[z]"] = results + last_update["[z]"] = world.time + + return results + +#undef SENSORS_UPDATE_PERIOD diff --git a/monkestation/code/modules/blueshield/devices/sensor.dm b/monkestation/code/modules/blueshield/devices/sensor.dm new file mode 100644 index 000000000000..6f8a5aca717b --- /dev/null +++ b/monkestation/code/modules/blueshield/devices/sensor.dm @@ -0,0 +1,8 @@ +/obj/item/sensor_device/blueshield + name = "blueshield's handheld monitor" + desc = "A unique model of handheld crew monitor that seems to have been customized for Executive Protection purposes." + icon = 'monkestation/code/modules/blueshield/icons/device.dmi' + icon_state = "blueshield_scanner" + +/obj/item/sensor_device/blueshield/attack_self(mob/user) + GLOB.blueshield_crewmonitor.show(user,src) diff --git a/monkestation/code/modules/blueshield/gun.dm b/monkestation/code/modules/blueshield/gun.dm new file mode 100644 index 000000000000..7179cb6fe755 --- /dev/null +++ b/monkestation/code/modules/blueshield/gun.dm @@ -0,0 +1,59 @@ +/* + Blueshield's Hellfire is between SC-1 and the Hellfire in terms of Damage and wound output +*/ + +/// Blueshield's Custom Hellfire +/obj/item/ammo_casing/energy/laser/hellfire/blueshield + projectile_type = /obj/projectile/beam/laser/hellfire + e_cost = LASER_SHOTS(13, 1000) + select_name = "maim" + +/obj/item/gun/energy/laser/hellgun/blueshield + name ="modified hellfire laser gun" + desc = "A lightly overtuned version of NT's Hellfire Laser rifle, scratches showing its age and the fact it has definitely been owned before. This one is more energy efficient without sacrificing damage." + icon_state = "hellgun" + ammo_type = list(/obj/item/ammo_casing/energy/laser/hellfire/blueshield) + +/obj/item/choice_beacon/blueshield + name = "gunset beacon" + desc = "A single use beacon to deliver a gunset of your choice. Please only call this in your office" + company_source = "Sol Defense Contracting" + company_message = span_bold("Supply Pod incoming, please stand by.") + +/obj/item/choice_beacon/blueshield/generate_display_names() + var/static/list/selectable_gun_types = list( + "Takbok Revolver Set" = /obj/item/storage/toolbox/guncase/skyrat/pistol/trappiste_small_case/takbok, + "Custom Hellfire Laser Rifle" = /obj/item/gun/energy/laser/hellgun/blueshield, + "Bogseo Submachinegun Gunset" = /obj/item/storage/toolbox/guncase/skyrat/xhihao_large_case/bogseo, + "Tech-9" = /obj/item/storage/toolbox/guncase/skyrat/pistol/tech_9, + ) + + return selectable_gun_types + +/obj/item/storage/toolbox/guncase/skyrat/pistol/tech_9 + desc = "A thick yellow gun case with foam inserts laid out to fit a weapon, magazines, and gear securely. The five square grid of Tech-9 is displayed prominently on the top." + + icon = 'monkestation/code/modules/blueshift/icons/obj/gunsets.dmi' + icon_state = "case_trappiste" + + lefthand_file = 'monkestation/code/modules/blueshift/icons/mob/inhands/cases_lefthand.dmi' + righthand_file = 'monkestation/code/modules/blueshift/icons/mob/inhands/cases_righthand.dmi' + inhand_icon_state = "yellowcase" + + weapon_to_spawn = /obj/item/gun/ballistic/automatic/pistol/tech_9/no_mag + extra_to_spawn = /obj/item/ammo_box/magazine/m35/rubber + +/obj/item/gun/ballistic/automatic/pistol/tech_9 + name = "\improper Glock-O" + desc = "The standard issue service pistol of blueshield agents." + burst_size = 10 //lol + fire_delay = 1 + + icon = 'monkestation/code/modules/blueshield/icons/gun.dmi' + icon_state = "tech9" + + fire_sound = 'monkestation/code/modules/blueshift/sounds/pistol_light.ogg' + accepted_magazine_type = /obj/item/ammo_box/magazine/m35 + +/obj/item/gun/ballistic/automatic/pistol/tech_9/no_mag + spawnwithmagazine = FALSE diff --git a/monkestation/code/modules/blueshield/icons/device.dmi b/monkestation/code/modules/blueshield/icons/device.dmi new file mode 100644 index 000000000000..449e43052746 Binary files /dev/null and b/monkestation/code/modules/blueshield/icons/device.dmi differ diff --git a/monkestation/code/modules/blueshield/icons/gun.dmi b/monkestation/code/modules/blueshield/icons/gun.dmi new file mode 100644 index 000000000000..ca61a471c230 Binary files /dev/null and b/monkestation/code/modules/blueshield/icons/gun.dmi differ diff --git a/monkestation/code/modules/blueshield/icons/praetorian.dmi b/monkestation/code/modules/blueshield/icons/praetorian.dmi new file mode 100644 index 000000000000..1632262e8b8a Binary files /dev/null and b/monkestation/code/modules/blueshield/icons/praetorian.dmi differ diff --git a/monkestation/code/modules/blueshield/icons/radio.dmi b/monkestation/code/modules/blueshield/icons/radio.dmi new file mode 100644 index 000000000000..9c5184305e15 Binary files /dev/null and b/monkestation/code/modules/blueshield/icons/radio.dmi differ diff --git a/monkestation/code/modules/blueshield/icons/worn_praetorian.dmi b/monkestation/code/modules/blueshield/icons/worn_praetorian.dmi new file mode 100644 index 000000000000..373986abe4de Binary files /dev/null and b/monkestation/code/modules/blueshield/icons/worn_praetorian.dmi differ diff --git a/monkestation/code/modules/jobs/job_types/blueshield.dm b/monkestation/code/modules/blueshield/job.dm similarity index 50% rename from monkestation/code/modules/jobs/job_types/blueshield.dm rename to monkestation/code/modules/blueshield/job.dm index 4384c79e49cc..bfc55ecd3142 100644 --- a/monkestation/code/modules/jobs/job_types/blueshield.dm +++ b/monkestation/code/modules/blueshield/job.dm @@ -4,38 +4,40 @@ auto_deadmin_role_flags = DEADMIN_POSITION_SECURITY department_head = list(JOB_HEAD_OF_SECURITY) faction = FACTION_STATION - total_positions = 0 - spawn_positions = 0 + total_positions = 1 + spawn_positions = 1 supervisors = "the Heads of Staff" - minimal_player_age = 7 - exp_requirements = 600 + minimal_player_age = 30 + exp_requirements = 7200 exp_required_type = EXP_TYPE_CREW - exp_required_type_department = EXP_TYPE_SECURITY + exp_required_type_department = EXP_TYPE_COMMAND exp_granted_type = EXP_TYPE_CREW config_tag = "BLUESHIELD" outfit = /datum/outfit/job/blueshield - plasmaman_outfit = /datum/outfit/plasmaman/security + plasmaman_outfit = /datum/outfit/plasmaman/blueshield - paycheck = PAYCHECK_CREW - paycheck_department = ACCOUNT_SEC + paycheck = PAYCHECK_COMMAND + paycheck_department = ACCOUNT_CMD - liver_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) + liver_traits = list(TRAIT_PRETENDER_ROYAL_METABOLISM) display_order = JOB_DISPLAY_ORDER_BLUESHIELD bounty_types = CIV_JOB_SEC departments_list = list( - /datum/job_department/security, + /datum/job_department/central_command, /datum/job_department/command, ) - family_heirlooms = list(/obj/item/book/manual/wiki/security_space_law, /obj/item/clothing/head/beret/sec) + family_heirlooms = list(/obj/item/bedsheet/captain, /obj/item/clothing/head/beret/blueshield) mail_goodies = list( - /obj/item/food/donut/caramel = 10, - /obj/item/food/donut/matcha = 10, - /obj/item/food/donut/blumpkin = 5 + /obj/item/storage/fancy/cigarettes/cigars/havana = 10, + /obj/item/stack/spacecash/c500 = 3, + /obj/item/disk/nuclear/fake/obvious = 2, + /obj/item/clothing/head/collectable/captain = 4, ) + rpg_title = "Guard" job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN @@ -45,32 +47,39 @@ /datum/outfit/job/blueshield name = "Blueshield" jobtype = /datum/job/blueshield - - id_trim = /datum/id_trim/job/blueshield - uniform = /obj/item/clothing/under/rank/security/officer/blueshirt - suit_store = /obj/item/gun/ballistic/automatic/pistol/paco/no_mag + uniform = /obj/item/clothing/under/rank/blueshield + suit = /obj/item/clothing/suit/armor/vest/blueshield/jacket + gloves = /obj/item/clothing/gloves/tackler/combat + id = /obj/item/card/id/advanced/centcom + shoes = /obj/item/clothing/shoes/jackboots + ears = /obj/item/radio/headset/headset_bs/alt + glasses = /obj/item/clothing/glasses/hud/security/sunglasses + implants = list(/obj/item/implant/mindshield) backpack_contents = list( - /obj/item/ammo_box/magazine/m35/rubber = 2, - /obj/item/restraints/handcuffs/cable/zipties = 1, - /obj/item/reagent_containers/spray/pepper = 1, - /obj/item/shield/riot/tele = 1 + /obj/item/choice_beacon/blueshield = 1, ) - head = /obj/item/clothing/head/beret/blueshield - suit = /obj/item/clothing/suit/armor/vest/blueshield/jacket - - belt = /obj/item/modular_computer/pda/security - shoes = /obj/item/clothing/shoes/sneakers/black - l_pocket = /obj/item/citationinator - r_pocket = /obj/item/assembly/flash/handheld - glasses = /obj/item/clothing/glasses/hud/security - ears = /obj/item/radio/headset/headset_com - gloves = /obj/item/clothing/gloves/color/black - shoes = /obj/item/clothing/shoes/jackboots/sec - backpack = /obj/item/storage/backpack/blueshield satchel = /obj/item/storage/backpack/satchel/blueshield duffelbag = /obj/item/storage/backpack/duffelbag/blueshield + head = /obj/item/clothing/head/beret/blueshield box = /obj/item/storage/box/survival/security + belt = /obj/item/modular_computer/pda/security + l_pocket = /obj/item/sensor_device/blueshield - implants = list(/obj/item/implant/mindshield) + id_trim = /datum/id_trim/job/blueshield + +/datum/outfit/plasmaman/blueshield + name = "Blueshield Plasmaman" + + head = /obj/item/clothing/head/helmet/space/plasmaman/blueshield + uniform = /obj/item/clothing/under/plasmaman/blueshield + +/datum/job_department/central_command + department_name = DEPARTMENT_CENTRAL_COMMAND + department_bitflags = DEPARTMENT_BITFLAG_CENTRAL_COMMAND + department_head = /datum/job/captain + department_experience_type = EXP_TYPE_CENTRAL_COMMAND + display_order = 1 + label_class = "command" + ui_color = "#86ff82" diff --git a/monkestation/code/modules/blueshield/landmarks.dm b/monkestation/code/modules/blueshield/landmarks.dm new file mode 100644 index 000000000000..e812eaee96b8 --- /dev/null +++ b/monkestation/code/modules/blueshield/landmarks.dm @@ -0,0 +1,2 @@ +/obj/effect/landmark/start/blueshield + name = "Blueshield" diff --git a/monkestation/code/modules/blueshield/modsuit/suit.dm b/monkestation/code/modules/blueshield/modsuit/suit.dm new file mode 100644 index 000000000000..7314f5f60f6a --- /dev/null +++ b/monkestation/code/modules/blueshield/modsuit/suit.dm @@ -0,0 +1,14 @@ +/obj/item/mod/control/pre_equipped/blueshield + worn_icon = 'monkestation/code/modules/blueshield/icons/worn_praetorian.dmi' + icon = 'monkestation/code/modules/blueshield/icons/praetorian.dmi' + icon_state = "praetorian-control" + theme = /datum/mod_theme/blueshield + applied_cell = /obj/item/stock_parts/cell/high + applied_modules = list( + /obj/item/mod/module/storage, + /obj/item/mod/module/magnetic_harness, + /obj/item/mod/module/flashlight, + /obj/item/mod/module/projectile_dampener, + /obj/item/mod/module/quick_carry, + /obj/item/mod/module/holster, + ) diff --git a/monkestation/code/modules/blueshield/modsuit/theme.dm b/monkestation/code/modules/blueshield/modsuit/theme.dm new file mode 100644 index 000000000000..ca1bd0838c52 --- /dev/null +++ b/monkestation/code/modules/blueshield/modsuit/theme.dm @@ -0,0 +1,59 @@ +/datum/mod_theme/blueshield + name = "praetorian" + desc = "A prototype of the Magnate-class suit issued to station Blueshields, still boasting exceptional protection worthy of an honor guard." + extended_desc = "A prototype of the Magnate-class suit issued for use with the station Blueshields, \ + it boasts the exceptional protection of its successor, while sacrificing some of the module capacity.\ + All of the protection of the Magnate, with none of the comfort! The visor uses blue-light to obscure \ + the face of its wearer, adding to its imposing figure. Compared to the sleek and luxurious design \ + that came after it, this suit does nothing to hide its purpose, the reinforced plating layered \ + over the insulated inner armor granting it protection against corrosive liquids, explosive blasts, \ + fires, electrical shocks, and contempt from the rest of the crew." + + default_skin = "praetorian" + armor_type = /datum/armor/mod_theme_security + atom_flags = PREVENT_CONTENTS_EXPLOSION_1 + slowdown_inactive = 1 + slowdown_active = 0.5 + allowed_suit_storage = list( + /obj/item/reagent_containers/spray/pepper, + /obj/item/restraints/handcuffs, + /obj/item/assembly/flash, + /obj/item/melee/baton, + ) + skins = list( + "praetorian" = list( + MOD_ICON_OVERRIDE = 'monkestation/code/modules/blueshield/icons/praetorian.dmi', + MOD_WORN_ICON_OVERRIDE = 'monkestation/code/modules/blueshield/icons/worn_praetorian.dmi', + HELMET_FLAGS = list( + UNSEALED_LAYER = null, + UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS, + UNSEALED_INVISIBILITY = HIDEEARS|HIDEHAIR, + SEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEYES|HIDEFACE|HIDESNOUT, + SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF, + UNSEALED_MESSAGE = HELMET_UNSEAL_MESSAGE, + SEALED_MESSAGE = HELMET_SEAL_MESSAGE, + ), + CHESTPLATE_FLAGS = list( + UNSEALED_CLOTHING = THICKMATERIAL, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + SEALED_INVISIBILITY = HIDEJUMPSUIT, + UNSEALED_MESSAGE = CHESTPLATE_UNSEAL_MESSAGE, + SEALED_MESSAGE = CHESTPLATE_SEAL_MESSAGE, + ), + GAUNTLETS_FLAGS = list( + UNSEALED_CLOTHING = THICKMATERIAL, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + CAN_OVERSLOT = TRUE, + UNSEALED_MESSAGE = GAUNTLET_UNSEAL_MESSAGE, + SEALED_MESSAGE = GAUNTLET_SEAL_MESSAGE, + ), + BOOTS_FLAGS = list( + UNSEALED_CLOTHING = THICKMATERIAL, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + CAN_OVERSLOT = TRUE, + UNSEALED_MESSAGE = BOOT_UNSEAL_MESSAGE, + SEALED_MESSAGE = BOOT_SEAL_MESSAGE, + ), + ), + ) diff --git a/monkestation/code/modules/blueshield/radio.dm b/monkestation/code/modules/blueshield/radio.dm new file mode 100644 index 000000000000..deddf9bc4eb8 --- /dev/null +++ b/monkestation/code/modules/blueshield/radio.dm @@ -0,0 +1,6 @@ +/obj/item/encryptionkey/heads/blueshield + name = "\proper the blueshield's encryption key" + icon_state = "cypherkey_centcom" + channels = list(RADIO_CHANNEL_COMMAND = 1, RADIO_CHANNEL_SECURITY = 1) + greyscale_config = /datum/greyscale_config/encryptionkey_centcom + greyscale_colors = "#1d2657#dca01b" diff --git a/monkestation/code/modules/blueshield/readme.md b/monkestation/code/modules/blueshield/readme.md new file mode 100644 index 000000000000..e136884a3158 --- /dev/null +++ b/monkestation/code/modules/blueshield/readme.md @@ -0,0 +1,24 @@ +## Title: + + +MODULE ID: BLUESHIELD + +### Description: + +This pr adds blueshield as a job into the correct folders + + +### Included files that are not contained in this module: + + - code/modules/jobs/jobs.dm > GLOBAL_LIST_INIT(security_positions, list() + - code/modules/jobs/access.dm > /proc/get_all_accesses() + + + + +### Credits: + + + +Job Ported by Kitsunemitsu +Items Ported by Dwasint diff --git a/monkestation/code/modules/blueshield/trim.dm b/monkestation/code/modules/blueshield/trim.dm new file mode 100644 index 000000000000..c1f35f30a688 --- /dev/null +++ b/monkestation/code/modules/blueshield/trim.dm @@ -0,0 +1,33 @@ +/datum/id_trim/job/blueshield + assignment = "Blueshield" + trim_state = "trim_blueshield" + department_color = COLOR_COMMAND_BLUE + subdepartment_color = COLOR_SECURITY_RED + sechud_icon_state = SECHUD_BLUESHIELD + extra_access = list( + ACCESS_BRIG, + ACCESS_CARGO, + ACCESS_COURT, + ACCESS_GATEWAY, + ) + minimal_access = list( + ACCESS_SECURITY, + ACCESS_ALL_PERSONAL_LOCKERS, + ACCESS_BRIG_ENTRANCE, + ACCESS_CENT_GENERAL, + ACCESS_COMMAND, + ACCESS_CONSTRUCTION, + ACCESS_ENGINEERING, + ACCESS_EVA, + ACCESS_MAINT_TUNNELS, + ACCESS_MEDICAL, + ACCESS_MINERAL_STOREROOM, + ACCESS_SCIENCE, + ACCESS_TELEPORTER, + ACCESS_WEAPONS, + ) + template_access = list( + ACCESS_CAPTAIN, + ACCESS_CHANGE_IDS + ) + job = /datum/job/blueshield diff --git a/monkestation/code/modules/blueshift/appliances/colony.dm b/monkestation/code/modules/blueshift/appliances/colony.dm index c25fb1fd0a81..1b3e683f427c 100644 --- a/monkestation/code/modules/blueshift/appliances/colony.dm +++ b/monkestation/code/modules/blueshift/appliances/colony.dm @@ -7,7 +7,10 @@ but good old electricity." icon = 'monkestation/code/modules/blueshift/icons/chemistry_machines.dmi' icon_state = "water_synth" + active_power_usage = 0 + amount = 100 anchored = FALSE + reagent_id = /datum/reagent/water /// Reagents that this can dispense, overrides the default list on init var/static/list/synthesizable_reagents = list( /datum/reagent/water, @@ -21,6 +24,9 @@ AddElement(/datum/element/repackable, repacked_type, 2 SECONDS) AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER) +/obj/machinery/plumbing/synthesizer/water_synth/ui_interact(mob/user, datum/tgui/ui) + return FALSE // nah its a flat 100 with no drain + // Deployable item for cargo for the water synth /obj/item/flatpacked_machine/water_synth diff --git a/monkestation/code/modules/blueshift/areas/station.dm b/monkestation/code/modules/blueshift/areas/station.dm index b16c6f06bfb3..fff014bc55a8 100644 --- a/monkestation/code/modules/blueshift/areas/station.dm +++ b/monkestation/code/modules/blueshift/areas/station.dm @@ -31,12 +31,6 @@ icon = 'monkestation/code/modules/blueshift/icons/areas/areas_station.dmi' icon_state = "nt_rep" -// Blueshield area -/area/station/command/heads_quarters/blueshield - name = "Blueshield's Office" - icon = 'monkestation/code/modules/blueshift/icons/areas/areas_station.dmi' - icon_state = "blueshield" - /* * Department areas */ diff --git a/monkestation/code/modules/blueshift/benos/human_changes.dm b/monkestation/code/modules/blueshift/benos/human_changes.dm index f7beb903e2cc..2264d87464aa 100644 --- a/monkestation/code/modules/blueshift/benos/human_changes.dm +++ b/monkestation/code/modules/blueshift/benos/human_changes.dm @@ -27,6 +27,7 @@ /mob/living/carbon/alien/adult/nova/Initialize(mapload) . = ..() AddComponent(/datum/component/seethrough_mob) + set_pain_mod("ALIEN", 0) GRANT_ACTION(/datum/action/cooldown/alien/nova/sleepytime) if(next_evolution) diff --git a/monkestation/code/modules/blueshift/clothing/nova_command.dm b/monkestation/code/modules/blueshift/clothing/nova_command.dm index cb8451f56e86..69cfe7abd0c6 100644 --- a/monkestation/code/modules/blueshift/clothing/nova_command.dm +++ b/monkestation/code/modules/blueshift/clothing/nova_command.dm @@ -29,58 +29,6 @@ icon_state = "captainblacksuit" can_adjust = FALSE -/* -* BLUESHIELD -*/ -//Why is this in command.dm? Simple: Centcom.dmi will already be packed with CC/NTNavy/AD/LL/SOL/FTU - all of them more event-based clothes, while this will appear -//on-station often. - -/obj/item/clothing/under/rank/blueshield - icon = 'monkestation/code/modules/blueshift/icons/obj/clothing/under/command.dmi' - worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/under/command.dmi' - worn_icon_digitigrade = 'monkestation/code/modules/blueshift/icons/mob/clothing/under/command_digi.dmi' - name = "blueshield's suit" - desc = "A classic bodyguard's suit, with custom-fitted Blueshield-Blue cuffs and a Nanotrasen insignia over one of the pockets." - icon_state = "blueshield" - strip_delay = 50 - armor_type = /datum/armor/clothing_under/rank_blueshield - sensor_mode = SENSOR_COORDS - random_sensor = FALSE - alt_covers_chest = TRUE - -/datum/armor/clothing_under/rank_blueshield - melee = 10 - bullet = 5 - laser = 5 - energy = 10 - bomb = 10 - fire = 50 - acid = 50 - -/obj/item/clothing/under/rank/blueshield/skirt - name = "blueshield's suitskirt" - desc = "A classic bodyguard's suitskirt, with custom-fitted Blueshield-Blue cuffs and a Nanotrasen insignia over one of the pockets." - icon_state = "blueshieldskirt" - body_parts_covered = CHEST|GROIN|ARMS - dying_key = DYE_REGISTRY_JUMPSKIRT - female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY - supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON - - -/obj/item/clothing/under/rank/blueshield/turtleneck - name = "blueshield's turtleneck" - desc = "A tactical jumper fit for only the best of bodyguards, with plenty of tactical pockets for your tactical needs." - icon_state = "bs_turtleneck" - -/obj/item/clothing/under/rank/blueshield/turtleneck/skirt - name = "blueshield's skirtleneck" - desc = "A tactical jumper fit for only the best of bodyguards - instead of tactical pockets, this one has a tactical lack of leg protection." - icon_state = "bs_skirtleneck" - body_parts_covered = CHEST|GROIN|ARMS - dying_key = DYE_REGISTRY_JUMPSKIRT - female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY - supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON - /* * NT CONSULTANT diff --git a/monkestation/code/modules/blueshift/clothing/nova_neck.dm b/monkestation/code/modules/blueshift/clothing/nova_neck.dm index 4a4835d562cd..e999df7ece5b 100644 --- a/monkestation/code/modules/blueshift/clothing/nova_neck.dm +++ b/monkestation/code/modules/blueshift/clothing/nova_neck.dm @@ -58,13 +58,6 @@ worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/neck.dmi' icon_state = "hosmantle_blue" //There's a red version if you remove the _blue, but its not coded in currently. -/obj/item/clothing/neck/mantle/bsmantle - name = "\proper the blueshield's mantle" - desc = "A plated mantle with command colors. Suitable for the one assigned to making sure they're still breathing." - icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/neck.dmi' - worn_icon = 'monkestation/code/modules/blueshift/icons/mob/clothing/neck.dmi' - icon_state = "bsmantle" - /obj/item/clothing/neck/mantle/capmantle name = "\proper the captain's mantle" desc = "A formal mantle to drape around the shoulders. Others stand on the shoulders of giants. You're the giant they stand on." diff --git a/monkestation/code/modules/blueshift/components/armament.dm b/monkestation/code/modules/blueshift/components/armament.dm index 78542490beb9..c7a8ea7f90f0 100644 --- a/monkestation/code/modules/blueshift/components/armament.dm +++ b/monkestation/code/modules/blueshift/components/armament.dm @@ -29,8 +29,17 @@ required_access = needed_access - RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(on_attack_hand)) - RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) + if(!istype(parent, /obj/item/armament_points_card)) + RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(on_attack_hand)) + RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) + else + RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND_SECONDARY, PROC_REF(on_attack_hand)) + RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(on_attack_hand)) + RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF_SECONDARY, PROC_REF(on_attack_hand)) + var/atom/atom_target = parent + atom_target.flags_1 |= HAS_CONTEXTUAL_SCREENTIPS_1 + RegisterSignal(parent, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(context)) + inserted_card = parent /datum/component/armament/Destroy(force) if(inserted_card) @@ -38,6 +47,16 @@ inserted_card = null return ..() +/datum/component/armament/proc/context(datum/source, + list/context, + obj/item/held_item, + mob/user, +) + PRIVATE_PROC(TRUE) + SIGNAL_HANDLER + context[SCREENTIP_CONTEXT_RMB] = "Open Armament Store" + return CONTEXTUAL_SCREENTIP_SET + /datum/component/armament/proc/on_attackby(atom/target, obj/item, mob/user) SIGNAL_HANDLER @@ -141,6 +160,8 @@ buy_ammo(usr, check, params["quantity"]) SStgui.update_uis(src) if("eject_card") + if(istype(parent, /obj/item/armament_points_card)) + return eject_card(usr) SStgui.update_uis(src) diff --git a/monkestation/code/modules/blueshift/icons/mob/clothing/ears.dmi b/monkestation/code/modules/blueshift/icons/mob/clothing/ears.dmi new file mode 100644 index 000000000000..4fdd7765ee58 Binary files /dev/null and b/monkestation/code/modules/blueshift/icons/mob/clothing/ears.dmi differ diff --git a/monkestation/code/modules/blueshift/items/ammo.dm b/monkestation/code/modules/blueshift/items/ammo.dm index 19f78deb4230..405abf2b71d4 100644 --- a/monkestation/code/modules/blueshift/items/ammo.dm +++ b/monkestation/code/modules/blueshift/items/ammo.dm @@ -286,7 +286,7 @@ /obj/projectile/bullet/c35sol name = ".35 Sol Short bullet" - damage = 20 + damage = 15 wound_bonus = -5 // Normal bullets are 20 bare_wound_bonus = 5 @@ -369,7 +369,7 @@ /obj/projectile/bullet/c35sol/ripper name = ".35 Sol ripper bullet" - damage = 15 + damage = 12 weak_against_armour = TRUE diff --git a/monkestation/code/modules/blueshift/items/company_guns.dm b/monkestation/code/modules/blueshift/items/company_guns.dm index 1377d24126e3..05719ce95ce4 100644 --- a/monkestation/code/modules/blueshift/items/company_guns.dm +++ b/monkestation/code/modules/blueshift/items/company_guns.dm @@ -131,7 +131,8 @@ fire_delay = 0.1 SECONDS - recoil = 1 + recoil = 2 + wield_recoil = 0.5 spread = 12.5 projectile_wound_bonus = -20 @@ -420,7 +421,7 @@ suppressor_x_offset = 9 - burst_size = 1 + burst_size = 2 fire_delay = 0.15 SECONDS actions_types = list() @@ -429,6 +430,7 @@ spread = 12.5 // Hope you didn't need to see anytime soon recoil = 2 + wield_recoil = 0.5 /obj/item/gun/ballistic/automatic/xhihao_smg/give_manufacturer_examine() AddElement(/datum/element/manufacturer_examine, COMPANY_XHIHAO) @@ -517,6 +519,7 @@ fire_delay = 1 SECONDS recoil = 3 + wield_recoil = 1 /obj/item/gun/ballistic/revolver/takbok/give_manufacturer_examine() AddElement(/datum/element/manufacturer_examine, COMPANY_TRAPPISTE) @@ -627,6 +630,7 @@ fire_delay = 1 SECONDS recoil = 3 + wield_recoil = 1 /obj/item/gun/ballistic/automatic/pistol/trappiste/give_manufacturer_examine() AddElement(/datum/element/manufacturer_examine, COMPANY_TRAPPISTE) @@ -761,7 +765,8 @@ fire_delay = 1.2 SECONDS actions_types = list() - recoil = 0.5 + recoil = 1.5 + wield_recoil = 0.5 spread = 2.5 projectile_wound_bonus = -20 @@ -824,6 +829,7 @@ fire_sound_volume = 100 // BOOM BABY recoil = 4 + wield_recoil = 2 weapon_weight = WEAPON_HEAVY burst_size = 1 @@ -962,6 +968,7 @@ desc = "An outdated sidearm rarely seen in use by some members of the CIN. A revolver type design with a four shell cylinder. That's right, shell, this one shoots twelve guage." accepted_magazine_type = /obj/item/ammo_box/magazine/internal/cylinder/rev12ga recoil = SAWN_OFF_RECOIL + wield_recoil = SAWN_OFF_RECOIL * 0.5 weapon_weight = WEAPON_MEDIUM icon = 'monkestation/code/modules/blueshift/icons/obj/company_and_or_faction_based/szot_dynamica/guns_32.dmi' icon_state = "bobr" @@ -1001,7 +1008,7 @@ bolt_type = BOLT_TYPE_OPEN - w_class = WEIGHT_CLASS_NORMAL + w_class = WEIGHT_CLASS_BULKY weapon_weight = WEAPON_MEDIUM slot_flags = ITEM_SLOT_SUITSTORE | ITEM_SLOT_BELT @@ -1015,8 +1022,8 @@ suppressor_x_offset = 11 - burst_size = 3 - fire_delay = 0.2 SECONDS + burst_size = 2 + fire_delay = 0.35 SECONDS spread = 7.5 @@ -1339,3 +1346,15 @@ #undef SHORT_MOD_LASER_SPEECH #undef MOD_LASER_SPEECH_COOLDOWN #undef DEFAULT_RUNECHAT_GUN_COLOR + +/obj/item/gun/ballistic/proc/on_wield() + SIGNAL_HANDLER + + recoil = wield_recoil + spread = spread * 0.75 + +/obj/item/gun/ballistic/proc/on_unwield() + SIGNAL_HANDLER + + recoil = initial(recoil) + spread = initial(spread) diff --git a/monkestation/code/modules/blueshift/items/deforest.dm b/monkestation/code/modules/blueshift/items/deforest.dm index fcaa75e0f7d7..1cbd5ffcbf51 100644 --- a/monkestation/code/modules/blueshift/items/deforest.dm +++ b/monkestation/code/modules/blueshift/items/deforest.dm @@ -348,7 +348,7 @@ base_icon_state = "morpital" icon_state = "morpital" list_reagents = list( - /datum/reagent/medicine/morphine = 5, + /datum/reagent/medicine/painkiller/morphine = 5, /datum/reagent/medicine/omnizine/protozine = 15, /datum/reagent/toxin/staminatoxin = 5, ) diff --git a/monkestation/code/modules/blueshift/items/magazines.dm b/monkestation/code/modules/blueshift/items/magazines.dm index c1b4f6b5b15b..2c1770049ecf 100644 --- a/monkestation/code/modules/blueshift/items/magazines.dm +++ b/monkestation/code/modules/blueshift/items/magazines.dm @@ -20,13 +20,13 @@ /obj/item/ammo_box/magazine/c35sol_pistol/stendo name = "\improper Sol extended pistol magazine" - desc = "An extended magazine for SolFed pistols, holds twenty-four rounds." + desc = "An extended magazine for SolFed pistols, holds sixteen rounds." icon_state = "pistol_35_stended" w_class = WEIGHT_CLASS_NORMAL - max_ammo = 24 + max_ammo = 16 /obj/item/ammo_box/magazine/c35sol_pistol/stendo/starts_empty start_empty = TRUE @@ -116,7 +116,7 @@ /obj/item/ammo_box/magazine/c585trappiste_pistol name = "\improper Trappiste pistol magazine" - desc = "A standard size magazine for Trappiste pistols, holds six rounds." + desc = "A standard size magazine for Trappiste pistols, holds sixteen rounds." icon = 'monkestation/code/modules/blueshift/icons/obj/company_and_or_faction_based/trappiste_fabriek/ammo.dmi' icon_state = "pistol_585_standard" @@ -127,7 +127,7 @@ ammo_type = /obj/item/ammo_casing/c585trappiste caliber = CALIBER_585TRAPPISTE - max_ammo = 6 + max_ammo = 16 /obj/item/ammo_box/magazine/c585trappiste_pistol/spawns_empty start_empty = TRUE diff --git a/monkestation/code/modules/blueshift/machines/station_armament.dm b/monkestation/code/modules/blueshift/machines/station_armament.dm index efda34c95c60..85f77452549b 100644 --- a/monkestation/code/modules/blueshift/machines/station_armament.dm +++ b/monkestation/code/modules/blueshift/machines/station_armament.dm @@ -41,9 +41,14 @@ w_class = WEIGHT_CLASS_TINY /// How many points does this card have to use at the vendor? var/points = 10 + var/armament_type + var/list/access /obj/item/armament_points_card/Initialize(mapload) . = ..() + if(armament_type) + AddComponent(/datum/component/armament, subtypesof(armament_type), access) + maptext = span_maptext("
[points]
") /obj/item/armament_points_card/examine(mob/user) diff --git a/monkestation/code/modules/blueshift/machines/thumper.dm b/monkestation/code/modules/blueshift/machines/thumper.dm index 9531db06035c..56c5c6c2b61f 100644 --- a/monkestation/code/modules/blueshift/machines/thumper.dm +++ b/monkestation/code/modules/blueshift/machines/thumper.dm @@ -44,15 +44,15 @@ ) /// How much of the listed types of ores should we spawn when spawning ore var/static/list/ore_spawn_values = list( - /obj/item/stack/ore/iron = 25, - /obj/item/stack/ore/glass/basalt = 25, - /obj/item/stack/ore/plasma = 15, - /obj/item/stack/ore/uranium = 10, - /obj/item/stack/ore/silver = 10, - /obj/item/stack/ore/gold = 10, - /obj/item/stack/ore/titanium = 10, - /obj/item/stack/ore/diamond = 5, - /obj/item/stack/ore/bluespace_crystal = 1, + /obj/item/stack/ore/iron = 8000, + /obj/item/stack/ore/glass/basalt = 8000, + /obj/item/stack/ore/plasma = 7000, + /obj/item/stack/ore/uranium = 6000, + /obj/item/stack/ore/silver = 4000, + /obj/item/stack/ore/gold = 4000, + /obj/item/stack/ore/titanium = 4000, + /obj/item/stack/ore/diamond = 2500, + /obj/item/stack/ore/bluespace_crystal = 1000, ) /// What's the limit for ore near us? Counts by stacks, not individual amounts of ore var/nearby_ore_limit = 5 @@ -204,7 +204,7 @@ var/is_there_a_thumper_too = FALSE for(var/turf/nearby_turf in orange(ore_spawn_range, src)) for(var/ore as anything in nearby_turf.contents) - if(istype(ore, /obj/item/stack/ore)) + if(istype(ore, /obj/item/boulder)) nearby_ore += 1 continue if(istype(ore, /obj/machinery/power/colony_ore_thumper)) @@ -243,8 +243,16 @@ for(var/iteration in 1 to rand(2, 4)) var/turf/target_turf = pick(nearby_valid_turfs) - var/obj/item/stack/new_ore = pick_weight(ore_weight_list) - new new_ore(target_turf, ore_spawn_values[new_ore.type]) + var/obj/item/stack/ore/new_ore = pick_weight(ore_weight_list) + var/obj/item/stack/ore/created_ore = new new_ore + var/obj/item/boulder/new_boulder = new (target_turf) + + var/list/new_mats = list() + for(var/datum/material/material as anything in created_ore.mats_per_unit) + new_mats[material] = ore_spawn_values[created_ore.type] + + qdel(created_ore) + new_boulder.set_custom_materials(new_mats) slam_jams -= slam_jams_needed diff --git a/monkestation/code/modules/blueshift/reagents/deforest.dm b/monkestation/code/modules/blueshift/reagents/deforest.dm index ca8751c02f28..556d1b96df25 100644 --- a/monkestation/code/modules/blueshift/reagents/deforest.dm +++ b/monkestation/code/modules/blueshift/reagents/deforest.dm @@ -13,6 +13,7 @@ /datum/reagent/medicine/lidocaine/overdose_process(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() + affected_mob.cause_pain(BODY_ZONES_ALL, -1 * REM * seconds_per_tick) affected_mob.adjustOrganLoss(ORGAN_SLOT_HEART,3 * REM * seconds_per_tick, 80) //Inverse Medicines// @@ -306,6 +307,7 @@ else // Much longer than that however, and you're not gonna have a good day if(!(our_guy.mob_biotypes & MOB_ROBOTIC)) our_guy.spray_blood(our_guy.dir, 2) // The before mentioned coughing up blood + our_guy.blood_particles(amount = rand(3, 6), angle = 0, min_deviation = 0, max_deviation = 360) our_guy.emote("cough") our_guy.visible_message( span_danger("[our_guy] suddenly snaps back from [our_guy.p_their()] inhuman speeds, coughing up a spray of blood!"), @@ -410,6 +412,7 @@ if(SPT_PROB(5, seconds_per_tick) && !(our_guy.mob_biotypes & MOB_ROBOTIC)) to_chat(our_guy, span_danger("You cough up a splatter of blood!")) our_guy.spray_blood(our_guy.dir, 1) + our_guy.blood_particles(amount = rand(3, 6), angle = 0, min_deviation = 0, max_deviation = 360) our_guy.emote("cough") if(SPT_PROB(10, seconds_per_tick)) diff --git a/monkestation/code/modules/blueshift/structures/locker.dm b/monkestation/code/modules/blueshift/structures/locker.dm index e44321f0875f..ce8340aac777 100644 --- a/monkestation/code/modules/blueshift/structures/locker.dm +++ b/monkestation/code/modules/blueshift/structures/locker.dm @@ -15,39 +15,6 @@ new /obj/item/clothing/head/helmet/toggleable/riot(src) new /obj/item/shield/riot(src) -/obj/item/storage/bag/garment/blueshield - name = "blueshield's garment bag" - desc = "A bag for storing extra clothes and shoes. This one belongs to the blueshield." - -/obj/item/storage/bag/garment/blueshield/PopulateContents() - new /obj/item/clothing/suit/hooded/wintercoat/nova/blueshield(src) - new /obj/item/clothing/head/beret/blueshield(src) - new /obj/item/clothing/head/beret/blueshield/navy(src) - new /obj/item/clothing/under/rank/blueshield(src) - new /obj/item/clothing/under/rank/blueshield/skirt(src) - new /obj/item/clothing/under/rank/blueshield/turtleneck(src) - new /obj/item/clothing/under/rank/blueshield/turtleneck/skirt(src) - new /obj/item/clothing/suit/armor/vest/blueshield(src) - new /obj/item/clothing/suit/armor/vest/blueshield/jacket(src) - new /obj/item/clothing/neck/mantle/bsmantle(src) - -/obj/structure/closet/secure_closet/blueshield - name = "blueshield's locker" - icon_state = "bs" - icon = 'monkestation/code/modules/blueshift/icons/obj/closet.dmi' - req_access = list(ACCESS_CAPTAIN) - -/obj/structure/closet/secure_closet/blueshield/New() - ..() - new /obj/item/storage/briefcase/secure(src) - new /obj/item/storage/belt/security/full(src) - new /obj/item/grenade/flashbang(src) - new /obj/item/assembly/flash/handheld(src) - new /obj/item/restraints/handcuffs(src) - new /obj/item/clothing/glasses/hud/security/sunglasses(src) - new /obj/item/storage/medkit/frontier/stocked(src) - new /obj/item/storage/bag/garment/blueshield(src) - /obj/structure/closet/secure_closet/nanotrasen_consultant name = "nanotrasen consultant's locker" diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/bottler.dm b/monkestation/code/modules/brewin_and_chewin/brewing/bottler.dm new file mode 100644 index 000000000000..69f4d333a4ec --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/bottler.dm @@ -0,0 +1,53 @@ +/obj/item/bottle_kit + name = "Bottling Kit" + desc = "A box that holds glasses fabricators, lables, caps and quarks ready for home brewing and bottling." + icon = 'monkestation/code/modules/brewin_and_chewin/icons/objects.dmi' + icon_state = "bottler_box" + w_class = WEIGHT_CLASS_NORMAL + custom_materials = list(/datum/material/iron = 2000, /datum/material/glass = 4000) + var/glass_colour = "brew_bottle" + var/fake_glass_name = "Kinda Blue" + +/obj/item/bottle_kit/examine(mob/user) + . = ..() + . += span_info("Current Glass Bottle Printing Type: [fake_glass_name].") + + +/obj/item/bottle_kit/attack_self(mob/user as mob) + ..() + glass_picker(user) + +/obj/item/bottle_kit/proc/glass_picker(mob/user as mob) + var/list/options = list() + options["Kinda Blue"] = "brew_bottle" + options["Redish"] = "brew_red_bottle" + options["Green-Adjcent"] = "brew_green_bottle" + options["Scuffed Platium"] = "brew_white_bottle" + options["Sorta Coal"] = "brew_coal_bottle" + options["Maybe Bronze"] = "brew_fancy_bottle" + options["Off-Amethyst"] = "brew_funky_bottle" + options["Odd Sky Shade"] = "brew_sky_bottle" + options["Washed Out Brass"] = "brew_saint_po_bottle" + options["Faded Caramel"] = "brew_gold_bottle" + options["Approximate Sea Shore"] = "brew_pianowoman_bottle" + options["Faded Dust"] = "brew_noir_bottle" + options["Close Honeycomb"] = "brew_bees_bottle" + + + if(!options.len) + to_chat(user, span_info("The bottle kit is limited to only normal blue bottles. Oh no!")) + glass_colour = "brew_bottle" + fake_glass_name = "Blue" + return + + var/choice = tgui_input_list(user, "What colour do you pick?", name, options) + + var/printing_choice = options[choice] + + if(!printing_choice) + glass_colour = "brew_bottle" + fake_glass_name = "Kinda Blue" + return + + fake_glass_name = choice + glass_colour = printing_choice diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/bottles.dm b/monkestation/code/modules/brewin_and_chewin/brewing/bottles.dm new file mode 100644 index 000000000000..bb7157e2ec16 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/bottles.dm @@ -0,0 +1,19 @@ +/obj/item/reagent_containers/cup/glass/bottle/small/brewing_bottle + name = "Flash Bottle" + desc = "A quickly printed bottle using a non-recycleable glass." + icon = 'monkestation/code/modules/brewin_and_chewin/icons/bottle.dmi' + icon_state = "brew_bottle" + + var/glass_name + var/glass_desc + +/obj/item/reagent_containers/cup/glass/bottle/small/brewing_bottle/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(target.type in typesof(/obj/item/reagent_containers/cup/glass) - typesof(/obj/item/reagent_containers/cup/glass/bottle)) + if(glass_name) + target.name = glass_name + if(glass_desc) + target.desc = glass_desc + if(reagents.total_volume <= 0) + glass_desc = null + glass_name = null diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/designs.dm b/monkestation/code/modules/brewin_and_chewin/brewing/designs.dm new file mode 100644 index 000000000000..644e17339dac --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/designs.dm @@ -0,0 +1,23 @@ +/datum/design/bottling_kit + name = "Bottling Kit" + id = "bottling_kit" + build_type = AUTOLATHE + materials = list(/datum/material/glass=2000, /datum/material/iron=2000) + build_path = /obj/item/bottle_kit + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_KITCHEN, + ) + departmental_flags = DEPARTMENT_BITFLAG_SERVICE + +/datum/design/recipe_card + name = "Fermentation Recipe Card" + id = "recipe_card" + build_type = AUTOLATHE + materials = list(/datum/material/iron=100) + build_path = /obj/item/recipe_card + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_KITCHEN, + ) + departmental_flags = DEPARTMENT_BITFLAG_SERVICE diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/fermintation_keg.dm b/monkestation/code/modules/brewin_and_chewin/brewing/fermintation_keg.dm new file mode 100644 index 000000000000..ba4f66a5f3da --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/fermintation_keg.dm @@ -0,0 +1,302 @@ +GLOBAL_LIST_EMPTY(custom_fermentation_recipes) + +/obj/structure/fermentation_keg + name = "fermentation keg" + desc = "A simple keg that is meant for making booze." + + icon = 'monkestation/code/modules/brewin_and_chewin/icons/objects.dmi' + icon_state = "barrel_tapless" + + density = TRUE + + /// The sound of fermentation + var/datum/looping_sound/boiling/soundloop + /// The volume of the barrel sounds + var/sound_volume = 25 + var/open_icon_state = "barrel_tapless_open" + + //After brewing we can sell or bottle, this is for the latter + var/ready_to_bottle = FALSE + var/brewing = FALSE + + ///our currently needed crops + var/list/recipe_crop_stocks + ///our currently selected recipe + var/datum/brewing_recipe/selected_recipe + ///our current price value used by exports + var/price_tag = 0 + ///our made item which we clear once its no longer ready to bottle + var/made_item + + + +/obj/structure/fermentation_keg/Initialize() + . = ..() + create_reagents(240, OPENCONTAINER | NO_REACT) //on agv it should be 120u for water then rest can be other needed chemicals + recipe_crop_stocks = list() + + soundloop = new(src, brewing) + soundloop.volume = sound_volume + +/obj/structure/fermentation_keg/attack_hand(mob/user) + if(!brewing && (!selected_recipe || ready_to_bottle)) + shopping_run(user) + return + + if(try_n_brew(user)) + start_brew() + ..() + +/obj/structure/fermentation_keg/attackby(obj/item/I, mob/user) + var/list/produce_list = list() + var/obj/item/storage/bag/plants/storage + + if(istype(I, /obj/item/bottle_kit)) + var/obj/item/bottle_kit/kit = I + bottle(kit.glass_colour) + + if(I.type in selected_recipe?.needed_items) + produce_list += I + + if(istype(I, /obj/item/food/grown)) + produce_list += I + + if(istype(I, /obj/item/storage/bag/plants)) + storage = I + for(var/obj/item/food/grown/item in storage.contents) + produce_list += item + + for(var/obj/item/food/grown/G in produce_list) + if(G.type in selected_recipe?.needed_crops) + var/amount = recipe_crop_stocks[G.type] || 0 + var/added_item = round(min(10, max(1, G.seed.potency / 10))) + recipe_crop_stocks[G.type] = amount + added_item + qdel(G) + + for(var/obj/item/item in produce_list) + if(item.type in selected_recipe?.needed_items) + var/amount = recipe_crop_stocks[item.type] || 0 + var/added_item = 1 + recipe_crop_stocks[item.type] = amount + added_item + qdel(item) + + . = ..() + +/obj/structure/fermentation_keg/examine(mob/user) + . =..() + if(ready_to_bottle) + . += span_boldnotice("[made_item]") + . += span_notice("Value: [price_tag]") + + else if(selected_recipe) + var/message = "Currently making: [selected_recipe.display_name].\n" + + for(var/datum/reagent/required_chem as anything in selected_recipe.needed_reagents) + message += "Reagent Needed: [initial(required_chem.name)] [selected_recipe.needed_reagents[required_chem]].\n" + + for(var/obj/item/food/grown/required_crop as anything in selected_recipe.needed_crops) + message += "Crop Needed: [capitalize(initial(required_crop.name))] [selected_recipe.needed_crops[required_crop]], Current Amount: [recipe_crop_stocks[required_crop] || 0].\n" + + for(var/obj/item/needed_item as anything in selected_recipe.needed_items) + message += "Item Needed: [capitalize(initial(needed_item.name))] [selected_recipe.needed_items[needed_item]], Current Amount: [recipe_crop_stocks[needed_item] || 0].\n" + + //time + if(selected_recipe.brew_time) + if(selected_recipe.brew_time >= 1 MINUTES) + message += "Once set, will take [selected_recipe.brew_time / 600] Minutes.\n" + else + message += "Once set, will take [selected_recipe.brew_time / 10] Seconds.\n" + + //How many are brewed + if(selected_recipe.brewed_amount) + message += "Will produce [selected_recipe.brewed_amount] bottles when finished.\n" + + if(selected_recipe.brewed_item && selected_recipe.brewed_item_count) + var/name_to_use = selected_recipe.secondary_name + if(!name_to_use) + name_to_use = selected_recipe.display_name + message += "Will produce [name_to_use] x [selected_recipe.brewed_item_count] when finished.\n" + + if(selected_recipe.helpful_hints) + message += "[selected_recipe.helpful_hints].\n" + + if(istype(selected_recipe, /datum/brewing_recipe/custom_recipe)) + var/datum/brewing_recipe/custom_recipe/recipe = selected_recipe + message += "Recipe Created By:[recipe.made_by]" + . += message + + +/obj/structure/fermentation_keg/proc/shopping_run(mob/user) + if(brewing) + return + + var/list/options = list() + for(var/path in subtypesof(/datum/brewing_recipe) - /datum/brewing_recipe/custom_recipe) + var/datum/brewing_recipe/recipe = path + var/prereq = initial(recipe.pre_reqs) + if((!ready_to_bottle && prereq == null) || (selected_recipe?.reagent_to_brew == prereq && ready_to_bottle)) + options[initial(recipe.display_name)] = recipe + + + for(var/datum/brewing_recipe/recipe in GLOB.custom_fermentation_recipes) + var/prereq = recipe.pre_reqs + if((!ready_to_bottle && prereq == null) || (selected_recipe?.reagent_to_brew == prereq && ready_to_bottle)) + options[recipe.display_name] = recipe + + if(options.len == 0) + to_chat(user, "Their is no further brewing to be done, clear this barrel out or sell it.") + return + + var/choice = tgui_input_list(user,"What brew do you want to make?", name, options) + + if(!choice) + return + + var/choice_to_spawn = options[choice] + + if(istype(choice_to_spawn, /datum/brewing_recipe/custom_recipe)) + selected_recipe = choice_to_spawn + else + selected_recipe = new choice_to_spawn + + //Second stage brewing gives no refunds! - This is intented design to help make it so folks dont quit halfway through and still get a rebate + ready_to_bottle = FALSE + price_tag = 150 + icon_state = open_icon_state + +//Remove only chemicals +/obj/structure/fermentation_keg/proc/clear_keg_reagents() + if(reagents) + //consume consume consume consume + reagents.clear_reagents() + +//Remove and reset +/obj/structure/fermentation_keg/proc/clear_keg(force = FALSE) + if(brewing) + return FALSE + + if(!force && ready_to_bottle) + return FALSE + + if(reagents) + reagents.clear_reagents() + + ready_to_bottle = FALSE + made_item = null + icon_state = open_icon_state + + recipe_crop_stocks.Cut() + + price_tag = 150 + + if(force) + selected_recipe = null + + return TRUE + +/obj/structure/fermentation_keg/proc/start_brew() + brewing = TRUE + + for(var/obj/item/food/grown/item as anything in selected_recipe.needed_crops) + if(!(item in recipe_crop_stocks)) + return + var/amount = recipe_crop_stocks[item] || 0 + recipe_crop_stocks[item] = amount - selected_recipe.needed_crops[item] + + for(var/obj/item/item as anything in selected_recipe.needed_items) + if(!(item in recipe_crop_stocks)) + return + var/amount = recipe_crop_stocks[item] || 0 + recipe_crop_stocks[item] = amount - selected_recipe.needed_items[item] + + clear_keg_reagents() + + soundloop.start() + addtimer(CALLBACK(src, PROC_REF(end_brew)), selected_recipe.brew_time) + icon_state = initial(icon_state) + +/obj/structure/fermentation_keg/proc/end_brew() + icon_state = "barrel_tapless_ready" + soundloop.stop() + ready_to_bottle = TRUE + brewing = FALSE + price_tag = selected_recipe.cargo_valuation + made_item = selected_recipe.display_name + +/obj/structure/fermentation_keg/proc/try_n_brew(mob/user) + var/ready = TRUE + if(!selected_recipe) + if(user) + to_chat(user, span_notice("You need to set a booze to brew!")) + ready = FALSE + + if(brewing) + if(user) + to_chat(user, span_notice("This keg is already brewing a mix!")) + ready = FALSE + + //Crops + for(var/obj/item/food/grown/needed_crop as anything in selected_recipe.needed_crops) + if(recipe_crop_stocks[needed_crop] < selected_recipe.needed_crops[needed_crop]) + if(user) + to_chat(user, span_notice("This keg lacks [initial(needed_crop.name)]!")) + ready = FALSE + + for(var/obj/item/needed_item as anything in selected_recipe.needed_crops) + if(recipe_crop_stocks[needed_item] < selected_recipe.needed_items[needed_item]) + if(user) + to_chat(user, span_notice("This keg lacks [initial(needed_item.name)]!")) + ready = FALSE + + for(var/datum/reagent/required_chem as anything in selected_recipe.needed_reagents) + if(selected_recipe.needed_reagents[required_chem] > reagents.get_reagent_amount(required_chem)) + if(user) + to_chat(user, span_notice("The keg's unable to brew well lacking [initial(required_chem.name)]!")) + ready = FALSE + + return ready + + +/obj/structure/fermentation_keg/proc/bottle(glass_colour) + if(ready_to_bottle) + + ready_to_bottle = FALSE + made_item = null + brewing = FALSE + price_tag = 150 + icon_state = open_icon_state + + if(selected_recipe.reagent_to_brew) + if(!glass_colour) + glass_colour = "brew_bottle" + + var/bottlecaps + for(bottlecaps=0, bottlecaps < selected_recipe.brewed_amount, bottlecaps++) + var/obj/item/reagent_containers/cup/glass/bottle/small/brewing_bottle/bottle_made = new /obj/item/reagent_containers/cup/glass/bottle/small/brewing_bottle(get_turf(src)) + bottle_made.icon_state = "[glass_colour]" + if(istype(selected_recipe, /datum/brewing_recipe/custom_recipe)) + var/datum/brewing_recipe/custom_recipe/recipe = selected_recipe + bottle_made.name = recipe.bottle_name + bottle_made.desc = recipe.bottle_desc + bottle_made.glass_name = recipe.glass_name + bottle_made.glass_desc = recipe.glass_desc + bottle_made.reagents.add_reagent(selected_recipe.reagent_to_brew, selected_recipe.per_brew_amount, list("reagents" = recipe.reagent_data)) + else + bottle_made.reagents.add_reagent(selected_recipe.reagent_to_brew, selected_recipe.per_brew_amount) + + if(selected_recipe.brewed_item) + var/items_given + for(items_given= 0, items_given < selected_recipe.brewed_item_count, items_given++) + new selected_recipe.brewed_item(get_turf(src)) + selected_recipe = null + + +/obj/structure/fermentation_keg/verb/reset_keg() + set name = "Clear Keg (Completely Resets)" + set category = "Object" + set src in range(1) + + if(!isdead(usr)) + clear_keg(TRUE) + else + to_chat(usr, span_notice("Sadly this keg isnt brewing spirits!")) diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/reagents.dm b/monkestation/code/modules/brewin_and_chewin/brewing/reagents.dm new file mode 100644 index 000000000000..cf7297591407 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/reagents.dm @@ -0,0 +1,27 @@ +/datum/reagent/consumable/ethanol/melon_liquor + name = "Melon Liquor" + description = "A relatively sweet and fruity 46 proof liquor." + taste_description = "fruity alcohol" + color = "#138808d0" // rgb: 19, 136, 8 + boozepwr = 30 + +/datum/reagent/consumable/ethanol/poison_wine + name = "Fungal Wine" + description = "Is this even wine? Toxic! Hallucinogenic! Probably consumed in boatloads by your superiors!" + taste_description = "purified alcoholic death" + color = "#000000d0" + boozepwr = 1 + +/datum/reagent/consumable/ethanol/poison_wine/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) + . = ..() + drinker.adjust_hallucinations(1.5 SECONDS) + drinker.adjust_drugginess(5 SECONDS) + + drinker.adjustToxLoss(3 * seconds_per_tick) + +/datum/reagent/consumable/ethanol/candy_wine + name = "Candy Liquor" + description = "Made from assorted sweets, candies and even flowers." + taste_description = "sweet and smooth alcohol" + color = "#E33232d0" // rgb: 227, 50, 50 + boozepwr = 15 diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/recipe_card.dm b/monkestation/code/modules/brewin_and_chewin/brewing/recipe_card.dm new file mode 100644 index 000000000000..fa378e1424d0 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/recipe_card.dm @@ -0,0 +1,80 @@ +/obj/item/recipe_card + name = "fermentation recipe card" + desc = "Used to write down your secret recipe card." + icon = 'monkestation/code/modules/brewin_and_chewin/icons/paper.dmi' + icon_state = "recipe_paper" + + var/list/stored_reagents = list() + var/list/stored_foods = list() + var/brewing_time = 2 MINUTES + +/obj/item/recipe_card/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(istype(target, /obj/item/food/grown)) + if(target.type in stored_foods) + return + var/amount = tgui_input_number(user, "How much of [target.name] is needed?", name, 10, 50, 1) + if(!amount) + return + stored_foods += list(target.type = amount) + return + + if(istype(target, /obj/structure/fermentation_keg)) + stored_reagents = list() + for(var/datum/reagent/reagent as anything in target.reagents.reagent_list) + stored_reagents += list(reagent.type = reagent.volume) + + +/obj/item/recipe_card/CtrlClick(mob/user) + . = ..() + submit_recipe(user) + +/obj/item/recipe_card/proc/submit_recipe(mob/user) + if(!length(stored_foods) || !length(stored_reagents)) + return + var/display_name = tgui_input_text(user, "What is this drink called?", name) + if(!display_name) + return + var/bottle_name = tgui_input_text(user, "What is this drink's bottle called?", name) + if(!bottle_name) + return + var/glass_name = tgui_input_text(user, "What is this drink's glass called?", name) + if(!glass_name) + return + + var/bottle_desc = tgui_input_text(user, "What is this drink's bottle description?", name, multiline = TRUE) + if(!bottle_desc) + return + var/glass_desc = tgui_input_text(user, "What is this drink's glass description?", name, multiline = TRUE) + if(!glass_desc) + return + + var/datum/brewing_recipe/custom_recipe/new_recipe = new + + new_recipe.made_by = user.name + new_recipe.glass_desc = glass_desc + new_recipe.glass_name = glass_name + new_recipe.bottle_name = bottle_name + new_recipe.bottle_desc = bottle_desc + new_recipe.brew_time = brewing_time + new_recipe.needed_crops = stored_foods + new_recipe.needed_reagents = stored_reagents + new_recipe.brewed_amount = 4 + new_recipe.display_name = display_name + new_recipe.cargo_valuation = 2000 + + var/list/reagent_data = list() + + var/total_reagent_count = 0 + for(var/datum/reagent/reagent as anything in stored_reagents) + total_reagent_count += stored_reagents[reagent] + + for(var/datum/reagent/reagent as anything in stored_reagents) + var/list/new_list = list() + new_list += reagent + new_list[reagent] = stored_reagents[reagent] / total_reagent_count + reagent_data += new_list + + new_recipe.reagent_data = reagent_data + GLOB.custom_fermentation_recipes += new_recipe + qdel(src) diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/recipes/_base.dm b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/_base.dm new file mode 100644 index 000000000000..e1dab0ca9842 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/_base.dm @@ -0,0 +1,29 @@ +/datum/brewing_recipe + ///the type path of the reagent + var/reagent_to_brew = /datum/reagent/consumable/ethanol + ///our display name + var/display_name = "Pure Coder Tears" + ///pre-reqs: Essentially do we need past recipes made of this, uses the reagent_to_brew var to know if this has been done + var/pre_reqs + ///the crops typepath we need goes typepath = amount. Amount is not just how many based on potency value up to a cap it adds values. + var/list/needed_crops = list() + ///the type paths of needed reagents in typepath = amount + var/list/needed_reagents = list() + ///list of items that aren't crops we need + var/list/needed_items = list() + ///our brewing time in deci seconds should use the SECONDS MINUTES HOURS helpers + var/brew_time = 1 SECONDS + ///the price this gets at cargo + var/cargo_valuation = 0 + ///amount of brewed creations used when either canning or bottling + var/brewed_amount = 1 + ///each bottle or canning gives how this much reagents + var/per_brew_amount = 50 + ///helpful hints + var/helpful_hints + ///if we have a secondary name some do if you want to hide the ugly info + var/secondary_name + ///typepath of our output if set we also make this item + var/brewed_item + ///amount of brewed items + var/brewed_item_count = 1 diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/recipes/beers.dm b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/beers.dm new file mode 100644 index 000000000000..020d9c307da8 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/beers.dm @@ -0,0 +1,21 @@ +/datum/brewing_recipe/light_beer + reagent_to_brew = /datum/reagent/consumable/ethanol/beer/light + display_name = "Light Beer" + needed_crops = list(/obj/item/food/grown/wheat = 40, /obj/item/food/grown/poppy = 5) + needed_reagents = list(/datum/reagent/water = 60) + + cargo_valuation = 1750 + brew_time = 2 MINUTES + brewed_amount = 12 + helpful_hints = "Can be brewed again into regular beer" + +/datum/brewing_recipe/beer + reagent_to_brew = /datum/reagent/consumable/ethanol/beer + pre_reqs = /datum/reagent/consumable/ethanol/beer/light + display_name = "Beer" + needed_crops = list(/obj/item/food/grown/wheat = 10, /obj/item/food/grown/poppy = 5) + needed_reagents = list(/datum/reagent/water = 60) + + cargo_valuation = 2250 + brew_time = 2 MINUTES + brewed_amount = 6 diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/recipes/custom.dm b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/custom.dm new file mode 100644 index 000000000000..df6301b10536 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/custom.dm @@ -0,0 +1,24 @@ +/datum/brewing_recipe/custom_recipe + reagent_to_brew = /datum/reagent/consumable/ethanol/custom_brew + var/bottle_name + var/bottle_desc + var/glass_name + var/glass_desc + + ///list of reagents we transfer PER UNIT so if its 30% ethanol put /datum/reagent/consumable/ethanol = 0.3 + var/list/reagent_data = list() + var/made_by + + +/datum/reagent/consumable/ethanol/custom_brew + name = "EVIL WIZARD POTION" + can_merge = FALSE + +/datum/reagent/consumable/ethanol/custom_brew/on_transfer(atom/A, methods, trans_volume) + . = ..() + if(!("reagents" in data)) + return + for(var/datum/reagent/reagent as anything in data["reagents"]) + var/multiplier = trans_volume * data["reagents"][reagent] + A.reagents.add_reagent(reagent, multiplier) + A.reagents.remove_all_type(/datum/reagent/consumable/ethanol/custom_brew, trans_volume) diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/recipes/liquors.dm b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/liquors.dm new file mode 100644 index 000000000000..a56a9b24598d --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/liquors.dm @@ -0,0 +1,21 @@ +/datum/brewing_recipe/melon_liquor + reagent_to_brew = /datum/reagent/consumable/ethanol/melon_liquor + display_name = "Melon Liquor" + needed_items = list(/obj/item/grown/log = 5) + needed_crops = list(/obj/item/food/grown/watermelon = 80, /obj/item/food/grown/poppy = 35) + needed_reagents = list(/datum/reagent/water = 160) + brewed_amount = 2 + + cargo_valuation = 2000 + brew_time = 6 MINUTES + +/datum/brewing_recipe/red_candy_liquor + reagent_to_brew = /datum/reagent/consumable/ethanol/candy_wine + display_name = "Red Candy Liquor" + pre_reqs = /datum/reagent/consumable/ethanol/wine + brewed_amount = 1 + needed_crops = list(/obj/item/food/grown/grapes = 10, /obj/item/food/grown/sunflower = 5, /obj/item/food/grown/harebell = 5) + needed_reagents = list(/datum/reagent/consumable/sugar = 15) + + cargo_valuation = 7000 + brew_time = 16 MINUTES diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/recipes/meads.dm b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/meads.dm new file mode 100644 index 000000000000..457fb36de060 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/meads.dm @@ -0,0 +1,9 @@ +/datum/brewing_recipe/mead + reagent_to_brew = /datum/reagent/consumable/ethanol/mead + display_name = "Honey Mead" + needed_reagents = list(/datum/reagent/water = 50, /datum/reagent/consumable/honey = 50) + brewed_amount = 4 + + cargo_valuation = 3000 + brew_time = 6 MINUTES + diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/recipes/misc.dm b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/misc.dm new file mode 100644 index 000000000000..8f58c78e63b4 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/misc.dm @@ -0,0 +1,84 @@ +/datum/brewing_recipe/gin + reagent_to_brew = /datum/reagent/consumable/ethanol/gin + display_name = "Gin" + needed_items = list(/obj/item/grown/log = 5) + needed_crops = list(/obj/item/food/grown/berries = 40, /obj/item/food/grown/citrus/lemon = 40) + needed_reagents = list(/datum/reagent/water = 160, /datum/reagent/consumable/sugar = 15) + brewed_amount = 3 + + cargo_valuation = 3200 + brew_time = 6 MINUTES + +/datum/brewing_recipe/tequila + reagent_to_brew = /datum/reagent/consumable/ethanol/tequila + display_name = "Tequila" + needed_items = list(/obj/item/grown/log = 5) + needed_crops = list(/obj/item/food/grown/citrus/lemon = 40, /obj/item/food/grown/citrus/lime = 40, /obj/item/food/grown/pineapple = 10) + needed_reagents = list(/datum/reagent/water = 50, /datum/reagent/consumable/salt = 5) + brewed_amount = 2 + + cargo_valuation = 2250 + brew_time = 3 MINUTES + +/datum/brewing_recipe/patron + reagent_to_brew = /datum/reagent/consumable/ethanol/patron + display_name = "Patron" + needed_crops = list(/obj/item/food/grown/wheat = 80) + needed_reagents = list(/datum/reagent/water = 30, /datum/reagent/consumable/mintextract = 5) + brewed_amount = 1 + + cargo_valuation = 2000 + brew_time = 1.5 MINUTES + +/datum/brewing_recipe/ale + reagent_to_brew = /datum/reagent/consumable/ethanol/ale + display_name = "Ale" + needed_crops = list(/obj/item/food/grown/wheat = 60, /obj/item/food/grown/poppy = 5) + needed_reagents = list(/datum/reagent/water = 120, /datum/reagent/consumable/honey = 5) + brewed_amount = 12 + + cargo_valuation = 2000 + brew_time = 9 MINUTES + +/datum/brewing_recipe/whiskey + reagent_to_brew = /datum/reagent/consumable/ethanol/whiskey + display_name = "Whiskey" + needed_crops = list(/obj/item/food/grown/wheat = 40) + needed_reagents = list(/datum/reagent/water = 120) + brewed_amount = 10 + + cargo_valuation = 2000 + brew_time = 15 MINUTES + +/datum/brewing_recipe/glucose + reagent_to_brew = /datum/reagent/consumable/nutriment/glucose + display_name = "Glucose" + needed_crops = list(/obj/item/food/grown/wheat = 60, /obj/item/food/grown/corn = 30) + needed_reagents = list(/datum/reagent/water = 120, /datum/reagent/consumable/honey = 5, /datum/reagent/consumable/sugar = 30) + brewed_amount = 3 + per_brew_amount = 15 + + cargo_valuation = 4750 + brew_time = 3 MINUTES + helpful_hints = "Further brewing can be done when finished." + +/datum/brewing_recipe/nothing + reagent_to_brew = /datum/reagent/consumable/nothing + pre_reqs = /datum/reagent/consumable/nutriment/glucose + display_name = "Nothing" + needed_reagents = list(/datum/reagent/water = 200) + brewed_amount = 2 + + cargo_valuation = 404 + brew_time = 7 MINUTES + +/datum/brewing_recipe/cream + reagent_to_brew = /datum/reagent/consumable/cream + display_name = "Cream" + brewed_amount = 3 + needed_crops = list(/obj/item/food/grown/soybeans = 40) + needed_reagents = list(/datum/reagent/consumable/vinegar = 10, /datum/reagent/consumable/milk = 30) + + cargo_valuation = 1600 + brew_time = 2 MINUTES + helpful_hints = "Further brewing can be done when finished." diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/recipes/rums.dm b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/rums.dm new file mode 100644 index 000000000000..bbaf16d971f9 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/rums.dm @@ -0,0 +1,22 @@ +/datum/brewing_recipe/rum + reagent_to_brew = /datum/reagent/consumable/ethanol/rum + display_name = "Rum" + brewed_amount = 4 + needed_items = list(/obj/item/grown/log = 5) + needed_crops = list(/obj/item/food/grown/sugarcane = 60) + needed_reagents = list(/datum/reagent/water = 120, /datum/reagent/consumable/salt = 5) + + cargo_valuation = 2000 + brew_time = 3 MINUTES + helpful_hints = "Further brewing can be done when finished." + +/datum/brewing_recipe/kahlua + reagent_to_brew = /datum/reagent/consumable/ethanol/kahlua + pre_reqs = /datum/reagent/consumable/ethanol/rum + display_name = "Kahlua" + + brewed_amount = 3 + needed_reagents = list(/datum/reagent/consumable/sugar = 15, /datum/reagent/consumable/coffee = 60) + + cargo_valuation = 5000 + brew_time = 2 MINUTES diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/recipes/vinegars.dm b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/vinegars.dm new file mode 100644 index 000000000000..e15ff0952ef8 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/vinegars.dm @@ -0,0 +1,39 @@ +/datum/brewing_recipe/vinegar + reagent_to_brew = /datum/reagent/consumable/vinegar + display_name = "Vinegar" + brewed_amount = 3 + needed_crops = list(/obj/item/food/grown/apple = 20, /obj/item/food/grown/pineapple = 10) + needed_reagents = list(/datum/reagent/water = 30) + + cargo_valuation = 2500 + brew_time = 3 MINUTES + helpful_hints = "Further brewing can be done when finished." + +/datum/brewing_recipe/cheese_wheel + reagent_to_brew = /datum/reagent/consumable/vinegar + pre_reqs = /datum/reagent/consumable/cream + display_name = "Cheese Wheels (Byproduct Vinegar)" + brewed_amount = 1 + per_brew_amount = 15 //make an excess + needed_crops = list(/obj/item/food/grown/apple = 20, /obj/item/food/grown/pineapple = 10) + needed_reagents = list(/datum/reagent/water = 30, /datum/reagent/consumable/milk = 30, /datum/reagent/consumable/vinegar = 5) + + cargo_valuation = 1000 + brew_time = 1 MINUTES + + brewed_item = /obj/item/food/cheese/wheel + brewed_item_count = 3 + secondary_name = "Cheese Wheel" + helpful_hints = "The bottles will produced Vinegar." + +/datum/brewing_recipe/enzyme + reagent_to_brew = /datum/reagent/consumable/enzyme + pre_reqs = /datum/reagent/consumable/vinegar + display_name = "Universal Enzymes" + brewed_amount = 1 + needed_crops = list(/obj/item/food/grown/grass = 120, /obj/item/food/grown/pineapple = 30, /obj/item/food/grown/citrus/orange = 30) + needed_reagents = list(/datum/reagent/water = 30, /datum/reagent/consumable/ethanol = 60) + + cargo_valuation = 7500 + brew_time = 6 MINUTES + diff --git a/monkestation/code/modules/brewin_and_chewin/brewing/recipes/wines.dm b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/wines.dm new file mode 100644 index 000000000000..439bfdccacfe --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/brewing/recipes/wines.dm @@ -0,0 +1,46 @@ +/datum/brewing_recipe/lizard_wine + reagent_to_brew = /datum/reagent/consumable/ethanol/lizardwine + display_name = "Lizard Wine" + needed_items = list(/obj/item/organ/external/tail/lizard = 1) + needed_crops = list(/obj/item/food/grown/poppy = 5) + needed_reagents = list(/datum/reagent/water = 50, /datum/reagent/consumable/ethanol = 100) + brewed_amount = 3 + + cargo_valuation = 10000 + brew_time = 10 MINUTES + +/datum/brewing_recipe/wine + reagent_to_brew = /datum/reagent/consumable/ethanol/wine + display_name = "Wine" + needed_items = list(/obj/item/grown/log = 5) + needed_crops = list(/obj/item/food/grown/grapes = 60) + needed_reagents = list(/datum/reagent/water = 160, /datum/reagent/consumable/sugar = 15) + brewed_amount = 2 + + cargo_valuation = 3000 + brew_time = 6 MINUTES + helpful_hints = "Further brewing can be done when finished." + +/datum/brewing_recipe/vermouth + reagent_to_brew = /datum/reagent/consumable/ethanol/vermouth + display_name = "Vermouth" + pre_reqs = /datum/reagent/consumable/ethanol/wine + needed_items = list(/obj/item/grown/log = 7) + needed_crops = list(/obj/item/food/grown/grapes = 60, /obj/item/food/grown/berries = 15) + needed_reagents = list(/datum/reagent/water = 160) + brewed_amount = 3 + + cargo_valuation = 5000 + brew_time = 8 MINUTES + +/datum/brewing_recipe/poison_wine + reagent_to_brew = /datum/reagent/consumable/ethanol/poison_wine + display_name = "Fungal Wine (poison)" + pre_reqs = /datum/reagent/consumable/ethanol/wine + brewed_amount = 1 + needed_items = list(/obj/item/grown/log = 5) + needed_crops = list(/obj/item/food/grown/grapes = 10, /obj/item/food/grown/mushroom/plumphelmet = 5) + needed_reagents = list(/datum/reagent/toxin/amatoxin = 15) + + cargo_valuation = 9000 + brew_time = 16 MINUTES diff --git a/monkestation/code/modules/brewin_and_chewin/cargo_exports.dm b/monkestation/code/modules/brewin_and_chewin/cargo_exports.dm new file mode 100644 index 000000000000..e760f62f55c2 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/cargo_exports.dm @@ -0,0 +1,13 @@ +/datum/export/fermented_kegs + cost = 0 + unit_name = "place holder" + export_types = list(/obj/structure/fermentation_keg) + +/datum/export/fermented_kegs/get_cost(obj/O) + var/obj/structure/fermentation_keg/keg = O + var/credit_value = keg.price_tag + unit_name = keg.selected_recipe?.display_name + if(!unit_name) + unit_name = "Unnamed Keg" + + return credit_value diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/cooking_containers.dm b/monkestation/code/modules/brewin_and_chewin/chewing/cooking_containers.dm new file mode 100644 index 000000000000..43500418a3bb --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/cooking_containers.dm @@ -0,0 +1,385 @@ +//Cooking containers are used in ovens, fryers and so on, to hold multiple ingredients for a recipe. +//They interact with the cooking process, and link up with the cooking code dynamically. + +//Originally sourced from the Aurora, heavily retooled to actually work with CHEWIN + + +//Holder for a portion of an incomplete meal, +//allows a cook to temporarily offload recipes to work on things factory-style, eliminating the need for 20 plates to get things done fast. + +/obj/item/reagent_containers/cooking_container + icon = 'monkestation/code/modules/brewin_and_chewin/icons/kitchen.dmi' + verb_exclaim = "" + var/shortname + var/place_verb = "into" + var/appliancetype //string + w_class = WEIGHT_CLASS_SMALL + volume = 240 //Don't make recipes using reagents in larger quantities than this amount; they won't work. + var/datum/chewin_cooking/recipe_tracker/tracker = null //To be populated the first time the plate is interacted with. + var/lip //Icon state of the lip layer of the object + var/removal_penalty = 0 //A flat quality reduction for removing an unfinished recipe from the container. + + possible_transfer_amounts = list(5,10,30,60,90,120,240) + amount_per_transfer_from_this = 10 + + reagent_flags = OPENCONTAINER | NO_REACT + var/list/fryer_data = list("High"=0) //Record of what deepfryer-cooking has been done on this food. + var/list/stove_data = list("High"=0 , "Medium" = 0, "Low"=0) //Record of what stove-cooking has been done on this food. + var/list/grill_data = list("High"=0 , "Medium" = 0, "Low"=0) //Record of what grill-cooking has been done on this food. + var/list/oven_data = list("High"=0 , "Medium" = 0, "Low"=0) //Record of what oven-cooking has been done on this food. + +/obj/item/reagent_containers/cooking_container/Initialize() + .=..() + appearance_flags |= KEEP_TOGETHER + RegisterSignal(src, COMSIG_STOVE_PROCESS, PROC_REF(process_stovetop)) + RegisterSignal(src, COMSIG_ITEM_OVEN_PROCESS, PROC_REF(process_bake)) + + +/obj/item/reagent_containers/cooking_container/examine(mob/user) + . = ..() + if(contents) + .+= get_content_info() + if(reagents.total_volume) + .+= get_reagent_info() + +/obj/item/reagent_containers/cooking_container/proc/get_content_info() + var/string = "It contains:
" + return string + +/obj/item/reagent_containers/cooking_container/proc/get_reagent_info() + return "It contains [reagents.total_volume] units of reagents." + +/obj/item/reagent_containers/cooking_container/attackby(var/obj/item/used_item, var/mob/user) + + #ifdef CHEWIN_DEBUG + logger.Log(LOG_CATEGORY_DEBUG"cooking_container/attackby() called!") + #endif + + if(istype(used_item, /obj/item/spatula)) + do_empty(user, target=null, reagent_clear = FALSE) + return + + if(!tracker && (contents.len || reagents.total_volume != 0)) + to_chat(user, "The [src] is full. Empty its contents first.") + else + process_item(used_item, user) + + return TRUE + +/obj/item/reagent_containers/cooking_container/after_attack_pour(mob/user, atom/target) + + + #ifdef CHEWIN_DEBUG + logger.Log(LOG_CATEGORY_DEBUG"cooking_container/standard_pour_into() called!") + #endif + + if(tracker) + if(alert(user, "There is an ongoing recipe in the [src]. Dump it out?",,"Yes","No") == "No") + return FALSE + for(var/datum/reagent/our_reagent in reagents.reagent_list) + if(our_reagent.data && istype(our_reagent.data, /list) && our_reagent.data["FOOD_QUALITY"]) + our_reagent.data["FOOD_QUALITY"] = 0 + + do_empty(user, target, reagent_clear = FALSE) + + #ifdef CHEWIN_DEBUG + logger.Log(LOG_CATEGORY_DEBUG"cooking_container/do_empty() completed!") + #endif + + . = ..() + + +/obj/item/reagent_containers/cooking_container/afterattack(var/obj/target, var/mob/user, var/flag) + if(!istype(target, /obj/item/reagent_containers)) + return FALSE + if(!flag) + return FALSE + if(tracker) + return FALSE + if(after_attack_pour(user, target)) + return TRUE + +/obj/item/reagent_containers/cooking_container/proc/process_item(var/obj/I, var/mob/user, var/lower_quality_on_fail = 0, var/send_message = TRUE) + + + #ifdef CHEWIN_DEBUG + logger.Log(LOG_CATEGORY_DEBUG"cooking_container/process_item() called!") + #endif + + //OK, time to load the tracker + if(!tracker) + if(lower_quality_on_fail) + for (var/obj/item/contained in contents) + contained?:food_quality -= lower_quality_on_fail + else + tracker = new /datum/chewin_cooking/recipe_tracker(src) + + var/return_value = 0 + switch(tracker.process_item_wrap(I, user)) + if(CHEWIN_NO_STEPS) + if(no_step_checks(I)) //literally fryers + if(send_message) + to_chat(user, "It doesn't seem like you can create a meal from that. Yet.") + if(lower_quality_on_fail) + for (var/datum/chewin_cooking/recipe_pointer/pointer in tracker.active_recipe_pointers) + pointer?:tracked_quality -= lower_quality_on_fail + if(CHEWIN_CHOICE_CANCEL) + if(send_message) + to_chat(user, "You decide against cooking with the [src].") + if(CHEWIN_COMPLETE) + if(send_message) + to_chat(user, "You finish cooking with the [src].") + qdel(tracker) + tracker = null + clear_cooking_data() + update_icon() + return_value = 1 + if(CHEWIN_SUCCESS) + if(send_message) + to_chat(user, "You have successfully completed a recipe step.") + clear_cooking_data() + return_value = 1 + update_icon() + if(CHEWIN_PARTIAL_SUCCESS) + if(send_message) + to_chat(user, "More must be done to complete this step of the recipe.") + if(CHEWIN_LOCKOUT) + if(send_message) + to_chat(user, "You can't make the same decision twice!") + + if(tracker && !tracker.recipe_started) + qdel(tracker) + tracker = null + return return_value + +//TODO: Handle the contents of the container being ruined via burning. +/obj/item/reagent_containers/cooking_container/proc/handle_burning() + return + +//TODO: Handle the contents of the container lighting on actual fire. +/obj/item/reagent_containers/cooking_container/proc/handle_ignition() + return FALSE + +/obj/item/reagent_containers/cooking_container/verb/empty() + set src in view(1) + set name = "Empty Container" + set category = "Object" + set desc = "Removes items from the container, excluding reagents." + do_empty(usr) + +/obj/item/reagent_containers/cooking_container/proc/do_empty(mob/user, var/atom/target = null, var/reagent_clear = TRUE) + #ifdef CHEWIN_DEBUG + logger.Log(LOG_CATEGORY_DEBUG"cooking_container/do_empty() called!") + #endif + + if(contents.len != 0) + if(tracker && removal_penalty) + for (var/obj/item/contained in contents) + contained?:food_quality -= removal_penalty + to_chat(user, span_warning("The quality of ingredients in the [src] was reduced by the extra jostling.")) + + //Handle quality reduction for reagents + if(reagents.total_volume != 0) + var/reagent_qual_reduction = round(reagents.total_volume/contents.len) + if(reagent_qual_reduction != 0) + for (var/obj/item/contained in contents) + contained?:food_quality -= reagent_qual_reduction + to_chat(user, span_warning("The quality of ingredients in the [src] was reduced by the presence of reagents in the container.")) + + + for (var/contained in contents) + var/atom/movable/AM = contained + remove_from_visible(AM) + if(!target) + AM.forceMove(get_turf(src)) + else + AM.forceMove(get_turf(target)) + + //TODO: Splash the reagents somewhere + if(reagent_clear) + reagents.clear_reagents() + + update_icon() + qdel(tracker) + tracker = null + clear_cooking_data() + + if(contents.len != 0) + to_chat(user, span_notice("You remove all the solid items from [src].")) + + +/obj/item/reagent_containers/cooking_container/AltClick(var/mob/user) + do_empty(user) + +//Deletes contents of container. +//Used when food is burned, before replacing it with a burned mess +/obj/item/reagent_containers/cooking_container/proc/clear() + QDEL_LIST(contents) + contents=list() + reagents.clear_reagents() + if(tracker) + qdel(tracker) + tracker = null + clear_cooking_data() + + +/obj/item/reagent_containers/cooking_container/proc/clear_cooking_data() + stove_data = list("High"=0 , "Medium" = 0, "Low"=0) + grill_data = list("High"=0 , "Medium" = 0, "Low"=0) + fryer_data = list("High"=0) + +/obj/item/reagent_containers/cooking_container/proc/label(var/number, var/CT = null) + //This returns something like "Fryer basket 1 - empty" + //The latter part is a brief reminder of contents + //This is used in the removal menu + . = shortname + if (!isnull(number)) + .+= " [number]" + .+= " - " + if (LAZYLEN(contents)) + var/obj/O = locate() in contents + return . + O.name //Just append the name of the first object + return . + "empty" + +/obj/item/reagent_containers/cooking_container/update_icon() + . = ..() + cut_overlays() + for(var/obj/item/our_item in vis_contents) + src.remove_from_visible(our_item) + + for(var/i=contents.len, i>=1, i--) + var/obj/item/our_item = contents[i] + src.add_to_visible(our_item) + if(lip) + add_overlay(image(src.icon, icon_state=lip, layer=ABOVE_OBJ_LAYER)) + +/obj/item/reagent_containers/cooking_container/proc/add_to_visible(var/obj/item/our_item) + our_item.pixel_x = initial(our_item.pixel_x) + our_item.pixel_y = initial(our_item.pixel_y) + our_item.vis_flags = VIS_INHERIT_LAYER | VIS_INHERIT_PLANE | VIS_INHERIT_ID + our_item.blend_mode = BLEND_INSET_OVERLAY + our_item.transform *= 0.6 + src.vis_contents += our_item + +/obj/item/reagent_containers/cooking_container/proc/remove_from_visible(var/obj/item/our_item) + our_item.vis_flags = 0 + our_item.blend_mode = 0 + our_item.transform = null + src.vis_contents.Remove(our_item) + +/obj/item/reagent_containers/cooking_container/plate + icon = 'monkestation/code/modules/brewin_and_chewin/icons/eris_kitchen.dmi' + name = "serving plate" + shortname = "plate" + desc = "A shitty serving plate. You probably shouldn't be seeing this." + icon_state = "plate" + appliancetype = PLATE + +/obj/item/reagent_containers/cooking_container/board + name = "cutting board" + shortname = "cutting_board" + desc = "Good for making sandwiches on, too." + icon_state = "cutting_board" + appliancetype = CUTTING_BOARD + +/obj/item/reagent_containers/cooking_container/oven + name = "oven tray" + shortname = "shelf" + desc = "Put ingredients in this; designed for use with an oven. Warranty void if used." + icon_state = "oven_dish" + lip = "oven_dish_lip" + appliancetype = OVEN + +/obj/item/reagent_containers/cooking_container/proc/process_bake(datum/source, obj/machinery/oven/oven, seconds_per_tick) + #ifdef CWJ_DEBUG + logger.Log(LOG_CATEGORY_DEBUG"grill/proc/process_bake data:", list("temperature: [oven.temperature]", "reference_time: [oven.reference_time]", " world.time: [world.time]", "cooking_timestamp: [oven.cooking_timestamp]", " grill_data: [grill_data]")) + #endif + + if(oven_data[oven.temperature]) + oven_data[oven.temperature] += seconds_per_tick * 10 + else + oven_data[oven.temperature] = seconds_per_tick * 10 + return COMPONENT_BAKING_GOOD_RESULT | COMPONENT_HANDLED_BAKING + +/obj/item/reagent_containers/cooking_container/proc/process_stovetop(datum/source, temperature, seconds_per_tick, obj/stove_object) + if(stove_data[temperature]) + stove_data[temperature] += seconds_per_tick * 10 + else + stove_data[temperature] = seconds_per_tick * 10 + process_item(stove_object, null, FALSE, FALSE) + return TRUE + +/obj/item/reagent_containers/cooking_container/pan + name = "pan" + desc = "An normal pan." + + icon_state = "pan" //Default state is the base icon so it looks nice in the map builder + lip = "pan_lip" + hitsound = 'sound/weapons/smash.ogg' + appliancetype = PAN + +/obj/item/reagent_containers/cooking_container/pot + name = "cooking pot" + shortname = "cooking pot" + desc = "Boil things with this. Maybe even stick 'em in a stew." + + icon_state = "pot" + lip = "pot_lip" + + hitsound = 'sound/weapons/smash.ogg' + removal_penalty = 5 + appliancetype = POT + w_class = WEIGHT_CLASS_BULKY + +/obj/item/reagent_containers/cooking_container/deep_basket + name = "deep fryer basket" + shortname = "basket" + desc = "Cwispy! Warranty void if used." + + icon_state = "deepfryer_basket" + lip = "deepfryer_basket_lip" + removal_penalty = 5 + appliancetype = DF_BASKET + +/obj/item/reagent_containers/cooking_container/proc/no_step_checks(obj/item/item) + return TRUE + +/obj/item/reagent_containers/cooking_container/deep_basket/no_step_checks(obj/item/item) + item.forceMove(src) + qdel(tracker) + update_icon() + return FALSE + + +/obj/item/reagent_containers/cooking_container/air_basket + name = "air fryer basket" + shortname = "basket" + desc = "Permanently laminated with dried oil and late-stage capitalism." + + icon_state = "airfryer_basket" + lip = "airfryer_basket_lip" + removal_penalty = 5 + appliancetype = AF_BASKET + + +/obj/item/reagent_containers/cooking_container/grill_grate + name = "grill grate" + shortname = "grate" + place_verb = "onto" + desc = "Primarily used to grill meat, place this on a grill and enjoy an ancient human tradition." + + icon_state = "grill_grate" + + appliancetype = GRILL + +/obj/item/reagent_containers/cooking_container/bowl + name = "cooking bowl" + shortname = "cooking bowl" + desc = "A bowl." + + icon_state = "bowl" + lip = "bowl_lip" + + removal_penalty = 2 + appliancetype = BOWL diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/food_additons.dm b/monkestation/code/modules/brewin_and_chewin/chewing/food_additons.dm new file mode 100644 index 000000000000..2fde194769c1 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/food_additons.dm @@ -0,0 +1,30 @@ +/obj/item + ///can in rare cases be on an item so generalizing onto items + var/food_quality = 1 + +/obj/item/food/examine(mob/user) + . = ..() + . += span_notice("The food's level of quality is [food_quality]") + + var/food_descriptor + if(food_quality < 0) + food_descriptor = "It looks gross. Someone cooked this poorly." + else if (food_quality >= 100) + food_descriptor = "What cruel twist of fate it must be, for this unparalleled artistic masterpiece can only be truly appreciated through its destruction. Does this dish's transient form belie the true nature of all things? You see totality of existence reflected through \the [src]." + else + switch(food_quality) + if(0) + food_descriptor = "It looks like an unappetizing a meal." + if(1 to 10) + food_descriptor = "The food is edible, but frozen dinners have been reheated with more skill." + if(11 to 20) + food_descriptor = "It looks adequately made." + if(21 to 30) + food_descriptor = "The quality of the food is is pretty good." + if(31 to 50) + food_descriptor = "This food looks very tasty." + if(61 to 70) + food_descriptor = "There's a special spark in this cooking, a measure of love and care unseen by the casual chef." + if(81 to 99) + food_descriptor = "The quality of this food is legendary. Words fail to describe it further. It must be eaten" + . += span_notice(food_descriptor) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/food_effects/food_posioning.dm b/monkestation/code/modules/brewin_and_chewin/chewing/food_effects/food_posioning.dm new file mode 100644 index 000000000000..2a9e39d1708e --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/food_effects/food_posioning.dm @@ -0,0 +1,19 @@ +/atom/movable/screen/alert/status_effect/food/food_poisoning + name = "Food Poisoning" + desc = "Suffering from food Poisoning" + icon_state = "gross2" + +/datum/status_effect/food/food_poisoning + duration = 1.5 MINUTES + id = "food_poisoning" + alert_type = /atom/movable/screen/alert/status_effect/food/food_poisoning + var/min_vomit_processes = 5 + +/datum/status_effect/food/food_poisoning/tick(seconds_per_tick, times_fired) + . = ..() + owner.adjust_hallucinations(0.5 SECONDS) + owner.adjust_drugginess(0.75 SECONDS) + if(prob(20) && min_vomit_processes <= 0) + owner.vomit(4, FALSE, FALSE) + min_vomit_processes = 5 + min_vomit_processes-- diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/fryer_overhaul.dm b/monkestation/code/modules/brewin_and_chewin/chewing/fryer_overhaul.dm new file mode 100644 index 000000000000..9cdf1cd244ad --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/fryer_overhaul.dm @@ -0,0 +1,82 @@ +/obj/machinery/deepfryer + icon = 'monkestation/code/modules/brewin_and_chewin/icons/eris_kitchen.dmi' + icon_state = "fryer" + var/obj/item/reagent_containers/cooking_container/deep_basket/basket + +/obj/machinery/deepfryer/update_icon_state() + . = ..() + if(basket) + icon_state = "fryer_off" + else + icon_state = "fryer" + +/obj/machinery/deepfryer/process(seconds_per_tick) + ..() + if(!basket) + return + if(basket.tracker) + basket.fryer_data[J_HI] += 10 * seconds_per_tick + else + var/datum/reagent/consumable/cooking_oil/frying_oil = reagents.has_reagent(/datum/reagent/consumable/cooking_oil) + if(!frying_oil) + return + for(var/obj/item/item as anything in basket.contents) + reagents.chem_temp = frying_oil.fry_temperature + if(!item) + continue + + reagents.trans_to(item, oil_use * seconds_per_tick, multiplier = fry_speed * 3) //Fried foods gain more of the reagent thanks to space magic + + cook_time += fry_speed * seconds_per_tick + if(cook_time >= 5 SECONDS && !frying_fried) + frying_fried = TRUE //frying... frying... fried + playsound(src.loc, 'sound/machines/ding.ogg', 50, TRUE) + audible_message(span_notice("[src] dings!")) + else if (cook_time >= 12 SECONDS && !frying_burnt) + frying_burnt = TRUE + visible_message(span_warning("[src] emits an acrid smell!")) + + use_power(active_power_usage) + +/obj/machinery/deepfryer/proc/start_fry(obj/item/frying_item, mob/user) + to_chat(user, span_notice("You put [frying_item] into [src].")) + if(istype(frying_item, /obj/item/freeze_cube)) + log_bomber(user, "put a freeze cube in a", src) + visible_message(span_userdanger("[src] starts glowing... Oh no...")) + playsound(src, 'sound/effects/pray_chaplain.ogg', 100) + add_filter("entropic_ray", 10, list("type" = "rays", "size" = 35, "color" = COLOR_VIVID_YELLOW)) + addtimer(CALLBACK(src, PROC_REF(blow_up)), 5 SECONDS) + + // Give them reagents to put frying oil in + if(isnull(frying_item.reagents)) + frying_item.create_reagents(50, INJECTABLE) + if(user.mind) + ADD_TRAIT(frying_item, TRAIT_FOOD_CHEF_MADE, REF(user.mind)) + SEND_SIGNAL(frying_item, COMSIG_ITEM_ENTERED_FRYER) + + icon_state = "fryer_on" + +/obj/machinery/deepfryer/proc/reset_frying(mob/user) + if(!basket) + return + for(var/obj/item/item as anything in basket.contents) + if(!QDELETED(item)) + item.AddElement(/datum/element/fried_item, cook_time) + if(user) + basket.process_item(src, user, lower_quality_on_fail=CHEWIN_BASE_QUAL_REDUCTION, send_message=TRUE) + frying_fried = FALSE + frying_burnt = FALSE + fry_loop.stop() + cook_time = 0 + icon_state = "fryer_off" + +/obj/machinery/deepfryer/attackby(obj/item/weapon, mob/user, params) + . = ..() + if(istype(weapon, /obj/item/reagent_containers/cooking_container/deep_basket) && !basket) + weapon.forceMove(src) + basket = weapon + icon_state = "fryer_on" + frying = TRUE + for(var/obj/item/item as anything in basket.contents) + start_fry(item, user) + fry_loop.start() diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/global_creation.dm b/monkestation/code/modules/brewin_and_chewin/chewing/global_creation.dm new file mode 100644 index 000000000000..b82f58fed439 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/global_creation.dm @@ -0,0 +1,11 @@ +/proc/initialize_cooking_recipes() + //All combination path datums, save for the default recipes we don't want. + var/list/recipe_paths = typesof(/datum/chewin_cooking/recipe) + recipe_paths -= /datum/chewin_cooking/recipe + for (var/path in recipe_paths) + var/datum/chewin_cooking/recipe/example_recipe = new path() + if(!GLOB.chewin_recipe_dictionary[example_recipe.cooking_container]) + GLOB.chewin_recipe_dictionary[example_recipe.cooking_container] = list() + GLOB.chewin_recipe_dictionary[example_recipe.cooking_container]["[example_recipe.unique_id]"] = example_recipe + + GLOB.chewin_recipe_list += example_recipe diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/items.dm b/monkestation/code/modules/brewin_and_chewin/chewing/items.dm new file mode 100644 index 000000000000..6c526ae43d6c --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/items.dm @@ -0,0 +1,14 @@ +/obj/item/spatula + name = "Spatula" + desc = "A Hydrodynamic Spatula. Port and Starboard attachments not included." + icon = 'monkestation/code/modules/brewin_and_chewin/icons/kitchen.dmi' + icon_state = "spat" + w_class = WEIGHT_CLASS_SMALL + +/obj/item + var/cooking_description_modifier + +/obj/item/examine(mob/user) + . = ..() + if(cooking_description_modifier) + . += span_notice(cooking_description_modifier) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/oven_overrides.dm b/monkestation/code/modules/brewin_and_chewin/chewing/oven_overrides.dm new file mode 100644 index 000000000000..20c4f2bd8f57 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/oven_overrides.dm @@ -0,0 +1,42 @@ +/obj/machinery/oven + ///our temperature for baked goods + var/temperature = J_LO + ///time stamps specifically for chewin recipes + var/cooking_timestamp = 0 + ///our reference timestamp + var/reference_time = 0 + ///our oven timer + var/oven_timer + ///timer duration + var/timer_duration = 0 + ///timer last start + var/timer_laststart = 0 + +/obj/machinery/oven/Initialize(mapload) + . = ..() + register_context() + +/obj/machinery/oven/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + context[SCREENTIP_CONTEXT_ALT_LMB] = "Set Timer" + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/oven/AltClick(mob/user) + . = ..() + if(!oven_timer) + timer_duration = tgui_input_number(user, "How long should the timer be in 10th of a seconds", min_value = 0, max_value = 10000000) + if(!timer_duration) + return + if(!open) + timer_laststart = world.time + oven_timer = addtimer(CALLBACK(src, PROC_REF(go_off_queen)), timer_duration, TIMER_UNIQUE | TIMER_STOPPABLE) + else + deltimer(oven_timer) + oven_timer = null + +/obj/machinery/oven/proc/go_off_queen() + timer_duration = 0 + timer_laststart = 0 + oven_timer = null + + playsound(src, 'sound/weapons/gun/general/empty_alarm.ogg', 25) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe.dm new file mode 100644 index 000000000000..aaaa53948c0b --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe.dm @@ -0,0 +1,868 @@ +/* +CHEWIN COOKING - A comprehensive cooking rework. +The recipe datum outlines a list of steps from getting a piece of food from point A to point B. +Recipes have steps that are held in a modular linked list, holding required steps, and optional ones to increase the total quality of the food. +Following a recipe incorrectly (IE, adding too much of an item, having the burner too hot, etc.) Will decrease the quality of the food.area +Recipes have clear start and end points. They start with a particular item and end with a particular item. +That said, a start item can follow multiple recipes until they eventually diverge as different steps are followed. +In the case two recipes have identical steps, the user should be prompted on what their intended result should be. (Donuts vs Bagels) +Recipes are loaded at startup. Food items reference it by the recipe_tracker datum +By following the steps correctly, good food can be made. +Food quality is calculated based on the steps taken. +*/ + +/datum/chewin_cooking/recipe + var/unique_id + var/name //Name for the cooking guide. Auto-populates if not set. + var/description //Description for the cooking guide. Auto-populates if not set. + var/recipe_guide //Step by step recipe guide. I hate it. + var/recipe_icon //Icon for the cooking guide. Auto-populates if not set. + var/recipe_icon_state //Icon state for the cooking guide. Auto-populates if not set. + + //The Cooking container the recipe is performed in. + var/cooking_container = null + + var/product_type //Type path for the product created by the recipe. An item of this type should ALSO have a recipe_tracker Datum. + var/product_name + var/product_count = 1 //how much of a thing is made per case of the recipe being followed. + + //Special variables that must be defined INSTEAD of product_type in order to create reagents instead of an object. + var/reagent_id + var/reagent_amount + var/reagent_name + var/reagent_desc + + var/icon_image_file + + var/quality_description //A decorator description tacked onto items when the recipe is completed. Used in future recipes. "The Bread looks Handmade." + + var/exclusive_option_mode = FALSE //triggers whether two steps in a process are exclusive- IE: you can do one or the other, but not both. + + var/list/active_exclusive_option_list = list() //Only needed during the creation process for tracking a given exclusive option dictionary. + + var/option_chain_mode = 0 //triggers whether two steps in a process are exclusive- IE: you can do one or the other, but not both. + + var/active_exclusive_option_chain //Only needed during the creation process for tracking items in an option chain. + + var/replace_reagents = FALSE //Determines if we entirely replace the contents of the food product with the slurry that goes into it. + + var/appear_in_default_catalog = TRUE //Everything appears in the catalog by default + /* + The Step Builder is iterated through to create new steps in the recipe dynamically. + _OPTIONAL steps are linked to the previously made REQUIRED step + CHEWIN_BEGIN steps must eventually terminate in a matching CHEWIN_END step + */ + var/list/step_builder = null + + var/datum/chewin_cooking/recipe_step/first_step //The first step in the linked list that will result in the final recipe + + var/datum/chewin_cooking/recipe_step/last_required_step //Reference to the last required step in the cooking process. + + var/datum/chewin_cooking/recipe_step/last_created_step //Reference to the last step made, regardless of if it was required or not. + ///this is the category shown in personal crafting menus + var/food_category = CATEGORY_MISC + ///this is our food buff override provided by other things + var/food_buff_override + +/datum/chewin_cooking/recipe/New() + + if(reagent_id && !reagent_amount) + CRASH("/datum/chewin_cooking/recipe/New: Reagent creating recipe must have reagent_amount defined! Recipe path=[src.type].") + + build_steps() + + if(ispath(product_type)) + var/obj/item/product_info = new product_type() + product_name = product_info.name + if(!name) + name = product_info.name + + if(!description) + description = product_info.desc + + QDEL_NULL(product_info) //We don't need this anymore. + + if(reagent_id) + var/datum/reagent/test_reagent = GLOB.chemical_reagents_list[reagent_id] + if(test_reagent) + if(!name) + name = test_reagent.name + if(!description) + description = test_reagent.description + + reagent_name = test_reagent.name + reagent_desc = test_reagent.description + + if(!name) + name = "NO NAME!" + + unique_id = sequential_id("recipe") + generate_crafting_helper() + +//Build out the recipe steps for a recipe, based on the step_builder list +/datum/chewin_cooking/recipe/proc/build_steps() + if(!step_builder) + CRASH("/datum/chewin_cooking/recipe/build_steps: Recipe has no step builder defined! Recipe path=[src.type].") + + if(!cooking_container) + CRASH("/datum/chewin_cooking/recipe/build_steps: Recipe has no cooking container defined! Recipe path=[src.type].") + + //Create a base step + create_step_base() + + for (var/step in step_builder) + if(islist(step)) + var/list/step_list = step + var/reason = "" + switch(step_list[1]) + if(CHEWIN_ADD_ITEM) + if(step_list.len < 2) + reason="Bad argument Length for CHEWIN_ADD_ITEM" + else if(!ispath(step_list[2])) + reason="Bad argument type for CHEWIN_ADD_ITEM at arg 2" + else + create_step_add_item(step_list[2], FALSE) + if(CHEWIN_ADD_ITEM_OPTIONAL) + if(step_list.len < 2) + reason="Bad argument Length for CHEWIN_ADD_ITEM_OPTIONAL" + else if(!ispath(step_list[2])) + reason="Bad argument type for CHEWIN_ADD_ITEM_OPTIONAL at arg 2" + else + create_step_add_item(step_list[2], TRUE) + if(CHEWIN_ADD_REAGENT) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_ADD_REAGENT" + else if(!ispath(step_list[2], /datum/reagent)) + reason="Bad reagent type for CHEWIN_ADD_REAGENT at arg 2" + else + create_step_add_reagent(step_list[2], step_list[3], FALSE) + if(CHEWIN_ADD_REAGENT_OPTIONAL) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_ADD_REAGENT_OPTIONAL" + else if(!ispath(step_list[2], /datum/reagent)) + reason="Bad reagent type for CHEWIN_ADD_REAGENT_OPTIONAL at arg 2" + else + create_step_add_reagent(step_list[2], step_list[3], TRUE) + + if(CHEWIN_ADD_REAGENT_CHOICE) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_ADD_REAGENT" + else if(!islist(step_list[2])) + reason="Bad reagent type for CHEWIN_ADD_REAGENT at arg 2" + else + create_step_add_reagent_choice(step_list[2], step_list[3], FALSE) + if(CHEWIN_ADD_REAGENT_CHOICE_OPTIONAL) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_ADD_REAGENT_OPTIONAL" + else if(!islist(step_list[2])) + reason="Bad reagent type for CHEWIN_ADD_REAGENT_OPTIONAL at arg 2" + else + create_step_add_reagent_choice(step_list[2], step_list[3], TRUE) + + if(CHEWIN_ADD_PRODUCE_CHOICE) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_ADD_PRODUCE_CHOICE" + else if(!islist(step_list[2])) + reason="Bad reagent type for CHEWIN_ADD_PRODUCE_CHOICE at arg 2" + else + create_step_add_produce_choice(step_list[2], FALSE) + if(CHEWIN_ADD_PRODUCE_CHOICE_OPTIONAL) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_ADD_PRODUCE_CHOICE_OPTIONAL" + else if(!islist(step_list[2])) + reason="Bad reagent type for CHEWIN_ADD_PRODUCE_CHOICE_OPTIONAL at arg 2" + else + create_step_add_produce_choice(step_list[2], TRUE) + + if(CHEWIN_USE_ITEM) + if(step_list.len < 2) + reason="Bad argument Length for CHEWIN_USE_ITEM" + else if(!ispath(step_list[2])) + reason="Bad argument type for CHEWIN_USE_ITEM at arg 2" + else + create_step_use_item(step_list[2], FALSE) + if(CHEWIN_USE_ITEM_OPTIONAL) + if(step_list.len < 2) + reason="Bad argument Length for CHEWIN_USE_ITEM_OPTIONAL" + else if(!ispath(step_list[2])) + reason="Bad argument type for CHEWIN_USE_ITEM_OPTIONAL at arg 2" + else + create_step_use_item(step_list[2], TRUE) + if(CHEWIN_ADD_PRODUCE) + if(step_list.len < 2) + reason="Bad argument Length for CHEWIN_ADD_PRODUCE" + else + create_step_add_produce(step_list[2], FALSE) + if(CHEWIN_ADD_PRODUCE_OPTIONAL) + if(step_list.len < 2) + reason="Bad argument Length for CHEWIN_ADD_PRODUCE_OPTIONAL" + else + create_step_add_produce(step_list[2], TRUE) + if(CHEWIN_USE_TOOL) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_USE_TOOL" + else + create_step_use_tool(step_list[2], step_list[3], FALSE) + if(CHEWIN_USE_TOOL_OPTIONAL) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_USE_TOOL_OPTIONAL" + else + create_step_use_tool(step_list[2], step_list[3], TRUE) + if(CHEWIN_USE_STOVE) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_USE_STOVE" + switch(step_list[2]) + if(J_LO) + if(step_list[3] > CHEWIN_BURN_TIME_LOW) + reason="Time too large for Low setting on CHEWIN_USE_STOVE; Food will automatically burn." + + if(J_MED) + if(step_list[3] > CHEWIN_BURN_TIME_MEDIUM) + reason="Time too large for Medium setting on CHEWIN_USE_STOVE; Food will automatically burn." + + if(J_HI) + if(step_list[3] > CHEWIN_BURN_TIME_HIGH) + reason="Time too large for High setting on CHEWIN_USE_STOVE; Food will automatically burn." + + else + reason="Unrecognized temperature for CHEWIN_USE_STOVE" + + if(!reason) + create_step_use_stove(step_list[2], step_list[3], FALSE) + if(CHEWIN_USE_STOVE_OPTIONAL) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_USE_STOVE_OPTIONAL" + switch(step_list[2]) + if(J_LO) + if(step_list[3] > CHEWIN_BURN_TIME_LOW) + reason="Time too large for Low setting on CHEWIN_USE_STOVE_OPTIONAL; Food will automatically burn." + + if(J_MED) + if(step_list[3] > CHEWIN_BURN_TIME_MEDIUM) + reason="Time too large for Medium setting on CHEWIN_USE_STOVE_OPTIONAL; Food will automatically burn." + + if(J_HI) + if(step_list[3] > CHEWIN_BURN_TIME_HIGH) + reason="Time too large for High setting on CHEWIN_USE_STOVE_OPTIONAL; Food will automatically burn." + else + reason="Unrecognized temperature for CHEWIN_USE_STOVE_OPTIONAL" + if(!reason) + create_step_use_stove(step_list[2], step_list[3], TRUE) + + if(CHEWIN_USE_GRILL) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_USE_GRILL" + switch(step_list[2]) + if(J_LO) + if(step_list[3] > CHEWIN_BURN_TIME_LOW) + reason="Time too large for Low setting on CHEWIN_USE_GRILL; Food will automatically burn." + + if(J_MED) + if(step_list[3] > CHEWIN_BURN_TIME_MEDIUM) + reason="Time too large for Medium setting on CHEWIN_USE_GRILL; Food will automatically burn." + + if(J_HI) + if(step_list[3] > CHEWIN_BURN_TIME_HIGH) + reason="Time too large for High setting on CHEWIN_USE_GRILL; Food will automatically burn." + + else + reason="Unrecognized temperature for CHEWIN_USE_GRILL" + + if(!reason) + create_step_use_grill(step_list[2], step_list[3], FALSE) + + if(CHEWIN_USE_GRILL_OPTIONAL) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_USE_GRILL_OPTIONAL" + switch(step_list[2]) + if(J_LO) + if(step_list[3] > CHEWIN_BURN_TIME_LOW) + reason="Time too large for Low setting on CHEWIN_USE_GRILL_OPTIONAL; Food will automatically burn." + + if(J_MED) + if(step_list[3] > CHEWIN_BURN_TIME_MEDIUM) + reason="Time too large for Medium setting on CHEWIN_USE_GRILL_OPTIONAL; Food will automatically burn." + + if(J_HI) + if(step_list[3] > CHEWIN_BURN_TIME_HIGH) + reason="Time too large for High setting on CHEWIN_USE_GRILL_OPTIONAL; Food will automatically burn." + else + reason="Unrecognized temperature for CHEWIN_USE_GRILL_OPTIONAL" + if(!reason) + create_step_use_grill(step_list[2], step_list[3], TRUE) + if(CHEWIN_USE_OVEN) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_USE_OVEN" + switch(step_list[2]) + if(J_LO) + if(step_list[3] > CHEWIN_BURN_TIME_LOW) + reason="Time too large for Low setting on CHEWIN_USE_OVEN; Food will automatically burn." + + if(J_MED) + if(step_list[3] > CHEWIN_BURN_TIME_MEDIUM) + reason="Time too large for Medium setting on CHEWIN_USE_OVEN; Food will automatically burn." + + if(J_HI) + if(step_list[3] > CHEWIN_BURN_TIME_HIGH) + reason="Time too large for High setting on CHEWIN_USE_OVEN; Food will automatically burn." + + else + reason="Unrecognized temperature for CHEWIN_USE_OVEN" + + if(!reason) + create_step_use_oven(step_list[2], step_list[3], FALSE) + + if(CHEWIN_USE_FRYER) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_USE_FRYER" + switch(step_list[2]) + if(J_HI) + if(step_list[3] > CHEWIN_BURN_TIME_HIGH) + reason="Time too large for High setting on CHEWIN_USE_FRYER; Food will automatically burn." + + else + reason="Unrecognized temperature for CHEWIN_USE_FRYER" + + if(!reason) + create_step_use_fryer(step_list[2], step_list[3], FALSE) + + if(CHEWIN_USE_OVEN_OPTIONAL) + if(step_list.len < 3) + reason="Bad argument Length for CHEWIN_USE_OVEN_OPTIONAL" + switch(step_list[2]) + if(J_LO) + if(step_list[3] > CHEWIN_BURN_TIME_LOW) + reason="Time too large for Low setting on CHEWIN_USE_OVEN_OPTIONAL; Food will automatically burn." + + if(J_MED) + if(step_list[3] > CHEWIN_BURN_TIME_MEDIUM) + reason="Time too large for Medium setting on CHEWIN_USE_OVEN_OPTIONAL; Food will automatically burn." + + if(J_HI) + if(step_list[3] > CHEWIN_BURN_TIME_HIGH) + reason="Time too large for High setting on CHEWIN_USE_OVEN_OPTIONAL; Food will automatically burn." + else + reason="Unrecognized temperature for CHEWIN_USE_OVEN_OPTIONAL" + if(!reason) + create_step_use_oven(step_list[2], step_list[3], TRUE) + + //Named Arguments modify the recipe in fixed ways + if("desc" in step_list) + set_step_desc(step_list["desc"]) + + if("base" in step_list) + set_step_base_quality(step_list["base"]) + + if("max" in step_list) + set_step_max_quality(step_list["max"]) + + if("prod_desc" in step_list) + set_step_custom_result_desc(step_list["prod_desc"]) + + if("food_buff" in step_list) + set_step_custom_food_buff(step_list["food_buff"]) + + if("finish_text" in step_list) + set_step_custom_finish_text(step_list["finish_text"]) + + if("qmod" in step_list) + if(!set_inherited_quality_modifier(step_list["qmod"])) + reason="qmod / inherited_quality_modifier declared on non add-item recipe step." + + if("remain_percent" in step_list) + if(step_list["remain_percent"] > 1 || step_list["remain_percent"] < 0) + reason="remain_percent must be between 1 and 0." + else if(!set_remain_percent_modifier(step_list["remain_percent"])) + reason="remain_percent / declared on non add-reagent recipe step." + + if("exact" in step_list) + if(!set_exact_type_required(step_list["exact"])) + reason="exact / exact type match declared on non add-item / use-item recipe step." + + if("reagent_skip" in step_list) + if(!set_reagent_skip(step_list["reagent_skip"])) + reason="reagent_skip / reagent_skip declared on non add-item / add-reagent recipe step." + + if("exclude_reagents" in step_list) + for(var/id in step_list["exclude_reagents"]) + var/datum/reagent/path = text2path(id) + if(!path) + path = id + if(!ispath(path, /datum/reagent)) + reason="exclude_reagents list has nonexistant reagent id [id]" + + if(!set_exclude_reagents(step_list["exclude_reagents"])) + reason="exclude_reagents declared on non add-item / add-reagent recipe step." + + if(reason) + CRASH("[src.type]/New: CHEWIN Step Builder failed. Reason: [reason]") + else + switch(step) + if(CHEWIN_BEGIN_EXCLUSIVE_OPTIONS) + begin_exclusive_options() + if(CHEWIN_END_EXCLUSIVE_OPTIONS) + end_exclusive_options() + if(CHEWIN_BEGIN_OPTION_CHAIN) + begin_option_chain() + if(CHEWIN_END_OPTION_CHAIN) + end_option_chain() + + if(exclusive_option_mode) + CRASH("/datum/chewin_cooking/recipe/New: Exclusive option active at end of recipe creation process. Recipe name=[name].") + + if(option_chain_mode) + CRASH("/datum/chewin_cooking/recipe/New: Option Chain active at end of recipe creation process. Recipe name=[name].") + + if(last_created_step.flags & CHEWIN_IS_OPTIONAL) + CRASH("/datum/chewin_cooking/recipe/New: Last option in builder is optional. It must be a required step! Recipe name=[name].") + +//----------------------------------------------------------------------------------- +//Commands for interacting with the recipe tracker +//----------------------------------------------------------------------------------- +//Add base step command. All other steps stem from this. Don't call twice! +/datum/chewin_cooking/recipe/proc/create_step_base() + var/datum/chewin_cooking/recipe_step/start/step = new /datum/chewin_cooking/recipe_step/start(cooking_container) + last_required_step = step + last_created_step = step + first_step = step + +//----------------------------------------------------------------------------------- +//Add reagent step shortcut commands +/datum/chewin_cooking/recipe/proc/create_step_add_reagent(var/reagent_id, var/amount, var/optional) + var/datum/chewin_cooking/recipe_step/add_reagent/step = new (reagent_id, amount, src) + return src.add_step(step, optional) + +//----------------------------------------------------------------------------------- +//Add reagent choice step shortcut commands +/datum/chewin_cooking/recipe/proc/create_step_add_reagent_choice(var/list/reagent_ids, var/amount, var/optional) + var/datum/chewin_cooking/recipe_step/add_reagent_choice/step = new (reagent_ids, amount, src) + return src.add_step(step, optional) + +//----------------------------------------------------------------------------------- +//Add produce step shortcut commands +/datum/chewin_cooking/recipe/proc/create_step_add_produce_choice(var/list/produces, var/optional) + var/datum/chewin_cooking/recipe_step/add_produce_choice/step = new (produces, src) + return src.add_step(step, optional) + +//----------------------------------------------------------------------------------- +//Add item step shortcut commands +/datum/chewin_cooking/recipe/proc/create_step_add_item(var/item_type, var/optional) + var/datum/chewin_cooking/recipe_step/add_item/step = new (item_type, src) + return src.add_step(step, optional) +//----------------------------------------------------------------------------------- +//Use item step shortcut commands +/datum/chewin_cooking/recipe/proc/create_step_use_item(var/item_type, var/optional) + var/datum/chewin_cooking/recipe_step/use_item/step = new (item_type, src) + return src.add_step(step, optional) + +//----------------------------------------------------------------------------------- +//Use item step shortcut commands +/datum/chewin_cooking/recipe/proc/create_step_add_produce(var/produce, var/optional) + var/datum/chewin_cooking/recipe_step/add_produce/step = new /datum/chewin_cooking/recipe_step/add_produce(produce, src) + return src.add_step(step, optional) +//----------------------------------------------------------------------------------- +//Use Tool step shortcut commands +/datum/chewin_cooking/recipe/proc/create_step_use_tool(var/type, var/quality, var/optional) + var/datum/chewin_cooking/recipe_step/use_tool/step = new (type, quality, src) + return src.add_step(step, optional) + +//----------------------------------------------------------------------------------- +//Use Fryer step shortcut commands +/datum/chewin_cooking/recipe/proc/create_step_use_fryer(var/heat, var/time, var/optional) + var/datum/chewin_cooking/recipe_step/use_fryer/step = new (heat, time, src) + return src.add_step(step, optional) + +//----------------------------------------------------------------------------------- +//Use Stove step shortcut commands +/datum/chewin_cooking/recipe/proc/create_step_use_stove(var/heat, var/time, var/optional) + var/datum/chewin_cooking/recipe_step/use_stove/step = new (heat, time, src) + return src.add_step(step, optional) +//----------------------------------------------------------------------------------- +//Use Grill step shortcut commands +/datum/chewin_cooking/recipe/proc/create_step_use_grill(var/heat, var/time, var/optional) + var/datum/chewin_cooking/recipe_step/use_grill/step = new (heat, time, src) + return src.add_step(step, optional) +//----------------------------------------------------------------------------------- +//Use Stove step shortcut commands +/datum/chewin_cooking/recipe/proc/create_step_use_oven(var/heat, var/time, var/optional) + var/datum/chewin_cooking/recipe_step/use_oven/step = new (heat, time, src) + return src.add_step(step, optional) +//----------------------------------------------------------------------------------- +//Customize the last step created +/datum/chewin_cooking/recipe/proc/set_step_desc(var/new_description) + last_created_step.desc = new_description + +/datum/chewin_cooking/recipe/proc/set_step_max_quality(var/quality) + last_created_step.flags |= CHEWIN_BASE_QUALITY_ENABLED + last_created_step.max_quality_award = quality + +/datum/chewin_cooking/recipe/proc/set_step_base_quality(var/quality) + last_created_step.flags |= CHEWIN_MAX_QUALITY_ENABLED + last_created_step.base_quality_award = quality + +/datum/chewin_cooking/recipe/proc/set_step_custom_result_desc(var/new_description) + last_created_step.custom_result_desc = new_description + +/datum/chewin_cooking/recipe/proc/set_step_custom_finish_text(var/new_finish_text) + last_created_step.finish_text = new_finish_text + +/datum/chewin_cooking/recipe/proc/set_step_custom_food_buff(var/new_food_buff) + last_created_step.custom_food_buff = new_food_buff + +/datum/chewin_cooking/recipe/proc/set_exact_type_required(var/boolean) + if((last_created_step.class == CHEWIN_ADD_ITEM) || (last_created_step.class == CHEWIN_USE_ITEM)) + last_created_step?:exact_path = boolean + return TRUE + else + return FALSE + +/datum/chewin_cooking/recipe/proc/set_reagent_skip(var/boolean) + if((last_created_step.class == CHEWIN_ADD_ITEM) || (last_created_step.class == CHEWIN_ADD_PRODUCE)) + last_created_step?:reagent_skip = boolean + return TRUE + else + return FALSE + +/datum/chewin_cooking/recipe/proc/set_exclude_reagents(var/list/exclude_list) + if((last_created_step.class == CHEWIN_ADD_ITEM) || (last_created_step.class == CHEWIN_ADD_PRODUCE)) + last_created_step?:exclude_reagents = exclude_list + return TRUE + else + return FALSE + +/datum/chewin_cooking/recipe/proc/set_inherited_quality_modifier(var/modifier) + if(last_created_step.class == CHEWIN_ADD_ITEM || last_created_step.class == CHEWIN_USE_TOOL || last_created_step.class == CHEWIN_ADD_PRODUCE) + last_created_step?:inherited_quality_modifier = modifier + return TRUE + else + return FALSE + +/datum/chewin_cooking/recipe/proc/set_remain_percent_modifier(var/modifier) + if(last_created_step.class == CHEWIN_ADD_REAGENT) + last_created_step?:remain_percent = modifier + return TRUE + else + return FALSE + +//----------------------------------------------------------------------------------- +//Setup for two options being exclusive to eachother. +//Performs a lot of internal checking to make sure that it doesn't break everything. +//If begin_exclusive_options is called, end_exclusive_options must eventually be called in order to close out and proceed to the next required step. + +/datum/chewin_cooking/recipe/proc/begin_exclusive_options() + if(exclusive_option_mode) + #ifdef CHEWIN_DEBUG + log_debug("/datum/chewin_cooking/recipe/proc/begin_exclusive_options: Exclusive option already active.") + log_debug("Recipe name=[name].") + #endif + return + else if(!first_step) + CRASH("/datum/chewin_cooking/recipe/proc/begin_exclusive_options: Exclusive list cannot be active before the first required step is defined. Recipe name=[src.type].") + exclusive_option_mode = TRUE + active_exclusive_option_list = list() + +/datum/chewin_cooking/recipe/proc/end_exclusive_options() + if(!exclusive_option_mode) + #ifdef CHEWIN_DEBUG + log_debug("/datum/chewin_cooking/recipe/proc/end_exclusive_options: Exclusive option already inactive.") + log_debug("Recipe name=[name].") + #endif + return + else if(active_exclusive_option_list.len == 0) + CRASH("/datum/chewin_cooking/recipe/proc/end_exclusive_options: Exclusive option list ended with no values added. Recipe name=[src.type].") + else if(option_chain_mode) + CRASH("/datum/chewin_cooking/recipe/proc/end_exclusive_options: Exclusive option cannot end while option chain is active. Recipe name=[src.type].") + + exclusive_option_mode = FALSE + + //Flatten exclusive options into the global list for easy referencing later. + //initiate the exclusive option list + for (var/datum/chewin_cooking/recipe_step/exclusive_option in active_exclusive_option_list) + if (!GLOB.chewin_optional_step_exclusion_dictionary["[exclusive_option.unique_id]"]) + GLOB.chewin_optional_step_exclusion_dictionary["[exclusive_option.unique_id]"] = list() + //populate the exclusive option list + for (var/datum/chewin_cooking/recipe_step/exclusive_option in active_exclusive_option_list) + for (var/datum/chewin_cooking/recipe_step/excluder in active_exclusive_option_list["[exclusive_option]"]) + if (exclusive_option.unique_id != excluder.unique_id) + GLOB.chewin_optional_step_exclusion_dictionary["[exclusive_option.unique_id]"] = excluder.unique_id + + active_exclusive_option_list = null + +//----------------------------------------------------------------------------------- +//Setup for a chain of optional steps to be added that order themselves sequentially. +//Optional steps with branching paths is NOT supported. +//If begin_option_chain is called, end_option_chain must eventually be called in order to close out and proceed to the next required step. +/datum/chewin_cooking/recipe/proc/begin_option_chain() + if(option_chain_mode) + #ifdef CHEWIN_DEBUG + log_debug("/datum/chewin_cooking/recipe/proc/begin_option_chain: Option Chain already active.") + log_debug("Recipe name=[name].") + #endif + return + if(!first_step) + CRASH("/datum/chewin_cooking/recipe/proc/begin_option_chain: Option Chain cannot be active before first required step is defined. Recipe name=[name].") + option_chain_mode =1 + +/datum/chewin_cooking/recipe/proc/end_option_chain() + if(!option_chain_mode) + #ifdef CHEWIN_DEBUG + log_debug("/datum/chewin_cooking/recipe/proc/end_option_chain: Option Chain already inactive.") + log_debug("Recipe name=[name].") + #endif + return + last_created_step.next_step = last_required_step + option_chain_mode = 0 + + +//----------------------------------------------------------------------------------- +//Function that dynamically adds a step into a given recipe matrix. +/datum/chewin_cooking/recipe/proc/add_step(var/datum/chewin_cooking/recipe_step/step, var/optional) + + //Required steps can't have exclusive options. + //If a given recipe needs to split into two branching required steps, it should be split into two different recipes. + if(!optional && exclusive_option_mode) + CRASH("/datum/chewin_cooking/recipe/proc/add_step: Required step added while exclusive option mode is on. Recipe name=[name].") + + if(!optional && option_chain_mode) + CRASH("/datum/chewin_cooking/recipe/proc/add_step: Required step added while option chain mode is on. Recipe name=[name].") + + if(optional) + switch(option_chain_mode) + //When the chain needs to be initialized + if(1) + last_required_step.optional_step_list += step + option_chain_mode = 2 + step.flags |= CHEWIN_IS_OPTION_CHAIN + //When the chain has already started. + if(2) + last_created_step.next_step = step + step.flags |= CHEWIN_IS_OPTION_CHAIN + else + last_required_step.optional_step_list += step + //Set the next step to loop back to the step it branched from. + step.next_step = last_required_step + else + last_required_step.next_step = step + + + //populate the previous step for optional backwards pathing. + if(option_chain_mode) + step.previous_step = last_created_step + else + step.previous_step = last_required_step + + //Update flags + if(!optional) + last_required_step.flags &= ~CHEWIN_IS_LAST_STEP + step.flags |= CHEWIN_IS_LAST_STEP + else + step.flags |= CHEWIN_IS_OPTIONAL + if(exclusive_option_mode) + step.flags |= CHEWIN_IS_EXCLUSIVE + if(option_chain_mode) + step.flags |= CHEWIN_IS_OPTION_CHAIN + + if(!optional) + last_required_step = step + + last_created_step = step + + //Handle exclusive options + if(exclusive_option_mode) + active_exclusive_option_list[step] = list() + for (var/datum/chewin_cooking/recipe_step/ex_step in active_exclusive_option_list) + if(ex_step == step.unique_id || step.in_option_chain(ex_step)) + continue + active_exclusive_option_list[ex_step] += step + return step + +//----------------------------------------------------------------------------------- +//default function for creating a product +/datum/chewin_cooking/recipe/proc/create_product(var/datum/chewin_cooking/recipe_pointer/pointer, var/mob/user) + var/datum/chewin_cooking/recipe_tracker/parent = pointer.parent_ref.resolve() + var/obj/item/container = parent.holder_ref.resolve() + if(container) + //Build up a list of reagents that went into this. + var/datum/reagents/slurry = new /datum/reagents(maximum=1000000) + slurry.my_atom = container + + //Filter out reagents based on settings + if(GLOB.chewin_step_dictionary_ordered["[CHEWIN_ADD_REAGENT]"]) + for(var/id in pointer.steps_taken) + if(!GLOB.chewin_step_dictionary_ordered["[CHEWIN_ADD_REAGENT]"][id]) + continue + var/datum/chewin_cooking/recipe_step/add_reagent/active_step = GLOB.chewin_step_dictionary_ordered["[CHEWIN_ADD_REAGENT]"][id] + var/amount_to_remove = active_step.required_reagent_amount * (1 - active_step.remain_percent) + if(!amount_to_remove) + continue + #ifdef CHEWIN_DEBUG + log_debug("/recipe/proc/create_product: Removing [amount_to_remove] units of id [active_step.required_reagent_id] from [container]") + #endif + container.reagents.remove_reagent(active_step.required_reagent_id, amount_to_remove, safety = 1) + + if(product_type) //Make a regular item + if(container.reagents.total_volume) + #ifdef CHEWIN_DEBUG + log_debug("/recipe/proc/create_product: Transferring container reagents of [container.reagents.total_volume] to slurry of current volume [slurry.total_volume] max volume [slurry.maximum_volume]") + #endif + container.reagents.trans_to(slurry, amount=container.reagents.total_volume) + + //Do reagent filtering on added items and produce + var/list/exclude_list = list() + for(var/obj/item/added_item in container.contents) + var/can_add = TRUE + var/list/exclude_specific_reagents = list() + #ifdef CHEWIN_DEBUG + log_debug("/recipe/proc/create_product: Analyzing reagents of [added_item].") + #endif + for(var/id in pointer.steps_taken) + #ifdef CHEWIN_DEBUG + log_debug("/recipe/proc/create_product: Comparing step id [id] for [added_item].") + #endif + if(id in exclude_list) //Only consider a step for removal one time. + #ifdef CHEWIN_DEBUG + log_debug("/recipe/proc/create_product: id in exclude list; skipping.") + #endif + continue + if(GLOB.chewin_step_dictionary_ordered["[CHEWIN_ADD_ITEM]"] && GLOB.chewin_step_dictionary_ordered["[CHEWIN_ADD_ITEM]"][id]) + var/datum/chewin_cooking/recipe_step/add_item/active_step = GLOB.chewin_step_dictionary_ordered["[CHEWIN_ADD_ITEM]"][id] + exclude_specific_reagents = active_step.exclude_reagents + if(active_step.reagent_skip) + #ifdef CHEWIN_DEBUG + log_debug("/recipe/proc/create_product: Reagent skip detected. Ignoring reagents from [added_item].") + #endif + can_add = FALSE + exclude_list += id + break + else if(GLOB.chewin_step_dictionary_ordered["[CHEWIN_ADD_PRODUCE]"] && GLOB.chewin_step_dictionary_ordered["[CHEWIN_ADD_PRODUCE]"][id]) + var/datum/chewin_cooking/recipe_step/add_produce/active_step = GLOB.chewin_step_dictionary_ordered["[CHEWIN_ADD_PRODUCE]"][id] + exclude_specific_reagents = active_step.exclude_reagents + if(active_step.reagent_skip) + #ifdef CHEWIN_DEBUG + log_debug("/recipe/proc/create_product: Reagent skip detected. Ignoring reagents from [added_item].") + #endif + can_add = FALSE + exclude_list += id + break + if(can_add) + if(exclude_specific_reagents.len) + for(var/id in exclude_specific_reagents) + #ifdef CHEWIN_DEBUG + log_debug("/recipe/proc/create_product: Removing [added_item.reagents.get_reagent_amount(id)] units of id [id] from [added_item]") + #endif + added_item.reagents.remove_reagent(id, added_item.reagents.get_reagent_amount(id), safety=TRUE) + #ifdef CHEWIN_DEBUG + log_debug("/recipe/proc/create_product: Adding [added_item.reagents.total_volume] units from [added_item] to slurry") + #endif + added_item.reagents.trans_to(slurry, amount=added_item.reagents.total_volume) + + //Purge the contents of the container we no longer need it + QDEL_LIST(container.contents) + container.contents = list() + + var/reagent_quality = calculate_reagent_quality(pointer) + + //Produce Item descriptions based on the steps taken + var/cooking_description_modifier = "" + for(var/id in pointer.steps_taken) + if(pointer.steps_taken[id] != "skip") + cooking_description_modifier += "[pointer.steps_taken[id]]\n" + + food_buff_override = pointer.custom_food_buff + + for(var/i = 0; i < product_count; i++) + var/obj/item/new_item = new product_type(container) + logger.Log(LOG_CATEGORY_DEBUG, "Item created with reagents of [new_item.reagents.total_volume]") + if(replace_reagents) + //Clearing out reagents in data. If initialize hasn't been called, we also null that out here. + #ifdef CHEWIN_DEBUG + log_debug("/recipe/proc/create_product: Clearing out reagents from the [new_item]") + #endif + new_item.reagents.clear_reagents() + #ifdef CHEWIN_DEBUG + log_debug("/recipe/proc/create_product: Transferring slurry of [slurry.total_volume] to [new_item] of total volume [new_item.reagents.total_volume]") + #endif + slurry.trans_to(new_item.reagents, amount=slurry.total_volume) + + new_item?:food_quality = pointer.tracked_quality + reagent_quality + new_item?:cooking_description_modifier = cooking_description_modifier + if(user) + ADD_TRAIT(new_item, TRAIT_FOOD_CHEF_MADE, user) + if(istype(new_item, /obj/item/food) && food_buff_override) + var/obj/item/food/food_item = new_item + food_item?:food_buffs = food_buff_override + + if(istype(new_item, /obj/item/food)) + var/obj/item/food/food_type = new_item + if(food_type.food_quality < 0) + food_type.food_buffs = /datum/status_effect/food/food_poisoning + //TODO: Consider making an item's base components show up in the reagents of the product. + else + //Purge the contents of the container we no longer need it + QDEL_LIST(container.contents) + container.contents = list() + + container.reagents.clear_reagents() + + if(reagent_id) //Make a reagent + //quality handling + var/total_quality = pointer.tracked_quality + calculate_reagent_quality(pointer) + + //Create our Reagent + container.reagents.add_reagent(reagent_id, reagent_amount, data=list("FOOD_QUALITY" = total_quality)) + + qdel(slurry) + +//Extra Reagents in a recipe take away recipe quality for every extra unit added to the concoction. +//Reagents are calculated in two areas. Here and /datum/chewin_cooking/recipe_step/add_reagent/calculate_quality +/datum/chewin_cooking/recipe/proc/calculate_reagent_quality(var/datum/chewin_cooking/recipe_pointer/pointer) + if(!GLOB.chewin_step_dictionary_ordered["[CHEWIN_ADD_REAGENT]"]) + return 0 + var/datum/chewin_cooking/recipe_tracker/parent = pointer.parent_ref.resolve() + var/obj/item/container = parent.holder_ref.resolve() + var/total_volume = container.reagents.total_volume + + var/calculated_volume = 0 + + var/calculated_quality = 0 + for(var/id in pointer.steps_taken) + if(!GLOB.chewin_step_dictionary_ordered["[CHEWIN_ADD_REAGENT]"][id]) + continue + var/datum/chewin_cooking/recipe_step/add_reagent/active_step = GLOB.chewin_step_dictionary_ordered["[CHEWIN_ADD_REAGENT]"][id] + calculated_volume += active_step.required_reagent_amount + + calculated_quality += active_step.base_quality_award + + return calculated_quality - (total_volume - calculated_volume) + + + +//----------------------------------------------------------------------------------- +/datum/chewin_cooking/proc/get_class_string(var/code) + switch(code) + if(CHEWIN_ADD_ITEM) + return "Add Item" + if(CHEWIN_USE_ITEM) + return "Use Item" + if(CHEWIN_ADD_REAGENT) + return "Add Reagent" + if(CHEWIN_ADD_REAGENT_CHOICE) + return "Add one of these Reagents" + if(CHEWIN_ADD_PRODUCE_CHOICE) + return "Add one of these Produce" + if(CHEWIN_ADD_PRODUCE) + return "Add Produce" + if(CHEWIN_USE_TOOL) + return "Use Tool" + if(CHEWIN_USE_STOVE) + return "Use Stove" + if(CHEWIN_USE_GRILL) + return "Use Grill" + if(CHEWIN_USE_OVEN) + return "Use Oven" + if(CHEWIN_USE_FRYER) + return "Use Fryer" + if(CHEWIN_USE_OTHER) + return "Custom Action" + if(CHEWIN_START) + return "Placeholder Action" diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/_base.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/_base.dm new file mode 100644 index 000000000000..4bd0b7178300 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/_base.dm @@ -0,0 +1,108 @@ +//A step in a recipe, whether optional or required +/datum/chewin_cooking/recipe_step + var/unique_id //Special ID for a given recipe, allows for referencing later by food objects to save on memory. + + var/class = CHEWIN_USE_OTHER //The classificaiton of the step involved. + + var/group_identifier = "None" //Different for every type of recipe. + + var/image/tooltip_image = null + + var/parent_recipe //The parent recipe of this particular step. Created on initialization with New() + + var/desc //A description of the step + + var/custom_result_desc //A custom description of the resulting quality on a successful completion. + + var/list/optional_step_list = list() //List of optional steps that can be followed from this point forward. + + var/max_quality_award = 0 //The maximum quality awarded by following a given step to the letter. + + var/base_quality_award = 0 + + var/flags = 0 + + var/custom_food_buff + + var/finish_text + + //The next required step for the parent recipe + var/datum/chewin_cooking/recipe_step/next_step + + //The previous required step for the current recipe + var/datum/chewin_cooking/recipe_step/previous_step + + var/auto_complete_enabled = FALSE //If the step can be completed without any further input. + + + +/datum/chewin_cooking/recipe_step/New(var/datum/chewin_cooking/recipe/our_recipe) + parent_recipe = our_recipe + unique_id = sequential_id("recipe_step") + + if(!tooltip_image) + src.set_image() + + //Add the recipe to our dictionary for future reference. + if(!GLOB.chewin_step_dictionary_ordered["[class]"]) + GLOB.chewin_step_dictionary_ordered["[class]"] = list() + GLOB.chewin_step_dictionary_ordered["[class]"]["[unique_id]"] = src + GLOB.chewin_step_dictionary["[unique_id]"] = src + +/datum/chewin_cooking/recipe_step/proc/set_image() + + +//Calculate how well the recipe step was followed to the letter. +/datum/chewin_cooking/recipe_step/proc/calculate_quality(var/obj/added_item, var/obj/item/reagent_containers/container) + return 0 + +//Check if the conditions of a recipe step was followed correctly. +/datum/chewin_cooking/recipe_step/proc/check_conditions_met() + return CHEWIN_CHECK_VALID + +//Check if a given step is in the same option chain as another step. +/datum/chewin_cooking/recipe_step/proc/in_option_chain(var/datum/chewin_cooking/recipe_step/step) + if(!step) + return FALSE + if(!(flags & CHEWIN_IS_OPTION_CHAIN) || !(step.flags & CHEWIN_IS_OPTION_CHAIN)) + return FALSE + + var/datum/chewin_cooking/recipe_step/target_step = src.previous_step + //traverse backwards on the chain. + while(target_step && !(target_step & CHEWIN_IS_OPTION_CHAIN)) + if(step.unique_id == target_step.unique_id) + return TRUE + target_step = target_step.previous_step + + //Traverse forwards on the chain. + target_step = src.next_step + while(target_step && !(target_step & CHEWIN_IS_OPTION_CHAIN)) + if(step.unique_id == target_step.unique_id) + return TRUE + target_step = src.next_step + + //We didn't find anything. Return False. + return FALSE + +//Automatically clamps food based on their maximum and minimum quality, if they are set. +/datum/chewin_cooking/recipe_step/proc/clamp_quality(var/raw_quality) + if((flags & CHEWIN_BASE_QUALITY_ENABLED) && (flags & CHEWIN_MAX_QUALITY_ENABLED)) + return clamp(raw_quality, base_quality_award, max_quality_award) + if(flags & CHEWIN_BASE_QUALITY_ENABLED) + return max(raw_quality, base_quality_award) + if(flags & CHEWIN_MAX_QUALITY_ENABLED) + return min(raw_quality, max_quality_award) + return raw_quality + +/datum/chewin_cooking/recipe_step/proc/get_step_result_text(var/obj/used_obj, step_quality) + if(custom_result_desc) + return custom_result_desc + else + return "skip" + +/datum/chewin_cooking/recipe_step/proc/follow_step(var/obj/added_item, var/obj/item/reagent_containers/container) + return CHEWIN_SUCCESS + +//Special function to check if the step has been satisfied. Sometimed just following the step is enough, but not always. +/datum/chewin_cooking/recipe_step/proc/is_complete(var/obj/added_item, var/datum/chewin_cooking/recipe_tracker/tracker) + return TRUE diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_item.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_item.dm new file mode 100644 index 000000000000..18a7cf7f6516 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_item.dm @@ -0,0 +1,74 @@ +//A cooking step that involves adding an item to the food. Is based on Item Type. +//This basically deletes the food used on it. + +//ENSURE THE INCOMING ITEM HAS var/quality DEFINED! +/datum/chewin_cooking/recipe_step/add_item + class = CHEWIN_ADD_ITEM + + var/required_item_type //Item required for the recipe step + + var/inherited_quality_modifier = 1 //The modifier we apply multiplicatively to balance quality scaling across recipes. + + var/exact_path = FALSE //Tests if the item has to be the EXACT ITEM PATH, or just a child of the item path. + + var/reagent_skip = FALSE + + var/list/exclude_reagents = list() + +//item_type: The type path of the object we are looking for. +//our_recipe: The parent recipe object, +/datum/chewin_cooking/recipe_step/add_item/New(var/item_type, var/datum/chewin_cooking/recipe/our_recipe) + + #ifdef CHEWIN_DEBUG + if(!ispath(item_type, /obj/item)) + log_debug("/datum/chewin_cooking/recipe_step/add_item/New(): item [item_type] is not a valid path") + #endif + + var/obj/item/example_item = new item_type() + if(example_item) + desc = "Add \a [example_item] into the recipe." + + required_item_type = item_type + group_identifier = item_type + tooltip_image = image(example_item.icon, icon_state=example_item.icon_state) + QDEL_NULL(example_item) + #ifdef CHEWIN_DEBUG + else + log_debug("/datum/chewin_cooking/recipe_step/add_item/New(): item [item_type] couldn't be created.") + #endif + ..(our_recipe) + + +/datum/chewin_cooking/recipe_step/add_item/check_conditions_met(var/obj/added_item, var/datum/chewin_cooking/recipe_tracker/tracker) + #ifdef CHEWIN_DEBUG + log_debug("Called add_item/check_conditions_met for [added_item], checking against item type [required_item_type]. Exact_path = [exact_path]") + #endif + if(!istype(added_item, /obj/item)) + return CHEWIN_CHECK_INVALID + if(exact_path) + if(added_item.type == required_item_type) + return CHEWIN_CHECK_VALID + else + if(istype(added_item, required_item_type)) + return CHEWIN_CHECK_VALID + return CHEWIN_CHECK_INVALID + +//The quality of add_item is special, in that it inherits the quality level of its parent and +//passes it along. +//May need "Balancing" with var/inherited_quality_modifier +/datum/chewin_cooking/recipe_step/add_item/calculate_quality(var/obj/added_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/raw_quality = added_item?:food_quality * inherited_quality_modifier + return clamp_quality(raw_quality) + +/datum/chewin_cooking/recipe_step/add_item/follow_step(var/obj/added_item, var/datum/chewin_cooking/recipe_tracker/tracker) + #ifdef CHEWIN_DEBUG + logger.Log(LOG_CATEGORY_DEBUG, "Called: /datum/chewin_cooking/recipe_step/add_item/follow_step") + #endif + var/obj/item/container = tracker.holder_ref.resolve() + if(container) + if(usr.canUnEquip(added_item)) + usr.dropItemToGround(added_item) + added_item.forceMove(container) + else + added_item.forceMove(container) + return CHEWIN_SUCCESS diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_produce.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_produce.dm new file mode 100644 index 000000000000..596611a73221 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_produce.dm @@ -0,0 +1,59 @@ +//A cooking step that involves using SPECIFICALLY Grown foods +/datum/chewin_cooking/recipe_step/add_produce + class=CHEWIN_ADD_PRODUCE + var/required_produce_type + var/base_potency + var/reagent_skip = FALSE + var/inherited_quality_modifier + + var/list/exclude_reagents = list() + +/datum/chewin_cooking/recipe_step/add_produce/New(var/obj/item/food/grown/produce, var/datum/chewin_cooking/recipe/our_recipe) + if(produce) + desc = "Add \a [produce] into the recipe." + required_produce_type = produce + group_identifier = produce + + var/obj/item/food/grown/grown = new produce + var/obj/item/seeds/plant_seed = grown.seed + base_potency = initial(plant_seed.potency) + qdel(grown) + else + CRASH("/datum/chewin_cooking/recipe_step/add_produce/New: [produce] not found. Exiting.") + ..(base_quality_award, our_recipe) + +/datum/chewin_cooking/recipe_step/add_produce/check_conditions_met(var/obj/added_item, var/datum/chewin_cooking/recipe_tracker/tracker) + #ifdef CHEWIN_DEBUG + log_debug("Called add_produce/check_conditions_met for [added_item] against [required_produce_type]") + #endif + + if(!istype(added_item, /obj/item/food/grown)) + return CHEWIN_CHECK_INVALID + + var/obj/item/food/grown/added_produce = added_item + + if(added_produce.type == required_produce_type) + return CHEWIN_CHECK_VALID + + return CHEWIN_CHECK_INVALID + +/datum/chewin_cooking/recipe_step/add_produce/calculate_quality(var/obj/added_item, var/datum/chewin_cooking/recipe_tracker/tracker) + + var/obj/item/food/grown/added_produce = added_item + + var/potency_raw = round(base_quality_award + (added_produce.seed.potency - base_potency) * inherited_quality_modifier) + + return clamp_quality(potency_raw) + +/datum/chewin_cooking/recipe_step/add_produce/follow_step(var/obj/added_item, var/datum/chewin_cooking/recipe_tracker/tracker) + #ifdef CHEWIN_DEBUG + log_debug("Called: /datum/chewin_cooking/recipe_step/add_produce/follow_step") + #endif + var/obj/item/container = tracker.holder_ref.resolve() + if(container) + if(usr.canUnEquip(added_item)) + usr.dropItemToGround(added_item) + added_item.forceMove(container) + else + added_item.forceMove(container) + return CHEWIN_SUCCESS diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_produce_choice.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_produce_choice.dm new file mode 100644 index 000000000000..1c0c3b9168f2 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_produce_choice.dm @@ -0,0 +1,63 @@ +//A cooking step that involves using SPECIFICALLY Grown foods +/datum/chewin_cooking/recipe_step/add_produce_choice + class=CHEWIN_ADD_PRODUCE_CHOICE + var/list/required_produce_types = list() + var/list/base_potencies = list() + var/reagent_skip = FALSE + var/inherited_quality_modifier + + var/list/exclude_reagents = list() + +/datum/chewin_cooking/recipe_step/add_produce_choice/New(list/choices = list(), var/datum/chewin_cooking/recipe/our_recipe) + if(!length(choices)) + CRASH("/datum/chewin_cooking/recipe_step/add_produce_choice/New: No list passed in. Exiting.") + + group_identifier = "" + required_produce_types = choices + for(var/obj/item/food/grown/produce as anything in choices) + if(produce) + group_identifier += produce + var/obj/item/food/grown/grown = new produce + var/obj/item/seeds/plant_seed = grown.seed + base_potencies |= produce + base_potencies[produce] = initial(plant_seed.potency) + qdel(grown) + else + CRASH("/datum/chewin_cooking/recipe_step/add_produce_choice/New: [produce] not found. Exiting.") + ..(base_quality_award, our_recipe) + +/datum/chewin_cooking/recipe_step/add_produce_choice/check_conditions_met(var/obj/added_item, var/datum/chewin_cooking/recipe_tracker/tracker) + #ifdef CHEWIN_DEBUG + log_debug("Called add_produce_choice/check_conditions_met for [added_item] against [required_produce_type]") + #endif + + if(!istype(added_item, /obj/item/food/grown)) + return CHEWIN_CHECK_INVALID + + var/obj/item/food/grown/added_produce = added_item + + if(added_produce.type in required_produce_types) + return CHEWIN_CHECK_VALID + + return CHEWIN_CHECK_INVALID + +/datum/chewin_cooking/recipe_step/add_produce_choice/calculate_quality(var/obj/added_item, var/datum/chewin_cooking/recipe_tracker/tracker) + + var/obj/item/food/grown/added_produce = added_item + + var/potency_raw = round(base_quality_award + (added_produce.seed.potency - base_potencies[added_produce.type]) * inherited_quality_modifier * required_produce_types[added_produce.type]) + + return clamp_quality(potency_raw) + +/datum/chewin_cooking/recipe_step/add_produce_choice/follow_step(var/obj/added_item, var/datum/chewin_cooking/recipe_tracker/tracker) + #ifdef CHEWIN_DEBUG + log_debug("Called: /datum/chewin_cooking/recipe_step/add_produce_choice/follow_step") + #endif + var/obj/item/container = tracker.holder_ref.resolve() + if(container) + if(usr.canUnEquip(added_item)) + usr.dropItemToGround(added_item) + added_item.forceMove(container) + else + added_item.forceMove(container) + return CHEWIN_SUCCESS diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_reagent.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_reagent.dm new file mode 100644 index 000000000000..f4f1d531ef4a --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_reagent.dm @@ -0,0 +1,82 @@ +//A cooking step that involves adding a reagent to the food. +/datum/chewin_cooking/recipe_step/add_reagent + class=CHEWIN_ADD_REAGENT + auto_complete_enabled = TRUE + var/expected_total + var/required_reagent_id + var/required_reagent_amount + var/remain_percent = 1 //What percentage of the reagent ends up in the product + +//reagent_id: The id of the required reagent to be added, E.G. 'salt'. +//amount: The amount of the required reagent that needs to be added. +//base_quality_award: The quality awarded by following this step. +//our_recipe: The parent recipe object, +/datum/chewin_cooking/recipe_step/add_reagent/New(var/reagent_id, var/amount, var/datum/chewin_cooking/recipe/our_recipe) + + var/datum/reagent/global_reagent = GLOB.chemical_reagents_list[reagent_id] + if(global_reagent) + desc = "Add [amount] unit[amount>1 ? "s" : ""] of [global_reagent.name]." + + required_reagent_id = reagent_id + group_identifier = reagent_id + + required_reagent_amount = amount + else + CRASH("/datum/chewin_cooking/recipe_step/add/reagent/New(): Reagent [reagent_id] not found. Recipe: [our_recipe]") + + ..(our_recipe) + + +/datum/chewin_cooking/recipe_step/add_reagent/check_conditions_met(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/obj/item/container = tracker.holder_ref.resolve() + + + if((container.reagents.total_volume + required_reagent_amount - container.reagents.get_reagent_amount(required_reagent_id)) > container.reagents.maximum_volume) + return CHEWIN_CHECK_FULL + + if(!istype(used_item, /obj/item/reagent_containers)) + return CHEWIN_CHECK_INVALID + if(!(used_item.reagents?.flags & OPENCONTAINER)) + return CHEWIN_CHECK_INVALID + + var/obj/item/reagent_containers/our_item = used_item + if(our_item.amount_per_transfer_from_this <= 0) + return CHEWIN_CHECK_INVALID + if(our_item.reagents.total_volume == 0) + return CHEWIN_CHECK_INVALID + + return CHEWIN_CHECK_VALID + +//Reagents are calculated in two areas. Here and /datum/chewin_cooking/recipe/proc/calculate_reagent_quality +/datum/chewin_cooking/recipe_step/add_reagent/calculate_quality(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/obj/item/container = tracker.holder_ref.resolve() + var/data = container.reagents.get_data(required_reagent_id) + var/cooked_quality = 0 + if(data && istype(data, /list) && data["FOOD_QUALITY"]) + cooked_quality = data["FOOD_QUALITY"] + return cooked_quality + + +/datum/chewin_cooking/recipe_step/add_reagent/follow_step(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/obj/item/reagent_containers/our_item = used_item + var/obj/item/container = tracker.holder_ref.resolve() + + var/trans = our_item.reagents.trans_to(container, our_item.amount_per_transfer_from_this) + + playsound(usr,'monkestation/sound/chemistry/transfer/beakerpour_0-10-1.ogg',50,1) + to_chat(usr, span_notice("You transfer [trans] units to \the [container].")) + + return CHEWIN_SUCCESS + +/datum/chewin_cooking/recipe_step/add_reagent/is_complete(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/obj/item/reagent_containers/our_item = used_item + var/obj/item/container = tracker.holder_ref.resolve() + + var/incoming_amount = max(0, min(our_item.amount_per_transfer_from_this, our_item.reagents.total_volume, (container.reagents.maximum_volume - container.reagents.total_volume))) + + var/incoming_valid_amount = incoming_amount + + var/resulting_total = container.reagents.get_reagent_amount(required_reagent_id) + incoming_valid_amount + if(resulting_total >= required_reagent_amount) + return TRUE + return FALSE diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_reagent_choice.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_reagent_choice.dm new file mode 100644 index 000000000000..7444ba8afb35 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/add_reagent_choice.dm @@ -0,0 +1,95 @@ +//A cooking step that involves adding a reagent to the food. +/datum/chewin_cooking/recipe_step/add_reagent_choice + class=CHEWIN_ADD_REAGENT_CHOICE + auto_complete_enabled = TRUE + var/expected_total + var/list/reagent_ids + var/required_reagent_amount + var/remain_percent = 1 //What percentage of the reagent ends up in the product + +//reagent_ids: list of reagent_id = quality from step. +//amount: The amount of the required reagent that needs to be added. +//base_quality_award: The quality awarded by following this step. +//our_recipe: The parent recipe object, +/datum/chewin_cooking/recipe_step/add_reagent_choice/New(var/list/reagent_ids = list(), var/amount, var/datum/chewin_cooking/recipe/our_recipe) + + if(!length(reagent_ids)) + CRASH("/datum/chewin_cooking/recipe_step/add/reagent/New(): No Reagent List Given") + + group_identifier = "" + for(var/datum/reagent/reagent as anything in reagent_ids) + var/datum/reagent/global_reagent = GLOB.chemical_reagents_list[reagent] + if(global_reagent) + desc = "Add [amount] unit[amount>1 ? "s" : ""] of [global_reagent.name]." + + group_identifier += "[initial(reagent.name)] " + else + CRASH("/datum/chewin_cooking/recipe_step/add/reagent/New(): Reagent [reagent] not found. Recipe: [our_recipe]") + + required_reagent_amount = amount + src.reagent_ids = reagent_ids + + ..(our_recipe) + + +/datum/chewin_cooking/recipe_step/add_reagent_choice/check_conditions_met(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/obj/item/container = tracker.holder_ref.resolve() + + + var/return_type = CHEWIN_CHECK_VALID + for(var/datum/reagent/required_reagent_id as anything in reagent_ids) + return_type = CHEWIN_CHECK_VALID + if((container.reagents.total_volume + required_reagent_amount - container.reagents.get_reagent_amount(required_reagent_id)) > container.reagents.maximum_volume) + return_type = CHEWIN_CHECK_FULL + + if(!istype(used_item, /obj/item/reagent_containers)) + return_type = CHEWIN_CHECK_INVALID + if(!(used_item.reagents?.flags & OPENCONTAINER)) + return_type = CHEWIN_CHECK_INVALID + + var/obj/item/reagent_containers/our_item = used_item + if(our_item.amount_per_transfer_from_this <= 0) + return_type = CHEWIN_CHECK_INVALID + if(our_item.reagents.total_volume == 0) + return_type = CHEWIN_CHECK_INVALID + + if(return_type == CHEWIN_CHECK_VALID) + return return_type + + return return_type + +//Reagents are calculated in two areas. Here and /datum/chewin_cooking/recipe/proc/calculate_reagent_quality +/datum/chewin_cooking/recipe_step/add_reagent_choice/calculate_quality(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/obj/item/container = tracker.holder_ref.resolve() + for(var/datum/reagent/reagent as anything in container.reagents.reagent_list) + if(!(reagent.type in reagent_ids)) + continue + if(reagent.volume < required_reagent_amount) + continue + return reagent_ids[reagent.type] + + +/datum/chewin_cooking/recipe_step/add_reagent_choice/follow_step(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/obj/item/reagent_containers/our_item = used_item + var/obj/item/container = tracker.holder_ref.resolve() + + var/trans = our_item.reagents.trans_to(container, our_item.amount_per_transfer_from_this) + + playsound(usr,'monkestation/sound/chemistry/transfer/beakerpour_0-10-1.ogg',50,1) + to_chat(usr, span_notice("You transfer [trans] units to \the [container].")) + + return CHEWIN_SUCCESS + +/datum/chewin_cooking/recipe_step/add_reagent_choice/is_complete(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/obj/item/reagent_containers/our_item = used_item + var/obj/item/container = tracker.holder_ref.resolve() + + var/incoming_amount = max(0, min(our_item.amount_per_transfer_from_this, our_item.reagents.total_volume, (container.reagents.maximum_volume - container.reagents.total_volume))) + + var/incoming_valid_amount = incoming_amount + + for(var/datum/reagent/required_reagent_id as anything in reagent_ids) + var/resulting_total = container.reagents.get_reagent_amount(required_reagent_id) + incoming_valid_amount + if(resulting_total >= required_reagent_amount) + return TRUE + return FALSE diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/recipe_start.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/recipe_start.dm new file mode 100644 index 000000000000..5e6a26290337 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/recipe_start.dm @@ -0,0 +1,11 @@ + +//The default starting step. +//Doesn't do anything, just holds the item. + +/datum/chewin_cooking/recipe_step/start + class = CHEWIN_START + var/required_container + +/datum/chewin_cooking/recipe_step/start/New(var/container) + required_container = container + diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_fryer.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_fryer.dm new file mode 100644 index 000000000000..fedcbedd7287 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_fryer.dm @@ -0,0 +1,62 @@ +//A cooking step that involves adding a reagent to the food. +/datum/chewin_cooking/recipe_step/use_fryer + class=CHEWIN_USE_FRYER + auto_complete_enabled = TRUE + var/time + var/heat + +//set_heat: The temperature the oven must bake at. +//set_time: How long something must be baked in the overn +//our_recipe: The parent recipe object +/datum/chewin_cooking/recipe_step/use_fryer/New(var/set_heat, var/set_time, var/datum/chewin_cooking/recipe/our_recipe) + + + + time = set_time + heat = set_heat + + desc = "Cook in an oven set to [heat] for [DisplayTimeText(time)]." + + ..(our_recipe) + + +/datum/chewin_cooking/recipe_step/use_fryer/check_conditions_met(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + + if(!istype(used_item, /obj/machinery/deepfryer)) + return CHEWIN_CHECK_INVALID + + return CHEWIN_CHECK_VALID + +//Reagents are calculated prior to object creation +/datum/chewin_cooking/recipe_step/use_fryer/calculate_quality(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/obj/item/reagent_containers/cooking_container/container = tracker.holder_ref.resolve() + + var/bad_cooking = 0 + for (var/key in container.fryer_data) + if (heat != key) + bad_cooking += container.fryer_data[key] + + bad_cooking = round(bad_cooking/(5 SECONDS)) + + var/good_cooking = round(time/3 SECONDS) - bad_cooking + + return clamp_quality(good_cooking) + + +/datum/chewin_cooking/recipe_step/use_fryer/follow_step(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + return CHEWIN_SUCCESS + +/datum/chewin_cooking/recipe_step/use_fryer/is_complete(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + + var/obj/item/reagent_containers/cooking_container/container = tracker.holder_ref.resolve() + + if(container.fryer_data[heat] >= time) + #ifdef CHEWIN_DEBUG + log_debug("use_fryer/is_complete() Returned True; comparing [heat]: [container.oven_data[heat]] to [time]") + #endif + return TRUE + + #ifdef CHEWIN_DEBUG + log_debug("use_fryer/is_complete() Returned False; comparing [heat]: [container.oven_data[heat]] to [time]") + #endif + return FALSE diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_grill.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_grill.dm new file mode 100644 index 000000000000..87b3ff8308e4 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_grill.dm @@ -0,0 +1,63 @@ +//A cooking step that involves adding a reagent to the food. +/datum/chewin_cooking/recipe_step/use_grill + class=CHEWIN_USE_GRILL + auto_complete_enabled = TRUE + var/time + var/heat + +//reagent_id: The id of the required reagent to be added, E.G. 'salt'. +//amount: The amount of the required reagent that needs to be added. +//base_quality_award: The quality awarded by following this step. +//our_recipe: The parent recipe object, +/datum/chewin_cooking/recipe_step/use_grill/New(var/set_heat, var/set_time, var/datum/chewin_cooking/recipe/our_recipe) + + + + time = set_time + heat = set_heat + + desc = "Cook on a grill set to [heat] for [DisplayTimeText(time)]." + + ..(our_recipe) + + +/datum/chewin_cooking/recipe_step/use_grill/check_conditions_met(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + + if(!istype(used_item, /obj/machinery/grill)) + return CHEWIN_CHECK_INVALID + + return CHEWIN_CHECK_VALID + +//Reagents are calculated prior to object creation +/datum/chewin_cooking/recipe_step/use_grill/calculate_quality(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/obj/item/reagent_containers/cooking_container/container = tracker.holder_ref.resolve() + + var/bad_cooking = 0 + for (var/key in container.grill_data) + if (heat != key) + bad_cooking += container.grill_data[key] + + bad_cooking = round(bad_cooking/(5 SECONDS)) + + var/good_cooking = round(time/3 SECONDS) - bad_cooking + + return clamp_quality(good_cooking) + + +/datum/chewin_cooking/recipe_step/use_grill/follow_step(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + return CHEWIN_SUCCESS + +/datum/chewin_cooking/recipe_step/use_grill/is_complete(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + + var/obj/item/reagent_containers/cooking_container/container = tracker.holder_ref.resolve() + + if(container.grill_data[heat] >= time) + #ifdef CHEWIN_DEBUG + log_debug("use_grill/is_complete() Returned True; comparing [heat]: [container.grill_data[heat]] to [time]") + #endif + return TRUE + + #ifdef CHEWIN_DEBUG + log_debug("use_grill/is_complete() Returned False; comparing [heat]: [container.grill_data[heat]] to [time]") + #endif + return FALSE diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_item.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_item.dm new file mode 100644 index 000000000000..17e3e4f86d96 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_item.dm @@ -0,0 +1,42 @@ +//A cooking step that involves using an item on the food. +/datum/chewin_cooking/recipe_step/use_item + class=CHEWIN_USE_ITEM + var/required_item_type + var/exact_path = FALSE //Tests if the item has to be the EXACT ITEM PATH, or just a child of the item path. + +//item_type: The type path of the object we are looking for. +//base_quality_award: The quality awarded by following this step. +//our_recipe: The parent recipe object +/datum/chewin_cooking/recipe_step/use_item/New(var/item_type, var/datum/chewin_cooking/recipe/our_recipe) + #ifdef CHEWIN_DEBUG + if(!ispath(item_type)) + log_debug("/datum/chewin_cooking/recipe_step/add_item/New(): item [item_type] is not a valid path") + #endif + + var/example_item = new item_type() + if(example_item) + desc = "Apply \a [example_item]." + + required_item_type = item_type + group_identifier = item_type + + QDEL_NULL(example_item) + #ifdef CHEWIN_DEBUG + else + log_debug("/datum/chewin_cooking/recipe_step/add_item/New(): item [item_type] couldn't be created.") + #endif + ..(our_recipe) + + +/datum/chewin_cooking/recipe_step/use_item/check_conditions_met(var/obj/added_item, var/datum/chewin_cooking/recipe_tracker/tracker) + if(src.exact_path) + if(added_item.type == required_item_type) + return CHEWIN_CHECK_VALID + else + if(istype(added_item,required_item_type)) + return CHEWIN_CHECK_VALID + return CHEWIN_CHECK_INVALID + +//Think about a way to make this more intuitive? +/datum/chewin_cooking/recipe_step/use_item/calculate_quality(var/obj/added_item) + return clamp_quality(0) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_oven.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_oven.dm new file mode 100644 index 000000000000..3f4981cfd10d --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_oven.dm @@ -0,0 +1,62 @@ +//A cooking step that involves adding a reagent to the food. +/datum/chewin_cooking/recipe_step/use_oven + class=CHEWIN_USE_OVEN + auto_complete_enabled = TRUE + var/time + var/heat + +//set_heat: The temperature the oven must bake at. +//set_time: How long something must be baked in the overn +//our_recipe: The parent recipe object +/datum/chewin_cooking/recipe_step/use_oven/New(var/set_heat, var/set_time, var/datum/chewin_cooking/recipe/our_recipe) + + + + time = set_time + heat = set_heat + + desc = "Cook in an oven set to [heat] for [DisplayTimeText(time)]." + + ..(our_recipe) + + +/datum/chewin_cooking/recipe_step/use_oven/check_conditions_met(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + + if(!istype(used_item, /obj/machinery/oven)) + return CHEWIN_CHECK_INVALID + + return CHEWIN_CHECK_VALID + +//Reagents are calculated prior to object creation +/datum/chewin_cooking/recipe_step/use_oven/calculate_quality(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/obj/item/reagent_containers/cooking_container/container = tracker.holder_ref.resolve() + + var/bad_cooking = 0 + for (var/key in container.oven_data) + if (heat != key) + bad_cooking += container.oven_data[key] + + bad_cooking = round(bad_cooking/(5 SECONDS)) + + var/good_cooking = round(time/3 SECONDS) - bad_cooking + + return clamp_quality(good_cooking) + + +/datum/chewin_cooking/recipe_step/use_oven/follow_step(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + return CHEWIN_SUCCESS + +/datum/chewin_cooking/recipe_step/use_oven/is_complete(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + + var/obj/item/reagent_containers/cooking_container/container = tracker.holder_ref.resolve() + + if(container.oven_data[heat] >= time) + #ifdef CHEWIN_DEBUG + log_debug("use_oven/is_complete() Returned True; comparing [heat]: [container.oven_data[heat]] to [time]") + #endif + return TRUE + + #ifdef CHEWIN_DEBUG + log_debug("use_oven/is_complete() Returned False; comparing [heat]: [container.oven_data[heat]] to [time]") + #endif + return FALSE diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_stove.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_stove.dm new file mode 100644 index 000000000000..1cd4317bbbbb --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_stove.dm @@ -0,0 +1,62 @@ +//A cooking step that involves adding a reagent to the food. +/datum/chewin_cooking/recipe_step/use_stove + class=CHEWIN_USE_STOVE + auto_complete_enabled = TRUE + var/time + var/heat + +//set_heat: The temperature the stove must cook at. +//set_time: How long something must be cook in the stove +//our_recipe: The parent recipe object +/datum/chewin_cooking/recipe_step/use_stove/New(var/set_heat, var/set_time, var/datum/chewin_cooking/recipe/our_recipe) + + + + time = set_time + heat = set_heat + + desc = "Cook on a stove set to [heat] for [DisplayTimeText(time)]." + + ..(our_recipe) + + +/datum/chewin_cooking/recipe_step/use_stove/check_conditions_met(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + + if(!used_item.GetComponent(/datum/component/stove)) + return CHEWIN_CHECK_INVALID + + return CHEWIN_CHECK_VALID + +//Reagents are calculated prior to object creation +/datum/chewin_cooking/recipe_step/use_stove/calculate_quality(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + var/obj/item/reagent_containers/cooking_container/container = tracker.holder_ref.resolve() + + var/bad_cooking = 0 + for (var/key in container.stove_data) + if (heat != key) + bad_cooking += container.stove_data[key] + + bad_cooking = round(bad_cooking / (5 SECONDS)) + + var/good_cooking = round(time / (3 SECONDS)) - bad_cooking + + return clamp_quality(good_cooking) + + +/datum/chewin_cooking/recipe_step/use_stove/follow_step(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + return CHEWIN_SUCCESS + +/datum/chewin_cooking/recipe_step/use_stove/is_complete(var/obj/used_item, var/datum/chewin_cooking/recipe_tracker/tracker) + + var/obj/item/reagent_containers/cooking_container/container = tracker.holder_ref.resolve() + + if(container.stove_data[heat] >= time) + #ifdef CHEWIN_DEBUG + log_debug("use_stove/is_complete() Returned True; comparing [heat]: [container.stove_data[heat]] to [time]") + #endif + return TRUE + + #ifdef CHEWIN_DEBUG + log_debug("use_stove/is_complete() Returned False; comparing [heat]: [container.stove_data[heat]] to [time]") + #endif + return FALSE diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_tool.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_tool.dm new file mode 100644 index 000000000000..71ac14c44c7c --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipe_steps/use_tool.dm @@ -0,0 +1,40 @@ +//A cooking step that involves using an item on the food. +/datum/chewin_cooking/recipe_step/use_tool + class=CHEWIN_USE_ITEM + var/tool_type + var/tool_quality + var/inherited_quality_modifier = 0.1 + +//item_type: The type path of the object we are looking for. +//base_quality_award: The quality awarded by following this step. +//our_recipe: The parent recipe object +/datum/chewin_cooking/recipe_step/use_tool/New(var/type, var/quality, var/datum/chewin_cooking/recipe/our_recipe) + + desc = "Use \a [type] tool of quality [quality] or higher." + + tool_type = type + tool_quality = quality + + ..(our_recipe) + + +/datum/chewin_cooking/recipe_step/use_tool/check_conditions_met(var/obj/item/added_item, var/datum/chewin_cooking/recipe_tracker/tracker) + if(!initial(added_item.tool_behaviour)) + return CHEWIN_CHECK_INVALID + + return CHEWIN_CHECK_VALID + +/datum/chewin_cooking/recipe_step/use_tool/follow_step(var/obj/added_item, var/obj/item/reagent_containers/cooking_container/container) + var/obj/item/our_tool = added_item + to_chat(usr, span_notice("You use the [added_item] according to the recipe.")) + + if(our_tool.toolspeed < tool_quality) + return to_chat(usr, span_notice("The low quality of the tool hurts the quality of the dish.")) + + return CHEWIN_SUCCESS + +//Think about a way to make this more intuitive? +/datum/chewin_cooking/recipe_step/use_tool/calculate_quality(var/obj/added_item) + var/obj/item/our_tool = added_item + var/raw_quality = (our_tool.toolspeed - tool_quality) * inherited_quality_modifier + return clamp_quality(raw_quality) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/black_eggs.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/black_eggs.dm new file mode 100644 index 000000000000..f10d0cda4fb6 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/black_eggs.dm @@ -0,0 +1,59 @@ +/datum/chewin_cooking/recipe/black_eggs + cooking_container = PAN + product_type = /obj/item/food/black_eggs + recipe_guide = "Crack eggs into a pan, add some vinegar and blood cook for 15 seconds on low." + step_builder = list( + + CHEWIN_BEGIN_OPTION_CHAIN, + list(CHEWIN_ADD_ITEM_OPTIONAL, /obj/item/food/butter, base=10, reagent_skip=TRUE), + list(CHEWIN_USE_STOVE_OPTIONAL, J_LO, 10 SECONDS, finish_text = "The butter melts in the pan!"), + CHEWIN_END_OPTION_CHAIN, + + list(CHEWIN_ADD_ITEM, /obj/item/food/egg, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/egg, qmod=0.5), + + list(CHEWIN_ADD_REAGENT, /datum/reagent/blood, 5, base=3), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/vinegar, 5, base=3), + + CHEWIN_BEGIN_EXCLUSIVE_OPTIONS, + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/blood, 15, remain_percent = 0.2 , base=3, prod_desc="Extra Bloody!"), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/capsaicin, 5, remain_percent = 0.2, base=6, prod_desc="Extra Spicy!"), + CHEWIN_END_EXCLUSIVE_OPTIONS, + + list(CHEWIN_USE_STOVE, J_LO, 15 SECONDS , finish_text = "You can smell scrambled eggs!") + + ) + +/datum/chewin_cooking/recipe/black_eggs_five + name = "Black Scrambled Eggs (5 Servings)" + cooking_container = PAN + product_type = /obj/item/food/black_eggs + product_count = 5 + recipe_guide = "Crack eggs into a pan, add some vinegar and blood cook for 25 seconds on low." + step_builder = list( + + CHEWIN_BEGIN_OPTION_CHAIN, + list(CHEWIN_ADD_ITEM_OPTIONAL, /obj/item/food/butter, base=10, reagent_skip=TRUE), + list(CHEWIN_USE_STOVE_OPTIONAL, J_LO, 10 SECONDS, finish_text = "The butter melts in the pan!"), + CHEWIN_END_OPTION_CHAIN, + + list(CHEWIN_ADD_ITEM, /obj/item/food/egg, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/egg, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/egg, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/egg, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/egg, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/egg, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/egg, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/egg, qmod=0.5), + + list(CHEWIN_ADD_REAGENT, /datum/reagent/blood, 15, base=4), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/vinegar, 15, base=5), + + CHEWIN_BEGIN_EXCLUSIVE_OPTIONS, + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/blood, 30, remain_percent = 0.2 , base=5, prod_desc="Extra Bloody!"), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/capsaicin, 15, remain_percent = 0.2, base=6, prod_desc="Extra Spicy!"), + CHEWIN_END_EXCLUSIVE_OPTIONS, + + list(CHEWIN_USE_STOVE, J_LO, 25 SECONDS , finish_text = "You can smell scrambled eggs!") + + ) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/converted_recipes.md b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/converted_recipes.md new file mode 100644 index 000000000000..22f38cca6d52 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/converted_recipes.md @@ -0,0 +1,8 @@ +This is just a file to track foods that has a chewin counterpart + /obj/item/food/fries + /obj/item/food/meat/steak/plain + /obj/item/food/fried_blood_sausage + /obj/item/food/salad/katsu_curry + /obj/item/food/bread/plain + /obj/item/food/black_eggs + /obj/item/food/lizard_dumplings diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/documentation.md b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/documentation.md new file mode 100644 index 000000000000..23a3a08776e4 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/documentation.md @@ -0,0 +1,117 @@ +# CHEWIN Step Builder Commands + +All steps in the step builder have the following format: + +## list(< CHEWIN_STEP_CLASS><_OPTIONAL>, < REQUIRED_ARGS>, < CUSTOM_ARGS>=value) + + +### `` +The name of any one of the recipe step types, custom or otherwise. Valid options are: + +- **CHEWIN_ADD_ITEM** + - Adds an item to the recipe. The object is inserted in the container. The product inherits the item's quality and reagents if able. + - **Required Arguments:** + - `type_path`: The type path of the item being added. + - **Example:** + - `list(CHEWIN_ADD_ITEM, /obj/item/food/breadslice)` + +- **CHEWIN_ADD_REAGENT** + - Adds a reagent to the recipe. The resulting reagent is stored in the container's reagent datum. The product inherits the reagents added if able. It's possible to sneak poison into food this way. + - **Required Arguments:** + - `reagent_id`: The type path of the reagent being added. + - `amount`: The amount of units the ingredient requires. + - **Example:** + - `list(CHEWIN_ADD_REAGENT, /datum/reagent/consumable/salt, 5)` + +- **CHEWIN_ADD_PRODUCE** + - Adds a grown item to the recipe. The item is inserted in the container. The product inherits reagents if able, and its quality scales with the plant's potency. + - **Required Arguments:** + - `plantname`: The path to the produce being added. + - **Example:** + - `list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/banana)` + +- **CHEWIN_USE_TOOL** + - Uses a tool on the item. Going far and beyond the quality of the tool increases the quality of the product. + - **Required Arguments:** + - `tool_quality`: The id of the reagent being added. + - `difficulty`: The minimum tool quality of the reagent not implemented at this time as skills are still a hot topic. + - **Example:** + - `list(CHEWIN_USE_TOOL, QUALITY_CUTTING, 5)` + +- **CHEWIN_USE_ITEM** + - Uses an item on the recipe. The object is not consumed. + - **Required Arguments:** + - `type_path`: The type path of the item being added. + - **Example:** + - `list(CHEWIN_USE_ITEM, /obj/item/rollingpin)` + *Use a rolling pin on the container.* + +- **CHEWIN_USE_STOVE** + - Cook the cooking container on a stove. Keep it on too long, it burns. + - **Required Arguments:** + - `temperature`: The required temperature to cook the food at. + - *Temperatures are macro'd by: `J_LO`, `J_MED`, `J_HI`.* + - `time`: The amount of time, in seconds, to keep the food on the stove. + - **Example:** + - `list(CHEWIN_USE_STOVE, J_LO, 40)` + *Cook on a stove set to "Low" for 40 seconds.* + +### `<_OPTIONAL>` +The tag `_OPTIONAL` can be tacked onto any command to make it an optional step not required to finish the recipe. + +- **Example:** + - `list(CHEWIN_ADD_ITEM_OPTIONAL, /obj/item/food/breadslice)` + +### `` +The required arguments for a specific class of step to function. They are not labeled and must be in order. See above for which classes of step have which required arguments. + +### `` +All custom arguments are declared in the format `key=value`. They are used to quickly modify a given step in a recipe. + +- **Example:** + - `list(CHEWIN_ADD_ITEM, /obj/item/food/breadslice, desc="a custom description")` + +#### Valid options are: +- **desc** + - Adds a custom description to the recipe step, when read from a cooking book. + - **Example:** `desc="a custom description"` + +- **base** + - Defines the base quality for a recipe step. This will become the LOWEST quality following a step can award. For some step classes, this will simply be the default awarded. If not defined, there is no minimum quality a step can add. + - **Example:** `base=4` + +- **max** + - Defines the maximum quality for a recipe step. This will become the HIGHEST quality following a step can award. If not defined, there is no maximum quality a step can add. + - **Example:** `max=10` + +- **result_desc** + - Adds a custom description to the result of the recipe step. This will be read off on the item product. + - **Example:** `result_desc="A Slice of Bread is in the sandwich."` + +- **exact** + - **CHEWIN_ADD_ITEM or CHEWIN_USE_ITEM ONLY:** + - Determines if the steps require an exact type path, or if a child will satisfy the requirements. If the type path is also preferable. + - **Example:** `exact=TRUE` + +- **qmod** + - **CHEWIN_ADD_ITEM, CHEWIN_USE_TOOL ONLY:** + - Modifier to adjust the `inherited_quality_modifier` on an `add_item` recipe step. + - **Example:** `qmod=0.5` + *Only 50% of the added item's quality will be inherited.* + +- **remain_percent** + - **CHEWIN_ADD_REAGENT ONLY:** + - Determines the percentage of a reagent that remains in the cooking of an item. IE- if you cook a steak with wine, you can make it so the wine doesn't wind up in the resulting food. + - **Example:** `remain_percent=0.1` + *Only 10% of the units expected to be added will apply to the resulting food injection.* + +- **reagent_skip** + - **CHEWIN_ADD_ITEM, CHEWIN_ADD_PRODUCE ONLY:** + - Outright excludes all reagents from the added item/produce from showing up in the product. + - **Example:** `reagent_skip=TRUE` + +- **exclude_reagents** + - **CHEWIN_ADD_ITEM, CHEWIN_ADD_PRODUCE ONLY:** + - Excludes the presence of a reagent in an item from the resulting meal. + - **Example:** `exclude_reagents=list(/datum/reagent/toxin/carpotoxin)` + *Removes the presence of Carpotoxin from the item.* diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/example_recipe.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/example_recipe.dm new file mode 100644 index 000000000000..61e029215592 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/example_recipe.dm @@ -0,0 +1,170 @@ +/* +========================================================= +CHEWIN STEP_BUILDER COMMANDS: +All steps in the step builder have the following format: +list(<_OPTIONAL>, , =value) + + The name any one of the recipe step types, custom or otherwise. + Valid options are: + CHEWIN_ADD_ITEM + Add an item to the recipe. The object is inserted in the container. + The product inherits the item's quality and reagents if able. + : + type_path - the type path of the item being added. + Example: list(CHEWIN_ADD_ITEM, /obj/item/food/breadslice) + + CHEWIN_ADD_REAGENT + Add a reagent to the recipe. The resulting reagent is stored in the container's reagent datum. + The product inherits the reagents added if able. It's possible to sneak poison into food this way. + : + reagent_id - the typepath of the reagent being added + amount - The amount of units the ingredient requires + Example: list(CHEWIN_ADD_REAGENT, /datum/reagent/consumable/salt, 5) + + CHEWIN_ADD_PRODUCE + Add a grown item to the recipe. The item is inserted in the container. + The product inherits reagents if able, and its quality scales with the plant's potency. + : + plantname - the path to the produce being added. + Example: list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/banana) + + CHEWIN_USE_TOOL + Uses a tool on the item. Going far and beyond the quality of the tool increases the quality of the product. + : + tool_quality - the id of the reagent being added + difficulty - The minimum tool quality of the reagent not implemented at this time as skills are still a hot topic + Example: list(CHEWIN_USE_TOOL, QUALITY_CUTTING, 5) + + CHEWIN_USE_ITEM + Uses an item on the recipe. The object is not consumed. + : + type_path - the type path of the item being added. + Example: list(CHEWIN_USE_ITEM, /obj/item/rollingpin) #Use a rolling pin on the container + + CHEWIN_USE_STOVE + Cook the cooking container on a stove. Keep it on too long, it burns. + : + temperature - the required temperature to cook the food at. + (Temperatures are macro'd by: J_LO, J_MED, J_HI) + time - the amount of time, in seconds, to keep the food on the stove. + Example: list(CHEWIN_USE_STOVE, J_LO, 40) #Cook on a stove set to "Low" for 40 seconds. + +<_OPTIONAL> + The tag _OPTIONAL can be tacked onto any command to make it an optional step not required to finish the recipe. + Example: list(CHEWIN_ADD_ITEM_OPTIONAL, /obj/item/food/breadslice) + + + The required arguments for a specific class of step to function. They are not labeled and must be in order. + See above for which classes of step have which required arguments. + + + All custom arguments are declared in the format key=value. They are used to quickly modify a given step in a recipe. + Example: list(CHEWIN_ADD_ITEM, /obj/item/food/breadslice, desc="a custom description") + Valid options are: + desc + Adds a custom description to the recipe step, when read from a cooking book. + Example: desc="a custom description" + + base + Defines the base quality for a recipe step. This will become the LOWEST quality following a step can award. + For some step classes, this will simply be the default awarded. + If not defined, there is no minimum quality a step can add. + Example: base=4 + + max + Defines the maximum quality for a recipe step. This will become the HIGHEST quality following a step can award. + If not defined, there is no maximum quality a step can add. + Example: max=10 + + result_desc + Adds a custom description to the result of the recipe step. This will be read off on the item product. + Example: result_desc="A Slice of Bread is in the sandwich." + + exact + CHEWIN_ADD_ITEM or CHEWIN_USE_ITEM ONLY: + Determines if the steps require an exact type path, or if a child will satisfy the requirements. + of the type path is also preferable. + Example: exact=TRUE + + qmod + CHEWIN_ADD_ITEM, CHEWIN_USE_TOOL ONLY: + modifier to adjust the inherited_quality_modifier on an add_item recipe step. + Example: qmod=0.5 //only 50% of the added item's quality will be inherited. + remain_percent + CHEWIN_ADD_REAGENT ONLY: + Determines the percentage of a reagent that remains in the cooking of an item. + IE- if you cook a steak with wine, you can make it so the wine doesn't wind up in the resulting food. + Example: remain_percent=0.1 //Only 10% of the units expected to be added will apply to the resulting food injection. + + reagent_skip + CHEWIN_ADD_ITEM, CHEWIN_ADD_PRODUCE ONLY: + Outright excludes all reagents from the added item/produce from showing up in the product. + Example: reagent_skip=TRUE + + exclude_reagents + CHEWIN_ADD_ITEM, CHEWIN_ADD_PRODUCE ONLY: + Excludes the presence of a reagent in an item from the resulting meal. + Example: exclude_reagents=list(/datum/reagent/toxin/carpotoxin) //Removes the presence of Carpotoxin from the item. + finish_text + when the step finishes a visible message will be sent + +========================================================= +*/ + +//Example Recipes +/datum/chewin_cooking/recipe/steak_stove + + //Name of the recipe. If not defined, it will just use the name of the product_type + name="Stove-Top cooked Steak" + + //The recipe will be cooked on a pan + cooking_container = PAN + + //The product of the recipe will be a steak. + product_type = /obj/item/food/meat/steak/plain + + //The product will have it's initial reagents wiped, prior to the recipe adding in reagents of its own. + replace_reagents = TRUE + + step_builder = list( + + //Butter your pan by adding a block of butter (no slices yet), and then melting it. Adding the butter unlocks the option to melt it on the stove. + CHEWIN_BEGIN_OPTION_CHAIN, + //base - the lowest amount of quality following this step can award. + //reagent_skip - Exclude the added item's reagents from being included the product + list(CHEWIN_ADD_ITEM_OPTIONAL, /obj/item/food/butter, base=10, reagent_skip=TRUE), + + //Melt the butter into the pan by cooking it on a stove set to Low for 10 seconds + list(CHEWIN_USE_STOVE_OPTIONAL, J_LO, 10 SECONDS, finish_text = "The butter melts in the pan!"), + CHEWIN_END_OPTION_CHAIN, + + //A steak is needed to start the meal. + //qmod- Half of the food quality of the parent will be considered. + //exclude_reagents- Carpotoxin will be filtered out of the steak. + list(CHEWIN_ADD_ITEM, /obj/item/food/meat/slab, qmod=0.5, exclude_reagents=list(/datum/reagent/toxin/carpotoxin)), + + //Add some mushrooms to give it some zest. Only one kind is allowed! + CHEWIN_BEGIN_EXCLUSIVE_OPTIONS, + list(CHEWIN_ADD_PRODUCE_OPTIONAL, /obj/item/food/grown/mushroom/libertycap, qmod=0.2, reagent_skip=TRUE), + list(CHEWIN_ADD_PRODUCE_OPTIONAL, /obj/item/food/grown/mushroom/reishi, qmod=0.4, reagent_skip=TRUE), + list(CHEWIN_ADD_PRODUCE_OPTIONAL, /obj/item/food/grown/mushroom/amanita, qmod=0.4, reagent_skip=TRUE), + list(CHEWIN_ADD_PRODUCE_OPTIONAL, /obj/item/food/grown/mushroom/plumphelmet, qmod=0.4, reagent_skip=TRUE), + CHEWIN_END_EXCLUSIVE_OPTIONS, + + //Beat that meat to increase its quality + list(CHEWIN_USE_TOOL_OPTIONAL, TOOL_HAMMER, 15), + + //You can add up to 3 units of salt to increase the quality. Any more will negatively impact it. + //base- for CHEWIN_ADD_REAGENT, the amount that this step will award if followed perfectly. + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/salt, 3, base=3), + + //You can add capaicin or wine, but not both + //prod_desc- A description appended to the resulting product. + CHEWIN_BEGIN_EXCLUSIVE_OPTIONS, + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/capsaicin, 5, base=6, prod_desc="The steak was Spiced with chili powder."), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/ethanol/wine, 5, remain_percent=0.1 ,base=6, prod_desc="The steak was sauteed in wine"), + CHEWIN_END_EXCLUSIVE_OPTIONS, + + //Cook on a stove, at medium temperature, for 30 seconds + list(CHEWIN_USE_STOVE, J_MED, 30 SECONDS) + ) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/french_fries.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/french_fries.dm new file mode 100644 index 000000000000..b69c8ceaf86d --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/french_fries.dm @@ -0,0 +1,8 @@ +/datum/chewin_cooking/recipe/fries + cooking_container = DF_BASKET + product_type = /obj/item/food/fries + recipe_guide = "Put potato wedges in a fryer, fry for 30 seconds." + step_builder = list( + list(CHEWIN_ADD_ITEM, /obj/item/food/grown/potato/wedges, qmod=0.5), + list(CHEWIN_USE_FRYER, J_HI, 10 SECONDS , finish_text = "The fries look gold and crispy!") + ) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/fried_blood_sausage.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/fried_blood_sausage.dm new file mode 100644 index 000000000000..9d94934c6dac --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/fried_blood_sausage.dm @@ -0,0 +1,56 @@ +/datum/chewin_cooking/recipe/fried_blood_sausage + cooking_container = PAN + product_type = /obj/item/food/fried_blood_sausage + recipe_guide = "Put blood sausages in a pan, cook for 30 seconds on medium." + step_builder = list( + + CHEWIN_BEGIN_OPTION_CHAIN, + list(CHEWIN_ADD_ITEM_OPTIONAL, /obj/item/food/butter, base=10, reagent_skip=TRUE), + list(CHEWIN_USE_STOVE_OPTIONAL, J_LO, 10 SECONDS, finish_text = "The butter melts in the pan!"), + CHEWIN_END_OPTION_CHAIN, + + list(CHEWIN_ADD_ITEM, /obj/item/food/raw_tiziran_sausage, qmod=0.5), + + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/korta_flour, 5, base=3), + + CHEWIN_BEGIN_EXCLUSIVE_OPTIONS, + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/blood, 15, remain_percent = 0.2 , base=3, prod_desc="Extra Bloody!"), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/honey, 15, remain_percent = 0.2 , base=4, prod_desc="Extra Sweet!"), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/capsaicin, 5, remain_percent = 0.2, base=6, prod_desc="Extra Spicy!"), + CHEWIN_END_EXCLUSIVE_OPTIONS, + + list(CHEWIN_USE_STOVE, J_MED, 30 SECONDS , finish_text = "You can smell fried blood sausage!") + + ) + +/datum/chewin_cooking/recipe/fried_blood_sausage_five + name = "Fried Blood Sausages (5 Servings)" + cooking_container = PAN + product_type = /obj/item/food/fried_blood_sausage + food_category = CAT_BULK + product_count = 5 + recipe_guide = "Put five blood sausages in a pan, cook for 45 seconds on medium." + step_builder = list( + + CHEWIN_BEGIN_OPTION_CHAIN, + list(CHEWIN_ADD_ITEM_OPTIONAL, /obj/item/food/butter, base=10, reagent_skip=TRUE), + list(CHEWIN_USE_STOVE_OPTIONAL, J_LO, 10 SECONDS, finish_text = "The butter melts in the pan!"), + CHEWIN_END_OPTION_CHAIN, + + list(CHEWIN_ADD_ITEM, /obj/item/food/raw_tiziran_sausage, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/raw_tiziran_sausage, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/raw_tiziran_sausage, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/raw_tiziran_sausage, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/raw_tiziran_sausage, qmod=0.5), + + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/korta_flour, 20, base=3), + + CHEWIN_BEGIN_EXCLUSIVE_OPTIONS, + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/blood, 30, remain_percent = 0.2 , base=3, prod_desc="Extra Bloody!"), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/honey, 30, remain_percent = 0.2 , base=4, prod_desc="Extra Sweet!"), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/capsaicin, 10, remain_percent = 0.2, base=6, prod_desc="Extra Spicy!"), + CHEWIN_END_EXCLUSIVE_OPTIONS, + + list(CHEWIN_USE_STOVE, J_MED, 56 SECONDS , finish_text = "You can smell fried blood sausages!") + + ) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/fried_rice.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/fried_rice.dm new file mode 100644 index 000000000000..bc3c2d2c35ae --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/fried_rice.dm @@ -0,0 +1,17 @@ +/datum/chewin_cooking/recipe/hurricane_rice + cooking_container = PAN + food_category = CAT_STOVETOP + product_type = /obj/item/food/salad/hurricane_rice + recipe_guide = "Add boiled rice to pan, crack an egg, add vegetables, cook for 15 seconds on high, add soysauce, cook for 5 seconds on high." + step_builder = list( + list(CHEWIN_ADD_ITEM, /obj/item/food/boiledrice, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/egg, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/chili, qmod=0.5), + + list(CHEWIN_ADD_ITEM_OPTIONAL, /obj/item/food/onion_slice, qmod=0.5), + list(CHEWIN_ADD_ITEM_OPTIONAL, /obj/item/food/pineappleslice, qmod=0.5), + + list(CHEWIN_USE_STOVE, J_HI, 15 SECONDS , finish_text = "You can smell almost finished fried rice, just needs some seasoning!"), + list(CHEWIN_ADD_REAGENT, /datum/reagent/consumable/soysauce, 3, base=3), + list(CHEWIN_USE_STOVE, J_HI, 5 SECONDS , finish_text = "You can smell fried rice!"), + ) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/katsu_curry.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/katsu_curry.dm new file mode 100644 index 000000000000..3f69d1af3f4a --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/katsu_curry.dm @@ -0,0 +1,61 @@ +/datum/chewin_cooking/recipe/katsu + cooking_container = DF_BASKET + product_type = /obj/item/food/katsu_fillet + recipe_guide = "Put raw cutlets with some reispan bread slices in a fryer, fry for 20 seconds." + step_builder = list( + list(CHEWIN_ADD_ITEM, /obj/item/food/meat/rawcutlet, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/breadslice/reispan, qmod=0.5), + list(CHEWIN_USE_FRYER, J_HI, 20 SECONDS) + ) + +/datum/chewin_cooking/recipe/katsu_curry + name = "Katsu Curry" + cooking_container = BOWL + product_type = /obj/item/food/salad/katsu_curry + recipe_guide = "Melt some butter in a bowl, add some rice, curry sauce and katsu." + step_builder = list( + list(CHEWIN_ADD_ITEM, /obj/item/food/butter, qmod=0.5), + list(CHEWIN_USE_STOVE, J_LO, 10 SECONDS, finish_text = "The butter melts in the bowl!"), + + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/soysauce, 5, base=3), + + list(CHEWIN_ADD_ITEM, /obj/item/food/boiledrice, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/katsu_fillet, qmod=0.5), + list(CHEWIN_ADD_REAGENT, /datum/reagent/consumable/nutriment/soup/curry_sauce, 5, base=3), + + CHEWIN_BEGIN_EXCLUSIVE_OPTIONS, + list(CHEWIN_ADD_PRODUCE_OPTIONAL, /obj/item/food/grown/chili, qmod=0.2, reagent_skip=TRUE, prod_desc = "Extra spicy!", food_buff = /datum/status_effect/food/sweaty), + list(CHEWIN_ADD_PRODUCE_OPTIONAL, /obj/item/food/grown/pineapple, qmod=0.2, reagent_skip=TRUE, prod_desc = "Mild and Sweet."), + CHEWIN_END_EXCLUSIVE_OPTIONS, + + list(CHEWIN_USE_STOVE, J_LO, 20 SECONDS), + ) + +/datum/chewin_cooking/recipe/katsu_curry_large + name = "Katsu Curry (5 Servings)" + cooking_container = POT + food_category = CAT_BULK + product_count = 5 + product_type = /obj/item/food/salad/katsu_curry + recipe_guide = "Melt some butter in a pot, add some rice, curry sauce and katsu, cook on low in the stove for 1 minute. Serves 5" + step_builder = list( + list(CHEWIN_ADD_ITEM, /obj/item/food/butter, qmod=0.5), + list(CHEWIN_USE_STOVE, J_LO, 10 SECONDS, finish_text = "The butter melts in the pot!"), + + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/soysauce, 15, base=3), + + list(CHEWIN_ADD_ITEM, /obj/item/food/boiledrice, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/boiledrice, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/boiledrice, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/katsu_fillet, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/katsu_fillet, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/katsu_fillet, qmod=0.5), + list(CHEWIN_ADD_REAGENT, /datum/reagent/consumable/nutriment/soup/curry_sauce, 25, base=3), + + CHEWIN_BEGIN_EXCLUSIVE_OPTIONS, + list(CHEWIN_ADD_PRODUCE_OPTIONAL, /obj/item/food/grown/chili, qmod=0.2, reagent_skip=TRUE, prod_desc = "Extra spicy!"), + list(CHEWIN_ADD_PRODUCE_OPTIONAL, /obj/item/food/grown/pineapple, qmod=0.2, reagent_skip=TRUE, prod_desc = "Mild and Sweet."), + CHEWIN_END_EXCLUSIVE_OPTIONS, + + list(CHEWIN_USE_STOVE, J_LO, 1 MINUTES), + ) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/kimchi.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/kimchi.dm new file mode 100644 index 000000000000..fbe196f189c1 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/kimchi.dm @@ -0,0 +1,90 @@ +/datum/chewin_cooking/recipe/kimchi + cooking_container = BOWL + product_type = /obj/item/food/kimchi + recipe_guide = "Mix Cabbage, Chili, and Salt in a bowl." + step_builder = list( + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/chili, qmod=0.5), + list(CHEWIN_ADD_REAGENT, /datum/reagent/consumable/salt, 5, base=3), + ) + +/datum/chewin_cooking/recipe/kimchi_inferno + cooking_container = BOWL + product_type = /obj/item/food/inferno_kimchi + recipe_guide = "Mix Cabbage, Ghost Chili, and Salt in a bowl." + step_builder = list( + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/ghost_chili, qmod=0.5), + list(CHEWIN_ADD_REAGENT, /datum/reagent/consumable/salt, 5, base=3), + ) + +/datum/chewin_cooking/recipe/garlic_kimchi + cooking_container = BOWL + product_type = /obj/item/food/garlic_kimchi + recipe_guide = "Mix Cabbage, Garlic, Chili, and Salt in a bowl." + step_builder = list( + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/chili, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/garlic, qmod=0.5), + list(CHEWIN_ADD_REAGENT, /datum/reagent/consumable/salt, 5, base=3), + ) + +/datum/chewin_cooking/recipe/kimchi_five + name = "Kimchi (5 Servings)" + cooking_container = POT + food_category = CAT_BULK + product_type = /obj/item/food/kimchi + product_count = 5 + recipe_guide = "Mix Cabbage, Chili, and Salt in a bowl." + step_builder = list( + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/chili, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/chili, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/chili, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/chili, qmod=0.5), + list(CHEWIN_ADD_REAGENT, /datum/reagent/consumable/salt, 20, base=3), + ) + +/datum/chewin_cooking/recipe/kimchi_inferno_five + name = "Inferno Kimchi (5 Servings)" + cooking_container = POT + food_category = CAT_BULK + product_count = 5 + product_type = /obj/item/food/inferno_kimchi + recipe_guide = "Mix Cabbage, Ghost Chili, and Salt in a bowl." + step_builder = list( + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/ghost_chili, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/ghost_chili, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/ghost_chili, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/ghost_chili, qmod=0.5), + list(CHEWIN_ADD_REAGENT, /datum/reagent/consumable/salt, 20, base=3), + ) + +/datum/chewin_cooking/recipe/garlic_kimchi_five + name = "Garlic Kimchi (5 Servings)" + cooking_container = POT + food_category = CAT_BULK + product_count = 5 + product_type = /obj/item/food/garlic_kimchi + recipe_guide = "Mix Cabbage, Garlic, Chili, and Salt in a bowl." + step_builder = list( + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/cabbage, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/chili, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/chili, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/chili, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/chili, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/garlic, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/garlic, qmod=0.5), + list(CHEWIN_ADD_PRODUCE, /obj/item/food/grown/garlic, qmod=0.5), + list(CHEWIN_ADD_REAGENT, /datum/reagent/consumable/salt, 20, base=3), + ) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/lizard_dumplings.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/lizard_dumplings.dm new file mode 100644 index 000000000000..830c89594e41 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/lizard_dumplings.dm @@ -0,0 +1,48 @@ +/datum/chewin_cooking/recipe/lizard_dumplings + cooking_container = POT + product_type = /obj/item/food/lizard_dumplings + product_count = 3 + recipe_guide = "Put wrapped potatoes in a pot, steam for 30 seconds on medium." + step_builder = list( + list(CHEWIN_ADD_REAGENT, /datum/reagent/water, 15, base=3), + + list(CHEWIN_ADD_ITEM, /obj/item/food/grown/potato, qmod=0.5), + + list(CHEWIN_ADD_REAGENT_CHOICE, list(/datum/reagent/consumable/korta_flour = 2, /datum/reagent/consumable/flour = 0.5), 5, base=4), + + CHEWIN_BEGIN_EXCLUSIVE_OPTIONS, + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/honey, 15, remain_percent = 0.2 , base=4, prod_desc="Extra Sweet!"), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/capsaicin, 5, remain_percent = 0.2, base=6, prod_desc="Extra Spicy!"), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/soysauce, 5, remain_percent = 0.2, base=6, prod_desc="Salty!"), + CHEWIN_END_EXCLUSIVE_OPTIONS, + + list(CHEWIN_USE_STOVE, J_MED, 30 SECONDS , finish_text = "You can smell fresh cooked dumplings!") + + ) + +/datum/chewin_cooking/recipe/lizard_dumplings_dozen + name = "Lizard Dumplings (12 Servings)" + cooking_container = POT + product_type = /obj/item/food/lizard_dumplings + food_category = CAT_BULK + product_count = 12 + recipe_guide = "Put wrapped potatoes in a pot, steam for 45 seconds on medium." + step_builder = list( + list(CHEWIN_ADD_REAGENT, /datum/reagent/water, 25, base=3), + + list(CHEWIN_ADD_ITEM, /obj/item/food/grown/potato, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/grown/potato, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/grown/potato, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/grown/potato, qmod=0.5), + + list(CHEWIN_ADD_REAGENT_CHOICE, list(/datum/reagent/consumable/korta_flour = 2, /datum/reagent/consumable/flour = 0.5), 15, base=3), + + CHEWIN_BEGIN_EXCLUSIVE_OPTIONS, + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/honey, 15, remain_percent = 0.2 , base=4, prod_desc="Extra Sweet!"), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/capsaicin, 10, remain_percent = 0.2, base=6, prod_desc="Extra Spicy!"), + list(CHEWIN_ADD_REAGENT_OPTIONAL, /datum/reagent/consumable/soysauce, 10, remain_percent = 0.2, base=6, prod_desc="Salty!"), + CHEWIN_END_EXCLUSIVE_OPTIONS, + + list(CHEWIN_USE_STOVE, J_MED, 45 SECONDS , finish_text = "You can smell fresh cooked dumplings!") + + ) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/oven_bread.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/oven_bread.dm new file mode 100644 index 000000000000..86a191ac061b --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/oven_bread.dm @@ -0,0 +1,9 @@ +//this is a testing recipe these recipes are for actual multistep things +/datum/chewin_cooking/recipe/bread + cooking_container = OVEN + product_type = /obj/item/food/bread/plain + recipe_guide = "Put dough in an oven, bake for 30 seconds on medium." + step_builder = list( + list(CHEWIN_ADD_ITEM, /obj/item/food/dough, qmod=0.5), + list(CHEWIN_USE_OVEN, J_LO, 30 SECONDS, , finish_text = "The smell of baked bread oozes out!") + ) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/recipe_crafting_helper_generator.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/recipe_crafting_helper_generator.dm new file mode 100644 index 000000000000..2fdfe3af2330 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/recipe_crafting_helper_generator.dm @@ -0,0 +1,148 @@ +/datum/chewin_cooking/recipe/proc/generate_crafting_helper() + var/datum/crafting_recipe/food/new_food_recipe = new + new_food_recipe.category = food_category + new_food_recipe.result = product_type + new_food_recipe.name = name + new_food_recipe.non_craftable = TRUE + + var/list/steps = list() + var/in_group = FALSE + for(var/iter in step_builder) + if(islist(iter)) + var/list/iteration_list = iter + switch(iteration_list[1]) + if(CHEWIN_ADD_PRODUCE_OPTIONAL) + var/obj/item/food/grown/grown_path = iteration_list[2] + if(!in_group) + steps += "Optional Step" + steps += "Add [initial(grown_path.name)] to [cooking_container]" + if(!in_group) + steps += "End Optional Step" + if(CHEWIN_ADD_PRODUCE) + var/obj/item/food/grown/grown_path = iteration_list[2] + steps += "Add [initial(grown_path.name)] to [cooking_container]" + if(CHEWIN_ADD_PRODUCE_CHOICE_OPTIONAL) + var/string = "" + var/first = TRUE + for(var/obj/item/food/grown/grown_path as anything in iteration_list[2]) + if(!first) + string += " or" + string += initial(grown_path.name) + first = FALSE + if(!in_group) + steps += "Optional Step" + steps += "Add [string] to [cooking_container]" + if(!in_group) + steps += "End Optional Step" + if(CHEWIN_ADD_PRODUCE_CHOICE) + var/string = "" + var/first = TRUE + for(var/obj/item/food/grown/grown_path as anything in iteration_list[2]) + if(!first) + string += " or" + string += initial(grown_path.name) + first = FALSE + steps += "Add [string] to [cooking_container]" + + if(CHEWIN_ADD_ITEM) + var/obj/item/item_path = iteration_list[2] + steps += "Add [initial(item_path.name)] to [cooking_container]" + if(CHEWIN_ADD_ITEM_OPTIONAL) + var/obj/item/item_path = iteration_list[2] + if(!in_group) + steps += "Optional Step" + steps += "Add [initial(item_path.name)] to [cooking_container]" + if(!in_group) + steps += "End Optional Step" + if(CHEWIN_ADD_REAGENT_OPTIONAL) + var/datum/reagent/reagent_path = iteration_list[2] + if(!in_group) + steps += "Optional Step" + steps += "Add [iteration_list[3]] units of [initial(reagent_path.name)] to [cooking_container]" + if(!in_group) + steps += "End Optional Step" + if(CHEWIN_ADD_REAGENT) + var/datum/reagent/reagent_path = iteration_list[2] + steps += "Add [iteration_list[3]] units of [initial(reagent_path.name)] to [cooking_container]" + if(CHEWIN_ADD_REAGENT_CHOICE_OPTIONAL) + var/string = "" + var/first = TRUE + for(var/datum/reagent/reagent_path as anything in iteration_list[2]) + if(!first) + string += " or" + string += initial(reagent_path.name) + first = FALSE + + if(!in_group) + steps += "Optional Step" + steps += "Add [iteration_list[3]] units of [string] to [cooking_container]" + if(!in_group) + steps += "End Optional Step" + if(CHEWIN_ADD_REAGENT_CHOICE) + var/string = "" + var/first = TRUE + for(var/datum/reagent/reagent_path as anything in iteration_list[2]) + if(!first) + string += " or " + string += initial(reagent_path.name) + first = FALSE + + steps += "Add [iteration_list[3]] units of [string] to [cooking_container]" + if(CHEWIN_USE_TOOL) + steps += "Use [iteration_list[2]] on [cooking_container]" + if(CHEWIN_USE_TOOL_OPTIONAL) + if(!in_group) + steps += "Optional Step" + steps += "Use [iteration_list[2]] on [cooking_container]" + if(!in_group) + steps += "End Optional Step" + if(CHEWIN_USE_ITEM) + steps += "Use [iteration_list[2]] on [cooking_container]" + if(CHEWIN_USE_ITEM_OPTIONAL) + if(!in_group) + steps += "Optional Step" + steps += "Use [iteration_list[2]] on [cooking_container]" + if(!in_group) + steps += "End Optional Step" + if(CHEWIN_USE_STOVE) + steps += "Cook on Stove on [iteration_list[2]] heat for [iteration_list[3] * 0.1] Seconds" + if(CHEWIN_USE_STOVE_OPTIONAL) + if(!in_group) + steps += "Optional Step" + steps += "Cook on Stove on [iteration_list[2]] heat for [iteration_list[3] * 0.1] Seconds" + if(!in_group) + steps += "End Optional Step" + if(CHEWIN_USE_FRYER) + steps += "Deepfr for [iteration_list[3] * 0.1] Seconds" + if(CHEWIN_USE_OVEN) + steps += "Cook in Oven on [iteration_list[2]] heat for [iteration_list[3] * 0.1] Seconds" + if(CHEWIN_USE_OVEN_OPTIONAL) + if(!in_group) + steps += "Optional Step" + steps += "Cook in Oven on [iteration_list[2]] heat for [iteration_list[3] * 0.1] Seconds" + if(!in_group) + steps += "End Optional Step" + if(CHEWIN_USE_GRILL) + steps += "Cook on Grill on [iteration_list[2]] heat for [iteration_list[3] * 0.1] Seconds" + if(CHEWIN_USE_GRILL_OPTIONAL) + if(!in_group) + steps += "Optional Step" + steps += "Cook on Grill on [iteration_list[2]] heat for [iteration_list[3] * 0.1] Seconds" + if(!in_group) + steps += "End Optional Step" + else + switch(iter) + if(CHEWIN_BEGIN_OPTION_CHAIN) + in_group = TRUE + steps += "Optional Steps" + if(CHEWIN_END_OPTION_CHAIN) + in_group = FALSE + steps += "End Optional Steps" + if(CHEWIN_BEGIN_EXCLUSIVE_OPTIONS) + in_group = TRUE + steps += "Exclusive Optional Steps" + if(CHEWIN_END_EXCLUSIVE_OPTIONS) + in_group = FALSE + steps += "End Exclusive Optional Steps" + new_food_recipe.steps = steps + GLOB.cooking_recipes += new_food_recipe diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/recipes/sandwhich_test.dm b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/sandwhich_test.dm new file mode 100644 index 000000000000..a6d2ed525a3c --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/recipes/sandwhich_test.dm @@ -0,0 +1,8 @@ +/datum/chewin_cooking/recipe/sandwich_basic + cooking_container = CUTTING_BOARD + product_type = /obj/item/food/sandwich + step_builder = list( + list(CHEWIN_ADD_ITEM, /obj/item/food/breadslice, qmod=0.5), + list(CHEWIN_ADD_ITEM, /obj/item/food/meat/cutlet, qmod=0.5, desc="It has meat in it.", result_desc="There is meat between the bread."), + list(CHEWIN_ADD_ITEM, /obj/item/food/breadslice, qmod=0.5) + ) diff --git a/monkestation/code/modules/brewin_and_chewin/chewing/tracker.dm b/monkestation/code/modules/brewin_and_chewin/chewing/tracker.dm new file mode 100644 index 000000000000..a553e8eed737 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/chewing/tracker.dm @@ -0,0 +1,458 @@ +//Datum held by objects that is the core component in a recipe. +//You use other items on an items with this datum to advance its recipe. +//Kept intentionally bare-bones because MANY of these objects are going to be made. +/datum/chewin_cooking/recipe_tracker + var/datum/weakref/holder_ref //The parent object holding the recipe tracker. + var/step_flags //A collection of the classes of steps the recipe can take next. + //This variable is a little complicated. + //It specifically references recipe_pointer objects each pointing to a different point in a different recipe. + var/list/active_recipe_pointers = list() + var/completion_lockout = FALSE //Freakin' cheaters... + var/list/completed_list = list()//List of recipes marked as complete. + var/recipe_started = FALSE //Tells if steps have been taken for this recipe + +/datum/chewin_cooking/recipe_tracker/New(var/obj/item/reagent_containers/container) + + #ifdef CHEWIN_DEBUG + log_debug("Called /datum/chewin_cooking/recipe_tracker/New") + #endif + holder_ref = WEAKREF(container) + src.generate_pointers() + src.populate_step_flags() + +//Call when a method is done incorrectly that provides a flat debuff to the whole meal. +/datum/chewin_cooking/recipe_tracker/proc/apply_flat_penalty(var/penalty) + if(active_recipe_pointers.len == 0) + return + + for (var/datum/chewin_cooking/recipe_pointer/pointer in active_recipe_pointers) + pointer.tracked_quality -= penalty + +//Generate recipe_pointer objects based on the global list +/datum/chewin_cooking/recipe_tracker/proc/generate_pointers() + + #ifdef CHEWIN_DEBUG + log_debug("Called /datum/chewin_cooking/recipe_tracker/proc/generate_pointers") + #endif + var/obj/item/reagent_containers/cooking_container/container = holder_ref.resolve() + + #ifdef CHEWIN_DEBUG + log_debug("Loading all references to [container] of type [container.type] using [container.appliancetype]") + #endif + //iterate through dictionary matching on holder type + if(GLOB.chewin_recipe_dictionary[container.appliancetype]) + for (var/key in GLOB.chewin_recipe_dictionary[container.appliancetype]) + #ifdef CHEWIN_DEBUG + log_debug("Loading [container.appliancetype] , [key] into pointer.") + #endif + active_recipe_pointers += new /datum/chewin_cooking/recipe_pointer(container.appliancetype, key, src) + +//Generate next steps +/datum/chewin_cooking/recipe_tracker/proc/get_step_options() + + #ifdef CHEWIN_DEBUG + log_debug("Called /datum/chewin_cooking/recipe_tracker/proc/get_step_options") + #endif + var/list/options = list() + for (var/datum/chewin_cooking/recipe_pointer/pointer in active_recipe_pointers) + options += pointer.get_possible_steps() + + #ifdef CHEWIN_DEBUG + log_debug("/datum/chewin_cooking/recipe_tracker/proc/get_step_options returned [options.len] options") + #endif + return options + + +/datum/chewin_cooking/recipe_tracker/proc/populate_step_flags() + #ifdef CHEWIN_DEBUG + log_debug("Called /datum/chewin_cooking/recipe_tracker/proc/populate_step_flags") + #endif + step_flags = 0 + for (var/datum/chewin_cooking/recipe_pointer/pointer in active_recipe_pointers) + var/flag_group = pointer.get_step_flags() + #ifdef CHEWIN_DEBUG + log_debug("Flag group returned with [flag_group]") + #endif + step_flags |= flag_group + +//Check if a recipe tracker has recipes loaded. +/datum/chewin_cooking/recipe_tracker/proc/has_recipes() + #ifdef CHEWIN_DEBUG + log_debug("Called /datum/chewin_cooking/recipe_tracker/proc/has_recipes") + #endif + return active_recipe_pointers.len + +//Wrapper function for analyzing process_item internally. +/datum/chewin_cooking/recipe_tracker/proc/process_item_wrap(var/obj/used_object, var/mob/user) + + #ifdef CHEWIN_DEBUG + log_debug("/datum/chewin_cooking/recipe_tracker/proc/process_item_wrap called!") + #endif + + var/response = process_item(used_object, user) + + if(response == CHEWIN_SUCCESS || response == CHEWIN_COMPLETE || response == CHEWIN_PARTIAL_SUCCESS) + if(!recipe_started) + recipe_started = TRUE + return response + +//Core function that checks if a object meets all the requirements for certain recipe actions. +/datum/chewin_cooking/recipe_tracker/proc/process_item(var/obj/used_object, var/mob/user) + #ifdef CHEWIN_DEBUG + log_debug("Called /datum/chewin_cooking/recipe_tracker/proc/process_item") + #endif + if(completion_lockout) + #ifdef CHEWIN_DEBUG + log_debug("/datum/chewin_cooking/recipe_tracker/proc/process_item held in lockout!") + #endif + return CHEWIN_LOCKOUT + var/list/valid_steps = list() + var/list/valid_unique_id_list = list() + var/use_class + + //Decide what action is being taken with the item, if any. + for (var/datum/chewin_cooking/recipe_pointer/pointer in active_recipe_pointers) + var/option_list = list() + option_list += pointer.get_possible_steps() + for (var/datum/chewin_cooking/recipe_step/step in option_list) + var/class_string = get_class_string(step.class) + var/is_valid = step.check_conditions_met(used_object, src) + #ifdef CHEWIN_DEBUG + log_debug("recipe_tracker/proc/process_item: Check conditions met returned [is_valid]") + #endif + if(is_valid == CHEWIN_CHECK_VALID) + if(!valid_steps["[class_string]"]) + valid_steps["[class_string]"] = list() + valid_steps["[class_string]"]+= step + + if(!valid_unique_id_list["[class_string]"]) + valid_unique_id_list["[class_string]"] = list() + valid_unique_id_list["[class_string]"] += step.unique_id + + if(!use_class) + use_class = class_string + if(valid_steps.len == 0) + #ifdef CHEWIN_DEBUG + log_debug("/recipe_tracker/proc/process_item returned no steps!") + #endif + return CHEWIN_NO_STEPS + + if(valid_steps.len > 1) + completion_lockout = TRUE + if(user) + var/list/choice = input(user, "There's two things you can do with this item!", "Choose One:") in valid_steps + completion_lockout = FALSE + if(!choice) + #ifdef CHEWIN_DEBUG + log_debug("/recipe_tracker/proc/process_item returned choice cancel!") + #endif + return CHEWIN_CHOICE_CANCEL + use_class = choice + else + use_class = 1 + #ifdef CHEWIN_DEBUG + log_debug("Use class determined: [use_class]") + #endif + + valid_steps = valid_steps[use_class] + valid_unique_id_list = valid_unique_id_list[use_class] + + var/has_traversed = FALSE + //traverse and cull pointers + for (var/datum/chewin_cooking/recipe_pointer/pointer in active_recipe_pointers) + var/used_id = FALSE + var/list/option_list = pointer.get_possible_steps() + for (var/datum/chewin_cooking/recipe_step/step in option_list) + if(!(step.unique_id in valid_unique_id_list)) + continue + else + used_id = TRUE + if(step.is_complete(used_object, src)) + has_traversed = TRUE + pointer.traverse(step.unique_id, used_object) + break + if (!used_id) + active_recipe_pointers.Remove(pointer) + qdel(pointer) + + + //attempt_complete_recursive(used_object, use_class) No, never again... + + //Choose to keep baking or finish now. + if(completed_list.len && (completed_list.len != active_recipe_pointers.len)) + + var/recipe_string = null + for(var/datum/chewin_cooking/recipe_pointer/pointer in completed_list) + if(!recipe_string) + recipe_string = "\a [pointer.current_recipe.name]" + else + recipe_string += ", or \a [pointer.current_recipe.name]" + if(user) + if(alert(user, "If you finish cooking now, you will create [recipe_string]. However, you feel there are possibilities beyond even this. Continue cooking anyways?",,"Yes","No") == "Yes") + //Cull finished recipe items + for (var/datum/chewin_cooking/recipe_pointer/pointer in completed_list) + active_recipe_pointers.Remove(pointer) + qdel(pointer) + completed_list = list() + + //Check if we completed our recipe + var/datum/chewin_cooking/recipe_pointer/chosen_pointer = null + if(completed_list.len >= 1) + #ifdef CHEWIN_DEBUG + log_debug("/recipe_tracker/proc/process_item YO WE ACTUALLY HAVE A COMPLETED A RECIPE!") + #endif + chosen_pointer = completed_list[1] + if(user) + if(completed_list.len > 1) + completion_lockout = TRUE + var/choice = input(user, "There's two things you complete at this juncture!", "Choose One:") in completed_list + completion_lockout = FALSE + if(choice) + chosen_pointer = completed_list[choice] + + //Call a proc that follows one of the steps in question, so we have all the nice to_chat calls. + var/datum/chewin_cooking/recipe_step/sample_step = valid_steps[1] + #ifdef CHEWIN_DEBUG + log_debug("/recipe_tracker/proc/process_item: Calling follow_step") + #endif + sample_step.follow_step(used_object, src) + + if(chosen_pointer) + chosen_pointer.current_recipe.create_product(chosen_pointer, user) + return CHEWIN_COMPLETE + populate_step_flags() + + if(has_traversed) + #ifdef CHEWIN_DEBUG + log_debug("/recipe_tracker/proc/process_item returned success!") + #endif + return CHEWIN_SUCCESS + + #ifdef CHEWIN_DEBUG + log_debug("/recipe_tracker/proc/process_item returned partial success!") + #endif + return CHEWIN_PARTIAL_SUCCESS + +//Sleep... My precious, monsterous child.... +/* +/datum/chewin_cooking/recipe_tracker/proc/attempt_complete_recursive( + var/obj/used_object, + var/use_class, + var/depth = 1, + var/list/considered_steps = null) + var/list/ourlist = null + if(depth == 1) + ourlist = active_recipe_pointers.Copy() + else + ourlist = considered_steps.Copy() + log_debug("/recipe_tracker/proc/attempt_complete_recursive entered second recursion!") + for (var/datum/chewin_cooking/recipe_pointer/pointer in ourlist) + var/option_list = list() + option_list += pointer.get_possible_steps() + var/has_valid_step = FALSE + var/had_traversal = FALSE + for (var/datum/chewin_cooking/recipe_step/step in option_list) + if(step.class != use_class) + continue + if(depth !=1 && !step.auto_complete_enabled) + continue + if(step.check_conditions_met(used_object, src) == CHEWIN_CHECK_VALID) + has_valid_step = TRUE + else + continue + if(step.is_complete(src)) + pointer.traverse(step.unique_id, used_object) + had_traversal = TRUE + break ///The first valid step is the only one we traverse, in the instance of multiple valid cases. + if(depth == 1 && !has_valid_step) + active_recipe_pointers.Remove(pointer) + ourlist.Remove(pointer) + else if(!had_traversal) + ourlist.Remove(pointer) + if(ourlist.len != 0 && depth !=5) + attempt_complete_recursive(used_object, use_class, depth=++depth, considered_steps = ourlist) +*/ +//=================================================================================== + + +//Points to a specific step in a recipe while considering the optional paths that recipe can take. +/datum/chewin_cooking/recipe_pointer + var/datum/chewin_cooking/recipe/current_recipe //The recipe being followed here. + var/datum/chewin_cooking/recipe_step/current_step //The current step in the recipe we are following. + + var/datum/weakref/parent_ref + + var/tracked_quality = 0 //The current level of quality within that recipe. + + var/list/steps_taken = list() //built over the course of following a recipe, tracks what has been done to the object. Format is unique_id:result + ///what our current food buff is + var/custom_food_buff + +/datum/chewin_cooking/recipe_pointer/New(start_type, recipe_id, var/datum/chewin_cooking/recipe_tracker/parent) + + #ifdef CHEWIN_DEBUG + log_debug("Called /datum/chewin_cooking/recipe_pointer/pointer/New([start_type], [recipe_id], parent)") + #endif + + parent_ref = WEAKREF(parent) + + #ifdef CHEWIN_DEBUG + if(!GLOB.chewin_recipe_dictionary[start_type][recipe_id]) + log_debug("Recipe [start_type]-[recipe_id] not found by tracker!") + #endif + + current_recipe = GLOB.chewin_recipe_dictionary[start_type][recipe_id] + + #ifdef CHEWIN_DEBUG + if(!current_recipe) + log_debug("Recipe [start_type]-[recipe_id] initialized as null!") + #endif + + current_step = current_recipe.first_step + + #ifdef CHEWIN_DEBUG + steps_taken["[current_step.unique_id]"]="Started with a [start_type]" + #endif + +//A list returning the next possible steps in a given recipe +/datum/chewin_cooking/recipe_pointer/proc/get_possible_steps() + + #ifdef CHEWIN_DEBUG + log_debug("Called /datum/chewin_cooking/recipe_pointer/proc/get_possible_steps") + if(!current_step) + log_debug("Recipe pointer in [current_recipe] has no current_step assigned?") + + if(!current_step.next_step) + log_debug("Recipe pointer in [current_recipe] has no next step.") + #endif + + //Build a list of all possible steps while accounting for exclusive step relations. + //Could be optimized, but keeps the amount of variables in the pointer low. + var/list/return_list = list(current_step.next_step) + for(var/datum/chewin_cooking/recipe_step/step in current_step.optional_step_list) + + if(steps_taken["[step.unique_id]"]) + //Traverse an option chain if one is present. + if(step.flags & CHEWIN_IS_OPTION_CHAIN) + var/datum/chewin_cooking/recipe_step/option_chain_step = step.next_step + while(option_chain_step.unique_id != current_step.unique_id) + if(!steps_taken["[option_chain_step.unique_id]"]) + return_list += option_chain_step + break + option_chain_step = option_chain_step.next_step + continue + + //Reference the global exclusion list to see if we can add this + var/exclude_step = FALSE + if(step.flags & CHEWIN_IS_EXCLUSIVE) + for (var/id in GLOB.chewin_optional_step_exclusion_dictionary["[step.unique_id]"]) + //Reference the global exclusion list to see if any of the taken steps + //Have the current step marked as exclusive. + if(steps_taken["[id]"]) + exclude_step = TRUE + break + + + if(!exclude_step) + return_list += step + #ifdef CHEWIN_DEBUG + else + log_debug("Ignoring step [step.unique_id] due to exclusion.") + #endif + + + #ifdef CHEWIN_DEBUG + log_debug("/datum/chewin_cooking/recipe_pointer/proc/get_possible_steps returned list of length [return_list.len]") + #endif + return return_list + +//Get the classes of all applicable next-steps for a recipe in a bitmask. +/datum/chewin_cooking/recipe_pointer/proc/get_step_flags() + #ifdef CHEWIN_DEBUG + log_debug("Called /datum/chewin_cooking/recipe_pointer/proc/get_step_flags") + if(!current_step) + log_debug("Recipe pointer in [current_recipe] has no current_step assigned?") + else if(!current_step.next_step) + log_debug("Recipe pointer in [current_recipe] has no next step.") + #endif + + //Build a list of all possible steps while accounting for exclusive step relations. + //Could be optimized, but keeps the amount of variables in the pointer low. + var/return_flags = current_step.next_step.class + for(var/datum/chewin_cooking/recipe_step/step in current_step.optional_step_list) + + if(steps_taken["[step.unique_id]"]) + //Traverse an option chain if one is present. + if(step.flags & CHEWIN_IS_OPTION_CHAIN) + var/datum/chewin_cooking/recipe_step/option_chain_step = step.next_step + while(option_chain_step.unique_id != current_step.unique_id) + if(!steps_taken["[option_chain_step.unique_id]"]) + return_flags |= option_chain_step.class + break + option_chain_step = option_chain_step.next_step + continue + + //Reference the global exclusion list to see if we can add this + var/exclude_step = FALSE + if(step.flags & CHEWIN_IS_EXCLUSIVE) + for (var/id in GLOB.chewin_optional_step_exclusion_dictionary["[step.unique_id]"]) + //Reference the global exclusion list to see if any of the taken steps + //Have the current step marked as exclusive. + if(steps_taken["[id]"]) + exclude_step = TRUE + break + if(!exclude_step) + return_flags |= step.class + return return_flags + +/datum/chewin_cooking/recipe_pointer/proc/has_option_by_id(var/id) + if(!GLOB.chewin_step_dictionary["[id]"]) + return FALSE + var/datum/chewin_cooking/recipe_step/active_step = GLOB.chewin_step_dictionary["[id]"] + var/list/possible_steps = get_possible_steps() + if(active_step in possible_steps) + return TRUE + return FALSE + +/datum/chewin_cooking/recipe_pointer/proc/traverse(var/id, var/obj/used_obj) + #ifdef CHEWIN_DEBUG + log_debug("/recipe_pointer/traverse: Traversing pointer from [current_step.unique_id] to [id].") + #endif + if(!GLOB.chewin_step_dictionary["[id]"]) + return FALSE + var/datum/chewin_cooking/recipe_tracker/tracker = parent_ref.resolve() + var/datum/chewin_cooking/recipe_step/active_step = GLOB.chewin_step_dictionary["[id]"] + + var/is_valid_step = FALSE + var/list/possible_steps = get_possible_steps() + for(var/datum/chewin_cooking/recipe_step/possible_step in possible_steps) + if(active_step.unique_id == possible_step.unique_id) + is_valid_step = TRUE + break + + if(!is_valid_step) + #ifdef CHEWIN_DEBUG + log_debug("/recipe_pointer/traverse: step [id] is not valid for recipe [current_recipe.unique_id]") + #endif + return FALSE + + var/step_quality = active_step.calculate_quality(used_obj, tracker) + tracked_quality += step_quality + steps_taken["[id]"] = active_step.get_step_result_text(used_obj, step_quality) + if(active_step.custom_food_buff) + custom_food_buff = active_step.custom_food_buff + if(active_step.finish_text) + var/datum/chewin_cooking/recipe_tracker/parent = parent_ref.resolve() + var/obj/item/resolved_ref = parent.holder_ref.resolve() + resolved_ref.say(active_step.finish_text) // I want runetext womp womp + + if(!(active_step.flags & CHEWIN_IS_OPTIONAL)) + current_step = active_step + + //The recipe has been completed. + if(!current_step.next_step && current_step.unique_id == id) + + tracker.completed_list += src + return TRUE + + return FALSE diff --git a/monkestation/code/modules/brewin_and_chewin/icons/bottle.dmi b/monkestation/code/modules/brewin_and_chewin/icons/bottle.dmi new file mode 100644 index 000000000000..3a2a818a8ca1 Binary files /dev/null and b/monkestation/code/modules/brewin_and_chewin/icons/bottle.dmi differ diff --git a/monkestation/code/modules/brewin_and_chewin/icons/eris_kitchen.dmi b/monkestation/code/modules/brewin_and_chewin/icons/eris_kitchen.dmi new file mode 100644 index 000000000000..a4d9b3dd4fe2 Binary files /dev/null and b/monkestation/code/modules/brewin_and_chewin/icons/eris_kitchen.dmi differ diff --git a/monkestation/code/modules/brewin_and_chewin/icons/grill.dmi b/monkestation/code/modules/brewin_and_chewin/icons/grill.dmi new file mode 100644 index 000000000000..5b999f1c6a4c Binary files /dev/null and b/monkestation/code/modules/brewin_and_chewin/icons/grill.dmi differ diff --git a/monkestation/code/modules/brewin_and_chewin/icons/kitchen.dmi b/monkestation/code/modules/brewin_and_chewin/icons/kitchen.dmi new file mode 100644 index 000000000000..5bbb7a8fd7c4 Binary files /dev/null and b/monkestation/code/modules/brewin_and_chewin/icons/kitchen.dmi differ diff --git a/monkestation/code/modules/brewin_and_chewin/icons/objects.dmi b/monkestation/code/modules/brewin_and_chewin/icons/objects.dmi new file mode 100644 index 000000000000..ca951cf3b1fc Binary files /dev/null and b/monkestation/code/modules/brewin_and_chewin/icons/objects.dmi differ diff --git a/monkestation/code/modules/brewin_and_chewin/icons/oven.dmi b/monkestation/code/modules/brewin_and_chewin/icons/oven.dmi new file mode 100644 index 000000000000..115df9f185eb Binary files /dev/null and b/monkestation/code/modules/brewin_and_chewin/icons/oven.dmi differ diff --git a/monkestation/code/modules/brewin_and_chewin/icons/paper.dmi b/monkestation/code/modules/brewin_and_chewin/icons/paper.dmi new file mode 100644 index 000000000000..286cf60046f5 Binary files /dev/null and b/monkestation/code/modules/brewin_and_chewin/icons/paper.dmi differ diff --git a/monkestation/code/modules/brewin_and_chewin/icons/scan.dmi b/monkestation/code/modules/brewin_and_chewin/icons/scan.dmi new file mode 100644 index 000000000000..5767c8ceaeab Binary files /dev/null and b/monkestation/code/modules/brewin_and_chewin/icons/scan.dmi differ diff --git a/monkestation/code/modules/brewin_and_chewin/icons/stove.dmi b/monkestation/code/modules/brewin_and_chewin/icons/stove.dmi new file mode 100644 index 000000000000..43ba9912808c Binary files /dev/null and b/monkestation/code/modules/brewin_and_chewin/icons/stove.dmi differ diff --git a/monkestation/code/modules/brewin_and_chewin/readme.md b/monkestation/code/modules/brewin_and_chewin/readme.md new file mode 100644 index 000000000000..1c90eda53e42 --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/readme.md @@ -0,0 +1,19 @@ +## Title: + + +MODULE ID: BREWIN_AND_CHEWIN + +### Description: + +This pr essentially works towards a slap craft varient for food items to add more immersion to foods, aswell as an overhaul to fermenting to allow you to better make beers and wines, adds pickling aswell. + + +### Included files that are not contained in this module: + + + +### Credits: + + + +Made by Dwasint diff --git a/monkestation/code/modules/brewin_and_chewin/uniqueness.dm b/monkestation/code/modules/brewin_and_chewin/uniqueness.dm new file mode 100644 index 000000000000..85480c8cd65a --- /dev/null +++ b/monkestation/code/modules/brewin_and_chewin/uniqueness.dm @@ -0,0 +1,70 @@ +GLOBAL_DATUM_INIT(uniqueness_repository, /repository/unique, new()) + +/repository/unique + var/list/generators + +/repository/unique/New() + ..() + generators = list() + +/repository/unique/proc/Generate() + var/generator_type = args[1] + var/datum/uniqueness_generator/generator = generators[generator_type] + if(!generator) + generator = new generator_type() + generators[generator_type] = generator + var/list/generator_args = args.Copy() // Cannot cut args directly, BYOND complains about it being readonly. + generator_args -= generator_type + return generator.Generate(arglist(generator_args)) + +/datum/uniqueness_generator/proc/Generate() + return + +/datum/uniqueness_generator/id_sequential + var/list/ids_by_key + +/datum/uniqueness_generator/id_sequential/New() + ..() + ids_by_key = list() + +/datum/uniqueness_generator/id_sequential/Generate(var/key, var/default_id = 100) + var/id = ids_by_key[key] + if(id) + id++ + else + id = default_id + + ids_by_key[key] = id + . = id + +/datum/uniqueness_generator/id_random + var/list/ids_by_key + +/datum/uniqueness_generator/id_random/New() + ..() + ids_by_key = list() + +/datum/uniqueness_generator/id_random/Generate(var/key, var/min, var/max) + var/list/ids = ids_by_key[key] + if(!ids) + ids = list() + ids_by_key[key] = ids + + if(ids.len >= (max - min) + 1) + stack_trace("Random ID limit reached for key [key].") + ids.Cut() + + if(ids.len >= 0.6 * ((max-min) + 1)) // if more than 60% of possible ids used + . = list() + for(var/i = min to max) + if(i in ids) + continue + . += i + var/id = pick(.) + ids += id + return id + else + do + . = rand(min, max) + while(. in ids) + ids += . diff --git a/monkestation/code/modules/can_spessmen_feel_pain/components/make_item_slow.dm b/monkestation/code/modules/can_spessmen_feel_pain/components/make_item_slow.dm new file mode 100644 index 000000000000..00f77f233fbb --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/components/make_item_slow.dm @@ -0,0 +1,61 @@ +/** + * Simple component that handles making an item slow the person holding it, + * as well as reverting it to its prior state when deleted. + */ +/datum/component/make_item_slow + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + /// The amount of slowdown applied to the item. + var/applied_slowdown = 1 + /// The slowdown of [parent] before the component was applied. + var/initial_slowdown = 0 + +/datum/component/make_item_slow/Initialize(applied_slowdown = 1) + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + var/obj/item/item_parent = parent + + if(item_parent.item_flags & SLOWS_WHILE_IN_HAND) // it already does it! + return COMPONENT_INCOMPATIBLE + + src.initial_slowdown = item_parent.slowdown + src.applied_slowdown = applied_slowdown + + make_slow() + +/datum/component/make_item_slow/Destroy() + revert_slow() + return ..() + +/** + * If this component is applied to a parent that already has the same typer component, just update the slowness to the new value. + */ +/datum/component/make_item_slow/InheritComponent(datum/component/make_item_slow/passed_component, original, applied_slowdown = 1) + src.applied_slowdown = applied_slowdown + make_slow() + +/** + * Apply our slowness to the attatched item. + */ +/datum/component/make_item_slow/proc/make_slow() + var/obj/item/item_parent = parent + var/mob/living/carbon/mob_holder = item_parent.loc + + item_parent.slowdown = applied_slowdown + item_parent.item_flags |= SLOWS_WHILE_IN_HAND + + if(istype(mob_holder)) + mob_holder.update_equipment_speed_mods() + +/** + * Remove our slowness from the attatched item. + */ +/datum/component/make_item_slow/proc/revert_slow() + var/obj/item/item_parent = parent + var/mob/living/carbon/mob_holder = item_parent.loc + + item_parent.slowdown = initial_slowdown + item_parent.item_flags &= ~SLOWS_WHILE_IN_HAND + + if(istype(mob_holder)) + mob_holder.update_equipment_speed_mods() diff --git a/monkestation/code/modules/can_spessmen_feel_pain/elements/temperature_pack.dm b/monkestation/code/modules/can_spessmen_feel_pain/elements/temperature_pack.dm new file mode 100644 index 000000000000..d88213b3d015 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/elements/temperature_pack.dm @@ -0,0 +1,107 @@ +/** + * Element to make an item into a "temperature pack". + * Temperature packs are hot or cold things that can be pressed against + * limbs experiencing pain to reduce it. + */ +/datum/element/temperature_pack + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + /// Amount of pain we restore every tick in the targeted limb. + var/pain_heal_rate = 0 + /// Pain modifier put on the limb we're targeting. + var/pain_modifier_on_limb = 1 + /// Body temperature change per tick. + var/temperature_change = 0 + +/datum/element/temperature_pack/Attach(obj/item/target, pain_heal_rate = 0, pain_modifier_on_limb = 1, temperature_change = 0) + . = ..() + + if(!isitem(target)) + return ELEMENT_INCOMPATIBLE + + src.pain_heal_rate = pain_heal_rate + src.pain_modifier_on_limb = pain_modifier_on_limb + src.temperature_change = temperature_change + + RegisterSignal(target, COMSIG_ITEM_ATTACK_SECONDARY, PROC_REF(try_apply_to_limb)) + RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(get_examine_text)) + +/datum/element/temperature_pack/Detach(obj/target) + . = ..() + UnregisterSignal(target, list( + COMSIG_ITEM_ATTACK_SECONDARY, + COMSIG_ATOM_EXAMINE, + )) + +/** + * Edit the examine text to show the item can be used as a temperature pack. + */ +/datum/element/temperature_pack/proc/get_examine_text(obj/item/source, mob/examiner, list/examine_list) + SIGNAL_HANDLER + + if(pain_heal_rate > 0) + examine_list += span_notice("Right-clicking on a hurt limb with this item can help soothe pain.") + +/** + * Try to apply [source] item onto [target] mob from [user]. + */ +/datum/element/temperature_pack/proc/try_apply_to_limb(obj/item/source, atom/target, mob/user, params) + SIGNAL_HANDLER + + . = SECONDARY_ATTACK_CALL_NORMAL // Normal operations + + if(!ishuman(target)) + return + + var/mob/living/carbon/human/target_mob = target + var/targeted_zone = target_mob.zone_selected + + if(!target_mob.pain_controller) + return + if(target_mob.stat == DEAD) + to_chat(user, span_warning("[target_mob] is dead!")) + return + if(!target_mob.get_bodypart_pain(targeted_zone, TRUE)) + to_chat(user, span_warning("That limb is not in pain.")) + return + + . = SECONDARY_ATTACK_CONTINUE_CHAIN // Past this point, no afterattacks + + for(var/datum/status_effect/temperature_pack/pre_existing_effect in target_mob.status_effects) + if(pre_existing_effect.targeted_zone == targeted_zone) + to_chat(user, span_warning("There is already something pressed against that limb.")) + return + if(pre_existing_effect.pressed_item == source) + to_chat(user, span_warning("You are already pressing [source] onto another limb.")) + return + + . = SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN // And past THIS point, no attack + + INVOKE_ASYNC(src, PROC_REF(apply_to_limb), source, target, user, targeted_zone) + +/** + * Actually apply [parent] temperature pack to [targeted_zone] limb on [target] mob from [user]. + */ +/datum/element/temperature_pack/proc/apply_to_limb(obj/item/parent, mob/living/carbon/target, mob/user, targeted_zone) + if(!do_after(user, 0.5 SECONDS, target)) + return + + var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(targeted_zone) + user.visible_message( + span_notice("[user] press [parent] against [target == user ? "their" : "[target]'s" ] [targeted_bodypart.name]."), + span_notice("You press [parent] against [target == user ? "your" : "[target]'s" ] [targeted_bodypart.name].") + ) + + var/selected_effect = temperature_change > 0 \ + ? /datum/status_effect/temperature_pack/heat \ + : /datum/status_effect/temperature_pack/cold + + target.apply_status_effect( + selected_effect, + user, + parent, + targeted_zone, + pain_heal_rate, + pain_modifier_on_limb, + temperature_change, + ) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/icons/hud/screen_full.dmi b/monkestation/code/modules/can_spessmen_feel_pain/icons/hud/screen_full.dmi new file mode 100644 index 000000000000..bf34384867fc Binary files /dev/null and b/monkestation/code/modules/can_spessmen_feel_pain/icons/hud/screen_full.dmi differ diff --git a/monkestation/code/modules/can_spessmen_feel_pain/icons/mob/inhands/pain_items_lhand.dmi b/monkestation/code/modules/can_spessmen_feel_pain/icons/mob/inhands/pain_items_lhand.dmi new file mode 100644 index 000000000000..2db6272ea114 Binary files /dev/null and b/monkestation/code/modules/can_spessmen_feel_pain/icons/mob/inhands/pain_items_lhand.dmi differ diff --git a/monkestation/code/modules/can_spessmen_feel_pain/icons/mob/inhands/pain_items_rhand.dmi b/monkestation/code/modules/can_spessmen_feel_pain/icons/mob/inhands/pain_items_rhand.dmi new file mode 100644 index 000000000000..fece08e14817 Binary files /dev/null and b/monkestation/code/modules/can_spessmen_feel_pain/icons/mob/inhands/pain_items_rhand.dmi differ diff --git a/monkestation/code/modules/can_spessmen_feel_pain/icons/mob/pain_items.dmi b/monkestation/code/modules/can_spessmen_feel_pain/icons/mob/pain_items.dmi new file mode 100644 index 000000000000..9786ccd5372a Binary files /dev/null and b/monkestation/code/modules/can_spessmen_feel_pain/icons/mob/pain_items.dmi differ diff --git a/monkestation/code/modules/can_spessmen_feel_pain/icons/obj/chemical.dmi b/monkestation/code/modules/can_spessmen_feel_pain/icons/obj/chemical.dmi new file mode 100644 index 000000000000..e2efb6e79d95 Binary files /dev/null and b/monkestation/code/modules/can_spessmen_feel_pain/icons/obj/chemical.dmi differ diff --git a/monkestation/code/modules/can_spessmen_feel_pain/icons/obj/pain_items.dmi b/monkestation/code/modules/can_spessmen_feel_pain/icons/obj/pain_items.dmi new file mode 100644 index 000000000000..2eb7cbfdcf76 Binary files /dev/null and b/monkestation/code/modules/can_spessmen_feel_pain/icons/obj/pain_items.dmi differ diff --git a/monkestation/code/modules/can_spessmen_feel_pain/icons/obj/syringe.dmi b/monkestation/code/modules/can_spessmen_feel_pain/icons/obj/syringe.dmi new file mode 100644 index 000000000000..94b2da421b00 Binary files /dev/null and b/monkestation/code/modules/can_spessmen_feel_pain/icons/obj/syringe.dmi differ diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm new file mode 100644 index 000000000000..f036f5a7afae --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/_base.dm @@ -0,0 +1,942 @@ +/** + * The pain controller datum. + * + * Attatched to a /carbon/human, this datum tracks all the pain values on all their bodyparts and handles updating them. + * This datum processes on alive humans every 2 seconds. + */ +/datum/pain + /// The parent mob we're tracking. + var/mob/living/carbon/parent + /// Modifier applied to all [adjust_pain] amounts + var/pain_modifier = 1 + /// Lazy Assoc list [id] to [modifier], all our pain modifiers affecting our final mod + var/list/pain_mods + /// Lazy Assoc list [zones] to [references to bodyparts], all the body parts we're tracking + var/list/body_zones + /// Natural amount of decay given to each limb per 5 ticks of process, increases over time + var/natural_pain_decay = -0.8 + /// The base amount of pain decay received. + var/base_pain_decay = -0.8 + /// Counter to track pain decay. Pain decay is only done once every 5 ticks. + var/natural_decay_counter = 0 + /// Amount of shock building up from higher levels of pain + /// When greater than current health, we go into shock + var/shock_buildup = 0 + /// Cooldown to track the last time we lost pain. + COOLDOWN_DECLARE(time_since_last_pain_loss) + /// Cooldown to track last time we sent a pain message. + COOLDOWN_DECLARE(time_since_last_pain_message) + +#ifdef TESTING + /// For testing. Does this pain datum print testing messages when it happens? + var/print_debug_messages = TRUE + /// For testing. Does this pain datum include ALL test messages, including very small and constant ones (like pain decay)? + var/print_debug_decay = FALSE +#endif + +/datum/pain/New(mob/living/carbon/human/new_parent) + if(!iscarbon(new_parent) || istype(new_parent, /mob/living/carbon/human/dummy)) + qdel(src) // If we're not a carbon, or a dummy, delete us + return null + + parent = new_parent + + body_zones = list() + for(var/obj/item/bodypart/parent_bodypart as anything in parent.bodyparts) + add_bodypart(parent, parent_bodypart, TRUE) + + if(!length(body_zones)) + stack_trace("Pain datum failed to find any body_zones to track!") + qdel(src) // If we have no bodyparts, delete us + return + + register_pain_signals() + base_pain_decay = natural_pain_decay + + addtimer(CALLBACK(src, PROC_REF(start_pain_processing), 1)) + +#ifdef TESTING + if(new_parent.z && !is_station_level(new_parent.z)) + print_debug_messages = FALSE +#endif + +/datum/pain/Destroy() + body_zones = null + if(parent) + STOP_PROCESSING(SSpain, src) + unregister_pain_signals() + parent = null + return ..() + +/datum/pain/proc/start_pain_processing() + if(parent.stat != DEAD) + START_PROCESSING(SSpain, src) + +/** + * Register all of our signals with our parent. + */ +/datum/pain/proc/register_pain_signals() + RegisterSignal(parent, COMSIG_CARBON_ATTACH_LIMB, PROC_REF(add_bodypart)) + RegisterSignal(parent, COMSIG_CARBON_GAIN_WOUND, PROC_REF(add_wound_pain)) + RegisterSignal(parent, COMSIG_CARBON_LOSE_WOUND, PROC_REF(remove_wound_pain)) + RegisterSignal(parent, COMSIG_CARBON_REMOVE_LIMB, PROC_REF(remove_bodypart)) + RegisterSignal(parent, COMSIG_LIVING_HEALTHSCAN, PROC_REF(on_analyzed)) + RegisterSignal(parent, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(remove_all_pain)) + RegisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(add_damage_pain)) + RegisterSignal(parent, COMSIG_MOB_STATCHANGE, PROC_REF(on_parent_statchance)) + RegisterSignals(parent, list(COMSIG_LIVING_SET_BODY_POSITION, COMSIG_LIVING_SET_BUCKLED), PROC_REF(check_lying_pain_modifier)) + RegisterSignals(parent, list(SIGNAL_ADDTRAIT(TRAIT_NO_PAIN_EFFECTS), SIGNAL_REMOVETRAIT(TRAIT_NO_PAIN_EFFECTS)), PROC_REF(refresh_pain_attributes)) + + if(ishuman(parent)) + RegisterSignal(parent, COMSIG_HUMAN_BURNING, PROC_REF(on_burn_tick)) + +/** + * Unregister all of our signals from our parent when we're done, if we have signals to unregister. + */ +/datum/pain/proc/unregister_pain_signals() + UnregisterSignal(parent, list( + COMSIG_CARBON_ATTACH_LIMB, + COMSIG_CARBON_GAIN_WOUND, + COMSIG_CARBON_LOSE_WOUND, + COMSIG_CARBON_REMOVE_LIMB, + COMSIG_HUMAN_BURNING, + COMSIG_LIVING_HEALTHSCAN, + COMSIG_LIVING_POST_FULLY_HEAL, + COMSIG_LIVING_SET_BODY_POSITION, + COMSIG_LIVING_SET_BUCKLED, + COMSIG_MOB_APPLY_DAMAGE, + COMSIG_MOB_STATCHANGE, + SIGNAL_ADDTRAIT(TRAIT_NO_PAIN_EFFECTS), + SIGNAL_REMOVETRAIT(TRAIT_NO_PAIN_EFFECTS), + )) + +/** + * Add a limb to be tracked. + * + * source - source of the signal / the mob who is gaining the limb / parent + * new_limb - the bodypart being attatched + * special - whether this limb being attatched should have side effects (if TRUE, likely being attatched on initialization) + */ +/datum/pain/proc/add_bodypart(mob/living/carbon/source, obj/item/bodypart/new_limb, special) + SIGNAL_HANDLER + + if(!istype(new_limb)) // pseudo-bodyparts are not tracked for simplicity (chainsaw arms) + return + + var/obj/item/bodypart/existing = body_zones[new_limb.body_zone] + if(!isnull(existing)) // if we already have a val assigned to this key, remove it + remove_bodypart(source, existing, FALSE, special) + + body_zones[new_limb.body_zone] = new_limb + + if(special || (HAS_TRAIT(source, TRAIT_LIMBATTACHMENT) && (new_limb.bodytype & BODYTYPE_ROBOTIC))) + new_limb.pain = 0 + else + adjust_bodypart_pain(new_limb.body_zone, new_limb.pain) + adjust_bodypart_pain(BODY_ZONE_CHEST, new_limb.pain / 3) + + RegisterSignal(new_limb, COMSIG_QDELETING, PROC_REF(limb_delete)) + +/** + * Remove a limb from being tracked. + * + * source - source of the signal / the mob who is losing the limb / parent + * lost_limb - the bodypart being removed + * special - whether this limb being removed should have side effects (if TRUE, likely being removed on initialization) + * dismembered - whether this limb was dismembered + */ +/datum/pain/proc/remove_bodypart(mob/living/carbon/source, obj/item/bodypart/lost_limb, dismembered, special) + SIGNAL_HANDLER + + var/bad_zone = lost_limb.body_zone + if(lost_limb != body_zones[bad_zone]) + CRASH("Pain datum tried to remove a bodypart that wasn't being tracked!") + + body_zones -= bad_zone + UnregisterSignal(lost_limb, COMSIG_QDELETING) + + if(!QDELETED(parent)) + if(!special && !(HAS_TRAIT(source, TRAIT_LIMBATTACHMENT) && (lost_limb.bodytype & BODYTYPE_ROBOTIC))) + var/limb_removed_pain = (dismembered ? PAIN_LIMB_DISMEMBERED : PAIN_LIMB_REMOVED) + if(!isnewplayer(usr)) //painful this should be avoided + adjust_bodypart_pain(BODY_ZONE_CHEST, limb_removed_pain) + adjust_bodypart_pain(BODY_ZONES_MINUS_CHEST, limb_removed_pain / 3) + + if(!QDELETED(lost_limb)) + lost_limb.pain = initial(lost_limb.pain) + REMOVE_TRAIT(lost_limb, TRAIT_PARALYSIS, PAIN_LIMB_PARALYSIS) + +/datum/pain/proc/limb_delete(obj/item/bodypart/source) + SIGNAL_HANDLER + + remove_bodypart(source.owner, source, special = TRUE) // Special I guess? Straight up deleted + +/** + * Add a pain modifier and update our overall modifier. + * + * key - key of the added modifier + * amount - multiplier of the modifier + * + * returns TRUE if our pain mod actually changed + */ +/datum/pain/proc/set_pain_modifier(key, amount) + var/existing_key = LAZYACCESS(pain_mods, key) + if(!isnull(existing_key)) + if(amount > 1 && existing_key >= amount) + return FALSE + if(amount < 1 && existing_key <= amount) + return FALSE + if(amount == 1) + return FALSE + + LAZYSET(pain_mods, key, amount) + refresh_pain_attributes() + return update_pain_modifier() + +/** + * Remove a pain modifier and update our overall modifier. + * + * key - key of the removed modifier + * + * returns TRUE if our pain mod actually changed + */ +/datum/pain/proc/unset_pain_modifier(key) + if(isnull(LAZYACCESS(pain_mods, key))) + return FALSE + + LAZYREMOVE(pain_mods, key) + return update_pain_modifier() + +/** + * Update our overall pain modifier. + * The pain modifier is multiplicative based on all the pain modifiers we have. + * + * returns TRUE if our pain modifier was changed after update, FALSE if it remained the same + */ +/datum/pain/proc/update_pain_modifier() + var/old_pain_mod = pain_modifier + pain_modifier = 1 + for(var/mod in pain_mods) + pain_modifier *= pain_mods[mod] + return old_pain_mod != pain_modifier + +/** + * Adjust the amount of pain in all [def_zones] provided by [amount] (multiplied by the [pain_modifier] if positive). + * + * def_zones - list of all zones being adjusted. Can be passed a non-list. + * amount - amount of pain being applied to all items in [def_zones]. If posiitve, multiplied by [pain_modifier]. + */ +/datum/pain/proc/adjust_bodypart_pain(list/def_zones, amount = 0, dam_type = BRUTE) + SHOULD_NOT_SLEEP(TRUE) // This needs to be asyncronously called in a lot of places, it should already check that this doesn't sleep but just in case. + + if(!islist(def_zones)) + def_zones = list(def_zones) + + // No pain at all + if(amount == 0) + return + if(amount > 0 && (parent.status_flags & GODMODE)) + return + + for(var/zone in shuffle(def_zones)) + var/adjusted_amount = round(amount, 0.01) + var/obj/item/bodypart/adjusted_bodypart = body_zones[check_zone(zone)] + if(isnull(adjusted_bodypart)) // it's valid - for if we're passed a zone we don't have + continue + + // Pain is negative (healing) + if(adjusted_amount < 0) + // Pain is negative and we're at min pain + if(adjusted_bodypart.pain <= adjusted_bodypart.min_pain) + continue + // Pain is negative and we're above soft cap, incraese the healing amount greatly + if(adjusted_bodypart.pain >= adjusted_bodypart.soft_max_pain) + adjusted_amount *= 3 + + // Pain is positive (dealing) + else + // Adjust incoming dealt pain by modifiers + adjusted_amount = round(adjusted_amount * pain_modifier * adjusted_bodypart.bodypart_pain_modifier, 0.01) + // Pain modifiers results in us taking 0 pain + // (If someone adds a negative pain mod and causes "inverse pain" (which you shouldn't) this needs to go) + if(adjusted_amount <= 0) + continue + + // Officially recieving pain at this point + adjusted_bodypart.last_received_pain_type = dam_type + +#ifdef TESTING + if(print_debug_messages) + testing("[amount] was adjusted down to [adjusted_amount]. (Modifiers: [pain_modifier], [adjusted_bodypart.bodypart_pain_modifier])") +#endif + + // Actually do the pain addition / subtraction here + adjusted_bodypart.pain = max(adjusted_bodypart.pain + adjusted_amount, adjusted_bodypart.min_pain) + + if(adjusted_amount > 0) + INVOKE_ASYNC(src, PROC_REF(on_pain_gain), adjusted_bodypart, amount, dam_type) + else if(adjusted_amount <= -1.5 || COOLDOWN_FINISHED(src, time_since_last_pain_loss)) + INVOKE_ASYNC(src, PROC_REF(on_pain_loss), adjusted_bodypart, amount, dam_type) + +#ifdef TESTING + if(print_debug_messages && (print_debug_decay || abs(adjusted_amount) > 1)) + testing("PAIN DEBUG: [parent] recived [adjusted_amount] pain to [adjusted_bodypart]. Part pain: [adjusted_bodypart.pain]") +#endif + + return TRUE + +/** + * Set the minimum amount of pain in all [def_zones] by [amount]. + * + * def_zones - list of all zones being adjusted. Can be passed a non-list. + * amount - amount of pain being all items in [def_zones] are set to. + */ +/datum/pain/proc/adjust_bodypart_min_pain(list/def_zones, amount = 0) + if(!amount) + return + + if(!islist(def_zones)) + def_zones = list(def_zones) + + for(var/zone in def_zones) + var/obj/item/bodypart/adjusted_bodypart = body_zones[zone] + if(isnull(adjusted_bodypart)) // it's valid - for if we're passed a zone we don't have + continue + + adjusted_bodypart.min_pain = max(adjusted_bodypart.min_pain + amount, 0) // Negative min pain is a neat idea ("banking pain") but not today + adjusted_bodypart.pain = max(adjusted_bodypart.pain, adjusted_bodypart.min_pain) + + return TRUE + +/** + * Called when pain is gained to apply side effects. + * Calls [affected_part]'s [on_gain_pain_effects] proc with arguments [amount]. + * Sends signal [COMSIG_CARBON_PAIN_GAINED] with arguments [mob/living/carbon/parent, obj/item/bodypart/affected_part, amount]. + * + * affected_part - the bodypart that gained the pain + * amount - amount of pain that was gained, post-[pain_modifier] applied + */ +/datum/pain/proc/on_pain_gain(obj/item/bodypart/affected_part, amount, type) + affected_part.on_gain_pain_effects(amount) + refresh_pain_attributes() + SEND_SIGNAL(parent, COMSIG_CARBON_PAIN_GAINED, affected_part, amount, type) + COOLDOWN_START(src, time_since_last_pain_loss, 30 SECONDS) + + if(amount > 12 && prob(25)) + do_pain_emote("scream", 5 SECONDS) + else if(amount > 6 && prob(10)) + do_pain_emote() + +/** + * Called when pain is lost, if the mob did not lose pain in the last 60 seconds. + * Calls [affected_part]'s [on_lose_pain_effects] proc with arguments [amount]. + * Sends signal [COMSIG_CARBON_PAIN_LOST] with arguments [mob/living/carbon/parent, obj/item/bodypart/affected_part, amount]. + * + * affected_part - the bodypart that lost pain + * amount - amount of pain that was lost + */ +/datum/pain/proc/on_pain_loss(obj/item/bodypart/affected_part, amount, type) + affected_part.on_lose_pain_effects(amount) + refresh_pain_attributes() + SEND_SIGNAL(parent, COMSIG_CARBON_PAIN_LOST, affected_part, amount, type) + +/** + * Hook into [/mob/living/proc/apply_damage] proc via signal and apply pain based on how much damage was gained. + * + * source - source of the signal / the mob being damaged / parent + * damage - the amount of damage sustained + * damagetype - the type of damage sustained + * def_zone - the limb being targeted with damage (either a bodypart zone or an obj/item/bodypart) + */ +/datum/pain/proc/add_damage_pain( + mob/living/carbon/source, + damage, + damagetype, + def_zone, + blocked = 0, + wound_bonus = 0, + bare_wound_bonus = 0, + sharpness = NONE, + attack_direction, + obj/item/attacking_item, +) + + SIGNAL_HANDLER + + if(damage <= 0 || (parent.status_flags & GODMODE)) + return + if(isbodypart(def_zone)) + var/obj/item/bodypart/targeted_part = def_zone + def_zone = targeted_part.body_zone + else + def_zone = check_zone(def_zone) + + // By default pain is calculated based on damage and wounding + // Attacks with a wound bonus add additional pain (usually, like 2-5) + // (Note that if they also succeed in applying a wound, more pain comes from that) + // Also, sharp attacks apply a smidge extra pain + var/pain = (2 * damage) + (0.1 * max(wound_bonus + bare_wound_bonus, 1)) * (sharpness ? 1.2 : 1) + switch(damagetype) + // Brute pain is dealt to the target zone + // pain is just divided by a random number, for variance + if(BRUTE) + pain *= (rand(60, 80) / 100) + + // Burn pain is dealt to the target zone + // pain is lower for weaker burns, but scales up for more damaging burns + if(BURN) + switch(damage) + if(1 to 10) + pain *= 0.25 + if(10 to 20) + pain *= 0.5 + if(20 to INFINITY) + pain *= 0.75 + + // Toxins pain is dealt to the chest (stomach and liver) + // Pain is determined by the liver's tox tolerance, liver damage, and stomach damage + // having a high amount of toxloss also adds additional pain + // + // Note: 99% of sources of toxdamage is done through adjusttoxloss, and as such doesn't go through this + if(TOX) + if(HAS_TRAIT(parent, TRAIT_TOXINLOVER) || HAS_TRAIT(parent, TRAIT_TOXIMMUNE)) + return + def_zone = BODY_ZONE_CHEST + var/obj/item/organ/internal/liver/our_liver = source.get_organ_slot(ORGAN_SLOT_LIVER) + var/obj/item/organ/internal/stomach/our_stomach = source.get_organ_slot(ORGAN_SLOT_STOMACH) + if(our_liver) + pain = damage / our_liver.toxTolerance + switch(our_liver.damage) + if(20 to 50) + pain += 1 + if(50 to 80) + pain += 2 + if(80 to INFINITY) + pain += 3 + else if(HAS_TRAIT(parent, TRAIT_LIVERLESS_METABOLISM)) + pain = 1 + else + pain = damage * 2 + + if(our_stomach) + switch(our_stomach.damage) + if(20 to 50) + pain += 1 + if(50 to 80) + pain += 2 + if(80 to INFINITY) + pain += 3 + else if(HAS_TRAIT(parent, TRAIT_NOHUNGER)) + pain = 1 + else + pain += 3 + + switch(source.getToxLoss()) + if(33 to 66) + pain += 1 + if(66 to INFINITY) + pain += 3 + + // Oxy pain is dealt to the head and chest + // pain is increasd based on lung damage and overall oxyloss + // + // Note: 99% of sources of oxydamage is done through adjustoxyloss, and as such doesn't go through this + if(OXY) + if(HAS_TRAIT(parent, TRAIT_NOBREATH)) + return + def_zone = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST) + var/obj/item/organ/internal/lungs/our_lungs = source.get_organ_slot(ORGAN_SLOT_LUNGS) + if(our_lungs) + switch(our_lungs.damage) + if(20 to 50) + pain += 1 + if(50 to 80) + pain += 2 + if(80 to INFINITY) + pain += 3 + else + pain += 5 + + switch(parent.getOxyLoss()) + if(0 to 20) + pain = 0 + if(20 to 50) + pain += 1 + if(50 to INFINITY) + pain += 3 + + // No pain from stamina loss + // In the future stamina can probably cause very sharp pain and replace stamcrit, + // but the system will require much finer tuning before then + if(STAMINA) + return + + // Head pain causes brain damage, so brain damage causes no pain (to prevent death spirals) + if(BRAIN) + return + + if(!def_zone || !pain) +#ifdef TESTING + if(print_debug_messages) + testing("PAIN DEBUG: [parent] recieved damage but no pain. ([def_zone ? "Nullified to [pain]" : "No def zone"])") +#endif + return + +#ifdef TESTING + if(print_debug_messages) + testing("PAIN DEBUG: [parent] is recieving [pain] of type [damagetype] to the [parse_zone(def_zone)]. (Original amount: [damage])") +#endif + + adjust_bodypart_pain(def_zone, pain, damagetype) + +/** + * Add pain in from a received wound based on severity. + * + * source - source of the signal / the mob being wounded / parent + * applied_wound - the wound being applied + * wounded_limb - the limb being wounded + */ +/datum/pain/proc/add_wound_pain(mob/living/carbon/source, datum/wound/applied_wound, obj/item/bodypart/wounded_limb) + SIGNAL_HANDLER + +#ifdef TESTING + if(print_debug_messages) + testing("PAIN DEBUG: [parent] is recieving a wound of level [applied_wound.severity] to the [parse_zone(wounded_limb.body_zone)].") +#endif + + adjust_bodypart_min_pain(wounded_limb.body_zone, applied_wound.severity * 5) + adjust_bodypart_pain(wounded_limb.body_zone, applied_wound.severity * 7.5) + +/** + * Remove pain from a healed wound. + * + * source - source of the signal / the mob being wounded / parent + * removed_wound - the wound being healed + * wounded_limb - the limb that was wounded + */ +/datum/pain/proc/remove_wound_pain(mob/living/carbon/source, datum/wound/removed_wound, obj/item/bodypart/wounded_limb) + SIGNAL_HANDLER + + adjust_bodypart_min_pain(wounded_limb.body_zone, -removed_wound.severity * 5) + adjust_bodypart_pain(wounded_limb.body_zone, -removed_wound.severity * 5) + +/** + * The process proc for pain. + * + * Applies and removes pain modifiers as they come and go. + * Causes various side effects based on pain. + * + * Triggers once every 2 seconds. + * Handles natural pain decay, which happens once every 5 processes (every 10 seconds) + */ +/datum/pain/process(seconds_per_tick) + if(!HAS_TRAIT(parent, TRAIT_ANALGESIA)) + var/has_pain = FALSE + var/just_cant_feel_anything = !parent.can_feel_pain() + var/no_recent_pain = COOLDOWN_FINISHED(src, time_since_last_pain_loss) + for(var/part in shuffle(body_zones)) + var/obj/item/bodypart/checked_bodypart = body_zones[part] + if(checked_bodypart.pain <= 0) + continue + has_pain = TRUE + if(just_cant_feel_anything || !COOLDOWN_FINISHED(src, time_since_last_pain_message)) + continue + // 1% chance per 8 pain being experienced to get a feedback message every second + if(!SPT_PROB(checked_bodypart.get_modified_pain() / 8, seconds_per_tick)) + continue + if(checked_bodypart.pain_feedback(seconds_per_tick, no_recent_pain)) + COOLDOWN_START(src, time_since_last_pain_message, 12 SECONDS) + + if(!has_pain) + // no-op if none of our bodyparts are in pain + return + + var/curr_pain = get_average_pain() + switch(curr_pain) + if(-INFINITY to 10) + shock_buildup = max(shock_buildup - 3, -30) // staying out of pain for a while gives you a small resiliency to shock (~1 minute) + + if(10 to 25) + shock_buildup = max(shock_buildup - 1, -30) + + if(25 to 40) + if(SPT_PROB(2, seconds_per_tick)) + do_pain_message(span_danger(pick("Everything aches.", "Everything feels sore."))) + + if(40 to 70) + if(!HAS_TRAIT(parent, TRAIT_NO_SHOCK_BUILDUP)) + shock_buildup += 1 + if(SPT_PROB(2, seconds_per_tick)) + do_pain_message(span_bolddanger(pick("Everything hurts.", "Everything feels very sore.", "It hurts."))) + + if(70 to INFINITY) + if(!HAS_TRAIT(parent, TRAIT_NO_SHOCK_BUILDUP)) + shock_buildup += 3 + if(SPT_PROB(2, seconds_per_tick)) + do_pain_message(span_userdanger(pick("Stop the pain!", "Everything hurts!"))) + + // If shock buildup exceeds our health + 30 ticks then well, we enter shock + // This means at 100 health you can be in moderate pain for 130 ticks / 260 seconds / ~4 minutes before falling into shock + if(shock_buildup >= (parent.health + 30) \ + && curr_pain >= 50 \ + && !HAS_TRAIT(parent, TRAIT_NO_SHOCK_BUILDUP) \ + && !is_undergoing_shock() \ + && !parent.undergoing_cardiac_arrest() \ + ) + parent.infect_disease_predefined(DISEASE_SHOCK, TRUE, "[ROUND_TIME()] Inflicted with Pain Shock [key_name(parent)]") + to_chat(parent, span_userdanger("You feel your body start to shut down!")) + if(parent.stat == CONSCIOUS && !parent.incapacitated(IGNORE_RESTRAINTS|IGNORE_GRAB) && !HAS_TRAIT(parent, TRAIT_NO_PAIN_EFFECTS)) + parent.visible_message(span_danger("[parent] grabs at their chest and stares into the distance as they go into shock!"), ignored_mobs = parent) + shock_buildup = -200 // requires another 200 ticks / 400 seconds / ~6 minutes of pain to go into shock again + return + + var/standard_effect_prob = (curr_pain * 0.05) - 0.75 // starts at 15, caps at 4.5 + var/rare_effect_prob = (curr_pain * 0.04) - 1.5 // starts at 40 + var/very_rare_effect_prob = (curr_pain * 0.03) - 2.25 // starts at 70 + + if(standard_effect_prob > 0) + if(!just_cant_feel_anything) + if(SPT_PROB(standard_effect_prob, seconds_per_tick)) + parent.adjust_stutter_up_to(10 SECONDS * pain_modifier, 30 SECONDS) + if(SPT_PROB(standard_effect_prob, seconds_per_tick)) + parent.adjust_jitter_up_to(20 SECONDS * pain_modifier, 60 SECONDS) + if(SPT_PROB(standard_effect_prob, seconds_per_tick)) + parent.adjust_dizzy_up_to(10 SECONDS * pain_modifier, 30 SECONDS) + if(curr_pain >= 70) + parent.adjust_confusion_up_to(8 SECONDS * pain_modifier, 24 SECONDS) + if(SPT_PROB(standard_effect_prob * 1.2, seconds_per_tick) && parent.stamina?.loss <= 80) + var/stam_taken = round((0.2 * curr_pain + 8) * pain_modifier) // 10 = 10, 100 = 28, good enough + if(just_cant_feel_anything) + parent.apply_damage(stam_taken * 1.2, STAMINA) + // First we apply damage, if that succeeds -> + // Check how much damage, if above a threshold -> + // Run a pain emote, if the pain emote succeeds as well -> + else if(parent.apply_damage(stam_taken, STAMINA) && stam_taken >= 15 && do_pain_emote(pick("wince", "gasp"))) + parent.visible_message(span_warning("[parent] doubles over in pain!")) + + if(rare_effect_prob > 0) + if(SPT_PROB(rare_effect_prob * 2, seconds_per_tick)) + var/list/options = list("wince", "whimper") + if(curr_pain >= 70) + options.Add("cry", "scream") + do_pain_emote(pick(options), 5 SECONDS) + if(SPT_PROB(rare_effect_prob, seconds_per_tick) && parent.body_position != LYING_DOWN && !just_cant_feel_anything) + parent.Knockdown(2 SECONDS * pain_modifier) + parent.visible_message(span_warning("[parent] collapses from pain!")) + if(SPT_PROB(rare_effect_prob, seconds_per_tick)) + var/obj/item/held_item = parent.get_active_held_item() + var/obj/item/bodypart/active_hand = parent.get_active_hand() + if(held_item && active_hand && parent.dropItemToGround(held_item)) + if(active_hand.bodytype & BODYTYPE_ROBOTIC) + to_chat(parent, span_danger("Your hand malfunctions, causing you to drop [held_item]!")) + parent.visible_message(span_warning("[parent]'s hand malfunctions, causing them to drop [held_item]!"), ignored_mobs = parent) + do_sparks(number = 1, source = parent) + else if(just_cant_feel_anything) + to_chat(parent, span_danger("Your hand spams and you drop [held_item]!")) + else + to_chat(parent, span_danger("Your fumble though the pain and drop [held_item]!")) + parent.visible_message(span_warning("[parent] fumbles around and drops [held_item]!"), ignored_mobs = parent) + do_pain_emote("gasp") + + if(very_rare_effect_prob > 0) + if(SPT_PROB(very_rare_effect_prob, seconds_per_tick)) + parent.vomit(50) + if(SPT_PROB(very_rare_effect_prob, seconds_per_tick) && !just_cant_feel_anything) + parent.adjust_confusion_up_to(8 SECONDS, 24 SECONDS) + + // Finally, handle pain decay over time + if(HAS_TRAIT(parent, TRAIT_STASIS) || parent.on_fire || parent.stat == DEAD) + return + + // Decay every 3 ticks / 6 seconds, or 1 ticks / 2 seconds if "sleeping" + var/every_x_ticks = HAS_TRAIT(parent, TRAIT_KNOCKEDOUT) ? 1 : 3 + + natural_decay_counter++ + if(natural_decay_counter % every_x_ticks != 0) + return + + natural_decay_counter = 0 + if(COOLDOWN_FINISHED(src, time_since_last_pain_loss) && parent.stat == CONSCIOUS) + // 0.16 per 10 seconds, ~0.1 per minute, 10 minutes for ~1 decay + natural_pain_decay = max(natural_pain_decay - 0.12, -4) + else + natural_pain_decay = base_pain_decay + + // modify our pain decay by our pain modifier (ex. 0.5 pain modifier = 2x natural pain decay, capped at ~3x) + var/pain_modified_decay = round(natural_pain_decay * (1 / max(pain_modifier, 0.33)), 0.01) + adjust_bodypart_pain(BODY_ZONES_ALL, pain_modified_decay) + +/** + * Whenever we buckle to something or lie down, get a pain bodifier. + */ +/datum/pain/proc/check_lying_pain_modifier(datum/source, new_buckled) + SIGNAL_HANDLER + + var/buckled_lying_modifier = 1 + if(parent.body_position == LYING_DOWN) + buckled_lying_modifier -= 0.1 + + if(new_buckled) + buckled_lying_modifier -= 0.1 + + if(buckled_lying_modifier < 1) + set_pain_modifier(PAIN_MOD_LYING, buckled_lying_modifier) + else + unset_pain_modifier(PAIN_MOD_LYING) + +/** + * While actively burning, cause pain + */ +/datum/pain/proc/on_burn_tick(datum/source) + SIGNAL_HANDLER + + var/mob/living/carbon/human/human_parent = parent + if(human_parent.get_thermal_protection() >= FIRE_SUIT_MAX_TEMP_PROTECT) + return + + // The more firestacks, the more pain we apply per burn tick, up to 2 per tick per bodypart. + // We can be liberal with this because when they're extinguished most of it will go away. + parent.apply_status_effect(/datum/status_effect/pain_from_fire, clamp(parent.fire_stacks * 0.2, 0, 2)) + +/** + * Apply or remove pain various modifiers from pain (mood, action speed, movement speed) based on the [average_pain]. + */ +/datum/pain/proc/refresh_pain_attributes(...) + SIGNAL_HANDLER + + if(!parent.can_feel_pain()) + clear_pain_attributes() + return + + switch(get_average_pain()) + if(-INFINITY to 20) + clear_pain_attributes() + if(20 to 40) + parent.mob_surgery_speed_mod = 0.9 + parent.add_movespeed_modifier(/datum/movespeed_modifier/pain/light) + parent.add_actionspeed_modifier(/datum/actionspeed_modifier/pain/light) + parent.add_mood_event("pain", /datum/mood_event/light_pain) + if(40 to 60) + parent.mob_surgery_speed_mod = 0.75 + parent.add_movespeed_modifier(/datum/movespeed_modifier/pain/medium) + parent.add_actionspeed_modifier(/datum/actionspeed_modifier/pain/medium) + parent.add_mood_event("pain", /datum/mood_event/med_pain) + if(60 to 80) + parent.mob_surgery_speed_mod = 0.6 + parent.add_movespeed_modifier(/datum/movespeed_modifier/pain/heavy) + parent.add_actionspeed_modifier(/datum/actionspeed_modifier/pain/heavy) + parent.add_mood_event("pain", /datum/mood_event/heavy_pain) + if(80 to INFINITY) + parent.mob_surgery_speed_mod = 0.5 + parent.add_movespeed_modifier(/datum/movespeed_modifier/pain/crippling) + parent.add_actionspeed_modifier(/datum/actionspeed_modifier/pain/crippling) + parent.add_mood_event("pain", /datum/mood_event/crippling_pain) + +/** + * Clears all pain related attributes + */ +/datum/pain/proc/clear_pain_attributes() + parent.mob_surgery_speed_mod = initial(parent.mob_surgery_speed_mod) + parent.remove_movespeed_modifier(MOVESPEED_ID_PAIN) + parent.remove_actionspeed_modifier(ACTIONSPEED_ID_PAIN) + parent.clear_mood_event("pain") + +/** + * Run a pain related emote, if a few checks are successful. + * + * emote - string, what emote we're running + * cooldown - what cooldown to set our emote cooldown to + * + * returns TRUE if successful. + */ +/datum/pain/proc/do_pain_emote(emote = pick(PAIN_EMOTES), cooldown = 3 SECONDS) + ASSERT(istext(emote)) + if(!parent.can_feel_pain()) + return FALSE + if(cooldown && !COOLDOWN_FINISHED(src, time_since_last_pain_message)) + return FALSE + if(parent.stat >= UNCONSCIOUS || parent.incapacitated(IGNORE_RESTRAINTS|IGNORE_GRAB)) + return FALSE + + parent.emote(emote) + COOLDOWN_START(src, time_since_last_pain_message, cooldown) + return TRUE + +/** + * Run a pain related message, if a few checks are successful. + * + * message - string, what message we're sending + * painless_message - optional string, what message we're sending if the mob doesn't "feel" pain + * cooldown - what cooldown to set our message cooldown to + * + * returns TRUE if successful. + * Returns FALSE if we failed to send a message, even if painless_message was provided and sent. + */ +/datum/pain/proc/do_pain_message(message, painless_message, cooldown = 0 SECONDS) + ASSERT(istext(message)) + + if(parent.client?.prefs) + if(parent.client.prefs.read_preference(/datum/preference/toggle/pain_messages)) + return FALSE + + if(!parent.can_feel_pain()) + if(painless_message) + to_chat(parent, painless_message) + return FALSE + if(parent.stat >= UNCONSCIOUS) + return FALSE + if(cooldown && !COOLDOWN_FINISHED(src, time_since_last_pain_message)) + return FALSE + + to_chat(parent, message) + COOLDOWN_START(src, time_since_last_pain_message, cooldown) + return TRUE + +/** + * Get the average pain of all bodyparts as a percent of the total pain. + */ +/datum/pain/proc/get_average_pain() + var/max_total_pain = 0 + var/total_pain = 0 + for(var/zone in body_zones) + var/obj/item/bodypart/adjusted_bodypart = body_zones[zone] + total_pain += adjusted_bodypart.pain + max_total_pain += adjusted_bodypart.soft_max_pain + + return 100 * total_pain / max_total_pain + +/** + * Returns a disease datum (Truthy value) if we are undergoing shock. + */ +/datum/pain/proc/is_undergoing_shock() + return locate(/datum/disease/advanced/premade/shock) in parent.diseases + +/** + * Remove all pain, pain paralysis, side effects, etc. from our mob after we're fully healed by something (like an adminheal) + */ +/datum/pain/proc/remove_all_pain(datum/source, heal_flags) + SIGNAL_HANDLER + + // Ideally pain would have its own heal flag but we live in a society + if(!(heal_flags & (HEAL_ADMIN|HEAL_WOUNDS|HEAL_STATUS))) + return + + for(var/zone in body_zones) + var/obj/item/bodypart/healed_bodypart = body_zones[zone] + adjust_bodypart_min_pain(zone, -INFINITY) + adjust_bodypart_pain(zone, -INFINITY) + // Shouldn't be necessary but you never know! + REMOVE_TRAIT(healed_bodypart, TRAIT_PARALYSIS, PAIN_LIMB_PARALYSIS) + + clear_pain_attributes() + shock_buildup = 0 + natural_pain_decay = base_pain_decay + +/** + * Determines if we should be processing or not. + */ +/datum/pain/proc/on_parent_statchance(mob/source) + SIGNAL_HANDLER + + if(source.stat == DEAD) + if(datum_flags & DF_ISPROCESSING) + STOP_PROCESSING(SSpain, src) + else + START_PROCESSING(SSpain, src) + +/** + * Signal proc for [COMSIG_LIVING_HEALTHSCAN] + * Reports how much pain [parent] is sustaining to [user]. + * + * Note, this report is relatively vague intentionally - + * rather than sending a detailed report of which bodyparts are in pain and how much, + * the patient is encouraged to elaborate on which bodyparts hurt the most, and how much they hurt. + * (To encourage a bit more interaction between the doctors.) + */ +/datum/pain/proc/on_analyzed(datum/source, list/render_list, advanced, mob/user, mode) + SIGNAL_HANDLER + + var/amount = "" + var/tip = "" + var/in_shock = !!is_undergoing_shock() + if(in_shock) + tip += span_bold("Neurogenic shock has begun and should be treated urgently. ") + + switch(get_average_pain()) + if(5 to 15) + amount = "minor" + tip += "Pain should subside in time." + if(15 to 30) + amount = "moderate" + tip += "Pain should subside in time and can be quickened with rest or painkilling medication." + if(30 to 50) + amount = "major" + tip += "Treat wounds and abate pain with rest, cryogenics, and painkilling medication." + if(50 to 80) + amount = "severe" + if(!in_shock) + tip += span_bold("Alert: Potential of neurogenic shock. ") + tip += "Treat wounds and abate pain with long rest, cryogenics, and moderate painkilling medication." + if(80 to INFINITY) + amount = "extreme" + if(!in_shock) + tip += span_bold("Alert: High potential of neurogenic shock. ") + tip += "Treat wounds and abate pain with long rest, cryogenics, and heavy painkilling medication." + + if(amount && tip) + render_list += "" + render_list += span_bold("Subject is experiencing [amount] pain. ") + render_list += tip + render_list += "\n" + +#ifdef TESTING + debug_print_pain() +#endif + +// ------ Pain debugging stuff. ------ +/datum/pain/vv_get_dropdown() + . = ..() + VV_DROPDOWN_OPTION("debug_pain", "Debug Pain") + VV_DROPDOWN_OPTION("set_limb_pain", "Adjust Limb Pain") + VV_DROPDOWN_OPTION("refresh_mod", "Refresh Pain Mod") + +/datum/pain/vv_do_topic(list/href_list) + . = ..() + if(href_list["debug_pain"]) + debug_print_pain() + if(href_list["set_limb_pain"]) + admin_adjust_bodypart_pain() + if(href_list["refresh_mod"]) + update_pain_modifier() + +/datum/pain/proc/debug_print_pain() + + var/list/final_print = list() + final_print += "
DEBUG PRINTOUT PAIN: [REF(src)]" + final_print += "[parent] has an average pain of [get_average_pain()]." + final_print += "[parent] has a pain modifier of [pain_modifier]." + final_print += " - - - - " + final_print += "[parent] bodypart printout: (min / current / soft max)" + for(var/part in body_zones) + var/obj/item/bodypart/checked_bodypart = body_zones[part] + final_print += "[checked_bodypart.name]: [checked_bodypart.min_pain] / [checked_bodypart.pain] / [checked_bodypart.soft_max_pain]" + + final_print += " - - - - " + final_print += "[parent] pain modifier printout:" + for(var/mod in pain_mods) + final_print += "[mod]: [pain_mods[mod]]" + + final_print += "
" + to_chat(usr, final_print.Join("\n")) + +/datum/pain/proc/admin_adjust_bodypart_pain() + var/zone = input(usr, "Which bodypart") as null|anything in BODY_ZONES_ALL + "All" + var/amount = input(usr, "How much?") as null|num + + if(isnull(amount) || isnull(zone)) + return + if(zone == "All") + zone = BODY_ZONES_ALL + + amount = clamp(amount, -200, 200) + adjust_bodypart_pain(zone, amount) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/bodyparts.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/bodyparts.dm new file mode 100644 index 000000000000..9a14a244f0fc --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/bodyparts.dm @@ -0,0 +1,286 @@ +// Bodypart extensions to handle pain +// Yes pain is handled on a per-bodypart basis +/obj/item/bodypart + /// The amount of pain this limb is experiencing (A bit for default) + var/pain = 15 + /// The min amount of pain this limb can experience + var/min_pain = 0 + /// The soft cap of pain that this limb can experience + /// This is not a hard cap, pain can go above this, but beyond this effects will not worsen + var/soft_max_pain = PAIN_LIMB_MAX + /// Modifier applied to pain that this part receives + var/bodypart_pain_modifier = 1 + /// The last type of pain we received. Determines what type of pain we're recieving. + var/last_received_pain_type = BRUTE + +// Adds pain to check-self. +/obj/item/bodypart/check_for_injuries(mob/living/carbon/human/examiner, list/check_list) + . = ..() + if(owner != examiner || !owner.can_feel_pain()) // haha you thought + return + + switch((get_modified_pain() / soft_max_pain) * 100) + if(10 to 40) + check_list += "\t [span_danger("Your [name] is experiencing mild pain \ + and [last_received_pain_type == BURN ? "burns" : "hurts"] to the touch.")]" + + if(40 to 70) + check_list += "\t [span_warning("Your [name] is experiencing moderate pain \ + and [last_received_pain_type == BURN ? "burns" : "hurts"] to the touch!")]" + + if(70 to INFINITY) + check_list += "\t [span_boldwarning("Your [name] is experiencing severe pain \ + and [last_received_pain_type == BURN ? "burns" : "hurts"] to the touch!")]" + +/** + * Gets our bodypart's effective pain (pain * pain modifiers). + * + * Returns our effective pain. + */ +/obj/item/bodypart/proc/get_modified_pain() + if(owner?.pain_controller) + return pain * bodypart_pain_modifier * owner.pain_controller.pain_modifier + else + return pain * bodypart_pain_modifier + +/** + * Effects on this bodypart has when pain is gained. + * + * amount - amount of pain gained + */ +/obj/item/bodypart/proc/on_gain_pain_effects(amount) + if(!owner) + return FALSE + + if(get_modified_pain() >= 65 && can_be_disabled && !HAS_TRAIT_FROM(src, TRAIT_PARALYSIS, PAIN_LIMB_PARALYSIS)) + owner.pain_message( + span_userdanger("Your [plaintext_zone] goes numb from the pain!"), + span_danger("You can't move your [plaintext_zone]!") + ) + ADD_TRAIT(src, TRAIT_PARALYSIS, PAIN_LIMB_PARALYSIS) + update_disabled() + + return TRUE + +/** + * Effects on this bodypart has when pain is lost and some time passes without any pain gain. + * + * amount - amount of pain lost + */ +/obj/item/bodypart/proc/on_lose_pain_effects(amount) + if(!owner) + return FALSE + + if(get_modified_pain() < 65 && HAS_TRAIT_FROM(src, TRAIT_PARALYSIS, PAIN_LIMB_PARALYSIS)) + owner.pain_message( + span_green("You can feel your [plaintext_zone] again!"), + span_green("You can move your [plaintext_zone] again!") + ) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, PAIN_LIMB_PARALYSIS) + update_disabled() + + return TRUE + +/** + * Feedback messages from this limb when it is sustaining pain. + * + * healing_pain - if TRUE, the bodypart has gone some time without recieving pain, and is healing. + */ +/obj/item/bodypart/proc/pain_feedback(seconds_per_tick, healing_pain) + var/list/feedback_phrases = list() + var/static/list/healing_phrases = list( + "but is improving", + "but is starting to dull", + "but the stinging is stopping", + "but feels faint", + ) + + switch(pain) + if(10 to 25) + owner.flash_pain_overlay(1) + feedback_phrases += list("aches", "feels sore", "stings slightly", "tingles", "twinges") + if(25 to 50) + owner.flash_pain_overlay(1) + feedback_phrases += list("hurts", "feels sore", "stings", "throbs", "pangs", "cramps", "feels wrong", "feels loose") + if(last_received_pain_type == BURN) + feedback_phrases += list("stings to the touch", "burns") + if(50 to 65) + if(SPT_PROB(4, seconds_per_tick)) + owner.pain_emote() + owner.flash_pain_overlay(2) + feedback_phrases += list("really hurts", "is losing feeling", "throbs painfully", "is in agony", "anguishes", "feels broken", "feels terrible") + if(last_received_pain_type == BURN) + feedback_phrases += list("burns to the touch", "burns", "singes") + if(65 to INFINITY) + if(SPT_PROB(8, seconds_per_tick)) + var/bonus_emote = pick(PAIN_EMOTES) + owner.pain_emote(pick("groan", "scream", bonus_emote)) + owner.flash_pain_overlay(2, 2 SECONDS) + feedback_phrases += list("is numb from the pain") + + if(feedback_phrases.len) + owner.pain_message(span_danger("Your [plaintext_zone] [pick(feedback_phrases)][healing_pain ? ", [pick(healing_phrases)]." : "!"]")) + return TRUE + +// --- Chest --- +/obj/item/bodypart/chest + soft_max_pain = PAIN_CHEST_MAX + +/obj/item/bodypart/chest/robot + // Augmented limbs start with maximum pain as a trade-off for becoming almost immune to it + // The idea being that the roboticist installing augments should take care of their patient + // following the period after they're augmented - anesthetic, rest, painkillers (from medbay) + pain = PAIN_CHEST_MAX + // As a trade off for starting with maximum pain, + // augmented limbs lose pain very rapidly and take very little in the way of pain. + // Why not a 0 modifier? I feel like it'll be unfun if they can just completely ignore the system. + bodypart_pain_modifier = 0.2 + +/obj/item/bodypart/chest/pain_feedback(seconds_per_tick, healing_pain) + var/list/feedback_phrases = list() + var/list/side_feedback = list() + var/static/list/healing_phrases = list( + "but is improving", + "but is starting to dull", + "but the stinging is stopping", + "but feels faint", + "but is settling", + "but it subsides", + ) + + switch(pain) + if(10 to 40) + owner.flash_pain_overlay(1) + feedback_phrases += list("aches", "feels sore", "stings slightly", "tingles", "twinges") + if(40 to 75) + owner.flash_pain_overlay(1, 2 SECONDS) + feedback_phrases += list("hurts", "feels sore", "stings", "throbs", "pangs", "cramps", "feels tight") + side_feedback += list("Your side hurts", "Your side pangs", "Your ribs hurt", "Your ribs pang", "Your neck stiffs") + if(75 to 110) + if(SPT_PROB(8, seconds_per_tick)) + owner.pain_emote() + owner.flash_pain_overlay(2, 2 SECONDS) + feedback_phrases += list("really hurts", "is losing feeling", "throbs painfully", "stings to the touch", "is in agony", "anguishes", "feels broken", "feels tight") + side_feedback += list("You feel a sharp pain in your side", "Your ribs feel broken") + if(110 to INFINITY) + if(SPT_PROB(12, seconds_per_tick)) + var/bonus_emote = pick(PAIN_EMOTES) + owner.pain_emote(pick("groan", "scream", bonus_emote)) + owner.flash_pain_overlay(2, 3 SECONDS) + feedback_phrases += list("hurts madly", "is in agony", "is anguishing", "burns to the touch", "feels terrible", "feels constricted") + side_feedback += list("You feel your ribs jostle in your [plaintext_zone]") + + if(side_feedback.len && last_received_pain_type == BRUTE && SPT_PROB(50, seconds_per_tick)) + owner.pain_message(span_danger("[pick(side_feedback)][healing_pain ? ", [pick(healing_phrases)]." : "!"]")) + else if(feedback_phrases.len) + owner.pain_message(span_danger("Your [plaintext_zone] [pick(feedback_phrases)][healing_pain ? ", [pick(healing_phrases)]." : "!"]")) + + return TRUE + +// --- Head --- +/obj/item/bodypart/head + soft_max_pain = PAIN_HEAD_MAX + +/obj/item/bodypart/head/robot + pain = PAIN_HEAD_MAX + bodypart_pain_modifier = 0.2 + +/obj/item/bodypart/head/on_gain_pain_effects(amount) + . = ..() + if(!.) + return FALSE + + if(amount >= 10) + // Large amounts of head pain causes minor brain damage + owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, min(pain / 5, 10), 50) + + return TRUE + +/obj/item/bodypart/head/pain_feedback(seconds_per_tick, healing_pain) + var/list/feedback_phrases = list() + var/list/side_feedback = list() + var/static/list/healing_phrases = list( + "but is improving", + "but is starting to dull", + "but the stinging is stopping", + "but the tension is stopping", + "but is settling", + "but it subsides", + "but the pressure fades", + ) + + switch(pain) + if(10 to 30) + owner.flash_pain_overlay(1) + feedback_phrases += list("aches", "feels sore", "stings slightly", "tingles", "twinges") + side_feedback += list("Your neck feels sore", "Your eyes feel tired") + if(30 to 60) + owner.flash_pain_overlay(1) + feedback_phrases += list("hurts", "feels sore", "stings", "throbs", "pangs") + side_feedback += list("Your neck aches badly", "Your eyes hurt", "You feel a migrane coming on", "You feel a splitting headache") + if(60 to 90) + owner.flash_pain_overlay(2) + feedback_phrases += list("really hurts", "is losing feeling", "throbs painfully", "is in agony", "anguishes", "feels broken", "feels terrible") + side_feedback += list("Your neck stiffs", "You feel pressure in your [plaintext_zone]", "The back of your eyes begin hurt", "You feel a terrible migrane") + if(90 to INFINITY) + var/bonus_emote = pick(PAIN_EMOTES) + owner.pain_emote(pick("groan", bonus_emote)) + owner.flash_pain_overlay(2, 2 SECONDS) + feedback_phrases += list("hurts madly", "is in agony", "is anguishing", "feels terrible", "is in agony", "feels tense") + side_feedback += list("You feel a splitting migrane", "Pressure floods your [plaintext_zone]", "Your [plaintext_zone] feels as if it's being squeezed", "Your eyes hurt to keep open") + + if(side_feedback.len && last_received_pain_type == BRUTE && SPT_PROB(50, seconds_per_tick)) + owner.pain_message(span_danger("[pick(side_feedback)][healing_pain ? ", [pick(healing_phrases)]." : "!"]")) + else if(feedback_phrases.len) + owner.pain_message(span_danger("Your [plaintext_zone] [pick(feedback_phrases)][healing_pain ? ", [pick(healing_phrases)]." : "!"]")) + + return TRUE + +// --- Legs --- +/obj/item/bodypart/leg/on_gain_pain_effects(amount) + . = ..() + if(!.) + return + + if(get_modified_pain() < 40) + return + if(amount < 5) // only big bursts of pain will cause a limp + return + owner.apply_status_effect(/datum/status_effect/limp/pain, src) + +// --- Right Leg --- +/obj/item/bodypart/leg/right/robot + pain = PAIN_LIMB_MAX * 0.5 + bodypart_pain_modifier = 0.2 + +/obj/item/bodypart/leg/right/robot/surplus + pain = 0 + bodypart_pain_modifier = 0.8 + +// --- Left Leg --- +/obj/item/bodypart/leg/left/robot + pain = PAIN_LIMB_MAX * 0.5 + bodypart_pain_modifier = 0.2 + +/obj/item/bodypart/leg/left/robot/surplus + pain = 0 + bodypart_pain_modifier = 0.8 + + +// --- Right Arm --- +/obj/item/bodypart/arm/right/robot + pain = PAIN_LIMB_MAX * 0.5 + bodypart_pain_modifier = 0.2 + +/obj/item/bodypart/arm/right/robot/surplus + pain = 0 + bodypart_pain_modifier = 0.8 + +// --- Left Arm --- +/obj/item/bodypart/arm/right/robot + pain = PAIN_LIMB_MAX * 0.5 + bodypart_pain_modifier = 0.2 + +/obj/item/bodypart/arm/left/robot/surplus + pain = 0 + bodypart_pain_modifier = 0.8 diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/causes/generic.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/causes/generic.dm new file mode 100644 index 000000000000..ce7d020df001 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/causes/generic.dm @@ -0,0 +1,55 @@ +// -- Causes of pain, from non-modular actions -- +/datum/brain_trauma/mild/concussion/on_life(seconds_per_tick, times_fired) + . = ..() + if(SPT_PROB(1, seconds_per_tick)) + owner.cause_pain(BODY_ZONE_HEAD, 10) + +// Shocks +/mob/living/carbon/human/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE) + . = ..() + if(!.) + return + + sharp_pain(BODY_ZONES_ALL, min((. / 2), 25), BURN) + set_timed_pain_mod(PAIN_MOD_RECENT_SHOCK, 0.5, 30 SECONDS) + +// Fleshmend of course heals pain. +/datum/status_effect/fleshmend/tick() + . = ..() + if(iscarbon(owner) && !owner.on_fire) + var/mob/living/carbon/carbon_owner = owner + carbon_owner.cause_pain(BODY_ZONES_ALL, -2) + +// Regen cores. +/datum/status_effect/regenerative_core/on_apply() + . = ..() + var/mob/living/carbon/human/human_owner = owner + if(istype(human_owner) && human_owner.pain_controller) + human_owner.cause_pain(BODY_ZONES_LIMBS, -25) + human_owner.cause_pain(BODY_ZONE_CHEST, -30) + human_owner.cause_pain(BODY_ZONE_HEAD, -15) // heals 90 pain total + +// Flight potion's flavor says "it hurts a shit ton bro", so it should cause decent pain +/datum/reagent/flightpotion/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE) + var/has_wings_before = exposed_mob.get_organ_slot(ORGAN_SLOT_EXTERNAL_WINGS) + . = ..() + if(iscarbon(exposed_mob) && exposed_mob.stat != DEAD) + var/mob/living/carbon/exposed_carbon = exposed_mob + if(reac_volume < 5 || !(ishumanbasic(exposed_carbon) || islizard(exposed_carbon) || ismoth(exposed_carbon))) + return + if(has_wings_before) + exposed_carbon.cause_pain(BODY_ZONE_HEAD, 10) + exposed_carbon.cause_pain(BODY_ZONE_CHEST, 45) + exposed_carbon.cause_pain(list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM), 18) + else + exposed_carbon.cause_pain(BODY_ZONE_HEAD, 16) + exposed_carbon.cause_pain(BODY_ZONE_CHEST, 75) + exposed_carbon.cause_pain(list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM), 30) + +/datum/wound/blunt/bone/moderate/chiropractice(mob/living/carbon/human/user) + . = ..() + user.cause_pain(limb.body_zone, 25) + +/datum/wound/blunt/bone/moderate/malpractice(mob/living/carbon/human/user) + . = ..() + user.cause_pain(limb.body_zone, 40) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/causes/opiods.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/causes/opiods.dm new file mode 100644 index 000000000000..fdbb8969da43 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/causes/opiods.dm @@ -0,0 +1,27 @@ +/datum/addiction/opioids + withdrawal_stage_messages = list( + "My body aches all over...", + "I need some pain relief...", + "It hurts all over...I need some opioids!", + ) + +/datum/addiction/opioids/withdrawal_stage_1_process(mob/living/carbon/affected_carbon, seconds_per_tick) + . = ..() + if(!affected_carbon.pain_controller) + return + if(affected_carbon.pain_controller.get_average_pain() <= 10 && SPT_PROB(8, seconds_per_tick)) + affected_carbon.cause_pain(BODY_ZONES_ALL, 0.5 * seconds_per_tick) + +/datum/addiction/opioids/withdrawal_stage_2_process(mob/living/carbon/affected_carbon, seconds_per_tick) + . = ..() + if(!affected_carbon.pain_controller) + return + if(affected_carbon.pain_controller.get_average_pain() <= 20 && SPT_PROB(8, seconds_per_tick)) + affected_carbon.cause_pain(BODY_ZONES_ALL, 1 * seconds_per_tick) + +/datum/addiction/opioids/withdrawal_stage_3_process(mob/living/carbon/affected_carbon, seconds_per_tick) + . = ..() + if(!affected_carbon.pain_controller) + return + if(affected_carbon.pain_controller.get_average_pain() <= 30 && SPT_PROB(8, seconds_per_tick)) + affected_carbon.cause_pain(BODY_ZONES_ALL, 1.5 * seconds_per_tick) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/causes/surgery.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/causes/surgery.dm new file mode 100644 index 000000000000..be9a8769490b --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/causes/surgery.dm @@ -0,0 +1,236 @@ +/datum/surgery_step + /// Moodlet given if a surgery is done without anesthetics + var/surgery_moodlet = /datum/mood_event/surgery + /// Pain overlay flashed if a surgery is done without anesthetics + var/pain_overlay_severity = 1 + /// How much pain this gives (given out in display_pain, so this might be given out twice) + var/pain_amount = 0 + /// What type of pain this gives + var/pain_type = BRUTE + +// Regex for updating existing display pain calls: +// display_pain\((.+)\) -> display_pain($1, target_zone = target_zone) // NON-MODULE CHANGE +/datum/surgery_step/display_pain(mob/living/carbon/target, pain_message, mechanical_surgery = FALSE, target_zone) + // Only feels pain if we feels pain + if(pain_amount <= 0 || isnull(target_zone) || !target.can_feel_pain()) + return FALSE + + // No pain from mechanics but still show the message (usually) + if(mechanical_surgery) + if(prob(70)) + target.pain_message(span_userdanger(pain_message)) + return FALSE + + target.cause_pain(target_zone, pain_amount, pain_type) + + if(target.IsSleeping() || target.stat >= UNCONSCIOUS) + if(target.has_status_effect(/datum/status_effect/grouped/anesthetic)) + target.add_mood_event("surgery", /datum/mood_event/anesthetic) + return FALSE + if(ispath(surgery_moodlet)) + target.add_mood_event("surgery", surgery_moodlet) + if(isnum(pain_overlay_severity)) + target.flash_pain_overlay(pain_overlay_severity) + // No message if the pain emote fails + if(!target.pain_emote()) + return FALSE + if(!target.pain_message(span_userdanger(pain_message))) + return FALSE + return TRUE + +/datum/surgery_step/brainwash/sleeper_agent + pain_amount = 36 + +/datum/surgery_step/sever_limb + pain_amount = 16 // Losing a limb also applies pain to chest + +/datum/surgery_step/repair_bone_hairline + pain_amount = 16 + +/datum/surgery_step/reset_compound_fracture + pain_amount = 24 + +/datum/surgery_step/fix_brain + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 24 + +/datum/surgery_step/debride + pain_amount = 12 + pain_type = BURN + +/datum/surgery_step/handle_cavity + pain_amount = 16 + +/datum/surgery_step/incise_heart + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + // It is extremely unlikely this surgery is done on alive people to feel (most) of this + pain_amount = 60 + +/datum/surgery_step/coronary_bypass + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 30 + +/datum/surgery_step/coronary_bypass/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + . = ..() + // Reduces pain from surgery a bit on success + target.cause_pain(target_zone, pain_amount * -0.5, pain_type) + +/datum/surgery_step/coronary_bypass/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery) + . = ..() + // Double pain from surgery + target.cause_pain(target_zone, pain_amount, pain_type) + +/datum/surgery_step/fix_eyes + pain_amount = 9 + +/datum/surgery_step/gastrectomy + pain_amount = 20 + +/datum/surgery_step/gastrectomy/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + . = ..() + // Reduces pain from surgery a bit on success + target.cause_pain(target_zone, pain_amount * -1.25, pain_type) + +/datum/surgery_step/gastrectomy/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery) + . = ..() + // Double pain from surgery + target.cause_pain(target_zone, pain_amount, pain_type) + +/datum/surgery_step/heal + pain_amount = 9 + +/datum/surgery_step/hepatectomy + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 20 + +/datum/surgery_step/hepatectomy/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + . = ..() + // Reduces pain from surgery a bit on success + target.cause_pain(target_zone, pain_amount * -1.25, pain_type) + +/datum/surgery_step/hepatectomy/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery) + . = ..() + // Double pain from surgery + target.cause_pain(target_zone, pain_amount, pain_type) + +/datum/surgery_step/extract_implant + pain_amount = 24 + +/datum/surgery_step/cut_fat + pain_amount = 16 + +/datum/surgery_step/lobectomy + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 20 + +/datum/surgery_step/incise + pain_amount = 12 + +/datum/surgery_step/incise/nobleed + pain_amount = 3 + +/datum/surgery_step/clamp_bleeders + pain_amount = 3 + +/datum/surgery_step/retract_skin + pain_amount = 12 + +/datum/surgery_step/close + pain_amount = 12 + pain_type = BURN + +/datum/surgery_step/saw + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + // no pain_amount here because it uses apply_damage, which causes pain + +/datum/surgery_step/drill + pain_amount = 24 + +/datum/surgery_step/reshape_face + pain_amount = 16 + +/datum/surgery_step/repair_innards + pain_amount = 16 + +/datum/surgery_step/stomach_pump + pain_amount = 12 + +/datum/surgery_step/brainwash + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 40 + +/datum/surgery_step/lobotomize + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 40 + +/datum/surgery_step/bionecrosis + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 40 + +/datum/surgery_step/pacify + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 40 + +/datum/surgery_step/viral_bond + pain_amount = 24 + pain_type = BURN + +/datum/surgery_step/wing_reconstruction + pain_amount = 9 + pain_type = BURN + +/datum/surgery_step/fold_cortex + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 40 + +/datum/surgery_step/imprint_cortex + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 40 + +/datum/surgery_step/reshape_ligaments + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 10 + pain_type = BURN + +/datum/surgery_step/reinforce_ligaments + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 10 + pain_type = BURN + +/datum/surgery_step/muscled_veins + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 15 + pain_type = BURN + +/datum/surgery_step/ground_nerves + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 15 + pain_type = BURN + +/datum/surgery_step/splice_nerves + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 15 + pain_type = BURN + +/datum/surgery_step/thread_veins + surgery_moodlet = /datum/mood_event/surgery/major + pain_overlay_severity = 2 + pain_amount = 15 + pain_type = BURN diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/effects.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/effects.dm new file mode 100644 index 000000000000..91f06698b764 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/effects.dm @@ -0,0 +1,109 @@ +// -- Pain effects - mood and modifiers. -- + +/atom/movable/screen/fullscreen/pain + icon = 'monkestation/code/modules/can_spessmen_feel_pain/icons/hud/screen_full.dmi' + icon_state = "painoverlay" + layer = UI_DAMAGE_LAYER + +/mob/living/proc/flash_pain_overlay(severity = 1, time = 1 SECONDS) + if(client?.prefs) + if(client.prefs.read_preference(/datum/preference/toggle/pain_flashes)) + clear_fullscreen("pain", time) + return + overlay_fullscreen("pain", /atom/movable/screen/fullscreen/pain, severity) + clear_fullscreen("pain", time) + +/datum/movespeed_modifier/pain + id = MOVESPEED_ID_PAIN + movetypes = GROUND + +// >= 100 total pain +/datum/movespeed_modifier/pain/light + multiplicative_slowdown = 0.1 + +// >= 200 total pain +/datum/movespeed_modifier/pain/medium + multiplicative_slowdown = 0.2 + +// >= 300 total pain +/datum/movespeed_modifier/pain/heavy + multiplicative_slowdown = 0.35 + +// >= 400 total pain +/datum/movespeed_modifier/pain/crippling + multiplicative_slowdown = 0.5 + +/datum/actionspeed_modifier/pain + id = ACTIONSPEED_ID_PAIN + +// >= 100 total pain +/datum/actionspeed_modifier/pain/light + multiplicative_slowdown = 0.2 + +// >= 200 total pain +/datum/actionspeed_modifier/pain/medium + multiplicative_slowdown = 0.2 + +// >= 300 total pain +/datum/actionspeed_modifier/pain/heavy + multiplicative_slowdown = 0.35 + +// >= 400 total pain +/datum/actionspeed_modifier/pain/crippling + multiplicative_slowdown = 0.5 + +/datum/mood_event/light_pain + description = "Everything aches." + mood_change = -3 + +/datum/mood_event/med_pain + description = "Everything feels sore." + mood_change = -6 + +/datum/mood_event/heavy_pain + description = "Everything hurts!" + mood_change = -10 + +/datum/mood_event/crippling_pain + description = "STOP THE PAIN!" + mood_change = -15 + +// Applied when you go under the knife with anesthesia +/datum/mood_event/anesthetic + description = "Thank science for modern medicine." + mood_change = 2 + timeout = 6 MINUTES + +// Applied by most surgeries if you get operated on without anesthetics +/datum/mood_event/surgery + description = "They're operating on me while I'm awake!" + mood_change = -6 + timeout = 3 MINUTES + +// Applied by some surgeries that are especially bad without anesthetics +/datum/mood_event/surgery/major + description = "THEY'RE CUTTING ME OPEN!!" + mood_change = -10 + timeout = 6 MINUTES + +/atom/movable/screen/alert/numbed + name = "Numbed" + desc = "Your body is numb, painless. You're under the effect of some kind of painkiller." + icon_state = "drugged" + +/datum/mood_event/narcotic_light + description = "I feel numb." + mood_change = 4 + timeout = 3 MINUTES + +/datum/emote/living/carbon/human/scream + +/datum/emote/living/carbon/human/scream/can_run_emote(mob/living/carbon/human/user, status_check, intentional) + if(intentional) + return ..() + + // Cut unintentional screems if they can't feel pain at the moment + if(!user.can_feel_pain()) + return FALSE + + return ..() diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/helpers.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/helpers.dm new file mode 100644 index 000000000000..4444c2f5b763 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/helpers.dm @@ -0,0 +1,154 @@ +// -- Helper procs and hooks for pain. -- +/mob/living + /// The pain controller datum - tracks, processes, and handles pain. + /// Only intialized on humans (currently), here for ease of access / future compatibillity? + var/datum/pain/pain_controller + +/mob/living/Destroy() + QDEL_NULL(pain_controller) + return ..() + +/mob/living/carbon/human/Initialize(mapload) + . = ..() + var/datum/pain/new_pain_controller = new(src) + if(!QDELETED(new_pain_controller)) + pain_controller = new_pain_controller + +/** + * Causes pain to this mob. + * + * Note that most damage causes pain regardless, but this is still useful for direct pain damage + * + * * target_zone - required, which zone or zones to afflict pain to + * * amount - how much pain to inflict + * * dam_type - the type of pain to inflict. Only [BRUTE] and [BURN] really matters. + */ +/mob/living/proc/cause_pain(target_zone, amount, dam_type = BRUTE) + ASSERT(!isnull(target_zone)) + ASSERT(isnum(amount)) + return pain_controller?.adjust_bodypart_pain(target_zone, amount, dam_type) + +/** + * Runs an emote on the pain emote cooldown + * Emote supplied does NOT need to be a pain emote + * + * If no emote is supplied, randomly picks from all pain-related emotes + * + * * emote - what emote key to run + * * cooldown - applies cooldown on doing similar pain related emotes + */ +/mob/living/proc/pain_emote(emote, cooldown) + return pain_controller?.do_pain_emote(emote, cooldown) + +/** + * Runs a pain message on the pain message cooldown + * + * * message - the message to send + * * painless_message - optional, the message to send if the mob does not feel pain + * * cooldown - applies cooldown on doing similar pain messages + */ +/mob/living/proc/pain_message(message, painless_message, cooldown) + return pain_controller?.do_pain_message(message, painless_message, cooldown) + +/** + * Adjust the minimum pain the target zone can experience for a time + * + * This means that the target zone will not be able to go below the specified pain amount + * + * * target_zone - required, which zone to afflict pain to + * * amount - how much min pain to increase + * * time - how long to incease the min pain to + */ +/mob/living/proc/apply_min_pain(target_zone, amount, time) + ASSERT(!isnull(target_zone)) + ASSERT(isnum(amount)) + ASSERT(isnum(time)) + return apply_status_effect(/datum/status_effect/minimum_bodypart_pain, target_zone, amount, time) + +/** + * Sets the pain modifier of [id] to [amount]. + */ +/mob/living/proc/set_pain_mod(id, amount) + ASSERT(isnum(amount)) + ASSERT(istext(id) || ispath(id)) + return pain_controller?.set_pain_modifier(id, amount) + +/** + * Unsets the pain mod at the supplied [id]. + */ +/mob/living/proc/unset_pain_mod(id) + ASSERT(istext(id) || ispath(id)) + return pain_controller?.unset_pain_modifier(id) + +/** + * Checks if this mob can feel pain. + * + * By default mobs cannot feel pain if they have a pain modifier of 0.5 or less. + */ +/mob/living/proc/can_feel_pain() + return pain_controller?.pain_modifier > 0.5 && !HAS_TRAIT(src, TRAIT_NO_PAIN_EFFECTS) + +/** + * Adjusts the progress of pain shock on the current mob. + * + * * amount - the number of ticks of progress to remove. Note that one tick = two seconds for pain. + * * down_to - the minimum amount of pain shock the mob can have. Defaults to -30, giving the mob a buffer against shock. + */ +/mob/living/proc/adjust_pain_shock(amount, down_to = -30) + if(isnull(pain_controller)) + return + if(amount > 0 && HAS_TRAIT(src, TRAIT_NO_SHOCK_BUILDUP)) + return + + ASSERT(isnum(amount)) + pain_controller.shock_buildup = max(pain_controller.shock_buildup + amount, down_to) + +/** + * Cause [amount] of [dam_type] sharp pain to [target_zones]. + * Sharp pain is for sudden spikes of pain that go away after [duration] deciseconds. + * + * * target_zones - requried, one or multiple target zones to apply sharp pain to + * * amount - how much sharp pain to inflict + * * dam_type - the type of sharp pain to inflict. Only [BRUTE] and [BURN] really matters. + * * duration - how long the sharp pain lasts for + */ +/mob/living/proc/sharp_pain(target_zones, amount, dam_type = BRUTE, duration = 1 MINUTES) + if(isnull(pain_controller)) + return + ASSERT(!isnull(target_zones)) + ASSERT(isnum(amount)) + + if(!islist(target_zones)) + target_zones = list(target_zones) + for(var/zone in target_zones) + apply_status_effect(/datum/status_effect/sharp_pain, zone, amount, dam_type, duration) + +/** + * Set [id] pain modifier to [amount], and + * unsets it after [time] deciseconds have elapsed. + */ +/mob/living/proc/set_timed_pain_mod(id, amount, time) + if(isnull(pain_controller)) + return + ASSERT(isnum(amount)) + ASSERT(isnum(time)) + ASSERT(istext(id) || ispath(id)) + if(time <= 0) + // no-op rather than stack trace or anything, so code with variable time can ignore it + return + + set_pain_mod(id, amount) + addtimer(CALLBACK(pain_controller, TYPE_PROC_REF(/datum/pain, unset_pain_modifier), id), time) + +/** + * Returns the bodypart pain of [zone]. + * If [get_modified] is TRUE, returns the bodypart's pain multiplied by any modifiers affecting it. + */ +/mob/living/proc/get_bodypart_pain(target_zone, get_modified = FALSE) + ASSERT(!isnull(target_zone)) + + var/obj/item/bodypart/checked_bodypart = pain_controller?.body_zones[target_zone] + if(isnull(checked_bodypart)) + return 0 + + return get_modified ? checked_bodypart.get_modified_pain() : checked_bodypart.pain diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/item_helpers.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/item_helpers.dm new file mode 100644 index 000000000000..b4c18b0a59de --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/item_helpers.dm @@ -0,0 +1,3 @@ +/obj/item + ///the pain damage we do + var/pain_damage diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/modifiers.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/modifiers.dm new file mode 100644 index 000000000000..3d30c8f8348b --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/modifiers.dm @@ -0,0 +1,125 @@ +// -- Pain modifiers. -- +// Species pain modifiers. +/datum/species/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) + . = ..() + if(isnum(species_pain_mod) && species_pain_mod != 1) + C.set_pain_mod(PAIN_MOD_SPECIES, species_pain_mod) + +/datum/species/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) + . = ..() + C.unset_pain_mod(PAIN_MOD_SPECIES) + +// Eternal youth gives a small bonus pain mod. +/datum/symptom/youth/Activate(datum/disease/advance/A) + . = ..() + if(!.) + return + switch(A.stage) + if(5) + A.affected_mob.set_pain_mod(name, 0.9) + +/datum/symptom/youth/End(datum/disease/advance/A) + . = ..() + if(!.) + return + A.affected_mob.unset_pain_mod(name) + +// Some Traumas + +/datum/brain_trauma/special/tenacity/on_gain() + . = ..() + owner.set_pain_mod(name, 0) + +/datum/brain_trauma/special/tenacity/on_lose() + owner.unset_pain_mod(name) + return ..() + +// Near death experience +/mob/living/carbon/human/set_health(new_value) + . = ..() + if(HAS_TRAIT_FROM(src, TRAIT_KNOCKEDOUT, CRIT_HEALTH_TRAIT)) + src.add_mood_event("near-death", /datum/mood_event/deaths_door) + set_pain_mod(PAIN_MOD_NEAR_DEATH, 0.1) + else + src.clear_mood_event("near-death") + unset_pain_mod(PAIN_MOD_NEAR_DEATH) + +// Stasis gives you a pain modifier and stops pain decay +// +// This is kind of a cop-out, I admit: +// Loigcally, you shouldn't feel any pain on stasis, since all of your body systems are frozen +// However, for balance this kneecaps surgery by making it a no-brainer to use stasis +// +// As a result, I'm opting to add just a "decent" pain modifier instead +/datum/status_effect/grouped/stasis/on_apply() + . = ..() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.set_pain_mod(id, 0.5) + +/datum/status_effect/grouped/stasis/on_remove() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.unset_pain_mod(id) + return ..() + +// Determination gives a hefty pain modifier +/datum/status_effect/determined/on_apply() + . = ..() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.set_pain_mod(id, 0.625) + ADD_TRAIT(owner, TRAIT_NO_PAIN_EFFECTS, TRAIT_STATUS_EFFECT(id)) + ADD_TRAIT(owner, TRAIT_NO_SHOCK_BUILDUP, TRAIT_STATUS_EFFECT(id)) + +/datum/status_effect/determined/on_remove() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.unset_pain_mod(id) + REMOVE_TRAIT(owner, TRAIT_NO_PAIN_EFFECTS, TRAIT_STATUS_EFFECT(id)) + REMOVE_TRAIT(owner, TRAIT_NO_SHOCK_BUILDUP, TRAIT_STATUS_EFFECT(id)) + return ..() + +// Fake healthy is supposed to mimic feeling no pain +/datum/status_effect/grouped/screwy_hud/fake_healthy/on_apply() + . = ..() + ADD_TRAIT(owner, TRAIT_NO_PAIN_EFFECTS, TRAIT_STATUS_EFFECT(id)) + +/datum/status_effect/grouped/screwy_hud/fake_healthy/on_remove() + . = ..() + REMOVE_TRAIT(owner, TRAIT_NO_PAIN_EFFECTS, TRAIT_STATUS_EFFECT(id)) + +// Being drunk gives a slight one, note the actual reagent gives one based on its strength +/datum/status_effect/inebriated/drunk/on_apply() + . = ..() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.set_pain_mod(id, 0.9) + +/datum/status_effect/inebriated/drunk/on_remove() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.unset_pain_mod(id) + return ..() + +// Being drowsy gives a very slight one +/datum/status_effect/drowsiness/on_apply() + . = ..() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.set_pain_mod(id, 0.95) + +/datum/status_effect/drowsiness/on_remove() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.unset_pain_mod(id) + return ..() + +// Reacting to all cases of gaining knocked out rather than just sleeping +/mob/living/on_knockedout_trait_gain(datum/source) + . = ..() + set_pain_mod(PAIN_MOD_KOD, 0.8) + +/mob/living/on_knockedout_trait_loss(datum/source) + . = ..() + unset_pain_mod(PAIN_MOD_KOD) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/pain_assistance_tools.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/pain_assistance_tools.dm new file mode 100644 index 000000000000..57d8200e5b9c --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/pain_assistance_tools.dm @@ -0,0 +1,559 @@ +// -- Implements and equipment to help reduce pain. -- +// Temperature pack stuff - things you can press to people to help reduce pain. +/// Heal rate and modifier for generic items that are frozen. +#define FROZEN_ITEM_PAIN_RATE 1 +#define FROZEN_ITEM_PAIN_MODIFIER 0.5 +#define FROZEN_ITEM_TEMPERATURE_CHANGE -5 + +// Holding a beer to your busted arm, now that's classic +/obj/item/reagent_containers/cup/glass/bottle/beer/Initialize(mapload) + . = ..() + if(reagents.get_reagent_amount(/datum/reagent/consumable/ethanol/beer) > 1) + AddElement(/datum/element/temperature_pack, \ + pain_heal_rate = 0.3, \ + pain_modifier_on_limb = 0.9, \ + temperature_change = -2) + +// Frozen items become usable temperature packs. +/datum/element/frozen/Attach(datum/target) + . = ..() + if(. == ELEMENT_INCOMPATIBLE) + return + if(!isitem(target)) + return + + target.AddElement(/datum/element/temperature_pack, FROZEN_ITEM_PAIN_RATE, FROZEN_ITEM_PAIN_MODIFIER, FROZEN_ITEM_TEMPERATURE_CHANGE) + +/datum/element/frozen/Detach(datum/source, ...) + . = ..() + if(!isitem(source)) + return + + source.RemoveElement(/datum/element/temperature_pack, FROZEN_ITEM_PAIN_RATE, FROZEN_ITEM_PAIN_MODIFIER, FROZEN_ITEM_TEMPERATURE_CHANGE) + +/// Temperature packs (heat packs, cold packs). Apply to hurt limb to un-hurty. +/obj/item/temperature_pack + name = "temperature pack" + desc = "A temperature pack, to soothe pain." + w_class = WEIGHT_CLASS_SMALL + icon = 'monkestation/code/modules/can_spessmen_feel_pain/icons/obj/pain_items.dmi' + lefthand_file = 'monkestation/code/modules/can_spessmen_feel_pain/icons/mob/inhands/pain_items_lhand.dmi' + righthand_file = 'monkestation/code/modules/can_spessmen_feel_pain/icons/mob/inhands/pain_items_rhand.dmi' + icon_state = "cold_pack" + throwforce = 0 + throw_speed = 2 + throw_range = 5 + attack_verb_continuous = list("pads") + attack_verb_simple = list("pads") + /// Whether our pack has been used. + var/used = FALSE + /// Whether our pack is active. + var/active = FALSE + /// The amount of pain that our pack heals when used. + var/pain_heal_amount = 0 + /// The modifier put onto the limb when used. + var/pain_limb_modifier = 1 + /// The change in temperature applied to the user while our pack is in use. + var/temperature_change = 0 + +/obj/item/temperature_pack/Initialize(mapload) + . = ..() + update_appearance() + +/obj/item/temperature_pack/attack_self(mob/user, modifiers) + . = ..() + if(.) + return + + if(used) + return + + used = TRUE + activate_pack(user) + return TRUE + +/obj/item/temperature_pack/examine(mob/user) + . = ..() + if(used) + if(active) + . += span_notice("It's used, but emanating [temperature_change > 0 ? "heat" : "a chill"].") + else + . += span_notice("It's used up and empty.") + else + . += span_notice("Use it in hand to activate the pack, [temperature_change > 0 ? "heating it up" : "cooling it down"].") + +/obj/item/temperature_pack/update_overlays() + . = ..() + if(!used || active) + if(temperature_change > 0) + . += "heat_overlay" + if(active) + . += "active_heat_overlay" + else + . += "cold_overlay" + if(active) + . += "active_cold_overlay" + +/** + * Activate [src] from [user], making it into a temperature pack that can be used, that expires in 5 minutes. + */ +/obj/item/temperature_pack/proc/activate_pack(mob/user) + addtimer(CALLBACK(src, PROC_REF(deactivate_pack)), 5 MINUTES) + to_chat(user, span_notice("You crack [src], [temperature_change > 0 ? "heating it up" : "cooling it down"].")) + AddElement(/datum/element/temperature_pack, pain_heal_amount, pain_limb_modifier, temperature_change) + active = TRUE + update_appearance() + +/** + * Deactivate [src], making it unusable, and sending signal [COMSIG_TEMPERATURE_PACK_EXPIRED]. + */ +/obj/item/temperature_pack/proc/deactivate_pack() + SEND_SIGNAL(src, COMSIG_TEMPERATURE_PACK_EXPIRED) + visible_message(span_notice("[src] fizzles as the last of its [temperature_change > 0 ? "heat" : "chill"] runs out.")) + RemoveElement(/datum/element/temperature_pack, pain_heal_amount, pain_limb_modifier, temperature_change) + active = FALSE + name = "used [name]" + desc = "A used up [name]. It's no use to anyone anymore." + update_appearance() + +// Head packs have a stronger modifier, but heals less. +/obj/item/temperature_pack/heat + name = "heat pack" + desc = "A heat pack. Crack it to turn it on and apply it to an aching limb to reduce joint stress and moderate pain." + temperature_change = 5 + pain_heal_amount = 3.6 + pain_limb_modifier = 0.5 + +// Cold packs heal more, but have a weaker modifier. +/obj/item/temperature_pack/cold + name = "cold pack" + desc = "A cold pack. Crack it on and apply it to a hurt limb to abate sharp pain." + temperature_change = -5 + pain_heal_amount = 6 + pain_limb_modifier = 0.75 + +/obj/item/reagent_containers/pill/aspirin + name = "aspirin pill" + desc = "Used to treat moderate pain and fever. Metabolizes slowly. Best at treating chest pain." + icon_state = "pill7" + list_reagents = list(/datum/reagent/medicine/painkiller/aspirin = 10) // Lasts ~4 minutes, heals ~20 pain in chest (lower in other parts) + rename_with_volume = TRUE + +/obj/item/reagent_containers/syringe/aspirin + name = "syringe (aspirin)" + desc = "Contains fiteen units of aspirin. Used to treat chest pain and fever. Metabolizes slowly." + list_reagents = list(/datum/reagent/medicine/painkiller/aspirin = 15) + +/obj/item/reagent_containers/pill/ibuprofen + name = "ibuprofen pill" + desc = "Used to treat mild pain, headaches, and fever. Metabolizes slowly. Best at treating head pain." + icon_state = "pill8" + list_reagents = list(/datum/reagent/medicine/painkiller/ibuprofen = 10) // Lasts ~4 minutes, heals ~20 pain in head (lower in other parts) + rename_with_volume = TRUE + +/obj/item/reagent_containers/syringe/ibuprofen + name = "syringe (ibuprofen)" + desc = "Contains fiteen units of ibuprofen. Used to treat head pain headaches, and fever. Metabolizes slowly." + list_reagents = list(/datum/reagent/medicine/painkiller/ibuprofen = 15) + +/obj/item/reagent_containers/pill/paracetamol + name = "paracetamol pill" + desc = "Used to treat moderate pain and headaches. Metabolizes slowly. Good as a general painkiller." + icon_state = "pill9" + list_reagents = list(/datum/reagent/medicine/painkiller/paracetamol = 10) // Lasts ~4 minutes, heals ~15 pain per bodypart + rename_with_volume = TRUE + +/obj/item/reagent_containers/syringe/paracetamol + name = "syringe (paracetamol)" + desc = "Contains fiteen units of Paracetamol. Used to treat general pain. Metabolizes slowly." + list_reagents = list(/datum/reagent/medicine/painkiller/paracetamol = 15) + +/obj/item/reagent_containers/pill/morphine/diluted + desc = "Used to treat major to severe pain. Causes moderate drowsiness. Mildly addictive." + icon_state = "pill11" + list_reagents = list(/datum/reagent/medicine/painkiller/morphine = 5) // Lasts ~1 minute, heals ~10 pain per bodypart (~100 pain) // NON-MODULE CHANGE + rename_with_volume = TRUE + +/obj/item/reagent_containers/syringe/morphine + name = "syringe (morphine)" + desc = "Contains three injections of Morphine. Used to treat major to severe pain. Causes moderate drowsiness. Mildly addictive." + list_reagents = list(/datum/reagent/medicine/painkiller/morphine = 15) // NON-MODULE CHANGE + +/obj/item/reagent_containers/pill/oxycodone + name = "oxycodone pill" + desc = "Used to treat severe to extreme pain. Rapid acting, may cause delirium. Very addictive." + icon_state = "pill12" + list_reagents = list(/datum/reagent/medicine/painkiller/oxycodone = 5) // Lasts ~1 minute, heals ~20 pain per bodypart (~200 pain) + rename_with_volume = TRUE + +/obj/item/reagent_containers/syringe/oxycodone + name = "syringe (oxycodone)" + desc = "Contains three injections of Oxycodone. Used to treat severe to extreme pain. Rapid acting, may cause delirium. Very addictive." + list_reagents = list(/datum/reagent/medicine/painkiller/oxycodone = 15) + +/obj/item/reagent_containers/pill/aspirin_para_coffee + name = "aspirin/paracetamol/caffeine pill" + desc = "A mix of Aspirin, Paracetamol and Coffee to produce an effective, but short lasting painkiller with little to no side effects. Do not take multiple at once." + list_reagents = list(/datum/reagent/medicine/painkiller/aspirin_para_coffee = 10) + +/obj/item/storage/pill_bottle/prescription + name = "prescription pill bottle" + desc = "Contains prescription pills." + /// Typepath of pill type to spawn + var/obj/item/reagent_containers/pill/pill_type = null + /// Number of pills to spawn + var/num_pills = 0 + +/obj/item/storage/pill_bottle/prescription/Initialize(mapload) + . = ..() + if(pill_type) + name = "[initial(pill_type.name)] bottle" + if(num_pills) + atom_storage.max_slots = num_pills + atom_storage.max_total_storage = num_pills + +/obj/item/storage/pill_bottle/prescription/PopulateContents() + if(num_pills && pill_type) + for(var/i in 1 to num_pills) + new pill_type(src) + +/obj/item/storage/pill_bottle/painkillers + name = "bottle of painkillers" + desc = "Contains multiple pills used to treat anywhere from mild to extreme pain. CAUTION: Do not take in conjunction with alcohol." + icon = 'monkestation/code/modules/can_spessmen_feel_pain/icons/obj/chemical.dmi' + custom_price = PAYCHECK_CREW * 3 + custom_premium_price = PAYCHECK_CREW * 3 + +/obj/item/storage/pill_bottle/painkillers/Initialize(mapload) + . = ..() + atom_storage.max_slots = 14 + atom_storage.max_total_storage = 14 + +/obj/item/storage/pill_bottle/painkillers/PopulateContents() + for(var/i in 1 to 3) + new /obj/item/reagent_containers/pill/aspirin(src) + for(var/i in 1 to 3) + new /obj/item/reagent_containers/pill/ibuprofen(src) + for(var/i in 1 to 3) + new /obj/item/reagent_containers/pill/paracetamol(src) + for(var/i in 1 to 3) + new /obj/item/reagent_containers/pill/morphine/diluted(src) + for(var/i in 1 to 2) + new /obj/item/reagent_containers/pill/oxycodone(src) + +/obj/item/reagent_containers/hypospray/medipen/morphine + name = "morphine medipen" + desc = "A medipen that contains a dosage of painkilling morphine. \ + WARNING: Do not use in combination with alcohol. Can cause drowsiness and addiction." + icon_state = "morphen" + inhand_icon_state = "morphen" + base_icon_state = "morphen" + list_reagents = list(/datum/reagent/medicine/painkiller/morphine = 10) // Heals ~20 pain (per limb) + +/// Miner pen. Heals about 30 pain to all limbs, causes ~150 addiction points +/obj/item/reagent_containers/hypospray/medipen/survival/painkiller + name = "survival painkiller medipen" + desc = "A medipen that contains a dosage of painkilling chemicals. \ + WARNING: Do not use in combination with alcohol. Can cause drowsiness." + icon = 'monkestation/code/modules/can_spessmen_feel_pain/icons/obj/syringe.dmi' + icon_state = "painkiller_stimpen" + base_icon_state = "painkiller_stimpen" + volume = 30 + amount_per_transfer_from_this = 30 + list_reagents = list( + /datum/reagent/medicine/painkiller/paracetamol = 10, // Heals ~10 pain (per limb) + /datum/reagent/medicine/painkiller/aspirin_para_coffee = 5, // Heals ~7.5 pain (per limb) + /datum/reagent/medicine/painkiller/morphine = 5, // Heals ~10 pain (per limb), causes drowsy + /datum/reagent/medicine/synaptizine = 10, // Cures drowsy from morphine + ) + +/// Medkit pen. Heals about 35 pain to all limbs, causes ~450 addiction points +/obj/item/reagent_containers/hypospray/medipen/emergency_painkiller + name = "emergency painkiller medipen" + desc = "A medipen that contains a dosage of heavy painkilling chemicals. \ + WARNING: Do not use in combination with alcohol. Can cause drowsiness and addiction." + icon = 'monkestation/code/modules/can_spessmen_feel_pain/icons/obj/syringe.dmi' + icon_state = "painkiller" + base_icon_state = "painkiller" + volume = 25 + amount_per_transfer_from_this = 25 + list_reagents = list( + /datum/reagent/medicine/painkiller/oxycodone = 7.5, // Heals ~25 pain (per limb) + /datum/reagent/medicine/painkiller/morphine = 5, // Heals ~10 pain (per limb), causes drowsy + /datum/reagent/medicine/synaptizine = 10, // Cures drowsyness from morphine + ) + +/obj/item/reagent_containers/hypospray/medipen/brute_painkiller + name = "ibaltifen painkiller medipen" + desc = "An autoinjector containing ibaltifen, used to treat pain caused by bruises and broken limbs. WARNING: Do not use in combination with alcohol." + icon = 'monkestation/code/modules/can_spessmen_feel_pain/icons/obj/syringe.dmi' + icon_state = "burn_painkiller_pen" + base_icon_state = "burn_painkiller_pen" + inhand_icon_state = "salacid" + list_reagents = list(/datum/reagent/medicine/painkiller/specialized/ibaltifen = 10) // ~20-25 pain healing (if brute pain, per limb) + +/obj/item/reagent_containers/hypospray/medipen/burn_painkiller + name = "anurifen painkiller medipen" + desc = "An autoinjector containing anurifen, used to treat pain caused by bruises and broken limbs. WARNING: Do not use in combination with alcohol." + icon = 'monkestation/code/modules/can_spessmen_feel_pain/icons/obj/syringe.dmi' + icon_state = "brute_painkiller_pen" + base_icon_state = "brute_painkiller_pen" + inhand_icon_state = "oxapen" + list_reagents = list(/datum/reagent/medicine/painkiller/specialized/anurifen = 10) // ~20-25 pain healing (if burn pain, per limb) + +/datum/armor/shock_blanket + laser = 20 + energy = 20 + bomb = 20 + bio = 10 + fire = 100 + acid = 50 + +/** + * Shock blanket item. Hit someone to cover them with the blanket. + * If they lie down and stay still, it will regulate their body temperature. + */ +/obj/item/shock_blanket + name = "shock blanket" + desc = "A metallic looking plastic blanket specifically designed to well insulate anyone seeking comfort underneath." + icon = 'monkestation/code/modules/can_spessmen_feel_pain/icons/obj/pain_items.dmi' + worn_icon = 'monkestation/code/modules/can_spessmen_feel_pain/icons/mob/pain_items.dmi' + lefthand_file = 'monkestation/code/modules/can_spessmen_feel_pain/icons/mob/inhands/pain_items_lhand.dmi' + righthand_file = 'monkestation/code/modules/can_spessmen_feel_pain/icons/mob/inhands/pain_items_rhand.dmi' + icon_state = "shockblanket" + base_icon_state = "shockblanket" + worn_icon_state = "shockblanket" + drop_sound = 'sound/items/handling/cloth_drop.ogg' + pickup_sound = 'sound/items/handling/cloth_pickup.ogg' + w_class = WEIGHT_CLASS_SMALL + slot_flags = ITEM_SLOT_OCLOTHING + body_parts_covered = CHEST + resistance_flags = FIRE_PROOF + heat_protection = CHEST|GROIN|LEGS|ARMS + cold_protection = CHEST|GROIN|LEGS|ARMS + max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT + armor_type = /datum/armor/shock_blanket + equip_delay_self = 3 SECONDS + equip_delay_other = 2 SECONDS + slowdown = 1.5 + throwforce = 0 + throw_speed = 1 + throw_range = 2 + custom_price = PAYCHECK_CREW * 2 + +/obj/item/shock_blanket/Initialize(mapload) + . = ..() + if(prob(5)) + name = pick("space blanket", "safety blanket") + + AddElement(/datum/element/bed_tuckable, 0, 0, 0) + AddElement(/datum/element/attack_equip) + +/obj/item/shock_blanket/examine(mob/user) + . = ..() + . += span_notice("To use: Apply to a patient experiencing shock or loss of body temperature. Keep patient still and lying down for maximum effect.") + +/obj/item/shock_blanket/attack_self(mob/user, modifiers) + . = ..() + if(.) + return + if(!user.dropItemToGround(src)) + return + + var/obj/structure/bed/bed_below = locate(/obj/structure/bed) in loc + to_chat(user, span_notice("You lay out [src] on [bed_below ? "[bed_below]" : "the floor"].")) + icon_state = "[initial(icon_state)]_dropped" + layer = MOB_LAYER + +/obj/item/shock_blanket/equipped(mob/user, slot) + . = ..() + if(!isliving(user)) + return + + if(slot_flags & slot) + RegisterSignal(user, list(COMSIG_LIVING_SET_BODY_POSITION, COMSIG_LIVING_SET_BUCKLED), PROC_REF(check_protection)) + RegisterSignal(user, list(COMSIG_QDELETING, COMSIG_MOVABLE_PRE_MOVE), PROC_REF(disable_protection)) + try_enable(user) + +/obj/item/shock_blanket/dropped(mob/user, silent) + . = ..() + disable_protection(user) + UnregisterSignal(user, list(COMSIG_LIVING_SET_BODY_POSITION, COMSIG_LIVING_SET_BUCKLED, COMSIG_QDELETING, COMSIG_MOVABLE_PRE_MOVE)) + + if(locate(/obj/structure/bed) in loc) + icon_state = "[base_icon_state]_dropped" + layer = MOB_LAYER + +/obj/item/shock_blanket/pickup(mob/user) + . = ..() + icon_state = base_icon_state + layer = initial(layer) + +/// If we can enable protection, does so. Returns true on success. +/obj/item/shock_blanket/proc/try_enable(mob/living/source) + if(source.body_position == LYING_DOWN || source.buckled) + enable_protection(source) + return TRUE + return FALSE + +/** + * Check if we should be recieving temperature protection. + * We only give protection if we're lying down or buckled - if we're moving, we don't get anything. + */ +/obj/item/shock_blanket/proc/check_protection(mob/living/source) + SIGNAL_HANDLER + + if(try_enable(source)) + return + + disable_protection(source) + +/** + * Enable the temperature protection. + */ +/obj/item/shock_blanket/proc/enable_protection(mob/living/source) + if(istype(source) && !(datum_flags & DF_ISPROCESSING)) + var/temp_change = "warmer" + if(source.bodytemperature > source.get_body_temp_normal(apply_change = FALSE)) + temp_change = "colder" + + to_chat(source, span_notice("You feel [temp_change] as [src] begins regulating your body temperature.")) + START_PROCESSING(SSobj, src) + +/** + * Disable the temperature protection. + */ +/obj/item/shock_blanket/proc/disable_protection(mob/living/source) + SIGNAL_HANDLER + + if(istype(source) && (datum_flags & DF_ISPROCESSING)) + var/temp_change = "freezing" + if(source.bodytemperature > source.get_body_temp_normal(apply_change = FALSE)) + temp_change = "hotter" + + to_chat(source, span_notice("You feel [temp_change] again as [src] stops regulating your body temperature.")) + + STOP_PROCESSING(SSobj, src) + +/obj/item/shock_blanket/process(seconds_per_tick) + var/mob/living/carbon/wearer = loc + if(!istype(wearer)) + disable_protection() + return + + var/target_temp = wearer.get_body_temp_normal(apply_change = FALSE) + if(wearer.bodytemperature > target_temp) + wearer.adjust_bodytemperature(-8 * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, target_temp) + else if(wearer.bodytemperature < (target_temp + 1)) + wearer.adjust_bodytemperature(8 * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, target_temp) + if(ishuman(wearer)) + var/mob/living/carbon/human/human_wearer = wearer + if(human_wearer.coretemperature > target_temp) + human_wearer.adjust_coretemperature(-8 * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, target_temp) + else if(human_wearer.coretemperature < (target_temp + 1)) + human_wearer.adjust_coretemperature(8 * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, 0, target_temp) + +/obj/item/shock_blanket/emergency + desc = "An emergency variant shock blanket intended to be placed in medkits for field treatment. Faster to apply to patients, but more restrictive to movement." + slowdown = 2.5 + equip_delay_self = 1.2 SECONDS + equip_delay_other = 1.2 SECONDS + +/obj/item/shock_blanket/emergency/Initialize(mapload) + . = ..() + name = "emergency [name]" + +// Change the contents of first-aid kids. +/obj/item/storage/medkit/emergency/Initialize(mapload) + . = ..() + atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL + atom_storage.max_slots = 12 + atom_storage.max_total_storage = 16 + +/obj/item/storage/medkit/emergency/PopulateContents() + if(empty) + return + var/static/list/items_inside = list( + /obj/item/healthanalyzer/simple = 1, + /obj/item/stack/medical/gauze = 1, + /obj/item/stack/medical/suture/emergency = 1, + /obj/item/stack/medical/ointment = 1, + /obj/item/reagent_containers/hypospray/medipen/ekit = 2, + /obj/item/reagent_containers/hypospray/medipen/emergency_painkiller = 2, + /obj/item/storage/pill_bottle/iron = 1, + /obj/item/shock_blanket/emergency = 1, + ) + generate_items_inside(items_inside, src) + +/obj/item/storage/medkit/regular/PopulateContents() + if(empty) + return + var/static/list/items_inside = list( + /obj/item/stack/medical/gauze = 1, + /obj/item/stack/medical/suture = 2, + /obj/item/stack/medical/mesh = 2, + /obj/item/reagent_containers/hypospray/medipen = 1, + /obj/item/reagent_containers/hypospray/medipen/morphine = 1, + ) + generate_items_inside(items_inside, src) + +/obj/item/storage/medkit/brute/PopulateContents() + if(empty) + return + var/static/list/items_inside = list( + /obj/item/reagent_containers/pill/patch/libital = 3, + /obj/item/stack/medical/gauze = 1, + /obj/item/storage/pill_bottle/probital = 1, + /obj/item/reagent_containers/hypospray/medipen/salacid = 1, + /obj/item/reagent_containers/hypospray/medipen/brute_painkiller = 1, + ) + generate_items_inside(items_inside, src) + +/obj/item/storage/medkit/fire/PopulateContents() + if(empty) + return + var/static/list/items_inside = list( + /obj/item/reagent_containers/pill/patch/aiuri = 3, + /obj/item/reagent_containers/spray/hercuri = 1, + /obj/item/stack/medical/ointment = 1, + /obj/item/reagent_containers/hypospray/medipen/oxandrolone = 1, + /obj/item/reagent_containers/hypospray/medipen/burn_painkiller = 1, + ) + generate_items_inside(items_inside, src) + +/obj/item/storage/medkit/advanced/PopulateContents() + if(empty) + return + var/static/list/items_inside = list( + /obj/item/reagent_containers/pill/patch/synthflesh = 3, + /obj/item/storage/pill_bottle/prescription/aspirin_para_coffee = 1, + /obj/item/reagent_containers/hypospray/medipen/atropine = 2, + /obj/item/stack/medical/gauze = 1, + /obj/item/storage/pill_bottle/penacid = 1 + ) + generate_items_inside(items_inside, src) + +// Pain implements added to various vendors. +/obj/machinery/vending/drugs + products_monke = list( + /obj/item/storage/pill_bottle/painkillers = 2, + ) + +/obj/machinery/vending/medical + products_monke = list( + /obj/item/shock_blanket/emergency = 3, + /obj/item/temperature_pack/cold = 2, + /obj/item/temperature_pack/heat = 2, + ) + +/obj/machinery/vending/wallmed + products_monke = list( + /obj/item/shock_blanket/emergency = 2, + /obj/item/temperature_pack/cold = 1, + /obj/item/temperature_pack/heat = 1, + ) + +#undef FROZEN_ITEM_PAIN_RATE +#undef FROZEN_ITEM_PAIN_MODIFIER +#undef FROZEN_ITEM_TEMPERATURE_CHANGE diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/pain_goodies.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/pain_goodies.dm new file mode 100644 index 000000000000..8a37b388760d --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/pain_goodies.dm @@ -0,0 +1,3 @@ +/obj/item/storage/pill_bottle/prescription/aspirin_para_coffee + pill_type = /obj/item/reagent_containers/pill/aspirin_para_coffee + num_pills = 3 diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/preferences.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/preferences.dm new file mode 100644 index 000000000000..5e5d3ff76e12 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/preferences.dm @@ -0,0 +1,13 @@ +/datum/preference/toggle/pain_flashes + category = PREFERENCE_CATEGORY_GAME_PREFERENCES + savefile_key = "pain_flashes" + savefile_identifier = PREFERENCE_PLAYER + + default_value = FALSE + +/datum/preference/toggle/pain_messages + category = PREFERENCE_CATEGORY_GAME_PREFERENCES + savefile_key = "pain_messages" + savefile_identifier = PREFERENCE_PLAYER + + default_value = FALSE diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/modified_reagents.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/modified_reagents.dm new file mode 100644 index 000000000000..fa0289905d61 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/modified_reagents.dm @@ -0,0 +1,175 @@ +// -- Reagents that modify pain. -- +/datum/reagent + /// Modifier applied by this reagent to the mob's pain. + /// This is both a multiplicative modifier to their overall received pain, + /// and an additive modifier to their per tick pain decay rate. + var/pain_modifier = null + +/datum/reagent/on_mob_metabolize(mob/living/carbon/user) + . = ..() + // hi melbert, this should have SHOULD_CALL_PARENT(TRUE) + if(isnull(pain_modifier) || !istype(user)) + return + + if(user.set_pain_mod("[PAIN_MOD_CHEMS]-[name]", pain_modifier) && !user.can_feel_pain()) + // If the painkiller's strong enough give them an alert + user.throw_alert("numbed", /atom/movable/screen/alert/numbed) + +/datum/reagent/on_mob_end_metabolize(mob/living/carbon/user) + . = ..() + if(isnull(pain_modifier) || !istype(user)) + return + user.unset_pain_mod("[PAIN_MOD_CHEMS]-[name]") + +/datum/reagent/on_mob_delete(mob/living/L) + . = ..() + if(!isnull(pain_modifier) && L.can_feel_pain()) + L.clear_alert("numbed") + +// Muscle stimulant is functionally morphine without downsides (it's rare) +/datum/reagent/medicine/muscle_stimulant + pain_modifier = 0.5 + +// Epinephrine helps pain very very slightly and helps against shock +/datum/reagent/medicine/epinephrine + pain_modifier = 0.9 + +/datum/reagent/medicine/epinephrine/on_mob_metabolize(mob/living/carbon/M) + ..() + ADD_TRAIT(M, TRAIT_ABATES_SHOCK, type) + +/datum/reagent/medicine/epinephrine/on_mob_end_metabolize(mob/living/carbon/M) + REMOVE_TRAIT(M, TRAIT_ABATES_SHOCK, type) + ..() + +/datum/reagent/medicine/epinephrine/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) + . = ..() + affected_mob.adjust_pain_shock(-1) + +// Atropine fills a simliar niche to epinephrine +/datum/reagent/medicine/atropine + pain_modifier = 0.8 + +/datum/reagent/medicine/atropine/on_mob_metabolize(mob/living/carbon/M) + ..() + ADD_TRAIT(M, TRAIT_ABATES_SHOCK, type) + +/datum/reagent/medicine/atropine/on_mob_end_metabolize(mob/living/carbon/M) + REMOVE_TRAIT(M, TRAIT_ABATES_SHOCK, type) + ..() + +/datum/reagent/medicine/atropine/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) + . = ..() + affected_mob.adjust_pain_shock(-2) + +// Miner's salve is described as a good painkiller +/datum/reagent/medicine/mine_salve + pain_modifier = 0.66 + +// Determined = fight or flight mode = should have less pain +/datum/reagent/determination + pain_modifier = 0.8 + +// Drugs reduce pain +/datum/reagent/drug/space_drugs + pain_modifier = 0.8 + +/datum/reagent/toxin/fentanyl + pain_modifier = 0.5 + +/datum/reagent/drug/cocaine + pain_modifier = 0.4 + +//Alcohol reduces pain based on boozepwr +/datum/reagent/consumable/ethanol/New() + if(boozepwr && isnull(pain_modifier)) + var/new_pain_modifier = 12 / (boozepwr * 0.2) + if(new_pain_modifier < 1) + pain_modifier = new_pain_modifier + return ..() + +/datum/reagent/consumable/ethanol/painkiller + pain_modifier = 0.75 + +// Abductor chem sets pain mod to 0 so abductors can do their surgeries +/datum/reagent/medicine/cordiolis_hepatico + pain_modifier = 0 + +// Healium functions as an anesthetic +/datum/reagent/healium + pain_modifier = 0.75 + +/datum/reagent/healium/on_mob_metabolize(mob/living/L) + . = ..() + L.apply_status_effect(/datum/status_effect/grouped/anesthetic, name) + +/datum/reagent/healium/on_mob_end_metabolize(mob/living/L) + . = ..() + L.remove_status_effect(/datum/status_effect/grouped/anesthetic, name) + +// Nitrous Oxide can apply some anesthetic, like the gas +/datum/reagent/nitrous_oxide + pain_modifier = 0.75 + +/datum/reagent/nitrous_oxide/on_mob_metabolize(mob/living/carbon/user) + . = ..() + RegisterSignal(user, SIGNAL_ADDTRAIT(TRAIT_KNOCKEDOUT), PROC_REF(apply_anesthetic)) + RegisterSignal(user, SIGNAL_REMOVETRAIT(TRAIT_KNOCKEDOUT), PROC_REF(remove_anesthetic)) + if(HAS_TRAIT(user, TRAIT_KNOCKEDOUT)) + apply_anesthetic(user) + +/datum/reagent/nitrous_oxide/on_mob_end_metabolize(mob/living/carbon/user) + . = ..() + UnregisterSignal(user, list(SIGNAL_ADDTRAIT(TRAIT_KNOCKEDOUT), SIGNAL_REMOVETRAIT(TRAIT_KNOCKEDOUT))) + remove_anesthetic(user) + +/datum/reagent/nitrous_oxide/proc/apply_anesthetic(mob/living/carbon/source) + SIGNAL_HANDLER + source.apply_status_effect(/datum/status_effect/grouped/anesthetic, type) + +/datum/reagent/nitrous_oxide/proc/remove_anesthetic(mob/living/carbon/source) + SIGNAL_HANDLER + source.remove_status_effect(/datum/status_effect/grouped/anesthetic, type) + +// Cryoxadone slowly heals pain, like wounds. +// It also helps against shock, sort of. +/datum/reagent/medicine/cryoxadone/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) + . = ..() + if(!.) + return + var/power = -0.00003 * (affected_mob.bodytemperature ** 2) + 3 + + ADD_TRAIT(affected_mob, TRAIT_ABATES_SHOCK, type) // To negate the fact that being cold is bad for shock + affected_mob.set_pain_mod(type, 0.5) // Heal pain faster + affected_mob.cause_pain(BODY_ZONES_ALL, -0.5 * power * REM * seconds_per_tick) + affected_mob.adjust_pain_shock(-power * REM * seconds_per_tick) + +/datum/reagent/medicine/cryoxadone/on_mob_end_metabolize(mob/living/carbon/user) + . = ..() + user.unset_pain_mod(type) + REMOVE_TRAIT(user, TRAIT_ABATES_SHOCK, type) + +// Saline glucose helps shock +/datum/reagent/medicine/salglu_solution/on_mob_metabolize(mob/living/carbon/M) + . = ..() + ADD_TRAIT(M, TRAIT_ABATES_SHOCK, type) + +/datum/reagent/medicine/salglu_solution/on_mob_end_metabolize(mob/living/carbon/M) + REMOVE_TRAIT(M, TRAIT_ABATES_SHOCK, type) + return ..() + +// Combat stimulants help against pain +/datum/reagent/medicine/stimulants + pain_modifier = 0.5 + +/datum/reagent/medicine/changelingadrenaline + pain_modifier = 0.5 + +// Diphenhydrame helps against disgust slightly +/datum/reagent/medicine/diphenhydramine/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + . = ..() + M.adjust_disgust(-3 * REM * seconds_per_tick ) + +/datum/reagent/consumable/laughter/on_mob_metabolize(mob/living/carbon/user) + pain_modifier = pick(0.8, 1, 1, 1, 1, 1.2) + return ..() diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/painkiller_related.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/painkiller_related.dm new file mode 100644 index 000000000000..5a763b6da3b7 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/painkiller_related.dm @@ -0,0 +1,50 @@ +// These chems are related to painkillers tangentially + +// Component in ibuprofen. +/datum/reagent/propionic_acid + name = "Propionic Acid" + description = "A pungent liquid that's often used in preservatives and synthesizing of other chemicals." + reagent_state = LIQUID + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + color = "#c7a9c9" + ph = 7 + +// Diphenhydramine can be upgraded into Dimenhydrinate, less good against allergens but better against nausea +/datum/reagent/medicine/dimenhydrinate + name = "Dimenhydrinate" + description = "Helps combat nausea and motion sickness." + reagent_state = LIQUID + color = "#98ffee" + metabolization_rate = 0.5 * REAGENTS_METABOLISM + ph = 10.6 + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + +/datum/reagent/medicine/dimenhydrinate/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + . = ..() + M.adjust_disgust(-8 * REM * seconds_per_tick) + if(M.nutrition > NUTRITION_LEVEL_FULL - 25) // Boosts hunger to a bit, assuming you've been vomiting + M.adjust_nutrition(2 * HUNGER_FACTOR * REM * seconds_per_tick) + +/datum/chemical_reaction/medicine/dimenhydrinate + results = list(/datum/reagent/medicine/dimenhydrinate = 3) + required_reagents = list(/datum/reagent/medicine/diphenhydramine = 1, /datum/reagent/nitrogen = 1, /datum/reagent/chlorine = 1) + optimal_ph_max = 12.5 + reaction_tags = REACTION_TAG_MODERATE | REACTION_TAG_HEALING | REACTION_TAG_OTHER | REACTION_TAG_DRUG + +// Good against nausea, easier to make than Dimenhydrinate +/datum/reagent/medicine/ondansetron + name = "Ondansetron" + description = "Prevents nausea and vomiting." + reagent_state = LIQUID + color = "#74d3ff" + metabolization_rate = 0.5 * REAGENTS_METABOLISM + ph = 10.6 + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + +/datum/reagent/medicine/ondansetron/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + . = ..() + if(SPT_PROB(8, seconds_per_tick)) + M.adjust_drowsiness(2 SECONDS * REM * seconds_per_tick) + if(SPT_PROB(15, seconds_per_tick) && M.get_bodypart_pain(BODY_ZONE_HEAD) <= PAIN_HEAD_MAX / 4) + M.cause_pain(BODY_ZONE_HEAD, 4) + M.adjust_disgust(-10 * REM * seconds_per_tick) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/painkillers.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/painkillers.dm new file mode 100644 index 000000000000..a217837a0e06 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/reagents/painkillers.dm @@ -0,0 +1,481 @@ + +/datum/chemical_reaction/medicine/ondansetron + results = list(/datum/reagent/medicine/ondansetron = 3) + required_reagents = list(/datum/reagent/fuel/oil = 1, /datum/reagent/nitrogen = 1, /datum/reagent/oxygen = 1) + required_catalysts = list(/datum/reagent/consumable/ethanol = 3) + optimal_ph_max = 11 + reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_OTHER | REACTION_TAG_DRUG + +/datum/chemical_reaction/medicine/aspirin + results = list(/datum/reagent/medicine/painkiller/aspirin = 3) + required_reagents = list(/datum/reagent/medicine/sal_acid = 1, /datum/reagent/acetone = 1, /datum/reagent/oxygen = 1) + required_catalysts = list(/datum/reagent/toxin/acid = 1) + reaction_tags = REACTION_TAG_MODERATE | REACTION_TAG_HEALING | REACTION_TAG_OTHER | REACTION_TAG_DRUG + +/datum/chemical_reaction/medicine/paracetamol + results = list(/datum/reagent/medicine/painkiller/paracetamol = 5) + required_reagents = list(/datum/reagent/phenol = 1, /datum/reagent/acetone = 1, /datum/reagent/hydrogen = 1, /datum/reagent/oxygen = 1, /datum/reagent/toxin/acid/nitracid = 1) + optimal_temp = 480 + reaction_tags = REACTION_TAG_MODERATE | REACTION_TAG_HEALING | REACTION_TAG_OTHER | REACTION_TAG_DRUG + +/datum/chemical_reaction/medicine/ibuprofen + results = list(/datum/reagent/medicine/painkiller/ibuprofen = 5) + required_reagents = list(/datum/reagent/propionic_acid = 1, /datum/reagent/phenol = 1, /datum/reagent/oxygen = 1, /datum/reagent/hydrogen = 1) + reaction_tags = REACTION_TAG_MODERATE | REACTION_TAG_HEALING | REACTION_TAG_OTHER | REACTION_TAG_DRUG + +/datum/chemical_reaction/propionic_acid + results = list(/datum/reagent/propionic_acid = 3) + required_reagents = list(/datum/reagent/carbon = 1, /datum/reagent/oxygen = 1, /datum/reagent/hydrogen = 1) + required_catalysts = list(/datum/reagent/toxin/acid = 1) + is_cold_recipe = TRUE + required_temp = 250 + optimal_temp = 200 + overheat_temp = 50 + reaction_tags = REACTION_TAG_EASY | REACTION_TAG_CHEMICAL + +/datum/chemical_reaction/medicine/aspirin_para_coffee + results = list(/datum/reagent/medicine/painkiller/aspirin_para_coffee = 3) + required_reagents = list(/datum/reagent/medicine/painkiller/aspirin = 1, /datum/reagent/medicine/painkiller/paracetamol = 1, /datum/reagent/consumable/coffee = 1) + optimal_ph_min = 2 + optimal_ph_max = 12 + reaction_tags = REACTION_TAG_MODERATE | REACTION_TAG_HEALING | REACTION_TAG_OTHER | REACTION_TAG_DRUG + +/datum/chemical_reaction/medicine/ibaltifen + results = list(/datum/reagent/medicine/painkiller/specialized/ibaltifen = 3) + required_reagents = list(/datum/reagent/propionic_acid = 1, /datum/reagent/chlorine = 1, /datum/reagent/copper = 1) + required_catalysts = list(/datum/reagent/medicine/c2/libital = 1) + reaction_tags = REACTION_TAG_MODERATE | REACTION_TAG_HEALING | REACTION_TAG_OTHER | REACTION_TAG_DRUG + +/datum/chemical_reaction/medicine/anurifen + results = list(/datum/reagent/medicine/painkiller/specialized/anurifen = 3) + required_reagents = list(/datum/reagent/propionic_acid= 1, /datum/reagent/fluorine = 1, /datum/reagent/phosphorus = 1) + required_catalysts = list(/datum/reagent/medicine/c2/aiuri = 1) + reaction_tags = REACTION_TAG_MODERATE | REACTION_TAG_HEALING | REACTION_TAG_OTHER | REACTION_TAG_DRUG + +// Not really reactions, but I'm leaving these here +// Gain oxycodone from juicing poppies +/obj/item/food/grown/poppy + juice_results = list(/datum/reagent/medicine/painkiller/oxycodone = 0) + +/obj/item/food/grown/poppy/geranium + juice_results = list() + +/obj/item/food/grown/poppy/lily + juice_results = list() + +// Painkillers! They help with pain. +/datum/reagent/medicine/painkiller + name = "prescription painkiller" + +/datum/reagent/medicine/painkiller/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + . = ..() + + // Painkillers make you numb. + if(current_cycle >= 5) + switch(pain_modifier) + if(0 to 0.45) + M.add_mood_event("numb", /datum/mood_event/narcotic_heavy, name) + if(0.45 to 0.55) + M.add_mood_event("numb", /datum/mood_event/narcotic_medium, name) + else + M.add_mood_event("numb", /datum/mood_event/narcotic_light, name) + + // However, drinking with painkillers is toxic. + var/highest_boozepwr = 0 + for(var/datum/reagent/consumable/ethanol/alcohol in M.reagents.reagent_list) + if(alcohol.boozepwr > highest_boozepwr) + highest_boozepwr = alcohol.boozepwr + + if(highest_boozepwr > 0) + M.apply_damage(round(highest_boozepwr / 33, 0.5) * REM * seconds_per_tick, TOX) + . = TRUE + +// Morphine is the well known existing painkiller. +// It's very strong but makes you sleepy. Also addictive. +/datum/reagent/medicine/painkiller/morphine + name = "Morphine" + description = "A painkiller that allows the patient to move at full speed even when injured. \ + Causes drowsiness and eventually unconsciousness in high doses. \ + Overdose causes minor dizziness and jitteriness." + reagent_state = LIQUID + color = "#A9FBFB" + metabolization_rate = 0.5 * REAGENTS_METABOLISM // 0.1 units per second + overdose_threshold = 30 + ph = 8.96 + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/opioids = 30) //5u = 100 progress, 25-30u = addiction + // Morphine is THE painkiller + pain_modifier = 0.4 + +/datum/reagent/medicine/painkiller/morphine/on_mob_metabolize(mob/living/L) + . = ..() + L.add_movespeed_mod_immunities(type, /datum/movespeed_modifier/damage_slowdown) + +/datum/reagent/medicine/painkiller/morphine/on_mob_end_metabolize(mob/living/L) + L.remove_movespeed_mod_immunities(type, /datum/movespeed_modifier/damage_slowdown) + return ..() + +/datum/reagent/medicine/painkiller/morphine/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + // Morphine heals a very tiny bit + M.adjustBruteLoss(-0.2 * REM * seconds_per_tick, FALSE) + M.adjustFireLoss(-0.1 * REM * seconds_per_tick, FALSE) + // Morphine heals pain, dur + M.cause_pain(BODY_ZONES_ALL, -2.5) + // Morphine causes a bit of disgust + if(M.disgust < DISGUST_LEVEL_VERYGROSS && SPT_PROB(50 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_disgust(2 * REM * seconds_per_tick) + + // The longer we're metabolzing it, the more we get sleepy + // for reference: (with 0.1 metabolism rate) + // ~2.5 units = 12 cycles = ~30 seconds + switch(current_cycle) + if(64) //~12 + to_chat(M, span_warning("You start to feel tired...")) + M.adjust_eye_blur(2 SECONDS * REM * seconds_per_tick) // just a hint teehee + if(prob(50)) + M.emote("yawn") + + if(96 to 144) // 20 to 30u + if(SPT_PROB(33, seconds_per_tick)) + M.adjust_drowsiness_up_to(1 * REM * seconds_per_tick, 6 SECONDS) + + if(144 to 192) // 30u to 40u + if(SPT_PROB(66, seconds_per_tick)) + M.adjust_drowsiness_up_to(1 * REM * seconds_per_tick, 12 SECONDS) + + if(192 to INFINITY) //40u onward + M.adjust_drowsiness_up_to(1 * REM * seconds_per_tick, 20 SECONDS) + M.Sleeping(4 SECONDS * REM * seconds_per_tick) + + ..() + return TRUE + +/datum/reagent/medicine/painkiller/morphine/overdose_process(mob/living/M, seconds_per_tick, times_fired) + ..() + if(SPT_PROB(18, seconds_per_tick)) + M.drop_all_held_items() + M.set_dizzy_if_lower(4 SECONDS) + M.set_jitter_if_lower(4 SECONDS) + +// Aspirin. Bad at headaches, good at everything else, okay at fevers. +// Use healing chest and limb pain primarily. +/datum/reagent/medicine/painkiller/aspirin + name = "Aspirin" + description = "A medication that combats pain and fever. Can cause mild nausea. Overdosing is toxic, and causes high body temperature, sickness, hallucinations, dizziness, and confusion." + reagent_state = LIQUID + color = "#9c46ff" + metabolization_rate = 0.25 * REAGENTS_METABOLISM + overdose_threshold = 25 + ph = 6.4 + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + pain_modifier = 0.6 + +/datum/reagent/medicine/painkiller/aspirin/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + // Not good at headaches, but very good at treating everything else. + M.adjustBruteLoss(-0.1 * REM * seconds_per_tick, FALSE) + M.adjustFireLoss(-0.05 * REM * seconds_per_tick, FALSE) + // Numbers seem low, but our metabolism is very slow + M.cause_pain(BODY_ZONE_HEAD, -0.08 * REM * seconds_per_tick) + M.cause_pain(BODY_ZONES_LIMBS, -0.16 * REM * seconds_per_tick) + M.cause_pain(BODY_ZONE_CHEST, -0.32 * REM * seconds_per_tick) + // Okay at fevers. + M.adjust_bodytemperature(-15 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, M.get_body_temp_normal()) + if(M.disgust < DISGUST_LEVEL_VERYGROSS && SPT_PROB(66 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_disgust(1.5 * REM * seconds_per_tick) + + ..() + return TRUE + +/datum/reagent/medicine/painkiller/aspirin/overdose_process(mob/living/carbon/M, seconds_per_tick, times_fired) + if(!istype(M)) + return + + // On overdose, heat up the body... + M.adjust_bodytemperature(30 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick) + // Causes sickness... + M.apply_damage(1 * REM * seconds_per_tick, TOX) + if(M.disgust < 100 && SPT_PROB(100 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_disgust(3 * REM * seconds_per_tick) + // ...Hallucinations after a while... + if(current_cycle >= 15 && SPT_PROB(75 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_hallucinations_up_to(6 SECONDS * REM * seconds_per_tick, 40 SECONDS) + // ...Dizziness after a longer while... + if(current_cycle >= 20 && SPT_PROB(50 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_dizzy_up_to(2 SECONDS * REM * seconds_per_tick, 10 SECONDS) + // ...And finally, confusion + if(current_cycle >= 25 && SPT_PROB(30 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_confusion_up_to(4 SECONDS, 12 SECONDS) + ..() + return TRUE + +// Paracetamol. Okay at headaches, okay at everything else, bad at fevers, less disgust. +// Use for general healing every type of pain. +/datum/reagent/medicine/painkiller/paracetamol // Also known as Acetaminophen, or Tylenol + name = "Paracetamol" + description = "A painkiller that combats mind to moderate pain, headaches, and low fever. Causes mild nausea. Overdosing causes liver damage, sickness, and can be lethal." + reagent_state = LIQUID + color = "#fcaeff" + metabolization_rate = 0.25 * REAGENTS_METABOLISM + overdose_threshold = 25 + ph = 4.7 + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + pain_modifier = 0.6 + +/datum/reagent/medicine/painkiller/paracetamol/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + // Good general painkiller. + // Numbers seem lowish, but our metabolism is very slow + M.adjustBruteLoss(-0.05 * REM * seconds_per_tick, FALSE) + M.adjustFireLoss(-0.05 * REM * seconds_per_tick, FALSE) + M.adjustToxLoss(-0.05 * REM * seconds_per_tick, FALSE) + M.cause_pain(BODY_ZONES_ALL, -0.2 * REM * seconds_per_tick) + // Not very good at treating fevers. + M.adjust_bodytemperature(-10 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, M.get_body_temp_normal()) + // Causes liver damage - higher dosages causes more liver damage. + M.adjustOrganLoss(ORGAN_SLOT_LIVER, volume / 30 * REM * seconds_per_tick) + if(M.disgust < DISGUST_LEVEL_VERYGROSS && SPT_PROB(66 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_disgust(1.2 * REM * seconds_per_tick) + + ..() + return TRUE + +/datum/reagent/medicine/painkiller/paracetamol/overdose_process(mob/living/carbon/M, seconds_per_tick, times_fired) + if(!istype(M)) + return + + // On overdose, cause sickness and liver damage. + M.adjustOrganLoss(ORGAN_SLOT_LIVER, 2 * REM * seconds_per_tick) + if(M.disgust < 100 && SPT_PROB(100 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_disgust(3 * REM * seconds_per_tick) + + return ..() + +// Ibuprofen. Best at headaches, best at fevers, less good at everything else. +// Use for treating head pain primarily. +/datum/reagent/medicine/painkiller/ibuprofen // Also known as Advil + name = "Ibuprofen" + description = "A medication that combats mild pain, headaches, and fever. Causes mild nausea and dizziness in higher dosages. Overdosing causes sickness, drowsiness, dizziness, and mild pain." + reagent_state = LIQUID + color = "#e695ff" + metabolization_rate = 0.25 * REAGENTS_METABOLISM + overdose_threshold = 30 + ph = 5.6 + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + pain_modifier = 0.6 + +/datum/reagent/medicine/painkiller/ibuprofen/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + // Really good at treating headaches. + M.adjustBruteLoss(-0.05 * REM * seconds_per_tick, FALSE) + M.adjustToxLoss(-0.1 * REM * seconds_per_tick, FALSE) + // Heals pain, numbers seem low but our metabolism is very slow + M.cause_pain(BODY_ZONE_HEAD, -0.32 * REM * seconds_per_tick) + M.cause_pain(BODY_ZONE_CHEST, -0.16 * REM * seconds_per_tick) + M.cause_pain(BODY_ZONES_LIMBS, -0.08 * REM * seconds_per_tick) + // Causes flat liver damage. + M.adjustOrganLoss(ORGAN_SLOT_LIVER, 0.25 * REM * seconds_per_tick) + // Really good at treating fevers. + M.adjust_bodytemperature(-25 * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, M.get_body_temp_normal()) + // Causes more disgust the longer it's in someone... + if(M.disgust < DISGUST_LEVEL_VERYGROSS && SPT_PROB(66 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_disgust(min(current_cycle * 0.02, 2.4) * REM * seconds_per_tick) + // ...and dizziness. + if(current_cycle >= 25 && SPT_PROB(30 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_dizzy_up_to(2 SECONDS * REM * seconds_per_tick, 10 SECONDS) + + ..() + return TRUE + +/datum/reagent/medicine/painkiller/ibuprofen/overdose_process(mob/living/carbon/M, seconds_per_tick, times_fired) + if(!istype(M)) + return + + // On overdose, causes liver damage and chest pain... + M.adjustOrganLoss(ORGAN_SLOT_LIVER, 1.5 * REM * seconds_per_tick) + M.cause_pain(BODY_ZONE_CHEST, 0.24 * REM * seconds_per_tick) + // Sickness... + if(M.disgust < 100 && SPT_PROB(100 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_disgust(3 * REM * seconds_per_tick) + // ...Drowsyness... + if(SPT_PROB(75 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_drowsiness(2 SECONDS * REM * seconds_per_tick) + // ...And dizziness + if(SPT_PROB(85 * max(1 - creation_purity, 0.5), seconds_per_tick)) + M.adjust_dizzy(4 SECONDS * REM * seconds_per_tick) + + return ..() + +// Combination drug of other painkillers. It's a real thing. Less side effects, heals pain generally, mildly toxic in high doses. +// Upgrade to paracetamol and aspirin if you go through the effort to get coffee. +/datum/reagent/medicine/painkiller/aspirin_para_coffee + name = "aspirin/paracetamol/caffeine" + description = "A combination drug that effectively treats moderate pain with low side effects when used in low dosage. Toxic in higher dosages." + reagent_state = LIQUID + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + color = "#e695ff" + metabolization_rate = REAGENTS_METABOLISM + pain_modifier = 0.75 + +/datum/reagent/medicine/painkiller/aspirin_para_coffee/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + // Heals all pain a bit if in low dosage. + if(volume <= 10) + // Number looks high, compared to other painkillers, + // but we have a comparatively much higher metabolism than them. + M.cause_pain(BODY_ZONES_ALL, -2.8 * REM * seconds_per_tick) + // Mildly toxic in higher dosages. + else if(SPT_PROB(volume * 3, seconds_per_tick)) + M.apply_damage(3 * REM * seconds_per_tick, TOX) + . = TRUE + + ..() + +// Oxycodone. Very addictive, heals pain very fast, also a drug. +/datum/reagent/medicine/painkiller/oxycodone + name = "Oxycodone" + description = "A drug that rapidly treats major to extreme pain. Highly addictive. Overdose can cause heart attacks." + reagent_state = LIQUID + color = "#ffcb86" + metabolization_rate = 0.5 * REAGENTS_METABOLISM + overdose_threshold = 30 + ph = 5.6 + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/opioids = 45) //5u = 150 progress, 15-20u = addiction + pain_modifier = 0.35 + +/datum/reagent/medicine/painkiller/oxycodone/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + M.adjustBruteLoss(-0.3 * REM * seconds_per_tick, FALSE) + M.adjustFireLoss(-0.2 * REM * seconds_per_tick, FALSE) + M.cause_pain(BODY_ZONES_ALL, -3.4 * REM * seconds_per_tick) + M.set_drugginess(20 SECONDS * REM * seconds_per_tick) + if(M.disgust < DISGUST_LEVEL_VERYGROSS && SPT_PROB(40, seconds_per_tick)) + M.adjust_disgust(2 * REM * seconds_per_tick) + if(SPT_PROB(33, seconds_per_tick)) + M.adjust_dizzy_up_to(2 SECONDS * REM * seconds_per_tick, 10 SECONDS) + + ..() + return TRUE + +/datum/reagent/medicine/painkiller/oxycodone/overdose_process(mob/living/carbon/M, seconds_per_tick, times_fired) + . = ..() + if(!ishuman(M)) + return + + var/mob/living/carbon/human/human_mob = M + if(SPT_PROB(12, seconds_per_tick)) + var/can_heart_fail = (!human_mob.undergoing_cardiac_arrest() && human_mob.can_heartattack()) + var/picked_option = rand(1, (can_heart_fail ? 6 : 3)) + switch(picked_option) + if(1) + to_chat(human_mob, span_danger("Your legs don't want to move.")) + human_mob.Paralyze(6 SECONDS * REM * seconds_per_tick) + if(2) + to_chat(human_mob, span_danger("Your breathing starts to shallow.")) + human_mob.losebreath = clamp(human_mob.losebreath + 3 * REM * seconds_per_tick, 0, 12) + human_mob.apply_damage((15 / creation_purity), OXY) + if(3) + human_mob.drop_all_held_items() + if(4) + to_chat(human_mob, span_danger("You feel your heart skip a beat.")) + human_mob.set_jitter_if_lower(6 SECONDS * REM * seconds_per_tick) + if(5) + to_chat(human_mob, span_danger("You feel the world spin.")) + human_mob.set_dizzy_if_lower(6 SECONDS * REM * seconds_per_tick) + if(6) + to_chat(human_mob, span_userdanger("You feel your heart seize and stop completely!")) + if(human_mob.stat == CONSCIOUS) + human_mob.visible_message(span_userdanger("[human_mob] clutches at [human_mob.p_their()] chest as if [human_mob.p_their()] heart stopped!"), ignored_mobs = human_mob) + human_mob.emote("scream") + human_mob.set_heartattack(TRUE) + metabolization_rate *= 4 + return TRUE + +/datum/reagent/medicine/painkiller/hydromorphone + name = "Hydromorphone" + description = "Pretty sure you wouldn't be able to feel anything" + reagent_state = LIQUID + color = "#ffcb86" + metabolization_rate = 0.5 * REAGENTS_METABOLISM + pain_modifier = 0.1 + +/datum/reagent/medicine/painkiller/hydromorphone/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + M.cause_pain(BODY_ZONES_ALL, -12 * REM * seconds_per_tick) + ..() + +// Future painkiller ideas: +// - Real world stuff +// Tramadol +// Fentanyl (Rework) (Also a potential anesthetic) +// Hydrocodone (And its combination drugs) +// Dihydromorphine +// Pethidine +// - Space stuff (Suffix: -fen) + +// A subtype of painkillers that will heal pain better +// depending on what type of pain the part's feeling +/datum/reagent/medicine/painkiller/specialized + name = "specialized painkiller" + addiction_types = list(/datum/addiction/opioids = 15) //5u = 50 progress, 60u = addiction + + /// How much pain we restore on life ticks, modified by modifiers (yeah?) + var/pain_heal_amount = 2.4 + /// What type of pain are we looking for? If we aren't experiencing this type, it will be 10x less effective + var/pain_type_to_look_for + /// What type of wound are we looking for? If our bodypart has this wound, it will be 1.5x more effective + var/wound_type_to_look_for + +/datum/reagent/medicine/painkiller/specialized/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + . = ..() + if(!M.pain_controller) + return + + for(var/obj/item/bodypart/part as anything in M.bodyparts) + if(!IS_ORGANIC_LIMB(part)) + continue + + var/final_pain_heal_amount = -1 * pain_heal_amount * REM * seconds_per_tick + if(pain_type_to_look_for && (part.last_received_pain_type != pain_type_to_look_for)) + final_pain_heal_amount *= 0.1 + if(wound_type_to_look_for && (locate(wound_type_to_look_for) in part.wounds)) + final_pain_heal_amount *= 1.5 + + M.cause_pain(part.body_zone, final_pain_heal_amount) + +// Libital, but helps pain: ib-alti-fen +// Heals lots of pain for bruise pain, otherwise lower +/datum/reagent/medicine/painkiller/specialized/ibaltifen + name = "Ibaltifen" + description = "A painkiller designed to combat pain caused by broken limbs and bruises." + reagent_state = LIQUID + color = "#feffae" + metabolization_rate = 0.5 * REAGENTS_METABOLISM + ph = 7.9 + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + pain_modifier = 0.75 + pain_type_to_look_for = BRUTE + wound_type_to_look_for = /datum/wound/blunt + +/datum/reagent/medicine/painkiller/specialized/ibaltifen/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + // a bit of libital influence + M.adjustOrganLoss(ORGAN_SLOT_LIVER, 0.5 * REM * seconds_per_tick) + M.adjustBruteLoss(-0.5 * REM * normalise_creation_purity() * seconds_per_tick) + ..() + return TRUE + +// Aiuri, but helps pain: an-uri-fen +// Heals lots of pain for burn pain, otherwise lower +/datum/reagent/medicine/painkiller/specialized/anurifen + name = "Anurifen" + description = "A painkiller designed to combat pain caused by burns." + reagent_state = LIQUID + color = "#c4aeff" + metabolization_rate = 0.5 * REAGENTS_METABOLISM + ph = 3.6 + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + pain_modifier = 0.75 + pain_type_to_look_for = BURN + wound_type_to_look_for = /datum/wound/burn + +/datum/reagent/medicine/painkiller/specialized/anurifen/on_mob_life(mob/living/carbon/M, seconds_per_tick, times_fired) + // a bit of aiuri influence + M.adjustOrganLoss(ORGAN_SLOT_EYES, 0.4 * REM * seconds_per_tick) + M.adjustFireLoss(-0.5 * REM * normalise_creation_purity() * seconds_per_tick) + ..() + return TRUE diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm new file mode 100644 index 000000000000..279d14a9262b --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/shock.dm @@ -0,0 +1,207 @@ +// -- Shock from too much pain. -- +/datum/disease/advanced/premade/shock + form = "Condition" + name = "Shock" + spread_text = "Neurogenic" // Only model pain shock + category = DISEASE_SHOCK + max_stages = 3 + stage_prob = 1 + cure_text = "Keep the patient still and lying down, maintain a high body temperature, stop blood loss, \ + and provide pain relievers while monitoring closely. Epinephrine and Saline-Glucose can also help." + agent = "Pain" + viable_mobtypes = list(/mob/living/carbon/human) + desc = "Occurs when a subject enters a state of shock due to high pain, blood loss, heart difficulties, and other injuries. \ + If left untreated, the subject may experience cardiac arrest." + severity = DISEASE_SEVERITY_DANGEROUS + disease_flags = NONE + spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS + visibility_flags = HIDDEN_PANDEMIC + bypasses_immunity = TRUE + /// How many conditions do we require to get cured? + var/conditions_required_to_cure = 4 + /// How many conditions do we need to not get a heart attack? + var/conditions_required_to_maintain = 3 + +/datum/disease/advanced/premade/shock/after_add() + affected_mob.apply_status_effect(/datum/status_effect/low_blood_pressure) + affected_mob.set_pain_mod(type, 1.2) + antigen = null + +/** + * Checks which cure conditions we fulfill. + * + * returns the total number of conditions we fulfill. + */ +/datum/disease/advanced/premade/shock/proc/check_cure_conditions() + if(!ishuman(affected_mob)) + return TRUE + var/mob/living/carbon/human = affected_mob + if(human.undergoing_cardiac_arrest()) + return FALSE + if(affected_mob.stat == DEAD) + return FALSE + + // We require [conditions_required_to_cure] of these to be fulfilled to be cured + var/conditions_fulfilled = 0 + + // Good: Body temperature is stable (not freezing, we don't care about heat) + if(affected_mob.bodytemperature > affected_mob.get_body_temp_cold_damage_limit()) + conditions_fulfilled += 1 + // Good: Sleeping (or unconscious I guess) + if(affected_mob.IsSleeping() || affected_mob.IsUnconscious()) + conditions_fulfilled += 1 + // Good: Having this trait (from salgu or epinephrine) + if(HAS_TRAIT(affected_mob, TRAIT_ABATES_SHOCK)) + conditions_fulfilled += 1 + // Good: Having lower pain + switch(affected_mob.pain_controller.get_average_pain()) + if(-INFINITY to 10) + // Almost guarantees you fulfill enough conditions if you get this low, assuming you have no major detractors + // Why? It might confuse some people if the person's like, not experiencing any pain at all + // but for some reason is still in shock, because they haven't done one of the other conditions arbitrarily + conditions_fulfilled += (conditions_required_to_cure + 1) + if(10 to 30) + conditions_fulfilled += 3 + if(30 to 40) + conditions_fulfilled += 2 + if(40 to 50) + conditions_fulfilled += 1 + + // Good: Painkillers (while conscious / in soft crit) + if(affected_mob.stat <= SOFT_CRIT && !affected_mob.can_feel_pain()) + conditions_fulfilled += 1 + + // Bad: Bleeding + if(human.is_bleeding()) + conditions_fulfilled -= 1 + // Very bad: Wounds + conditions_fulfilled -= min(LAZYLEN(human.all_wounds), 4) + // Somewhat bad: Standing up + if(affected_mob.body_position == STANDING_UP) + conditions_fulfilled -= 2 + // Bad: In deepcrit (dying) + if(affected_mob.stat > SOFT_CRIT) + conditions_fulfilled -= 1 + + return conditions_fulfilled + +/datum/disease/advanced/premade/shock/cure(add_resistance, mob/living/carbon/target) + affected_mob.remove_status_effect(/datum/status_effect/low_blood_pressure) + affected_mob.unset_pain_mod(type) + return ..() + +/datum/disease/advanced/premade/shock/activate(seconds_per_tick, times_fired) + . = ..() + if(!ishuman(affected_mob)) + return + + if(check_cure_conditions() >= conditions_required_to_cure) + cure() + return + var/mob/living/carbon/human = affected_mob + if(!.) + return + + if(isnull(affected_mob.pain_controller)) + cure() + return FALSE + + if(affected_mob.stat == DEAD) + cure() + return FALSE + + var/cure_level = check_cure_conditions() + testing("[affected_mob] undergoing shock: [cure_level] cure conditions achieved.") + + // Having a few cure conditions present ([conditions_required_to_maintain]) will keep us below stage 3 + if(stage > 2 && cure_level >= conditions_required_to_maintain) + update_stage(2) + + // If we have enough conditions present to cure us, roll for a cure + if(stage <= 2 && has_cure(cure_level) && SPT_PROB(cure_level, seconds_per_tick)) + to_chat(affected_mob, span_bold(span_green("Your body feels awake and active again!"))) + cure() + return FALSE + + switch(stage) + // compensated (or nonprogressive) - still able to sustain themselves + // - agitation, anxiety + // - nausea or vomiting + // - chills + if(1) + cure_text = "Subject is in stage one of shock. \ + Provide immediate pain relief and stop blood loss to prevent worsening condition. \ + Keep the patient still and lying down, and be sure to moderate their temprature. \ + Supply epinephrine and saline-glucose if condition worsens." + if(SPT_PROB(0.5, seconds_per_tick)) + to_chat(affected_mob, span_danger("Your chest feels uncomfortable.")) + affected_mob.pain_emote(pick("mumble", "grumble")) + affected_mob.flash_pain_overlay(1) + if(SPT_PROB(1, seconds_per_tick)) + to_chat(affected_mob, span_danger("You feel nauseous.")) + if(prob(50)) + affected_mob.vomit(35) + if(SPT_PROB(2, seconds_per_tick)) + to_chat(affected_mob, span_danger("You feel anxious.")) + affected_mob.adjust_jitter(rand(12 SECONDS, 16 SECONDS)) + if(SPT_PROB(6, seconds_per_tick)) + to_chat(affected_mob, span_danger("You feel cold.")) + affected_mob.pain_emote("shiver", 3 SECONDS) + affected_mob.adjust_bodytemperature(-5 * seconds_per_tick, affected_mob.get_body_temp_cold_damage_limit() + 5) // Not lethal + + // decompensated (or progressive) - unable to maintain themselves + // - mental issues + // - difficulty breathing / high heart rate + // - decrease in body temperature + if(2) + cure_text = "Subject is in stage one of shock. \ + Provide immediate pain relief and stop blood loss to prevent cardiac arrest. \ + Keep the patient still and lying down, and be sure to moderate their temprature. \ + Supply epinephrine and saline-glucose if condition worsens." + + if(SPT_PROB(10, seconds_per_tick)) + affected_mob.adjust_stutter_up_to(10 SECONDS, 120 SECONDS) + if(SPT_PROB(1, seconds_per_tick)) + to_chat(affected_mob, span_danger("Your chest feels wrong!")) + affected_mob.pain_emote(pick("mumble", "grumble")) + affected_mob.flash_pain_overlay(2) + if(SPT_PROB(2, seconds_per_tick)) + to_chat(affected_mob, span_danger("You can't focus on anything!")) + affected_mob.adjust_confusion(rand(4 SECONDS, 8 SECONDS)) + if(SPT_PROB(2, seconds_per_tick)) + to_chat(affected_mob, span_danger("You're having difficulties breathing!")) + affected_mob.losebreath = clamp(affected_mob.losebreath + 4, 0, 12) + if(SPT_PROB(2, seconds_per_tick)) + to_chat(affected_mob, span_danger("You skip a breath!")) + affected_mob.pain_emote("gasp", 3 SECONDS) + affected_mob.apply_damage(rand(5, 15), OXY) + if(SPT_PROB(1, seconds_per_tick)) + affected_mob.emote("faint") + if(SPT_PROB(8, seconds_per_tick)) + to_chat(affected_mob, span_danger("You feel freezing!")) + affected_mob.pain_emote("shiver", 3 SECONDS) + affected_mob.adjust_bodytemperature(-10 * seconds_per_tick, affected_mob.get_body_temp_cold_damage_limit() - 5) // uh oh + + // irreversible - point of no return, system failure + // cardiac arrest + if(3) + cure_text = "Subject is in stage three of shock. Cardiac arrest is imminent - urgent action is needed. \ + Prepare a defibrillator on standby and moderate their body temperature." + if(SPT_PROB(10, seconds_per_tick)) + affected_mob.adjust_stutter_up_to(10 SECONDS, 120 SECONDS) + if(SPT_PROB(8, seconds_per_tick)) + affected_mob.adjust_slurring_up_to(10 SECONDS, 36 SECONDS) + if(SPT_PROB(2, seconds_per_tick)) + affected_mob.emote("faint") + if(SPT_PROB(33, seconds_per_tick)) + if(human.can_heartattack()) + to_chat(affected_mob, span_userdanger("Your heart stops!")) + affected_mob.visible_message(span_danger("[affected_mob] grabs at their chest and collapses!"), ignored_mobs = affected_mob) + human.set_heartattack(TRUE) + cure() + return FALSE + else + affected_mob.losebreath += 10 + else if(SPT_PROB(10, seconds_per_tick)) + to_chat(affected_mob, span_userdanger(pick("You feel your heart skip a beat...", "You feel your body shutting down...", "You feel your heart beat irregularly..."))) + affected_mob.adjust_bodytemperature(-10 * seconds_per_tick, affected_mob.get_body_temp_cold_damage_limit() - 20) // welp diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/species.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/species.dm new file mode 100644 index 000000000000..9a1c06ef3bbb --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/species.dm @@ -0,0 +1,4 @@ +/// -- Extensions of species and species procs. -- +/datum/species + /// Pain modifier that this species receives. + var/species_pain_mod = 1 diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/anesthetics.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/anesthetics.dm new file mode 100644 index 000000000000..03f24a52b8a0 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/anesthetics.dm @@ -0,0 +1,42 @@ +/// Anesthetics, for use in surgery - to stop pain. +/datum/status_effect/grouped/anesthetic + id = "anesthetics" + alert_type = /atom/movable/screen/alert/status_effect/anesthetics + +/datum/status_effect/grouped/anesthetic/on_creation(mob/living/new_owner, source) + if(!istype(get_area(new_owner), /area/station/medical)) + // if we're NOT in medical, give no alert. N2O floods or whatever. + alert_type = null + + return ..() + +/datum/status_effect/grouped/anesthetic/on_apply() + . = ..() + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_KNOCKEDOUT), PROC_REF(try_removal)) + +/datum/status_effect/grouped/anesthetic/on_remove() + . = ..() + UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_KNOCKEDOUT)) + +/datum/status_effect/grouped/anesthetic/get_examine_text() + return span_warning("[owner.p_Theyre()] out cold.") + +/datum/status_effect/grouped/anesthetic/proc/try_removal(datum/source) + SIGNAL_HANDLER + + if(HAS_TRAIT(owner, TRAIT_KNOCKEDOUT)) + return + + qdel(src) + +/atom/movable/screen/alert/status_effect/anesthetics + name = "Anesthetic" + desc = "Everything's woozy... The world goes dark... You're on anesthetics. \ + Good luck in surgery! If it's actually surgery, that is." + icon_state = "paralysis" + +// Extend "too much N2O" so we can apply anesthesia if it knocks the guy out +/obj/item/organ/internal/lungs/too_much_n2o(mob/living/carbon/breather, datum/gas_mixture/breath, n2o_pp, old_n2o_pp) + . = ..() + if(HAS_TRAIT(breather, TRAIT_KNOCKEDOUT)) + breather.apply_status_effect(/datum/status_effect/grouped/anesthetic, /datum/gas/nitrous_oxide) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/fire_pain.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/fire_pain.dm new file mode 100644 index 000000000000..b359a5a477b6 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/fire_pain.dm @@ -0,0 +1,42 @@ +/// Handler for pain from fire. Goes up the longer you're on fire, largely goes away when extinguished +/datum/status_effect/pain_from_fire + id = "sharp_pain_from_fire" + status_type = STATUS_EFFECT_REFRESH + alert_type = null + remove_on_fullheal = TRUE + heal_flag_necessary = HEAL_ADMIN|HEAL_WOUNDS|HEAL_STATUS + + /// Amount of pain being given + var/pain_amount = 0 + +/datum/status_effect/pain_from_fire/on_creation(mob/living/new_owner, pain_amount = 0) + src.pain_amount = pain_amount + return ..() + +/datum/status_effect/pain_from_fire/refresh(mob/living/new_owner, added_pain_amount = 0) + if(added_pain_amount <= 0) + return + pain_amount += added_pain_amount + owner.cause_pain(BODY_ZONES_ALL, added_pain_amount, BURN) + +/datum/status_effect/pain_from_fire/on_apply() + if(isnull(owner.pain_controller) || pain_amount <= 0) + return FALSE + + RegisterSignal(owner, COMSIG_LIVING_EXTINGUISHED, PROC_REF(remove_on_signal)) + owner.cause_pain(BODY_ZONES_ALL, pain_amount, BURN) + return TRUE + +/datum/status_effect/pain_from_fire/on_remove() + if(QDELING(owner)) + return + UnregisterSignal(owner, COMSIG_LIVING_EXTINGUISHED) + owner.cause_pain(BODY_ZONES_ALL, -3 * pain_amount, BURN) + +/// When signalled, terminate. +/datum/status_effect/pain_from_fire/proc/remove_on_signal(datum/source) + SIGNAL_HANDLER + + if(QDELING(owner) || QDELING(src)) + return + qdel(src) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/low_blood_pressure.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/low_blood_pressure.dm new file mode 100644 index 000000000000..30b1d0f40592 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/low_blood_pressure.dm @@ -0,0 +1,21 @@ +/datum/status_effect/low_blood_pressure + id = "low_blood_pressure" + tick_interval = -1 + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/low_blood_pressure + +/datum/status_effect/low_blood_pressure/on_apply() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.physiology.bleed_mod *= 0.75 + return TRUE + +/datum/status_effect/low_blood_pressure/on_remove() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.physiology.bleed_mod /= 0.75 + +/atom/movable/screen/alert/status_effect/low_blood_pressure + name = "Low blood pressure" + desc = "Your blood pressure is low right now. Your organs aren't getting enough blood." + icon_state = "highbloodpressure" diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/min_pain.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/min_pain.dm new file mode 100644 index 000000000000..27fd47b70c97 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/min_pain.dm @@ -0,0 +1,50 @@ +/// A handler for temporarily increasing the minimum amount of pain a bodypart can be in. +/datum/status_effect/minimum_bodypart_pain + id = "min_bodypart_pain" + status_type = STATUS_EFFECT_MULTIPLE + alert_type = null + remove_on_fullheal = TRUE + heal_flag_necessary = HEAL_ADMIN|HEAL_WOUNDS|HEAL_STATUS + + /// The min pain we're setting the bodypart to + var/min_amount = 0 + /// The zone we're afflicting + var/targeted_zone = BODY_ZONE_CHEST + +/datum/status_effect/minimum_bodypart_pain/on_creation( + mob/living/carbon/human/new_owner, + targeted_zone, + min_amount = 0, + duration = 0, +) + + src.duration = duration + src.targeted_zone = targeted_zone + src.min_amount = min_amount + return ..() + +/datum/status_effect/minimum_bodypart_pain/on_apply() + if(!ishuman(owner)) + return FALSE + + var/mob/living/carbon/human/human_owner = owner + if(!human_owner.pain_controller) + return FALSE + + if(!targeted_zone || min_amount == 0) + return FALSE + + var/obj/item/bodypart/afflicted_bodypart = human_owner.pain_controller.body_zones[targeted_zone] + if(!afflicted_bodypart) + return FALSE + + human_owner.pain_controller.adjust_bodypart_min_pain(targeted_zone, min_amount) + return TRUE + +/datum/status_effect/minimum_bodypart_pain/on_remove() + var/mob/living/carbon/human/human_owner = owner + var/obj/item/bodypart/afflicted_bodypart = human_owner.pain_controller?.body_zones[targeted_zone] + if(!afflicted_bodypart) + return + + human_owner.pain_controller.adjust_bodypart_min_pain(targeted_zone, -min_amount) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/pain_limp.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/pain_limp.dm new file mode 100644 index 000000000000..fb2110254ccb --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/pain_limp.dm @@ -0,0 +1,68 @@ +/// Limping from extreme pain in the legs. +/datum/status_effect/limp/pain + id = "limp_pain" + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/limp/pain + remove_on_fullheal = TRUE + heal_flag_necessary = HEAL_ADMIN|HEAL_WOUNDS|HEAL_STATUS + +/datum/status_effect/limp/pain/on_creation(mob/living/new_owner, obj/item/bodypart/next_leg) + src.next_leg = next_leg + return ..() + +/datum/status_effect/limp/pain/on_apply() + . = ..() + if(!.) + return + + var/mob/living/carbon/human/owner_human = owner + if(!owner_human) + return FALSE + if(!istype(owner_human) || isnull(owner_human?.pain_controller)) + return FALSE + + RegisterSignals(owner, list(COMSIG_CARBON_PAIN_GAINED, COMSIG_CARBON_PAIN_LOST), PROC_REF(update_limp)) + owner.pain_message( + span_danger("Your [next_leg?.plaintext_zone || "leg"] hurts to walk on!"), + span_danger("You struggle to walk on your [next_leg?.plaintext_zone || "leg"]!"), + ) + +/datum/status_effect/limp/pain/get_examine_text() + return span_warning("[owner.p_Theyre()] limping with every move.") + +/datum/status_effect/limp/pain/on_remove() + . = ..() + UnregisterSignal(owner, list(COMSIG_CARBON_PAIN_GAINED, COMSIG_CARBON_PAIN_LOST)) + if(!QDELING(owner)) + owner.pain_message( + span_green("Your pained limp stops!"), + span_green("It becomes easier to walk again."), + ) + +/datum/status_effect/limp/pain/update_limp() + var/mob/living/carbon/human/limping_human = owner + + left = limping_human.pain_controller.body_zones[BODY_ZONE_L_LEG] + right = limping_human.pain_controller.body_zones[BODY_ZONE_R_LEG] + + if(!left && !right) + qdel(src) + return + + slowdown_left = 0 + slowdown_right = 0 + + if(left?.get_modified_pain() >= 30) + slowdown_left = left.get_modified_pain() / 10 + + if(right?.get_modified_pain() >= 30) + slowdown_right = right.get_modified_pain() / 10 + + // this handles losing your leg with the limp and the other one being in good shape as well + if(slowdown_left < 3 && slowdown_right < 3) + qdel(src) + return + +/atom/movable/screen/alert/status_effect/limp/pain + name = "Pained Limping" + desc = "The pain in your legs is unbearable, forcing you to limp!" diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/sharp_pain.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/sharp_pain.dm new file mode 100644 index 000000000000..d9dfb9c8023c --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/sharp_pain.dm @@ -0,0 +1,61 @@ +/// Sharp pain. Used for a lot of pain at once, as a little of it is healed after the effect runs out. +/datum/status_effect/sharp_pain + id = "sharp_pain" + status_type = STATUS_EFFECT_MULTIPLE + alert_type = null + remove_on_fullheal = TRUE + heal_flag_necessary = HEAL_ADMIN|HEAL_WOUNDS|HEAL_STATUS + + /// Amount of pain being given + var/pain_amount = 0 + /// Type of pain being given + var/pain_type + /// The amount of pain we had before recieving the sharp pain + var/initial_pain_amount = 0 + /// The zone we're afflicting + var/targeted_zone + +/datum/status_effect/sharp_pain/on_creation( + mob/living/carbon/human/new_owner, + targeted_zone, + pain_amount = 0, + pain_type = BRUTE, + duration = 0, +) + + src.duration = duration + src.targeted_zone = targeted_zone + src.pain_amount = pain_amount + src.pain_type = pain_type + return ..() + +/datum/status_effect/sharp_pain/on_apply() + if(!ishuman(owner)) + return FALSE + + var/mob/living/carbon/human/human_owner = owner + if(!human_owner.pain_controller) + return FALSE + + if(!targeted_zone || pain_amount == 0) + return FALSE + + var/obj/item/bodypart/afflicted_bodypart = human_owner.pain_controller.body_zones[targeted_zone] + if(!afflicted_bodypart) + return FALSE + + initial_pain_amount = afflicted_bodypart.pain + human_owner.pain_controller.adjust_bodypart_pain(targeted_zone, pain_amount, pain_type) + return TRUE + +/datum/status_effect/sharp_pain/on_remove() + var/mob/living/carbon/human/human_owner = owner + var/obj/item/bodypart/afflicted_bodypart = human_owner.pain_controller?.body_zones[targeted_zone] + if(!afflicted_bodypart) + return + + var/healed_amount = pain_amount * -0.33 + if((afflicted_bodypart.pain + healed_amount) < initial_pain_amount) + healed_amount = initial_pain_amount - afflicted_bodypart.pain + + human_owner.pain_controller.adjust_bodypart_pain(targeted_zone, healed_amount, pain_type) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/temp_pack.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/temp_pack.dm new file mode 100644 index 000000000000..bc5f230aff60 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/status_effects/temp_pack.dm @@ -0,0 +1,171 @@ +/// Status effects applied when pressing a hot or cold item onto a bodypart, to soothe pain. +/datum/status_effect/temperature_pack + id = "temp_pack" + status_type = STATUS_EFFECT_MULTIPLE + on_remove_on_mob_delete = TRUE + tick_interval = 5 SECONDS + processing_speed = STATUS_EFFECT_NORMAL_PROCESS + alert_type = null + /// The item we're using to heal pain. + var/obj/item/pressed_item + /// The mob holding the [pressed_item] to [owner]. Can be [owner]. + var/mob/living/holder + /// The zone we're healing. + var/targeted_zone = BODY_ZONE_CHEST + /// The amount we heal per tick. Positive number. + var/pain_heal_amount = 0 + /// The pain modifier placed on the limb. + var/pain_modifier = 1 + /// The change in temperature while applied. + var/temperature_change = 0 + +/datum/status_effect/temperature_pack/on_creation( + mob/living/new_owner, + mob/living/holder, + obj/item/pressed_item, + targeted_zone = BODY_ZONE_CHEST, + pain_heal_amount = 0, + pain_modifier = 1, + temperature_change = 0, +) + + src.holder = holder + src.pressed_item = pressed_item + src.targeted_zone = targeted_zone + src.pain_heal_amount = pain_heal_amount + src.pain_modifier = pain_modifier + src.temperature_change = temperature_change + return ..() + +/datum/status_effect/temperature_pack/on_apply() + if(!ishuman(owner)) + return FALSE + + var/mob/living/carbon/human/human_owner = owner + if(!human_owner.pain_controller || human_owner.stat == DEAD) + return FALSE + + if(QDELETED(pressed_item)) + return FALSE + + if(QDELETED(holder)) + return FALSE + + for(var/datum/status_effect/temperature_pack/pre_existing_effect in owner.status_effects) + if(pre_existing_effect == src) + continue + if(pre_existing_effect.targeted_zone == targeted_zone) + return FALSE + + var/obj/item/bodypart/held_bodypart = human_owner.pain_controller.body_zones[targeted_zone] + if(!held_bodypart) + return FALSE + + held_bodypart.bodypart_pain_modifier *= pain_modifier + pressed_item.AddComponent(/datum/component/make_item_slow) + RegisterSignal(pressed_item, list(COMSIG_QDELETING, COMSIG_ITEM_DROPPED, COMSIG_TEMPERATURE_PACK_EXPIRED), PROC_REF(stop_effects)) + if(holder != owner) + RegisterSignal(holder, COMSIG_MOVABLE_MOVED, PROC_REF(check_adjacency)) + return TRUE + +/datum/status_effect/temperature_pack/tick() + if(QDELETED(holder) || QDELETED(pressed_item) || owner.stat == DEAD || !holder.is_holding(pressed_item)) + stop_effects(silent = TRUE) + return + + var/mob/living/carbon/human/human_owner = owner + if(!human_owner.get_bodypart_pain(targeted_zone, TRUE)) + stop_effects(silent = FALSE) + return + + if(temperature_change) + owner.adjust_bodytemperature(temperature_change, human_owner.get_body_temp_cold_damage_limit() + 5, human_owner.get_body_temp_heat_damage_limit() - 5) + var/obj/item/bodypart/held_bodypart = human_owner.pain_controller.body_zones[targeted_zone] + if(held_bodypart && prob(66)) + human_owner.cause_pain(targeted_zone, -pain_heal_amount) + if(prob(10)) + to_chat(human_owner, span_italics(span_notice("[pressed_item] dulls the pain in your [held_bodypart.name] a little."))) + +/** + * Check on move whether [holder] is still adjacent to [owner]. + */ +/datum/status_effect/temperature_pack/proc/check_adjacency(datum/source) + SIGNAL_HANDLER + + if(!in_range(holder, owner)) + stop_effects(silent = FALSE) + +/** + * Stop the effects of this status effect, deleting it, and sending a message if [silent] is TRUE. + */ +/datum/status_effect/temperature_pack/proc/stop_effects(datum/source, silent = FALSE) + SIGNAL_HANDLER + + if(!silent && !QDELETED(holder) && !QDELETED(pressed_item)) + to_chat(holder, span_notice("You stop pressing [pressed_item] against [owner == holder ? "yourself":"[owner]"].")) + qdel(src) + +/datum/status_effect/temperature_pack/on_remove() + var/mob/living/carbon/human/human_owner = owner + var/obj/item/bodypart/held_bodypart = human_owner.pain_controller?.body_zones[targeted_zone] + held_bodypart?.bodypart_pain_modifier /= pain_modifier + qdel(pressed_item.GetComponent(/datum/component/make_item_slow)) + UnregisterSignal(pressed_item, list(COMSIG_QDELETING, COMSIG_ITEM_DROPPED, COMSIG_TEMPERATURE_PACK_EXPIRED)) + UnregisterSignal(holder, COMSIG_MOVABLE_MOVED) + + pressed_item = null + holder = null + +/// Cold stuff needs to stay cold. +/datum/status_effect/temperature_pack/cold + id = "cold_pack" + temperature_change = -2 + +/datum/status_effect/temperature_pack/cold/on_apply() + . = ..() + if(!.) + return + + var/mob/living/carbon/human/human_owner = owner + var/obj/item/bodypart/held_bodypart = human_owner.pain_controller.body_zones[targeted_zone] + to_chat(human_owner, span_green("You wince as [owner == holder ? "you press" : "[holder] presses"] [pressed_item] against your [parse_zone(held_bodypart.body_zone)], but eventually the chill starts to dull the pain.")) + human_owner.pain_emote("wince", 3 SECONDS) + +/datum/status_effect/temperature_pack/cold/get_examine_text() + var/mob/living/carbon/human/human_owner = owner + var/obj/item/bodypart/held_bodypart = human_owner.pain_controller.body_zones[targeted_zone] + return span_danger("[holder == owner ? "[owner.p_Theyre()]" : "[holder] is"] pressing a cold [pressed_item.name] against [owner.p_their()] [parse_zone(held_bodypart.body_zone)].") + +/datum/status_effect/temperature_pack/cold/tick() + if(pressed_item.resistance_flags & ON_FIRE) + stop_effects(silent = TRUE) + return + + return ..() + +/// And warm stuff needs to stay warm. +/datum/status_effect/temperature_pack/heat + id = "heat_pack" + temperature_change = 2 + +/datum/status_effect/temperature_pack/heat/on_apply() + . = ..() + if(!.) + return + + var/mob/living/carbon/human/human_owner = owner + var/obj/item/bodypart/held_bodypart = human_owner.pain_controller.body_zones[targeted_zone] + to_chat(human_owner, span_green("You gasp as [owner == holder ? "you press" : "[holder] presses"] [pressed_item] against your [held_bodypart.name], but eventually the warmth starts to dull the pain.")) + human_owner.pain_emote("gasp", 3 SECONDS) + +/datum/status_effect/temperature_pack/head/get_examine_text() + var/mob/living/carbon/human/human_owner = owner + var/obj/item/bodypart/held_bodypart = human_owner.pain_controller.body_zones[targeted_zone] + return span_danger("[holder == owner ? "[owner.p_Theyre()]" : "[holder] is"] pressing a warm [pressed_item.name] against [owner.p_their()] [held_bodypart.name].") + +/datum/status_effect/temperature_pack/heat/tick() + if(HAS_TRAIT(pressed_item, TRAIT_FROZEN)) + stop_effects(silent = TRUE) + return + + return ..() diff --git a/monkestation/code/modules/can_spessmen_feel_pain/pain/traits.dm b/monkestation/code/modules/can_spessmen_feel_pain/pain/traits.dm new file mode 100644 index 000000000000..065b51865734 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/pain/traits.dm @@ -0,0 +1,101 @@ +// Less vulnerable to pain (lower pain modifier) +/datum/quirk/pain_resistance + name = "Hypoalgesia" + desc = "You're more resistant to pain - Your pain naturally decreases faster and you receive less overall." + icon = FA_ICON_FIST_RAISED + value = 8 + gain_text = "You feel duller." + lose_text = "You feel sharper." + medical_record_text = "Patient has Hypoalgesia, and is less susceptible to pain stimuli than most." + mail_goodies = list(/obj/item/temperature_pack/heat) + +/datum/quirk/pain_resistance/add() + var/mob/living/carbon/carbon_holder = quirk_holder + if(istype(carbon_holder)) + carbon_holder.set_pain_mod(PAIN_MOD_QUIRK, 0.9) + +/datum/quirk/pain_resistance/remove() + var/mob/living/carbon/carbon_holder = quirk_holder + if(istype(carbon_holder)) + carbon_holder.unset_pain_mod(PAIN_MOD_QUIRK) + +// More vulnerabile to pain (increased pain modifier) +/datum/quirk/pain_vulnerability + name = "Hyperalgesia" + desc = "You're less resistant to pain - Your pain naturally decreases slower and you receive more overall." + icon = FA_ICON_USER_INJURED + value = -6 + gain_text = span_danger("You feel sharper.") + lose_text = span_notice("You feel duller.") + medical_record_text = "Patient has Hyperalgesia, and is more susceptible to pain stimuli than most." + mail_goodies = list(/obj/item/temperature_pack/cold) + +/datum/quirk/pain_vulnerability/add() + var/mob/living/carbon/carbon_holder = quirk_holder + if(istype(carbon_holder)) + carbon_holder.set_pain_mod(PAIN_MOD_QUIRK, 1.15) + +/datum/quirk/pain_vulnerability/remove() + var/mob/living/carbon/carbon_holder = quirk_holder + if(istype(carbon_holder)) + carbon_holder.unset_pain_mod(PAIN_MOD_QUIRK) + + +// More vulnerable to pain + get pain from more actions (Glass bones and paper skin) +/datum/quirk/allodynia + name = "Allodynia" + desc = "Your nerves are extremely sensitive - you may receive pain from things that wouldn't normally be painful, such as hugs." + icon = FA_ICON_TIRED + value = -10 + gain_text = span_danger("You feel fragile.") + lose_text = span_notice("You feel less delicate.") + medical_record_text = "Patient has Allodynia, and is extremely sensitive to touch, pain, and similar stimuli." + mail_goodies = list(/obj/item/temperature_pack/cold, /obj/item/temperature_pack/heat) + COOLDOWN_DECLARE(time_since_last_touch) + +/datum/quirk/allodynia/add() + var/mob/living/carbon/carbon_holder = quirk_holder + if(istype(carbon_holder)) + carbon_holder.set_pain_mod(PAIN_MOD_QUIRK, 1.2) + RegisterSignal(quirk_holder, list(COMSIG_LIVING_GET_PULLED, COMSIG_CARBON_HELP_ACT), PROC_REF(cause_body_pain)) + +/datum/quirk/allodynia/remove() + var/mob/living/carbon/carbon_holder = quirk_holder + if(istype(carbon_holder)) + carbon_holder.unset_pain_mod(PAIN_MOD_QUIRK) + UnregisterSignal(quirk_holder, list(COMSIG_LIVING_GET_PULLED, COMSIG_CARBON_HELP_ACT)) + +/** + * Causes pain to arm zones if they're targeted, and the chest zone otherwise. + * + * source - quirk_holder / the mob being touched + * toucher - the mob that's interacting with source (pulls, hugs, etc) + */ +/datum/quirk/allodynia/proc/cause_body_pain(datum/source, mob/living/toucher) + SIGNAL_HANDLER + + if(!COOLDOWN_FINISHED(src, time_since_last_touch)) + return + + if(quirk_holder.stat != CONSCIOUS) + return + + to_chat(quirk_holder, span_danger("[toucher] touches you, causing a wave of sharp pain throughout your [parse_zone(toucher.zone_selected)]!")) + actually_hurt(toucher.zone_selected, 9) + +/** + * Actually cause the pain to the target limb, causing a visual effect, emote, and a negative moodlet. + * + * zone - the body zone being affected + * amount - the amount of pain being added + */ +/datum/quirk/allodynia/proc/actually_hurt(zone, amount) + var/mob/living/carbon/carbon_holder = quirk_holder + if(!istype(carbon_holder)) + return + + new /obj/effect/temp_visual/annoyed(quirk_holder.loc) + carbon_holder.cause_pain(zone, amount) + INVOKE_ASYNC(quirk_holder, TYPE_PROC_REF(/mob/living, pain_emote)) + quirk_holder.add_mood_event("bad_touch", /datum/mood_event/very_bad_touch) + COOLDOWN_START(src, time_since_last_touch, 30 SECONDS) diff --git a/monkestation/code/modules/can_spessmen_feel_pain/readme.md b/monkestation/code/modules/can_spessmen_feel_pain/readme.md new file mode 100644 index 000000000000..18513d949f33 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/readme.md @@ -0,0 +1,21 @@ +## Title: + + +MODULE ID: SPESSMAN_PAIN + +### Description: + +This pr adds a "lite" version of baymed pain to the game. + + +### Included files that are not contained in this module: + - defines/monkestation/pain.dm + + + +### Credits: + + + +Made by MrMelbert (https://github.com/MrMelbert/MapleStationCode/pull/17) +Ported and Adapted by Dwasint diff --git a/monkestation/code/modules/can_spessmen_feel_pain/subsystem.dm b/monkestation/code/modules/can_spessmen_feel_pain/subsystem.dm new file mode 100644 index 000000000000..690da8aa97f1 --- /dev/null +++ b/monkestation/code/modules/can_spessmen_feel_pain/subsystem.dm @@ -0,0 +1,5 @@ +PROCESSING_SUBSYSTEM_DEF(pain) + name = "Pain" + flags = SS_NO_INIT | SS_BACKGROUND + priority = 20 + wait = 2 SECONDS diff --git a/monkestation/code/modules/cassettes/machines/media/HTML5_player.dm b/monkestation/code/modules/cassettes/machines/media/HTML5_player.dm index 58c6cd2233da..8e262c8fe272 100644 --- a/monkestation/code/modules/cassettes/machines/media/HTML5_player.dm +++ b/monkestation/code/modules/cassettes/machines/media/HTML5_player.dm @@ -18,6 +18,11 @@ function SetMusic(url, time, volume, balance) { if(url != "") player.addEventListener("canplay", setTime, false); player.src = url; } +function SetVolume(volume, balance) { + var player = document.getElementById('player'); + player.volume = +volume; +} + diff --git a/monkestation/code/modules/cassettes/machines/media/media_manager.dm b/monkestation/code/modules/cassettes/machines/media/media_manager.dm index 8e0bf91cf616..0d7a15e4d5a5 100644 --- a/monkestation/code/modules/cassettes/machines/media/media_manager.dm +++ b/monkestation/code/modules/cassettes/machines/media/media_manager.dm @@ -111,9 +111,10 @@ var/client/owner // Client this is actually running in var/forced=0 // If true, current url overrides area media sources var/playerstyle // Choice of which player plugin to use - var/const/WINDOW_ID = "statwindow.mediapanel" // Which elem in skin.dmf to use + var/const/WINDOW_ID = "outputwindow.mediapanel" // Which elem in skin.dmf to use var/balance=0 // do you know what insanity is? Value from -100 to 100 where -100 is left and 100 is right var/signal_synced = 0 //used to check if we have our signal created + var/lobby_music = FALSE /datum/media_manager/New(var/client/C) ASSERT(istype(C)) @@ -130,8 +131,9 @@ /datum/media_manager/proc/send_update() if(!(owner.prefs)) return - if(owner.prefs.channel_volume["[CHANNEL_JUKEBOX]"]) - volume *= (owner.prefs.channel_volume["[CHANNEL_JUKEBOX]"] * 0.01) + if(!lobby_music) + if(owner.prefs.channel_volume["[CHANNEL_JUKEBOX]"]) + volume = (owner.prefs.channel_volume["[CHANNEL_JUKEBOX]"]) if(!owner.prefs.read_preference(/datum/preference/toggle/hear_music)) owner << output(list2params(list("", (world.time - 0) / 10, volume * 1, 0)), "[WINDOW_ID]:SetMusic") diff --git a/monkestation/code/modules/cybernetics/augments/_base_changes.dm b/monkestation/code/modules/cybernetics/augments/_base_changes.dm index 1872722458b7..823287cffc33 100644 --- a/monkestation/code/modules/cybernetics/augments/_base_changes.dm +++ b/monkestation/code/modules/cybernetics/augments/_base_changes.dm @@ -88,7 +88,7 @@ bodypart_overlay = new bodypart_overlay_path bodypart_overlay.unique_properties(src) ownerlimb.add_bodypart_overlay(bodypart_overlay) - owner.update_body_parts() + owner?.update_body_parts() return ..() /obj/item/organ/internal/cyberimp/remove_from_limb() diff --git a/monkestation/code/modules/cybernetics/minigame/airlock_hacking_datum.dm b/monkestation/code/modules/cybernetics/minigame/airlock_hacking_datum.dm index b178c5a89ccc..2f7658387e56 100644 --- a/monkestation/code/modules/cybernetics/minigame/airlock_hacking_datum.dm +++ b/monkestation/code/modules/cybernetics/minigame/airlock_hacking_datum.dm @@ -44,4 +44,4 @@ * Generates the airlock's hacking datum. */ /obj/machinery/door/airlock/proc/set_hacking() - return new /datum/hacking/airlock(src) + //return new /datum/hacking/airlock(src) diff --git a/monkestation/code/modules/cybernetics/minigame/general_hacking.dm b/monkestation/code/modules/cybernetics/minigame/general_hacking.dm index 0d81da8bdbc2..4ecdfb84cddd 100644 --- a/monkestation/code/modules/cybernetics/minigame/general_hacking.dm +++ b/monkestation/code/modules/cybernetics/minigame/general_hacking.dm @@ -7,12 +7,11 @@ PROCESSING_SUBSYSTEM_DEF(hacking) /atom /// Some atoms can be hacked so awesome - var/datum/hacking/hacking = null + var/datum/hacking/hacking /atom/Destroy(force) . = ..() - if(hacking) - QDEL_NULL(hacking) + QDEL_NULL(hacking) /// Attempts to open the hacking interface /atom/proc/attempt_hacking_interaction(mob/user) diff --git a/monkestation/code/modules/factory_type_beat/ai_behaviours/latch_onto.dm b/monkestation/code/modules/factory_type_beat/ai_behaviours/latch_onto.dm new file mode 100644 index 000000000000..6cb5258f0768 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/ai_behaviours/latch_onto.dm @@ -0,0 +1,16 @@ + +/datum/ai_behavior/hunt_target/latch_onto + +/datum/ai_behavior/hunt_target/latch_onto/setup(datum/ai_controller/controller, hunting_target_key, hunting_cooldown_key) + . = ..() + var/mob/living/living_pawn = controller.pawn + if(living_pawn.buckled) + return FALSE + +/datum/ai_behavior/hunt_target/latch_onto/target_caught(mob/living/hunter, obj/hunted) + if(hunter.buckled) + return FALSE + if(!hunted.buckle_mob(hunter, force = TRUE)) + return FALSE + hunted.visible_message(span_notice("[hunted] has been latched onto by [hunter]!")) + return TRUE diff --git a/monkestation/code/modules/factory_type_beat/boulder.dm b/monkestation/code/modules/factory_type_beat/boulder.dm new file mode 100644 index 000000000000..ce203ade508f --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/boulder.dm @@ -0,0 +1,284 @@ +/** + * The objects that ore vents produce, which is refined into minerals. + */ +/obj/item/boulder + name = "boulder" + desc = "This rocks." + icon_state = "ore" + icon = 'monkestation/code/modules/factory_type_beat/icons/ore.dmi' + item_flags = NO_MAT_REDEMPTION + throw_range = 2 + throw_speed = 0.5 + drag_slowdown = 1.5 // It's still a big rock. + ///When a refinery machine is working on this boulder, we'll set this. Re reset when the process is finished, but the boulder may still be refined/operated on further. + var/obj/machinery/bouldertech/processed_by = null + /// How many steps of refinement this boulder has gone through. Starts at 5-8, goes down one each machine process. + var/durability = 5 + /// What was the size of the boulder when it was spawned? This is used for inheiriting the icon_state. + var/boulder_size = BOULDER_SIZE_SMALL + /// Used in inheriting the icon_state from our parent vent in update_icon. + var/boulder_string = "boulder" + /// Cooldown used to prevents boulders from getting processed back into a machine immediately after being processed. + COOLDOWN_DECLARE(processing_cooldown) + + /// Static list of all minerals to populate gulag boulders with. + var/list/static/gulag_minerals = list( + /datum/material/diamond = 1, + /datum/material/gold = 8, + /datum/material/iron = 95, + /datum/material/plasma = 30, + /datum/material/silver = 20, + /datum/material/titanium = 8, + /datum/material/uranium = 3, + ) + /// Static list of all minerals to populate gulag boulders with, but with bluespace added where safe. + var/list/static/expanded_gulag_minerals = list( + /datum/material/bluespace = 1, + /datum/material/diamond = 1, + /datum/material/gold = 8, + /datum/material/iron = 94, + /datum/material/plasma = 30, + /datum/material/silver = 20, + /datum/material/titanium = 8, + /datum/material/uranium = 3, + ) + +/obj/item/boulder/Initialize(mapload) + . = ..() + register_context() + AddComponent(/datum/component/two_handed, require_twohands = TRUE, force_unwielded = 0, force_wielded = 5) //Heavy as all hell, it's a boulder, dude. + +/obj/item/boulder/Destroy(force) + SSore_generation.available_boulders -= src + processed_by = null + return ..() + +/obj/item/boulder/examine(mob/user) + . = ..() + . += span_notice("This boulder would take [durability] more steps to refine or break.") + +/obj/item/boulder/examine_more(mob/user) + . = ..() + . += span_notice("[span_bold("Boulders")] can either be cracked open by [span_bold("mining tools")], or processed into sheets with [span_bold("refineries or smelters")]. Undisturbed boulders can be collected by the [span_bold("BRM")].") + +/obj/item/boulder/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) + if(held_item?.tool_behaviour == TOOL_MINING || HAS_TRAIT(user, TRAIT_BOULDER_BREAKER)) + context[SCREENTIP_CONTEXT_RMB] = "Crush boulder into ore" + return CONTEXTUAL_SCREENTIP_SET + +/obj/item/boulder/attack_self(mob/user, list/modifiers) + . = ..() + if(.) + return + if(HAS_TRAIT(user, TRAIT_BOULDER_BREAKER)) + manual_process(null, user, INATE_BOULDER_SPEED_MULTIPLIER) + return + +/obj/item/boulder/attack_hand_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + if(HAS_TRAIT(user, TRAIT_BOULDER_BREAKER)) + manual_process(null, user, INATE_BOULDER_SPEED_MULTIPLIER) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/item/boulder/CanAllowThrough(atom/movable/mover, border_dir) + . = ..() + if(istype(mover, /obj/item/boulder)) //This way, boulders can only go one at a time on conveyor belts, but everyone else can go through. + return FALSE + +/obj/item/boulder/attackby_secondary(obj/item/weapon, mob/user, params) + . = ..() + if(HAS_TRAIT(user, TRAIT_BOULDER_BREAKER) || HAS_TRAIT(weapon, TRAIT_BOULDER_BREAKER)) + manual_process(weapon, user, INATE_BOULDER_SPEED_MULTIPLIER) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + if(weapon.tool_behaviour == TOOL_MINING) + manual_process(weapon, user) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ..() + +/obj/item/boulder/attack_basic_mob(mob/user, list/modifiers) + . = ..() + if(.) + return + if(HAS_TRAIT(user, TRAIT_BOULDER_BREAKER)) + manual_process(null, user, INATE_BOULDER_SPEED_MULTIPLIER) //A little hacky but it works around the speed of the blackboard task selection process for now. + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/item/boulder/update_icon_state() + . = ..() + switch(boulder_size) + if(BOULDER_SIZE_SMALL) + icon_state = "[boulder_string]_small" + if(BOULDER_SIZE_MEDIUM) + icon_state = "[boulder_string]_medium" + if(BOULDER_SIZE_LARGE) + icon_state = "[boulder_string]_large" + else + icon_state = "[boulder_string]_small" + +/** + * This is called when a boulder is processed by a mob or tool, and reduces the durability of the boulder. + * @param obj/item/weapon The weapon that is being used to process the boulder, that we pull toolspeed from. If null, we use the override_speed_multiplier instead. + * @param mob/living/user The mob that is processing the boulder. + * @param override_speed_multiplier The speed multiplier to use if weapon is null. The do_after will take 2 * this value seconds to complete. + * @param continued Whether or not this is a continued process, or the first one. If true, we don't play the "You swing at the boulder" message. + */ +/obj/item/boulder/proc/manual_process(obj/item/weapon, mob/living/user, override_speed_multiplier, continued = FALSE) + var/process_speed = 0 + //Handle weapon conditions. + if(weapon) + if(HAS_TRAIT(weapon, TRAIT_INSTANTLY_PROCESSES_BOULDERS)) + durability = 0 + process_speed = weapon.toolspeed + weapon.play_tool_sound(src, 50) + if(!continued) + to_chat(user, span_notice("You swing at \the [src]...")) + + // Handle user conditions/override conditions. + else if (override_speed_multiplier || HAS_TRAIT(user, TRAIT_BOULDER_BREAKER)) + if(user) + if(HAS_TRAIT(user, TRAIT_INSTANTLY_PROCESSES_BOULDERS)) + durability = 0 + else if(override_speed_multiplier) + process_speed = override_speed_multiplier + else + process_speed = INATE_BOULDER_SPEED_MULTIPLIER + playsound(src, 'sound/effects/rocktap1.ogg', 50) + if(!continued) + to_chat(user, span_notice("You scrape away at \the [src]... speed is [process_speed].")) + else + CRASH("No weapon, acceptable user, or override speed multiplier passed to manual_process()") + if(durability > 0) + if(!do_after(user, (2 * process_speed SECONDS), target = src)) + return + if(!user.Adjacent(src)) + return + durability-- + user.apply_damage(4, STAMINA) + if(durability <= 0) + convert_to_ore() + to_chat(user, span_notice("You finish working on \the [src], and it crumbles into ore.")) + playsound(src, 'sound/effects/rock_break.ogg', 50) + user.mind?.adjust_experience(/datum/skill/mining, MINING_SKILL_BOULDER_SIZE_XP * 0.2) + qdel(src) + return + var/msg = (durability == 1 ? "is crumbling!" : "looks weaker!") + to_chat(user, span_notice("\The [src] [msg]")) + manual_process(weapon, user, override_speed_multiplier, continued = TRUE) + +/** + * This function is called while breaking boulders manually, and drops ore based on the boulder's mineral content. + * Quantity of ore spawned here is 1 less than if the boulder was processed by a machine, but clamped at 10 maximum, 1 minimum. + */ +/obj/item/boulder/proc/convert_to_ore() + for(var/datum/material/picked in custom_materials) + var/obj/item/stack/ore/cracked_ore // Take the associated value and convert it into ore stacks... + var/quantity = clamp(round((custom_materials[picked] - SHEET_MATERIAL_AMOUNT)/SHEET_MATERIAL_AMOUNT), 1, 10) //but less resources than if they processed it by hand. + + var/cracked_ore_type = picked.ore_type + if(isnull(cracked_ore_type)) + stack_trace("boulder found containing material type [picked.type] with no set ore_type") + continue + cracked_ore = new cracked_ore_type (drop_location(), quantity) + SSblackbox.record_feedback("tally", "ore_mined", quantity, cracked_ore) + +/** + * Handles the boulder's processing cooldown to check if it's ready to be processed again. + */ +/obj/item/boulder/proc/can_get_processed() + return COOLDOWN_FINISHED(src, processing_cooldown) + +/** + * Starts the boulder's processing cooldown. + */ +/obj/item/boulder/proc/restart_processing_cooldown() + COOLDOWN_START(src, processing_cooldown, 2 SECONDS) + +/** + * Moves boulder contents to the drop location, and then deletes the boulder. + */ +/obj/item/boulder/proc/break_apart() + var/list/quips = list("Clang!", "Crack!", "Bang!", "Clunk!", "Clank!") + if(length(contents)) + visible_message(span_notice("[pick(quips)] Something falls out of \the [src]!")) + playsound(loc, 'sound/effects/picaxe1.ogg', 60, FALSE) + for(var/obj/item/content as anything in contents) + content.forceMove(get_turf(src)) + qdel(src) + +/** + * This is called when a boulder is spawned from a vent, and is used to set the boulder's icon as well as durability. + * We also set our boulder_size variable, which is used for inheiriting the icon_state later on if processed. + * @param obj/structure/ore_vent/parent_vent The vent that spawned this boulder to generate consistent boulder icons. If null, we use the default size. + * @param size The size of the boulder to spawn. If parent_vent is defined, this is ignored. + * @param is_artifact Whether or not this boulder is an artifact boulder. If true, we use the artifact boulder icon state regardless of size. + */ +/obj/item/boulder/proc/flavor_boulder(obj/structure/ore_vent/parent_vent, size = BOULDER_SIZE_SMALL, is_artifact = FALSE) + var/durability_min = size + var/durability_max = size + BOULDER_SIZE_SMALL + if(parent_vent) + durability_min = parent_vent.boulder_size + durability_max = parent_vent.boulder_size + BOULDER_SIZE_SMALL + durability = rand(durability_min, durability_max) //randomize durability a bit for some flavor. + boulder_size = size + if(parent_vent) + boulder_size = parent_vent.boulder_size + boulder_string = parent_vent.boulder_icon_state + update_appearance(UPDATE_ICON_STATE) + +/** + * Unique proc for gulag-style boulders, which adds a random amount of minerals to the boulder. + */ +/obj/item/boulder/proc/add_gulag_minerals() + var/datum/material/new_material = pick_weight(gulag_minerals) + var/list/new_mats = list() + new_mats[new_material] = SHEET_MATERIAL_AMOUNT * rand(1,3) //We only want a few sheets of material in the gulag boulders + set_custom_materials(new_mats) + +/obj/item/boulder/artifact + name = "artifact boulder" + desc = "This boulder is brimming with strange energy. Cracking it open could contain something unusual for science." + icon_state = "boulder_artifact" + /// References to the relic inside the boulder, if any. + var/obj/artifact_inside + +/obj/item/boulder/artifact/Initialize(mapload) + . = ..() + artifact_inside = spawn_artifact(src) /// This could be poggers for archaeology in the future. + +/obj/item/boulder/artifact/Destroy(force) + QDEL_NULL(artifact_inside) + return ..() + +/obj/item/boulder/artifact/convert_to_ore() + . = ..() + artifact_inside.forceMove(drop_location()) + artifact_inside = null + +/obj/item/boulder/artifact/break_apart() + artifact_inside = null + return ..() + + +/obj/item/boulder/gulag + name = "low-quality boulder" + desc = "This rocks. It's a low quality boulder, so it's probably not worth as much." + +/obj/item/boulder/gulag/Initialize(mapload) + . = ..() + add_gulag_minerals(gulag_minerals) + +/obj/item/boulder/gulag_expanded + name = "low-density boulder" + desc = "This rocks. It's not very well packed, and can't contain as many minerals." + +/obj/item/boulder/gulag_expanded/Initialize(mapload) + . = ..() + add_gulag_minerals(expanded_gulag_minerals) + +/obj/item/boulder/shabby + name = "shabby boulder" + desc = "A bizzare, twisted boulder. Wait, wait no, it's just a rock." + custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.1, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 1.1) + durability = 1 diff --git a/monkestation/code/modules/factory_type_beat/circuits.dm b/monkestation/code/modules/factory_type_beat/circuits.dm new file mode 100644 index 000000000000..61b0fdb7d352 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/circuits.dm @@ -0,0 +1,46 @@ +/obj/item/circuitboard/machine/brm + name = "Boulder Retrieval Matrix" + greyscale_colors = CIRCUIT_COLOR_SUPPLY + build_path = /obj/machinery/bouldertech/brm + req_components = list( + /datum/stock_part/capacitor = 1, + /datum/stock_part/scanning_module = 1, + /datum/stock_part/micro_laser = 1, + ) + +/obj/item/circuitboard/machine/refinery + name = "Boulder Refinery" + greyscale_colors = CIRCUIT_COLOR_SUPPLY + build_path = /obj/machinery/bouldertech/refinery + req_components = list( + /obj/item/reagent_containers/cup/beaker = 1, + /obj/item/assembly/igniter/condenser = 1, + /datum/stock_part/manipulator = 2, + /datum/stock_part/matter_bin = 1, + ) + +/obj/item/circuitboard/machine/smelter + name = "Boulder Smelter" + greyscale_colors = CIRCUIT_COLOR_SUPPLY + build_path = /obj/machinery/bouldertech/refinery/smelter + req_components = list( + /obj/item/assembly/igniter = 1, + /datum/stock_part/manipulator = 2, + /datum/stock_part/matter_bin = 2, + ) + +/obj/item/circuitboard/machine/big_manipulator + name = "Big Manipulator" + greyscale_colors = CIRCUIT_COLOR_ENGINEERING + build_path = /obj/machinery/big_manipulator + req_components = list( + /datum/stock_part/manipulator = 1, + ) + +/obj/item/circuitboard/machine/assembler + name = "Assembler" + greyscale_colors = CIRCUIT_COLOR_ENGINEERING + build_path = /obj/machinery/assembler + req_components = list( + /datum/stock_part/manipulator = 1, + ) diff --git a/monkestation/code/modules/factory_type_beat/debug.dm b/monkestation/code/modules/factory_type_beat/debug.dm new file mode 100644 index 000000000000..7f38eebb1485 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/debug.dm @@ -0,0 +1,49 @@ +/proc/count_lists() +#ifndef OPENDREAM + var/list_count = 0 + for(var/list/list) + list_count++ + + var/file = file("data/list_count/[GLOB.round_id].txt") + + WRITE_FILE(file, list_count) +#endif + +/proc/save_types() +#ifndef OPENDREAM + var/datum/D + var/atom/A + var/list/counts = new + for(A) counts[A.type] = (counts[A.type]||0) + 1 + for(D) counts[D.type] = (counts[D.type]||0) + 1 + + var/F = file("data/type_tracker/[GLOB.round_id]-stat_track.txt") + for(var/i in counts) + WRITE_FILE(F, "[i]\t[counts[i]]\n") +#endif + +/proc/save_datums() +#ifndef OPENDREAM + var/datum/D + var/list/counts = new + for(D) counts[D.type] = (counts[D.type]||0) + 1 + + var/F = file("data/type_tracker/[GLOB.round_id]-datums-[world.time].txt") + for(var/i in counts) + WRITE_FILE(F, "[i]\t[counts[i]]\n") +#endif + +///these procs don't work on od +SUBSYSTEM_DEF(memory_stats) + name = "Mem Stats" + init_order = INIT_ORDER_AIR + priority = FIRE_PRIORITY_AIR + wait = 5 MINUTES + flags = SS_NO_INIT | SS_BACKGROUND + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + +/datum/controller/subsystem/memory_stats/fire(resumed) + if(world.system_type == MS_WINDOWS) + var/memory_summary = call_ext("memorystats", "get_memory_stats")() + if(memory_summary) + rustg_file_write(memory_summary, "data/mem_stat/[GLOB.round_id]-memstat.txt") diff --git a/monkestation/code/modules/factory_type_beat/designs.dm b/monkestation/code/modules/factory_type_beat/designs.dm new file mode 100644 index 000000000000..e8b790b565cb --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/designs.dm @@ -0,0 +1,236 @@ +#define FABRICATOR_SUBCATEGORY_MATERIALS "/Materials" + +/datum/design/manipulator_filter + name = "Manipulator Filter" + desc = "This can be inserted into a manipulator to give it filters." + id = "manipulator_filter" + build_path = /obj/item/manipulator_filter + build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE | COLONY_FABRICATOR + category = list( + RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_CARGO + ) + materials = list(/datum/material/iron = 2000) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SERVICE + +/datum/design/manipulator_filter_cargo + name = "Manipulator Filter (Department)" + desc = "This can be inserted into a manipulator to give it filters." + id = "manipulator_filter_cargo" + build_path = /obj/item/manipulator_filter/cargo + build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE | COLONY_FABRICATOR + category = list( + RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_CARGO + ) + materials = list(/datum/material/iron = 2000) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SERVICE + +/datum/design/manipulator_filter_internal + name = "Manipulator Filter (Internal)" + desc = "This can be inserted into a manipulator to give it filters." + id = "manipulator_filter_internal" + build_path = /obj/item/manipulator_filter/internal_filter + build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE | COLONY_FABRICATOR + category = list( + RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_CARGO + ) + materials = list(/datum/material/iron = 2000) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SERVICE + +/datum/design/board/big_manipulator + name = "Big Manipulator Board" + desc = "The circuit board for a big manipulator." + id = "big_manipulator" + build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE | COLONY_FABRICATOR + build_path = /obj/item/circuitboard/machine/big_manipulator + category = list( + RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ENGINEERING + ) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SERVICE + +/datum/design/board/assembler + name = "Assembler Board" + desc = "The circuit board for an assembler." + id = "assembler" + build_path = /obj/item/circuitboard/machine/assembler + build_type = COLONY_FABRICATOR | IMPRINTER | AWAY_IMPRINTER + category = list( + RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ENGINEERING + ) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SERVICE + +/datum/design/dissolution_chamber + name = "Dissolution Chamber" + id = "dissolution_chamber" + build_type = COLONY_FABRICATOR | AUTOLATHE | PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/flatpacked_machine/ore_processing/dissolution_chamber + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_SUBCATEGORY_MATERIALS, + ) + construction_time = 10 SECONDS + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO + +/datum/design/chemical_washer + name = "Chemical Washer" + id = "chemical_washer" + build_type = COLONY_FABRICATOR | AUTOLATHE | PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/flatpacked_machine/ore_processing/chemical_washer + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_SUBCATEGORY_MATERIALS, + ) + construction_time = 10 SECONDS + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO + +/datum/design/chemical_injector + name = "Chemical Injector" + id = "chemical_injector" + build_type = COLONY_FABRICATOR | AUTOLATHE | PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/flatpacked_machine/ore_processing/chemical_injector + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_SUBCATEGORY_MATERIALS, + ) + construction_time = 10 SECONDS + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO + +/datum/design/crystalizer + name = "Crystalizer" + id = "crystalizer" + build_type = COLONY_FABRICATOR | AUTOLATHE | PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/flatpacked_machine/ore_processing/crystalizer + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_SUBCATEGORY_MATERIALS, + ) + construction_time = 10 SECONDS + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO + +/datum/design/crusher + name = "Crusher" + id = "crusher" + build_type = COLONY_FABRICATOR | AUTOLATHE | PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/flatpacked_machine/ore_processing/crusher + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_SUBCATEGORY_MATERIALS, + ) + construction_time = 10 SECONDS + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO + +/datum/design/enricher + name = "Enrichment Chamber" + id = "enricher" + build_type = COLONY_FABRICATOR | AUTOLATHE | PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/flatpacked_machine/ore_processing/enricher + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_SUBCATEGORY_MATERIALS, + ) + construction_time = 10 SECONDS + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO + +/datum/design/purification_chamber + name = "Purification Chamber" + id = "purification_chamber" + build_type = COLONY_FABRICATOR | AUTOLATHE | PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/flatpacked_machine/ore_processing/purification_chamber + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_SUBCATEGORY_MATERIALS, + ) + construction_time = 10 SECONDS + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO + +/datum/design/brine_chamber + name = "Brine Chamber Controller" + id = "brine_chamber" + build_type = COLONY_FABRICATOR | AUTOLATHE | PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 15, + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/flatpacked_machine/ore_processing/brine_chamber + category = list( + RND_CATEGORY_INITIAL, + FABRICATOR_SUBCATEGORY_MATERIALS, + ) + construction_time = 30 SECONDS + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO + +// Autolathe-able circuitboards for starting with boulder processing machines. +/datum/design/board/smelter + name = "Boulder Smelter" + desc = "A circuitboard for a boulder smelter. Lowtech enough to be printed from the lathe." + id = "b_smelter" + build_type = AUTOLATHE | COLONY_FABRICATOR + materials = list( + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + /datum/material/iron = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/circuitboard/machine/smelter + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_CARGO, + ) + departmental_flags = DEPARTMENT_BITFLAG_CARGO + +/datum/design/board/refinery + name = "Boulder Refinery" + desc = "A circuitboard for a boulder refinery. Lowtech enough to be printed from the lathe." + id = "b_refinery" + build_type = AUTOLATHE | COLONY_FABRICATOR + materials = list( + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + /datum/material/iron = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/circuitboard/machine/refinery + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_CARGO, + ) + departmental_flags = DEPARTMENT_BITFLAG_CARGO + + +/datum/design/board/brm + name = "Boulder Retrieval Matrix" + id = "brm" + materials = list( + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/circuitboard/machine/brm + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_TELEPORT, + ) + departmental_flags = DEPARTMENT_BITFLAG_CARGO + +#undef FABRICATOR_SUBCATEGORY_MATERIALS diff --git a/monkestation/code/modules/factory_type_beat/effects.dm b/monkestation/code/modules/factory_type_beat/effects.dm new file mode 100644 index 000000000000..ef0d6fb0adda --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/effects.dm @@ -0,0 +1,21 @@ +/obj/effect/temp_visual/mining_overlay/vent + icon = 'monkestation/code/modules/factory_type_beat/icons/vent_overlays.dmi' + icon_state = "unknown" + duration = 45 + pixel_x = 0 + pixel_y = 0 + easing_style = CIRCULAR_EASING|EASE_IN + +/obj/effect/decal/cleanable/rubble + name = "rubble" + desc = "A pile of rubble." + icon = 'monkestation/code/modules/factory_type_beat/icons/debris.dmi' + icon_state = "rubble" + mergeable_decal = FALSE + beauty = -10 + +/obj/effect/decal/cleanable/rubble/Initialize(mapload) + . = ..() + flick("rubble_bounce", src) + icon_state = "rubble" + update_appearance(UPDATE_ICON_STATE) diff --git a/monkestation/code/modules/factory_type_beat/flatpacks.dm b/monkestation/code/modules/factory_type_beat/flatpacks.dm new file mode 100644 index 000000000000..2a08025476cc --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/flatpacks.dm @@ -0,0 +1,35 @@ +/obj/item/flatpacked_machine/ore_processing + icon_state = "colony_lathe_packed" + +/obj/item/flatpacked_machine/ore_processing/dissolution_chamber + name = "flat-packed dissolution chamber" + type_to_deploy = /obj/machinery/bouldertech/dissolution_chamber + +/obj/item/flatpacked_machine/ore_processing/chemical_washer + name = "flat-packed chemical washer" + type_to_deploy = /obj/machinery/bouldertech/chemical_washer + +/obj/item/flatpacked_machine/ore_processing/chemical_injector + name = "flat-packed chemical injector" + type_to_deploy = /obj/machinery/bouldertech/chemical_injector + +/obj/item/flatpacked_machine/ore_processing/crystalizer + name = "flat-packed crystalizer" + type_to_deploy = /obj/machinery/bouldertech/crystalizer + +/obj/item/flatpacked_machine/ore_processing/crusher + name = "flat-packed crusher" + type_to_deploy = /obj/machinery/bouldertech/crusher + +/obj/item/flatpacked_machine/ore_processing/enricher + name = "flat-packed enrichment chamber" + type_to_deploy = /obj/machinery/bouldertech/enricher + +/obj/item/flatpacked_machine/ore_processing/purification_chamber + name = "flat-packed purification chamber" + type_to_deploy = /obj/machinery/bouldertech/purification_chamber + +/obj/item/flatpacked_machine/ore_processing/brine_chamber + name = "flat-packed brine chamber controller" + desc = "This is a massive deploy so clear space (5x5). This acts as the lower left corner" + type_to_deploy = /obj/structure/brine_chamber/controller diff --git a/monkestation/code/modules/factory_type_beat/icons/big_manipulator.dmi b/monkestation/code/modules/factory_type_beat/icons/big_manipulator.dmi new file mode 100644 index 000000000000..b6e878e18984 Binary files /dev/null and b/monkestation/code/modules/factory_type_beat/icons/big_manipulator.dmi differ diff --git a/monkestation/code/modules/factory_type_beat/icons/big_manipulator_core.dmi b/monkestation/code/modules/factory_type_beat/icons/big_manipulator_core.dmi new file mode 100644 index 000000000000..614b4d51cbbf Binary files /dev/null and b/monkestation/code/modules/factory_type_beat/icons/big_manipulator_core.dmi differ diff --git a/monkestation/code/modules/factory_type_beat/icons/big_manipulator_hand.dmi b/monkestation/code/modules/factory_type_beat/icons/big_manipulator_hand.dmi new file mode 100644 index 000000000000..e165441e8052 Binary files /dev/null and b/monkestation/code/modules/factory_type_beat/icons/big_manipulator_hand.dmi differ diff --git a/monkestation/code/modules/factory_type_beat/icons/debris.dmi b/monkestation/code/modules/factory_type_beat/icons/debris.dmi new file mode 100644 index 000000000000..10b73560cbb1 Binary files /dev/null and b/monkestation/code/modules/factory_type_beat/icons/debris.dmi differ diff --git a/monkestation/code/modules/factory_type_beat/icons/items.dmi b/monkestation/code/modules/factory_type_beat/icons/items.dmi new file mode 100644 index 000000000000..9084cf3f8d28 Binary files /dev/null and b/monkestation/code/modules/factory_type_beat/icons/items.dmi differ diff --git a/monkestation/code/modules/factory_type_beat/icons/mining.dmi b/monkestation/code/modules/factory_type_beat/icons/mining.dmi new file mode 100644 index 000000000000..cdc886d85acd Binary files /dev/null and b/monkestation/code/modules/factory_type_beat/icons/mining.dmi differ diff --git a/monkestation/code/modules/factory_type_beat/icons/mining_machines.dmi b/monkestation/code/modules/factory_type_beat/icons/mining_machines.dmi new file mode 100644 index 000000000000..1be820a1fe41 Binary files /dev/null and b/monkestation/code/modules/factory_type_beat/icons/mining_machines.dmi differ diff --git a/monkestation/code/modules/factory_type_beat/icons/ore.dmi b/monkestation/code/modules/factory_type_beat/icons/ore.dmi new file mode 100644 index 000000000000..7cc3b8820577 Binary files /dev/null and b/monkestation/code/modules/factory_type_beat/icons/ore.dmi differ diff --git a/monkestation/code/modules/factory_type_beat/icons/processing.dmi b/monkestation/code/modules/factory_type_beat/icons/processing.dmi new file mode 100644 index 000000000000..f154d3c13274 Binary files /dev/null and b/monkestation/code/modules/factory_type_beat/icons/processing.dmi differ diff --git a/monkestation/code/modules/factory_type_beat/icons/terrain.dmi b/monkestation/code/modules/factory_type_beat/icons/terrain.dmi new file mode 100644 index 000000000000..fd930fe709dc Binary files /dev/null and b/monkestation/code/modules/factory_type_beat/icons/terrain.dmi differ diff --git a/monkestation/code/modules/factory_type_beat/icons/vent_overlays.dmi b/monkestation/code/modules/factory_type_beat/icons/vent_overlays.dmi new file mode 100644 index 000000000000..54ac3d7a819b Binary files /dev/null and b/monkestation/code/modules/factory_type_beat/icons/vent_overlays.dmi differ diff --git a/monkestation/code/modules/factory_type_beat/machinery/assembler.dm b/monkestation/code/modules/factory_type_beat/machinery/assembler.dm new file mode 100644 index 000000000000..65c31219c962 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/machinery/assembler.dm @@ -0,0 +1,333 @@ +/obj/machinery/assembler + name = "assembler" + desc = "Produces a set recipe when given the materials, some say a small cargo technican is stuck inside making these things." + circuit = /obj/item/circuitboard/machine/assembler + + var/speed_multiplier = 1 + var/datum/crafting_recipe/chosen_recipe + var/crafting = FALSE + + var/static/list/crafting_recipes = list() + var/list/crafting_inventory = list() + + icon = 'monkestation/code/modules/factory_type_beat/icons/mining_machines.dmi' + icon_state = "assembler" + + +/obj/machinery/assembler/Initialize(mapload) + . = ..() + + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered), + ) + AddElement(/datum/element/connect_loc, loc_connections) + AddComponent(/datum/component/hovering_information, /datum/hover_data/assembler) + register_context() + + if(!length(crafting_recipes)) + create_recipes() + +/obj/machinery/assembler/RefreshParts() + . = ..() + var/datum/stock_part/manipulator/locate_servo = locate() in component_parts + if(!locate_servo) + return + speed_multiplier = 1 / locate_servo.tier + +/obj/machinery/assembler/Destroy() + . = ..() + for(var/atom/movable/movable in crafting_inventory) + movable.forceMove(get_turf(src)) + crafting_inventory -= movable + +/obj/machinery/assembler/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + if(chosen_recipe) + var/processable = "Accepts: " + var/comma = FALSE + for(var/atom/atom as anything in chosen_recipe.reqs) + if(comma) + processable += ", " + processable += initial(atom.name) + comma = !comma + context[SCREENTIP_CONTEXT_MISC] = processable + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/assembler/examine(mob/user) + . = ..() + if(chosen_recipe) + . += span_notice(chosen_recipe.name) + for(var/atom/atom as anything in chosen_recipe.reqs) + . += span_notice("[initial(atom.name)]: [chosen_recipe.reqs[atom]]") + +/obj/machinery/assembler/proc/create_recipes() + for(var/datum/crafting_recipe/recipe as anything in subtypesof(/datum/crafting_recipe) - /datum/crafting_recipe/stack) + if(initial(recipe.non_craftable) || !initial(recipe.always_available)) + continue + crafting_recipes += new recipe + +/obj/machinery/assembler/attack_hand(mob/living/user, list/modifiers) + . = ..() + var/datum/crafting_recipe/choice = tgui_input_list(user, "Choose a recipe", name, crafting_recipes) + if(!choice) + return + chosen_recipe = choice + for(var/atom/movable/listed as anything in crafting_inventory) + listed.forceMove(get_turf(src)) + crafting_inventory -= listed + +/obj/machinery/assembler/CanAllowThrough(atom/movable/mover, border_dir) + if(!anchored) + return FALSE + if(!chosen_recipe) + return FALSE + var/failed = TRUE + for(var/atom/movable/movable as anything in chosen_recipe.reqs) + if(istype(mover, movable)) + failed = FALSE + break + if(failed) + return FALSE + if(!check_item(mover)) + return FALSE + return ..() + +/obj/machinery/assembler/proc/on_entered(datum/source, atom/movable/atom_movable) + SIGNAL_HANDLER + INVOKE_ASYNC(src, PROC_REF(accept_item), atom_movable) + +/obj/machinery/assembler/proc/accept_item(atom/movable/atom_movable) + if(!chosen_recipe) + return + if(isstack(atom_movable)) + var/obj/item/stack/stack = atom_movable + if(!(stack.merge_type in chosen_recipe.reqs)) + return FALSE + else + var/failed = TRUE + for(var/atom/movable/movable as anything in chosen_recipe.reqs) + if(istype(atom_movable, movable)) + failed = FALSE + break + if(failed) + return FALSE + + atom_movable.forceMove(src) + crafting_inventory += atom_movable + check_recipe_state() + + +/obj/machinery/assembler/can_drop_off(atom/movable/target) + if(!check_item(target)) + return FALSE + return TRUE + + +/obj/machinery/assembler/proc/check_item(atom/movable/atom_movable) + if(!chosen_recipe) + return + if(isstack(atom_movable)) + var/obj/item/stack/stack = atom_movable + if(!(stack.merge_type in chosen_recipe.reqs)) + return FALSE + + if(!isstack(atom_movable)) + var/failed = TRUE + for(var/atom/movable/movable as anything in chosen_recipe.reqs) + if(istype(atom_movable, movable)) + failed = FALSE + break + if(failed) + return FALSE + + var/list/reqs = chosen_recipe.reqs.Copy() + for(var/atom/movable/listed in reqs) + reqs[listed] *= 10 // we can queue 10 crafts of everything + + for(var/atom/movable/item in crafting_inventory) + if(isstack(item)) + var/obj/item/stack/stack = item + if(item in reqs) + reqs[item.type] -= stack.amount + if(reqs[item.type] <= 0) + reqs -= item.type + else + for(var/atom/movable/movable as anything in chosen_recipe.reqs) + if(istype(item, movable)) + reqs[movable]-- + if(reqs[movable] <= 0) + reqs -= movable + if(!length(reqs)) + return FALSE + + var/passed = FALSE + for(var/atom/movable/movable as anything in chosen_recipe.reqs) + if(istype(atom_movable, movable)) + passed = TRUE + break + if(passed) + return TRUE + + if(isstack(atom_movable)) + var/obj/item/stack/stack = atom_movable + if((stack.merge_type in reqs)) + return TRUE + + return FALSE + + +/obj/machinery/assembler/proc/check_recipe_state() + if(!chosen_recipe) + return + var/list/reqs = chosen_recipe.reqs.Copy() + if(!length(reqs)) + return + + for(var/atom/movable/item in crafting_inventory) + if(isstack(item)) + var/obj/item/stack/stack = item + if(stack.merge_type in reqs) + reqs[stack.merge_type] -= stack.amount + if(reqs[stack.merge_type] <= 0) + reqs -= stack.merge_type + else + for(var/atom/movable/movable as anything in chosen_recipe.reqs) + if(istype(item, movable)) + reqs[movable]-- + if(reqs[movable] <= 0) + reqs -= movable + if(!length(reqs)) + start_craft() + +/obj/machinery/assembler/proc/start_craft() + if(crafting) + return + crafting = TRUE + + if(!machine_do_after_visable(src, chosen_recipe.time * speed_multiplier * 3)) + return + + var/list/requirements = chosen_recipe.reqs + var/list/Deletion = list() + var/list/stored_parts = list() + var/data + var/amt + var/insanity = 500 + main_loop: + insanity-- + if(insanity <= 0) + return + for(var/path_key in requirements) + amt = chosen_recipe.reqs?[path_key] + if(!amt)//since machinery & structures can have 0 aka CRAFTING_MACHINERY_USE - i.e. use it, don't consume it! + continue main_loop + if(ispath(path_key, /obj/item/stack)) + var/obj/item/stack/S + var/obj/item/stack/SD + while(amt > 0) + S = locate(path_key) in crafting_inventory + if(S.amount >= amt) + if(!locate(S.type) in Deletion) + SD = new S.type() + Deletion += SD + S.use(amt) + SD = locate(S.type) in Deletion + SD.amount += amt + continue main_loop + else + amt -= S.amount + if(!locate(S.type) in Deletion) + Deletion += S + else + data = S.amount + S = locate(S.type) in Deletion + S.add(data) + crafting_inventory -= S + else + var/atom/movable/I + while(amt > 0) + I = locate(path_key) in crafting_inventory + Deletion += I + crafting_inventory -= I + amt-- + var/list/partlist = list(chosen_recipe.parts.len) + for(var/M in chosen_recipe.parts) + partlist[M] = chosen_recipe.parts[M] + for(var/part in chosen_recipe.parts) + if(isstack(part)) + var/obj/item/stack/ST = locate(part) in Deletion + if(ST.amount > partlist[part]) + ST.amount = partlist[part] + stored_parts += ST + Deletion -= ST + continue + else + while(partlist[part] > 0) + var/atom/movable/AM = locate(part) in Deletion + stored_parts += AM + Deletion -= AM + partlist[part] -= 1 + while(Deletion.len) + var/DL = Deletion[Deletion.len] + Deletion.Cut(Deletion.len) + if(istype(DL, /obj/item/storage)) + var/obj/item/storage/container = DL + container.emptyStorage() + else if(isstructure(DL)) + var/obj/structure/structure = DL + structure.dump_contents(structure.drop_location()) + qdel(DL) + + var/atom/movable/I + if(ispath(chosen_recipe.result, /obj/item/stack)) + I = new chosen_recipe.result(src, chosen_recipe.result_amount || 1) + I.forceMove(drop_location()) + else + I = new chosen_recipe.result (src) + I.forceMove(drop_location()) + if(I.atom_storage && chosen_recipe.delete_contents) + for(var/obj/item/thing in I) + qdel(thing) + I.CheckParts(stored_parts, chosen_recipe) + I.forceMove(drop_location()) + + crafting = FALSE + check_recipe_state() + + +/datum/hover_data/assembler + var/obj/effect/overlay/hover/recipe_icon + var/last_type + +/datum/hover_data/assembler/New(datum/component/hovering_information, atom/parent) + . = ..() + recipe_icon = new(null) + recipe_icon.maptext_width = 64 + recipe_icon.maptext_y = 32 + recipe_icon.maptext_x = -4 + recipe_icon.alpha = 125 + +/datum/hover_data/assembler/setup_data(obj/machinery/assembler/source, mob/enterer) + . = ..() + if(!source.chosen_recipe) + return + if(last_type != source.chosen_recipe.result) + update_image(source) + var/image/new_image = new(source) + new_image.appearance = recipe_icon.appearance + SET_PLANE_EXPLICIT(new_image, new_image.plane, source) + if(!isturf(source.loc)) + new_image.loc = source.loc + else + new_image.loc = source + add_client_image(new_image, enterer.client) + +/datum/hover_data/assembler/proc/update_image(obj/machinery/assembler/source) + if(!source.chosen_recipe) + return + last_type = source.chosen_recipe.result + + var/atom/atom = source.chosen_recipe.result + + recipe_icon.icon = initial(atom.icon) + recipe_icon.icon_state = initial(atom.icon_state) diff --git a/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/chemical_infuser.dm b/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/chemical_infuser.dm new file mode 100644 index 000000000000..d34edeeed4d4 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/chemical_infuser.dm @@ -0,0 +1,129 @@ +/obj/machinery/atmospherics/components/unary/chemical_infuser + name = "chemical infuser" + desc = "An afront to both chemists and atmospheric technicans." + + layer = BELOW_OBJ_LAYER + + icon_state = "reaction_chamber" + icon = 'icons/obj/plumbing/plumbers.dmi' + + initialize_directions = EAST + + var/static/list/chemical_infuser_recipes = list() + var/datum/chemical_infuser_recipe/chosen_recipe + var/processing = FALSE + +/obj/machinery/atmospherics/components/unary/chemical_infuser/Initialize(mapload) + . = ..() + create_reagents(1000, TRANSPARENT) + AddComponent(/datum/component/plumbing/chemical_infuser) + +/obj/machinery/atmospherics/components/unary/chemical_infuser/set_init_directions() + . = ..() + switch(dir) + if(SOUTH) + initialize_directions = EAST + if(NORTH) + initialize_directions = WEST + if(WEST) + initialize_directions = SOUTH + if(EAST) + initialize_directions = NORTH + +/obj/machinery/atmospherics/components/unary/chemical_infuser/ui_interact(mob/user, datum/tgui/ui) + if(!length(chemical_infuser_recipes)) + create_recipes() + chosen_recipe = tgui_input_list(user, "Choose a recipe to focus on.", name, chemical_infuser_recipes) + +/obj/machinery/atmospherics/components/unary/chemical_infuser/proc/create_recipes() + for(var/datum/chemical_infuser_recipe/new_recipes as anything in subtypesof(/datum/chemical_infuser_recipe)) + chemical_infuser_recipes += new new_recipes + +/obj/machinery/atmospherics/components/unary/chemical_infuser/examine(mob/user) + . = ..() + if(chosen_recipe) + . += "[chosen_recipe.name] requires:" + for(var/datum/reagent/reagent as anything in chosen_recipe.required_reagents) + var/amount = reagents.get_reagent_amount(reagent) + . += "[reagent.name]: [amount] / [chosen_recipe.required_reagents[reagent]]" + for(var/datum/gas/gas as anything in chosen_recipe.required_gases) + var/datum/gas_mixture/mixture = airs[1] + mixture.assert_gas(gas) + var/gas_amount = mixture.gases[gas][MOLES] + . += "[gas.name]: [gas_amount] / [chosen_recipe.required_gases[gas]]" + +/obj/machinery/atmospherics/components/unary/chemical_infuser/process_atmos() + if(!chosen_recipe) + return + + var/passes_all_gases = TRUE + for(var/datum/gas/gas as anything in chosen_recipe.required_gases) + var/datum/gas_mixture/mixture = airs[1] + mixture.assert_gas(gas) + var/gas_amount = mixture.gases[gas][MOLES] + if(gas_amount < chosen_recipe.required_gases[gas]) + passes_all_gases = FALSE + break + if(!passes_all_gases) + return + + var/passes_all_chemicals = TRUE + for(var/datum/reagent/reagent as anything in chosen_recipe.required_reagents) + var/amount = reagents.get_reagent_amount(reagent) + if(amount < chosen_recipe.required_reagents[reagent]) + passes_all_chemicals = FALSE + break + if(!passes_all_chemicals) + return + + if(!processing) + playsound(get_turf(src), 'sound/effects/bubbles2.ogg', 25, TRUE) + var/list/seen = viewers(4, get_turf(src)) + var/iconhtml = icon2html(src, seen) + audible_message(span_notice("[iconhtml] The solution bubbles fiercely!")) + addtimer(CALLBACK(src, PROC_REF(create_recipe)), 7 SECONDS) + processing = TRUE + +/obj/machinery/atmospherics/components/unary/chemical_infuser/proc/create_recipe() + processing = FALSE + for(var/datum/reagent/reagent as anything in chosen_recipe.required_reagents) + reagents.remove_all_type(reagent, chosen_recipe.required_reagents[reagent]) + var/datum/gas_mixture/mixture = airs[1] + + for(var/datum/gas/gas as anything in chosen_recipe.required_gases) + mixture.remove_specific(gas, chosen_recipe.required_gases[gas]) + + for(var/datum/reagent/reagent as anything in chosen_recipe.outputs) + reagents.add_reagent(reagent, chosen_recipe.outputs[reagent]) + +/datum/component/plumbing/chemical_infuser + demand_connects = NORTH + supply_connects = SOUTH + +/datum/component/plumbing/chemical_infuser/Initialize(start=TRUE, _ducting_layer, _turn_connects=TRUE, datum/reagents/custom_receiver) + . = ..() + if(!istype(parent, /obj/machinery/atmospherics/components/unary/chemical_infuser)) + return COMPONENT_INCOMPATIBLE + +/datum/component/plumbing/chemical_infuser/can_give(amount, reagent, datum/ductnet/net) + . = ..() + var/obj/machinery/plumbing/reaction_chamber/reaction_chamber = parent + if(!. || !reaction_chamber.emptying || reagents.is_reacting == TRUE) + return FALSE + +/datum/component/plumbing/chemical_infuser/send_request(dir) + var/obj/machinery/atmospherics/components/unary/chemical_infuser/chamber = parent + if(!chamber.chosen_recipe) + return + + for(var/required_reagent in chamber.chosen_recipe.required_reagents) + var/has_reagent = FALSE + for(var/datum/reagent/containg_reagent as anything in reagents.reagent_list) + if(required_reagent == containg_reagent.type) + has_reagent = TRUE + if(containg_reagent.volume + CHEMICAL_QUANTISATION_LEVEL < chamber.chosen_recipe.required_reagents[required_reagent]) + process_request(min(chamber.chosen_recipe.required_reagents[required_reagent] - containg_reagent.volume, MACHINE_REAGENT_TRANSFER) , required_reagent, dir) + return + if(!has_reagent) + process_request(min(chamber.chosen_recipe.required_reagents[required_reagent], MACHINE_REAGENT_TRANSFER), required_reagent, dir) + return diff --git a/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/chemical_infuser_recipes/_base.dm b/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/chemical_infuser_recipes/_base.dm new file mode 100644 index 000000000000..d4cf68eb86cf --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/chemical_infuser_recipes/_base.dm @@ -0,0 +1,5 @@ +/datum/chemical_infuser_recipe + var/name = "Test" + var/list/outputs = list() + var/list/required_gases = list() + var/list/required_reagents = list() diff --git a/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/chemical_infuser_recipes/sulfur.dm b/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/chemical_infuser_recipes/sulfur.dm new file mode 100644 index 000000000000..1dd00d6b4114 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/chemical_infuser_recipes/sulfur.dm @@ -0,0 +1,26 @@ +/datum/chemical_infuser_recipe/sulfur + name = "Sulfur" + required_reagents = list(/datum/reagent/gunpowder = 5) + required_gases = list(/datum/gas/oxygen = 5) + outputs = list(/datum/reagent/sulfur = 50) + +/datum/chemical_infuser_recipe/sulfur_trioxide + name = "Sulfur Trioxide" + + required_reagents = list(/datum/reagent/sulfur/dioxide = 5) + required_gases = list(/datum/gas/oxygen = 5) + outputs = list(/datum/reagent/sulfur/trioxide = 10) + +/datum/chemical_infuser_recipe/sulfuric_acid + name = "Sulfuric Acid" + + required_gases = list(/datum/gas/oxygen = 5) + required_reagents = list(/datum/reagent/sulfur/trioxide = 5) + outputs = list(/datum/reagent/toxin/acid = 10) + + +/datum/reagent/sulfur/dioxide + name = "Sulfur Dioxide" + +/datum/reagent/sulfur/trioxide + name = "sulfur Trioxide" diff --git a/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/pressurised_reactions/_base.dm b/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/pressurised_reactions/_base.dm new file mode 100644 index 000000000000..1823238c1ed7 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/pressurised_reactions/_base.dm @@ -0,0 +1,5 @@ +/datum/pressurized_reaction + var/name = "Test" + var/list/outputs = list() + var/required_pressure = 0 + var/list/required_reagents = list() diff --git a/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/pressurised_reactions/sulfur.dm b/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/pressurised_reactions/sulfur.dm new file mode 100644 index 000000000000..df643cb43e2d --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/pressurised_reactions/sulfur.dm @@ -0,0 +1,5 @@ +/datum/pressurized_reaction/sulfur_dioxide + name = "Sulfur Dioxide" + required_pressure = 300 + required_reagents = list(/datum/reagent/sulfur = 50) + outputs = list(/datum/reagent/sulfur/dioxide = 50) diff --git a/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/pressurized_reaction_chamber.dm b/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/pressurized_reaction_chamber.dm new file mode 100644 index 000000000000..fca6dbfbe1b7 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/machinery/atmos_chem/pressurized_reaction_chamber.dm @@ -0,0 +1,112 @@ +/obj/machinery/atmospherics/components/unary/pressurized_reaction_chamber + name = "pressurized reaction chamber" + desc = "An afront to both chemists and atmospheric technicans." + + icon_state = "reaction_chamber" + icon = 'icons/obj/plumbing/plumbers.dmi' + + initialize_directions = EAST + + var/static/list/pressurized_reaction_recipes = list() + var/datum/pressurized_reaction/chosen_recipe + var/processing = FALSE + +/obj/machinery/atmospherics/components/unary/pressurized_reaction_chamber/Initialize(mapload) + . = ..() + create_reagents(1000, TRANSPARENT) + AddComponent(/datum/component/plumbing/pressurized_reaction_chamber) + +/obj/machinery/atmospherics/components/unary/pressurized_reaction_chamber/set_init_directions() + . = ..() + switch(dir) + if(SOUTH) + initialize_directions = EAST + if(NORTH) + initialize_directions = WEST + if(WEST) + initialize_directions = SOUTH + if(EAST) + initialize_directions = NORTH + +/obj/machinery/atmospherics/components/unary/pressurized_reaction_chamber/ui_interact(mob/user, datum/tgui/ui) + if(!length(pressurized_reaction_recipes)) + create_recipes() + chosen_recipe = tgui_input_list(user, "Choose a recipe to focus on.", name, pressurized_reaction_recipes) + +/obj/machinery/atmospherics/components/unary/pressurized_reaction_chamber/proc/create_recipes() + for(var/datum/pressurized_reaction/new_recipes as anything in subtypesof(/datum/pressurized_reaction)) + pressurized_reaction_recipes += new new_recipes + +/obj/machinery/atmospherics/components/unary/pressurized_reaction_chamber/examine(mob/user) + . = ..() + if(chosen_recipe) + . += "[chosen_recipe.name] requires:" + for(var/datum/reagent/reagent as anything in chosen_recipe.required_reagents) + var/amount = reagents.get_reagent_amount(reagent) + . += "[reagent.name]: [amount] / [chosen_recipe.required_reagents[reagent]]" + . += "[chosen_recipe.required_pressure]kPa of pressure." + +/obj/machinery/atmospherics/components/unary/pressurized_reaction_chamber/process_atmos() + if(!chosen_recipe) + return + + var/passes_all_chemicals = TRUE + for(var/datum/reagent/reagent as anything in chosen_recipe.required_reagents) + var/amount = reagents.get_reagent_amount(reagent) + if(amount < chosen_recipe.required_reagents[reagent]) + passes_all_chemicals = FALSE + break + if(!passes_all_chemicals) + return + var/datum/gas_mixture/mixture = airs[1] + var/pressure = mixture.return_pressure() + if(pressure < chosen_recipe.required_pressure) + return + + if(!processing) + playsound(get_turf(src), 'sound/effects/bubbles2.ogg', 25, TRUE) + var/list/seen = viewers(4, get_turf(src)) + var/iconhtml = icon2html(src, seen) + audible_message(span_notice("[iconhtml] The solution bubbles fiercely!")) + addtimer(CALLBACK(src, PROC_REF(create_recipe)), 7 SECONDS) + processing = TRUE + +/obj/machinery/atmospherics/components/unary/pressurized_reaction_chamber/proc/create_recipe() + processing = FALSE + for(var/datum/reagent/reagent as anything in chosen_recipe.required_reagents) + reagents.remove_all_type(reagent, chosen_recipe.required_reagents[reagent]) + + for(var/datum/reagent/reagent as anything in chosen_recipe.outputs) + reagents.add_reagent(reagent, chosen_recipe.outputs[reagent]) + +/datum/component/plumbing/pressurized_reaction_chamber + demand_connects = NORTH + supply_connects = SOUTH + +/datum/component/plumbing/pressurized_reaction_chamber/Initialize(start=TRUE, _ducting_layer, _turn_connects=TRUE, datum/reagents/custom_receiver) + . = ..() + if(!istype(parent, /obj/machinery/atmospherics/components/unary/pressurized_reaction_chamber)) + return COMPONENT_INCOMPATIBLE + +/datum/component/plumbing/pressurized_reaction_chamber/can_give(amount, reagent, datum/ductnet/net) + . = ..() + var/obj/machinery/plumbing/reaction_chamber/reaction_chamber = parent + if(!. || !reaction_chamber.emptying || reagents.is_reacting == TRUE) + return FALSE + +/datum/component/plumbing/pressurized_reaction_chamber/send_request(dir) + var/obj/machinery/atmospherics/components/unary/pressurized_reaction_chamber/chamber = parent + if(!chamber.chosen_recipe) + return + + for(var/required_reagent in chamber.chosen_recipe.required_reagents) + var/has_reagent = FALSE + for(var/datum/reagent/containg_reagent as anything in reagents.reagent_list) + if(required_reagent == containg_reagent.type) + has_reagent = TRUE + if(containg_reagent.volume + CHEMICAL_QUANTISATION_LEVEL < chamber.chosen_recipe.required_reagents[required_reagent]) + process_request(min(chamber.chosen_recipe.required_reagents[required_reagent] - containg_reagent.volume, MACHINE_REAGENT_TRANSFER) , required_reagent, dir) + return + if(!has_reagent) + process_request(min(chamber.chosen_recipe.required_reagents[required_reagent], MACHINE_REAGENT_TRANSFER), required_reagent, dir) + return diff --git a/monkestation/code/modules/factory_type_beat/machinery/brine_chamber.dm b/monkestation/code/modules/factory_type_beat/machinery/brine_chamber.dm new file mode 100644 index 000000000000..45fa27f2bde3 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/machinery/brine_chamber.dm @@ -0,0 +1,144 @@ +/obj/structure/brine_chamber + name = "brine chamber" + desc = "Converts water into brine." + icon = 'monkestation/code/modules/factory_type_beat/icons/mining_machines.dmi' + icon_state = "brine_chamber" + density = TRUE + anchored = TRUE + can_atmos_pass = ATMOS_PASS_NO + + +//pain +/obj/structure/brine_chamber/proc/assert_sprite() + var/obj/structure/brine_chamber/above = locate(/obj/structure/brine_chamber) in get_step(src, NORTH) + var/obj/structure/brine_chamber/below = locate(/obj/structure/brine_chamber) in get_step(src, SOUTH) + var/obj/structure/brine_chamber/left = locate(/obj/structure/brine_chamber) in get_step(src, WEST) + var/obj/structure/brine_chamber/right = locate(/obj/structure/brine_chamber) in get_step(src, EAST) + + if(!above && !below) + icon_state = "brine_chamber" + return + if(above && below) + icon_state = "brine_chamber_vertical" + return + if((above || below) && (left || right)) + icon_state = "brine_corner" + if(above && left) + dir = NORTH + if(above && right) + dir = SOUTH + if(below && left) + dir = WEST + if(below && right) + dir = EAST + +/obj/structure/brine_chamber/controller/assert_sprite() + return + +/obj/structure/brine_chamber/Initialize(mapload) + . = ..() + AddElement(/datum/element/give_turf_traits, string_list(list(TRAIT_BLOCK_LIQUID_SPREAD))) + +/obj/structure/brine_chamber/controller + icon_state = "brine_chamber_controller" + + var/list/turfs = list() + var/list/walls = list() + var/process_count = 0 + +/obj/structure/brine_chamber/controller/Initialize(mapload) + . = ..() + var/turf/our_turf = get_turf(src) + var/turf/inner_turf = get_step(src, NORTH) + inner_turf = get_step(inner_turf, EAST) + var/list/spawn_turfs = CORNER_OUTLINE(inner_turf, 2, 2) + var/list/full_turfs = CORNER_BLOCK(our_turf, 4, 4) + turfs = full_turfs - spawn_turfs + + for(var/turf/spawned_turf in spawn_turfs) + if(spawned_turf == our_turf) + continue + if(spawned_turf.is_blocked_turf(TRUE)) + repack() + break + var/obj/structure/brine_chamber/new_piece = new (spawned_turf) + walls += new_piece + for(var/obj/structure/brine_chamber/chamber as anything in walls) + chamber.assert_sprite() + + create_reagents(3000, TRANSPARENT) + AddComponent(/datum/component/plumbing/brine_controller) + AddComponent(/datum/component/plumbing/chemical_washer_water) + AddElement(/datum/element/repackable, item_to_pack_into = /obj/item/flatpacked_machine/ore_processing/brine_chamber, repacking_time = 3 SECONDS) + + START_PROCESSING(SSobj, src) + +/obj/structure/brine_chamber/controller/Destroy() + . = ..() + repack(TRUE) + +/obj/structure/brine_chamber/controller/process(seconds_per_tick) + if(process_count < 10) + process_count++ + return + process_count = 0 + + var/turf/inside_turf = pick(turfs) + if(reagents.total_volume) + inside_turf.add_liquid_from_reagents(reagents, FALSE, reagents.chem_temp, reagents.total_volume) + reagents.remove_all(reagents.total_volume) + if(!inside_turf?.liquids) + return + var/water_volume = inside_turf.liquids.liquid_group.reagents.get_reagent_amount(/datum/reagent/water) + inside_turf.liquids.liquid_group.reagents.remove_all_type(/datum/reagent/water, water_volume * 0.1) + inside_turf.add_liquid(/datum/reagent/brine, water_volume * 0.1, FALSE, 300) + + +/obj/structure/brine_chamber/controller/proc/repack(from_destroy = FALSE) + for(var/atom/movable/wall as anything in walls) + walls -= wall + qdel(wall) + if(!from_destroy) + new/obj/item/flatpacked_machine/ore_processing/brine_chamber(src.drop_location()) + turfs = null + + +/datum/component/plumbing/brine_controller + supply_connects = SOUTH + supply_color = COLOR_GREEN + extend_pipe_to_edge = TRUE + + ducting_layer = FOURTH_DUCT_LAYER + + +///returns TRUE when they can give the specified amount and reagent. called by process request +/datum/component/plumbing/brine_controller/can_give(amount, reagent, datum/ductnet/net) + if(amount <= 0) + return + var/obj/structure/brine_chamber/controller/host = parent + var/turf/inside_turf = pick(host.turfs) + if(!inside_turf.liquids) + return + + if(reagent) //only asked for one type of reagent + for(var/datum/reagent/contained_reagent as anything in inside_turf.liquids.liquid_group.reagents.reagent_list) + if(contained_reagent.type == reagent) + return TRUE + else if(inside_turf.liquids.liquid_group.reagents.total_volume) //take whatever + return TRUE + + return FALSE + +///this is where the reagent is actually transferred and is thus the finish point of our process() +/datum/component/plumbing/brine_controller/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net) + if(!target || !target.reagents) + return FALSE + var/obj/structure/brine_chamber/controller/host = parent + var/turf/inside_turf = pick(host.turfs) + if(!inside_turf.liquids) + return + + if(reagent) + inside_turf.liquids.liquid_group.transfer_specific_reagents(target.recipient_reagents_holder, amount, reagent) + else + inside_turf.liquids.liquid_group.transfer_specific_reagents(target.recipient_reagents_holder, amount, reagents_to_check = list(/datum/reagent/brine)) diff --git a/monkestation/code/modules/factory_type_beat/machinery/grabber.dm b/monkestation/code/modules/factory_type_beat/machinery/grabber.dm new file mode 100644 index 000000000000..21ef501f12bf --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/machinery/grabber.dm @@ -0,0 +1,506 @@ +/// Manipulator Core. Main part of the mechanism that carries out the entire process. +/obj/machinery/big_manipulator + name = "Big Manipulator" + desc = "Take and drop objects. Innovation..." + icon = 'monkestation/code/modules/factory_type_beat/icons/big_manipulator_core.dmi' + icon_state = "core" + density = TRUE + circuit = /obj/item/circuitboard/machine/big_manipulator + greyscale_colors = "#d8ce13" + greyscale_config = /datum/greyscale_config/big_manipulator + /// How many time manipulator need to take and drop item. + var/working_speed = 2 SECONDS + /// Using high tier manipulators speeds up big manipulator and requires more energy. + var/power_use_lvl = 0.2 + /// When manipulator already working with item inside he don't take any new items. + var/on_work = FALSE + /// Activate mechanism. + var/on = FALSE + /// Dir to get turf where we take items. + var/take_here = NORTH + /// Dir to get turf where we drop items. + var/drop_here = SOUTH + /// Turf where we take items. + var/turf/take_turf + /// Turf where we drop items. + var/turf/drop_turf + /// Obj inside manipulator. + var/datum/weakref/containment_obj + /// Other manipulator component. + var/obj/effect/big_manipulator_hand/manipulator_hand + ///are we hacked? + var/hacked = FALSE + ///our installed filter + var/obj/item/manipulator_filter/filter + ///our failed attempts + var/failed_attempts = 0 + var/atom/movable/failed_item + +/obj/machinery/big_manipulator/Initialize(mapload) + . = ..() + take_turf = get_step(src, take_here) + drop_turf = get_step(src, drop_here) + create_manipulator_hand() + RegisterSignal(manipulator_hand, COMSIG_QDELETING, PROC_REF(on_hand_qdel)) + manipulator_lvl() + +/obj/machinery/big_manipulator/Destroy(force) + . = ..() + failed_item = null + if(filter) + filter.forceMove(get_turf(src)) + filter = null + qdel(manipulator_hand) + if(isnull(containment_obj)) + return + var/obj/obj_resolve = containment_obj?.resolve() + if(isnull(obj_resolve)) + return + obj_resolve.forceMove(get_turf(obj_resolve)) + + +/obj/machinery/big_manipulator/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change) + . = ..() + take_and_drop_turfs_check() + if(isnull(get_turf(src))) + qdel(manipulator_hand) + return + if(!manipulator_hand) + create_manipulator_hand() + manipulator_hand.forceMove(get_turf(src)) + +/obj/machinery/big_manipulator/wrench_act(mob/living/user, obj/item/tool) + . = ..() + default_unfasten_wrench(user, tool, time = 1 SECONDS) + return TRUE + +/obj/machinery/big_manipulator/wrench_act_secondary(mob/living/user, obj/item/tool) + . = ..() + if(on_work || on) + to_chat(user, span_warning("[src] is activated!")) + return + rotate_big_hand() + playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE) + return TRUE + +/obj/machinery/big_manipulator/can_be_unfasten_wrench(mob/user, silent) + if(on_work || on) + to_chat(user, span_warning("[src] is activated!")) + return FAILED_UNFASTEN + return ..() + +/obj/machinery/big_manipulator/default_unfasten_wrench(mob/user, obj/item/wrench, time) + . = ..() + if(. == SUCCESSFUL_UNFASTEN) + take_and_drop_turfs_check() + +/obj/machinery/big_manipulator/screwdriver_act(mob/living/user, obj/item/tool) + if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool)) + return TRUE + return TRUE + +/obj/machinery/big_manipulator/crowbar_act(mob/living/user, obj/item/tool) + . = ..() + if(default_deconstruction_crowbar(tool)) + return TRUE + return TRUE + +/obj/machinery/big_manipulator/RefreshParts() + . = ..() + + manipulator_lvl() + +/// Creat manipulator hand effect on manipulator core. +/obj/machinery/big_manipulator/proc/create_manipulator_hand() + manipulator_hand = new/obj/effect/big_manipulator_hand(get_turf(src)) + manipulator_hand.dir = take_here + +/// Check servo tier and change manipulator speed, power_use and colour. +/obj/machinery/big_manipulator/proc/manipulator_lvl() + var/datum/stock_part/manipulator/locate_servo = locate() in component_parts + if(!locate_servo) + return + switch(locate_servo.tier) + if(1) + working_speed = 2 SECONDS + power_use_lvl = 0.2 + set_greyscale(COLOR_YELLOW) + manipulator_hand?.set_greyscale(COLOR_YELLOW) + if(2) + working_speed = 1.4 SECONDS + power_use_lvl = 0.4 + set_greyscale(COLOR_ORANGE) + manipulator_hand?.set_greyscale(COLOR_ORANGE) + if(3) + working_speed = 0.8 SECONDS + power_use_lvl = 0.6 + set_greyscale(COLOR_RED) + manipulator_hand?.set_greyscale(COLOR_RED) + if(4) + working_speed = 0.2 SECONDS + power_use_lvl = 0.8 + set_greyscale(COLOR_PURPLE) + manipulator_hand?.set_greyscale(COLOR_PURPLE) + + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * power_use_lvl + +/// Changing take and drop turf tiles when we anchore manipulator or if manipulator not in turf. +/obj/machinery/big_manipulator/proc/take_and_drop_turfs_check() + if(anchored && isturf(src.loc)) + take_turf = get_step(src, take_here) + drop_turf = get_step(src, drop_here) + else + take_turf = null + drop_turf = null + +/// Changing take and drop turf dirs and also changing manipulator hand sprite dir. +/obj/machinery/big_manipulator/proc/rotate_big_hand() + switch(take_here) + if(NORTH) + manipulator_hand.item_x = 64 + manipulator_hand.item_y = 32 + take_here = EAST + drop_here = WEST + if(EAST) + manipulator_hand.item_x = 32 + manipulator_hand.item_y = 0 + take_here = SOUTH + drop_here = NORTH + if(SOUTH) + manipulator_hand.item_x = 0 + manipulator_hand.item_y = 32 + take_here = WEST + drop_here = EAST + if(WEST) + manipulator_hand.item_x = -32 + manipulator_hand.item_y = 0 + take_here = NORTH + drop_here = SOUTH + manipulator_hand.dir = take_here + take_and_drop_turfs_check() + +/// Deliting hand will destroy our manipulator core. +/obj/machinery/big_manipulator/proc/on_hand_qdel() + SIGNAL_HANDLER + + deconstruct(TRUE) + +/// Pre take and drop proc from [take and drop procs loop]: +/// Check if we have item on take_turf to start take and drop loop +/obj/machinery/big_manipulator/proc/is_work_check() + if(filter) + var/atom/movable = filter_return() + if(movable) + try_take_thing(take_turf, movable) + return + + if(hacked) + for(var/mob/living/take_item in take_turf.contents) + try_take_thing(take_turf, take_item) + break + for(var/obj/take_item in take_turf.contents) + if(take_item.anchored) + continue + try_take_thing(take_turf, take_item) + break + +/obj/machinery/big_manipulator/proc/filter_return() + if(!filter) + return null + for(var/atom/movable/listed in take_turf.contents) + if(filter.check_filter(listed)) + return listed + +/// First take and drop proc from [take and drop procs loop]: +/// Check if we can take item from take_turf to work with him. This proc also calling from ATOM_ENTERED signal. +/obj/machinery/big_manipulator/proc/try_take_thing(datum/source, atom/movable/target) + SIGNAL_HANDLER + if(target == failed_item) + failed_item = null + return + + if(!on) + return + if(!anchored) + return + if(QDELETED(source) || QDELETED(target)) + return + if(on_work) + return + if(!directly_use_power(active_power_usage)) + on = FALSE + say("Not enough energy!") + return + failed_item = null + + if(filter) + if(passes_filter(target)) + start_work(target) + return + + if(isitem(target) || (isliving(target) && hacked) || (isobj(target) && !target.anchored)) + start_work(target) + +/obj/machinery/big_manipulator/proc/passes_filter(atom/movable/target) + if(!filter) + return FALSE + return filter.check_filter(target) + +/// Second take and drop proc from [take and drop procs loop]: +/// Taking our item and start manipulator hand rotate animation. +/obj/machinery/big_manipulator/proc/start_work(atom/movable/target) + target.forceMove(src) + containment_obj = WEAKREF(target) + manipulator_hand.picked = target + manipulator_hand.update_appearance() + on_work = TRUE + do_rotate_animation(1) + addtimer(CALLBACK(src, PROC_REF(drop_thing), target), working_speed) + +/// Third take and drop proc from [take and drop procs loop]: +/// Drop our item and start manipulator hand backward animation. +/obj/machinery/big_manipulator/proc/drop_thing(atom/movable/target) + if(!drop_turf.can_drop_off(target)) + failed_attempts++ + if(failed_attempts >= 10) + do_rotate_animation(0) + addtimer(CALLBACK(src, PROC_REF(end_work_failed), target), working_speed) + return + addtimer(CALLBACK(src, PROC_REF(drop_thing), target), working_speed) + return + failed_attempts = 0 + target.forceMove(drop_turf) + manipulator_hand.picked = null + manipulator_hand.update_appearance() + do_rotate_animation(0) + addtimer(CALLBACK(src, PROC_REF(end_work)), working_speed) + +/// Fourth and last take and drop proc from take and drop procs loop: +/// Finishes work and begins to look for a new item for [take and drop procs loop]. +/obj/machinery/big_manipulator/proc/end_work() + on_work = FALSE + is_work_check() + +/obj/machinery/big_manipulator/proc/end_work_failed(atom/movable/target) + target.forceMove(take_turf) + failed_item = target + manipulator_hand.picked = null + manipulator_hand.update_appearance() + on_work = FALSE + failed_attempts = 0 + is_work_check() + +/// Rotates manipulator hand 90 degrees. +/obj/machinery/big_manipulator/proc/do_rotate_animation(backward) + animate(manipulator_hand, transform = matrix(90, MATRIX_ROTATE), working_speed*0.5) + addtimer(CALLBACK(src, PROC_REF(finish_rotate_animation), backward), working_speed*0.5) + +/// Rotates manipulator hand from 90 degrees to 180 or 0 if backward. +/obj/machinery/big_manipulator/proc/finish_rotate_animation(backward) + animate(manipulator_hand, transform = matrix(180 * backward, MATRIX_ROTATE), working_speed*0.5) + +/obj/machinery/big_manipulator/ui_interact(mob/user, datum/tgui/ui) + if(!anchored) + to_chat(user, span_warning("[src] isn't attached to the ground!")) + return + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "BigManipulator") + ui.open() + +/obj/machinery/big_manipulator/AltClick(mob/user) + . = ..() + if(!filter) + return + filter.forceMove(get_turf(src)) + filter = null + +/obj/machinery/big_manipulator/ui_data(mob/user) + var/list/data = list() + data["active"] = on + return data + +/obj/machinery/big_manipulator/ui_act(action, params, datum/tgui/ui) + . = ..() + if(.) + return + switch(action) + if("on") + on = !on + if(on) + RegisterSignal(take_turf, COMSIG_ATOM_ENTERED, PROC_REF(try_take_thing)) + else + UnregisterSignal(take_turf, COMSIG_ATOM_ENTERED) + is_work_check() + return TRUE + +/// Manipulator hand. Effect we animate to show that the manipulator is working and moving something. +/obj/effect/big_manipulator_hand + name = "Manipulator claw" + desc = "Take and drop objects. Innovation..." + icon = 'monkestation/code/modules/factory_type_beat/icons/big_manipulator_hand.dmi' + icon_state = "hand" + layer = LOW_ITEM_LAYER + anchored = TRUE + appearance_flags = KEEP_TOGETHER | LONG_GLIDE | TILE_BOUND | PIXEL_SCALE + greyscale_config = /datum/greyscale_config/manipulator_hand + pixel_x = -32 + pixel_y = -32 + + ///item offset x + var/item_x = 32 + var/item_y = 64 + var/atom/movable/picked + +/obj/effect/big_manipulator_hand/update_overlays() + . = ..() + if(picked) + var/mutable_appearance/ma = mutable_appearance(picked.icon, picked.icon_state, picked.layer, src, appearance_flags = KEEP_TOGETHER) + ma.color = picked.color + ma.appearance = picked.appearance + ma.appearance_flags = appearance_flags + ma.plane = plane + ma.pixel_x = item_x + ma.pixel_y = item_y + . += ma + +/turf/proc/can_drop_off(atom/movable/target) + if(isclosedturf(src)) + return FALSE + for(var/obj/structure/listed in contents) + if(!listed.can_drop_off(target)) + return FALSE + for(var/obj/machinery/listed in contents) + if(!listed.can_drop_off(target)) + return FALSE + + return TRUE + +/obj/structure/proc/can_drop_off(atom/movable/target) + return TRUE + +/obj/machinery/proc/can_drop_off(atom/movable/target) + return TRUE + + +/obj/item/manipulator_filter + name = "manipulator filter" + desc = "A filter specifically designed to work inside of a manipulator." + + icon = 'monkestation/code/modules/factory_type_beat/icons/items.dmi' + icon_state = "filter" + + var/list/filtered_items = list() + var/max_filtered_items = 5 + + +/obj/item/manipulator_filter/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + if(istype(target, /obj/machinery/big_manipulator)) + try_attach(target) + return + + if(target == src) + return ..() + if(!proximity_flag) + return ..() + if(!ismovable(target)) + return ..() + if(istype(target, /obj/effect/decal/conveyor_sorter)) + return + if(is_type_in_list(target, filtered_items)) + to_chat(user, span_warning("[target] is already in [src]'s sorting list!")) + return + if(length(filtered_items) >= max_filtered_items) + to_chat(user, span_warning("[src] already has [max_filtered_items] things within the sorting list!")) + return + filtered_items += target.type + to_chat(user, span_notice("[target] has been added to [src]'s sorting list.")) + +/obj/item/manipulator_filter/examine(mob/user) + . = ..() + . += span_notice("This sorter can sort up to [max_filtered_items] Items.") + . += span_notice("Use Alt-Click to reset the sorting list.") + . += span_notice("Attack things to attempt to add to the sorting list.") + +/obj/item/manipulator_filter/AltClick(mob/user) + visible_message("[src] pings, resetting its sorting list!") + playsound(src, 'sound/machines/ping.ogg', 30, TRUE) + filtered_items = list() + +/obj/item/manipulator_filter/proc/try_attach(obj/machinery/big_manipulator/target) + if(target.filter) + return FALSE + target.filter = src + src.forceMove(target) + return TRUE + +/obj/item/manipulator_filter/proc/check_filter(atom/movable/target) + if(target.type in filtered_items) + return TRUE + return FALSE + + +/obj/item/manipulator_filter/cargo + name = "manipulator filter" + desc = "A filter specifically designed to work inside of a manipulator." + +/obj/item/manipulator_filter/cargo/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + if(istype(target, /obj/machinery/big_manipulator)) + try_attach(target) + return + +/obj/item/manipulator_filter/attack_self(mob/user, modifiers) + . = ..() + var/choice = tgui_input_list(user, "Add a destination to check", name, GLOB.TAGGERLOCATIONS - filtered_items) + if(!choice) + return + + if(length(filtered_items) >= max_filtered_items) + return + + filtered_items |= choice + +/obj/item/manipulator_filter/cargo/check_filter(atom/movable/target) + if(istype(target, /obj/item/delivery)) + var/obj/item/delivery/item = target + var/name_tag = GLOB.TAGGERLOCATIONS[item.sort_tag] + if(name_tag in filtered_items) + return TRUE + + if(istype(target, /obj/item/mail)) + var/obj/item/mail/item = target + var/name_tag = GLOB.TAGGERLOCATIONS[item.sort_tag] + if(name_tag in filtered_items) + return TRUE + + if(SEND_SIGNAL(target, COMSIG_FILTER_CHECK, filtered_items)) + return TRUE + + return FALSE + + +/obj/item/manipulator_filter/internal_filter + name = "internal filter" + desc = "Checks the contents inside of an object and if it matches any of the filters grabs the object" + +/obj/item/manipulator_filter/internal_filter/check_filter(atom/movable/target) + for(var/atom/movable/listed in target.contents) + if(listed.type in filtered_items) + return TRUE + return FALSE + + +/proc/departmental_destination_to_tag(destination) + switch(destination) + if(/area/station/engineering/main) + return "Engineering" + if(/area/station/science/research) + return "Research" + if(/area/station/hallway/secondary/service) + return "Hydroponics" + if(/area/station/service/bar/atrium) + return "Bar" + if(/area/station/security/office, /area/station/security/brig, /area/station/security/brig/upper) + return "Security" + if(/area/station/medical/medbay/central, /area/station/medical/medbay, /area/station/medical/treatment_center, /area/station/medical/storage) + return "Medbay" diff --git a/monkestation/code/modules/factory_type_beat/machinery/splitter.dm b/monkestation/code/modules/factory_type_beat/machinery/splitter.dm new file mode 100644 index 000000000000..14134a57a192 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/machinery/splitter.dm @@ -0,0 +1,55 @@ +/obj/structure/belt_splitter + name = "belt splitter" + desc = "takes an input from one side and tries to output it on any side that has a belt." + + icon = 'monkestation/code/modules/factory_type_beat/icons/mining_machines.dmi' + icon_state = "splitter" + + anchored = TRUE + + var/current_split_number = 1 + + var/list/direction_order = list(NORTH, EAST, SOUTH, WEST) + +/obj/structure/belt_splitter/Initialize(mapload) + . = ..() + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(try_split), + ) + AddComponent(/datum/component/connect_loc_behalf, src, loc_connections) + AddComponent(/datum/component/simple_rotation) + +/obj/structure/belt_splitter/Destroy() + . = ..() + +/obj/structure/belt_splitter/setDir() + . = ..() + rebuild_directions() + +/obj/structure/belt_splitter/wrench_act(mob/living/user, obj/item/tool) + . = ..() + default_unfasten_wrench(user, tool) + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/structure/belt_splitter/proc/rebuild_directions() + direction_order = list(NORTH, EAST, SOUTH, WEST) + direction_order -= dir + +/obj/structure/belt_splitter/proc/try_split(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs) + if(arrived.anchored) + return + var/not_passed = TRUE + var/failed_attempts = 0 + while(not_passed && failed_attempts < 10) + failed_attempts++ + var/direction = direction_order[current_split_number] + current_split_number++ + if(current_split_number > length(direction_order)) + current_split_number = 1 + if(direction == dir) + direction = direction_order[current_split_number] + + if(!(locate(/obj/machinery/conveyor) in get_step(src, direction))) + continue + arrived.forceMove(get_step(src, direction)) + not_passed = FALSE diff --git a/monkestation/code/modules/factory_type_beat/machinery/test_boulder_spawner.dm b/monkestation/code/modules/factory_type_beat/machinery/test_boulder_spawner.dm new file mode 100644 index 000000000000..24704dc1a767 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/machinery/test_boulder_spawner.dm @@ -0,0 +1,21 @@ +/obj/structure/test_boulder_spawner + name = "DEBUG BOULDER SPAWNER" + desc = "... Why? How?" + + icon = 'monkestation/code/modules/factory_type_beat/icons/mining_machines.dmi' + icon_state = "unloader-corner" + + var/spawn_dir = EAST + + var/processing = FALSE + +/obj/structure/test_boulder_spawner/attack_hand(mob/living/user, list/modifiers) + . = ..() + if(!processing) + START_PROCESSING(SSobj, src) + else + STOP_PROCESSING(SSobj, src) + +/obj/structure/test_boulder_spawner/process(seconds_per_tick) + var/atom/movable/new_item = new /obj/item/boulder/gulag_expanded(get_turf(src)) + new_item.forceMove(get_step(src, spawn_dir)) diff --git a/monkestation/code/modules/factory_type_beat/map_templates.dm b/monkestation/code/modules/factory_type_beat/map_templates.dm new file mode 100644 index 000000000000..1efe3376dcf2 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/map_templates.dm @@ -0,0 +1,30 @@ + +/datum/map_template/ruin/icemoon/underground/vent + name = "Icemoon Ore Vent" + id = "ore_vent_i" + description = "A vent that spews out ore. Seems to be a natural phenomenon." //Make this a subtype that only spawns medium and large vents. Some smalls will go to the top level. + suffix = "icemoon_underground_ore_vent.dmm" + allow_duplicates = TRUE + cost = 0 + mineral_cost = 1 + always_place = TRUE + +/datum/map_template/ruin/icemoon/ruin/vent + name = "Surface Icemoon Ore Vent" + id = "ore_vent_i" + description = "A vent that spews out ore. Seems to be a natural phenomenon. Smaller than the underground ones." + suffix = "icemoon_surface_ore_vent.dmm" + allow_duplicates = TRUE + cost = 0 + mineral_cost = 1 + always_place = TRUE + +/datum/map_template/ruin/lavaland/vent + name = "Ore Vent" + id = "ore_vent" + description = "A vent that spews out ore. Seems to be a natural phenomenon." + suffix = "lavaland_surface_ore_vent.dmm" + allow_duplicates = TRUE + cost = 0 + mineral_cost = 1 + always_place = TRUE diff --git a/monkestation/code/modules/factory_type_beat/mobs/node_drone.dm b/monkestation/code/modules/factory_type_beat/mobs/node_drone.dm new file mode 100644 index 000000000000..aeeb88729ccb --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/mobs/node_drone.dm @@ -0,0 +1,154 @@ +#define FLY_IN_STATE 1 +#define FLY_OUT_STATE 2 +#define NEUTRAL_STATE 3 + +/** + * Mining drones that are spawned when starting a ore vent's wave defense minigame. + * They will latch onto the vent to defend it from lavaland mobs, and will flee if attacked by lavaland mobs. + * If the drone survives, they will fly away to safety as the vent spawns ores. + * If the drone dies, the wave defense will fail. + */ + +/mob/living/basic/node_drone + name = "NODE drone" + desc = "Standard in-atmosphere drone, used by Nanotrasen to operate and excavate valuable ore vents." + icon = 'monkestation/code/modules/factory_type_beat/icons/mining.dmi' + icon_state = "mining_node_active" + icon_living = "mining_node_active" + icon_dead = "mining_node_active" + + maxHealth = 500 + health = 500 + density = TRUE + pass_flags = PASSTABLE|PASSGRILLE|PASSMOB + mob_size = MOB_SIZE_LARGE + mob_biotypes = MOB_ROBOTIC + faction = list(FACTION_STATION, FACTION_NEUTRAL) + light_outer_range = 4 + basic_mob_flags = DEL_ON_DEATH + + speak_emote = list("chirps") + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "clangs" + response_harm_simple = "clang against" + + ai_controller = /datum/ai_controller/basic_controller/node_drone + + /// Is the drone currently attached to a vent? + var/active_node = FALSE + /// What status do we currently track for icon purposes? + var/flying_state = NEUTRAL_STATE + /// Weakref to the vent the drone is currently attached to. + var/obj/structure/ore_vent/attached_vent = null + /// Set when the drone is begining to leave lavaland after the vent is secured. + var/escaping = FALSE + +/mob/living/basic/node_drone/death(gibbed) + . = ..() + explosion(origin = src, light_impact_range = 1, smoke = 1) + +/mob/living/basic/node_drone/Destroy() + attached_vent?.node = null //clean our reference to the vent both ways. + attached_vent = null + return ..() + + +/mob/living/basic/node_drone/examine(mob/user) + . = ..() + var/sameside = user.faction_check_atom(src, exact_match = FALSE) + if(sameside) + . += span_notice("This drone is currently attached to a mineral vent. You should protect it from harm to secure the mineral vent.") + else + . += span_warning("This vile Nanotrasen trash is trying to destroy the environment. Attack it to free the mineral vent from its grasp.") + +/mob/living/basic/node_drone/update_icon_state() + . = ..() + + icon_state = "mining_node_active" + + if(flying_state == FLY_IN_STATE || flying_state == FLY_OUT_STATE) + icon_state = "mining_node_flying" + +/mob/living/basic/node_drone/proc/arrive(obj/structure/ore_vent/parent_vent) + attached_vent = parent_vent + flying_state = FLY_IN_STATE + update_appearance(UPDATE_ICON_STATE) + pixel_z = 400 + animate(src, pixel_z = 0, time = 2 SECONDS, easing = QUAD_EASING|EASE_OUT, flags = ANIMATION_PARALLEL) + + +/** + * Called when wave defense is completed. Visually flicks the escape sprite and then deletes the mob. + */ +/mob/living/basic/node_drone/proc/escape() + var/funny_ending = FALSE + flying_state = FLY_OUT_STATE + update_appearance(UPDATE_ICON_STATE) + if(prob(1)) + say("I have to go now, my planet needs me.") + funny_ending = TRUE + visible_message(span_notice("The drone flies away to safety as the vent is secured.")) + animate(src, pixel_z = 400, time = 2 SECONDS, easing = QUAD_EASING|EASE_IN, flags = ANIMATION_PARALLEL) + sleep(2 SECONDS) + if(funny_ending) + playsound(src, 'sound/effects/explosion3.ogg', 50, FALSE) //node drone died on the way back to his home planet. + visible_message(span_notice("...or maybe not.")) + qdel(src) + + +/mob/living/basic/node_drone/proc/pre_escape() + if(attached_vent) + attached_vent.unbuckle_mob(src) + attached_vent = null + if(!escaping) + escaping = TRUE + flick("mining_node_escape", src) + addtimer(CALLBACK(src, PROC_REF(escape)), 1.9 SECONDS) + return + +/// The node drone AI controller +// Generally, this is a very simple AI that will try to find a vent and latch onto it, unless attacked by a lavaland mob, who it will try to flee from. +/datum/ai_controller/basic_controller/node_drone + blackboard = list( + BB_BASIC_MOB_FLEEING = FALSE, // Will flee when the vent lies undefended. + BB_CURRENT_HUNTING_TARGET = null, // Hunts for vents. + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, // Use this to find vents to run away from + ) + + ai_traits = STOP_MOVING_WHEN_PULLED + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = null + planning_subtrees = list( + // Priority is see if lavaland mobs are attacking us to flee from them. + /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee, + // Fly you fool + /datum/ai_planning_subtree/flee_target/node_drone, + // Otherwise, look for and execute hunts for vents to latch onto. + /datum/ai_planning_subtree/find_and_hunt_target/look_for_vent, + ) + +// Node subtree to hunt down ore vents. +/datum/ai_planning_subtree/find_and_hunt_target/look_for_vent + hunting_behavior = /datum/ai_behavior/hunt_target/latch_onto/node_drone + hunt_targets = list(/obj/structure/ore_vent) + hunt_range = 7 // Hunt vents to the end of the earth. + +// node drone behavior for buckling down on a vent. +/datum/ai_behavior/hunt_target/latch_onto/node_drone + hunt_cooldown = 5 SECONDS + +// Evasion behavior. +/datum/ai_planning_subtree/flee_target/node_drone + flee_behaviour = /datum/ai_behavior/run_away_from_target/drone + +/datum/ai_behavior/run_away_from_target/drone + action_cooldown = 1 SECONDS + run_distance = 3 + + +#undef FLY_IN_STATE +#undef FLY_OUT_STATE +#undef NEUTRAL_STATE diff --git a/monkestation/code/modules/factory_type_beat/ore_vent.dm b/monkestation/code/modules/factory_type_beat/ore_vent.dm new file mode 100644 index 000000000000..cfb933cedd8b --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/ore_vent.dm @@ -0,0 +1,525 @@ +#define MAX_ARTIFACT_ROLL_CHANCE 10 +#define MINERAL_TYPE_OPTIONS_RANDOM 4 +#define OVERLAY_OFFSET_START 0 +#define OVERLAY_OFFSET_EACH 5 +#define MINERALS_PER_BOULDER 3 + +/obj/structure/ore_vent + name = "ore vent" + desc = "An ore vent, brimming with underground ore. Scan with an advanced mining scanner to start extracting ore from it." + icon = 'monkestation/code/modules/factory_type_beat/icons/terrain.dmi' + icon_state = "ore_vent" + move_resist = MOVE_FORCE_EXTREMELY_STRONG + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF //This thing will take a beating. + anchored = TRUE + density = TRUE + can_buckle = TRUE + + /// Has this vent been tapped to produce boulders? Cannot be untapped. + var/tapped = FALSE + /// Has this vent been scanned by a mining scanner? Cannot be scanned again. Adds ores to the vent's description. + var/discovered = FALSE + /// Is this type of vent exempt from the 15 vent limit? Think the free iron/glass vent or boss vents. This also causes it to not roll for random mineral breakdown. + var/unique_vent = FALSE + /// What icon_state do we use when the ore vent has been tapped? + var/icon_state_tapped = "ore_vent_active" + + /// A weighted list of what minerals are contained in this vent, with weight determining how likely each mineral is to be picked in produced boulders. + var/list/mineral_breakdown = list() + /// What size boulders does this vent produce? + var/boulder_size = BOULDER_SIZE_SMALL + /// Reference to this ore vent's NODE drone, to track wave success. + var/mob/living/basic/node_drone/node = null //this path is a placeholder. + /// String containing the formatted list of ores that this vent can produce, and who first discovered this vent. + var/ore_string = "" + /// Associated list of vent size weights to pick from. + var/list/ore_vent_options = list( + LARGE_VENT_TYPE = 3, + MEDIUM_VENT_TYPE = 5, + SMALL_VENT_TYPE = 7, + ) + + /// What string do we use to warn the player about the excavation event? + var/excavation_warning = "Are you ready to excavate this ore vent?" + ///Are we currently spawning mobs? + var/spawning_mobs = FALSE + /// A list of mobs that can be spawned by this vent during a wave defense event. + var/list/defending_mobs = list( + /mob/living/basic/mining/goliath, + /mob/living/basic/mining/legion/spawner_made, + /mob/living/basic/mining/watcher, + /mob/living/basic/mining/lobstrosity/lava, + /mob/living/basic/mining/brimdemon, + /mob/living/basic/mining/bileworm, + ) + ///What items can be used to scan a vent? + var/static/list/scanning_equipment = list( + /obj/item/t_scanner/adv_mining_scanner, + /obj/item/mining_scanner, + ) + + /// What base icon_state do we use for this vent's boulders? + var/boulder_icon_state = "boulder" + /// Percent chance that this vent will produce an artifact boulder. + var/artifact_chance = 0 + /// We use a cooldown to prevent the wave defense from being started multiple times. + COOLDOWN_DECLARE(wave_cooldown) + COOLDOWN_DECLARE(manual_vent_cooldown) + COOLDOWN_DECLARE(next_attack) + + +/obj/structure/ore_vent/Initialize(mapload) + if(mapload) + generate_description() + register_context() + SSore_generation.possible_vents += src + boulder_icon_state = pick(list( + "boulder", + "rock", + "stone", + )) + if(tapped) + SSore_generation.processed_vents += src + icon_state = icon_state_tapped + update_appearance(UPDATE_ICON_STATE) + add_overlay(mutable_appearance('monkestation/code/modules/factory_type_beat/icons/terrain.dmi', "well", ABOVE_MOB_LAYER, src, ABOVE_MOB_LAYER)) + return ..() + +/obj/structure/ore_vent/Destroy() + SSore_generation.possible_vents -= src + node = null + if(tapped) + SSore_generation.processed_vents -= src + return ..() + +/obj/structure/ore_vent/attackby(obj/item/attacking_item, mob/user, params) + . = ..() + if(.) + return TRUE + if(!is_type_in_list(attacking_item, scanning_equipment)) + return TRUE + if(tapped) + balloon_alert_to_viewers("vent tapped!") + return TRUE + scan_and_confirm(user) + return TRUE + +/obj/structure/ore_vent/attack_hand(mob/living/user, list/modifiers) + . = ..() + if(.) + return + if(!HAS_TRAIT(user, TRAIT_BOULDER_BREAKER)) + return + if(!discovered) + to_chat(user, span_notice("You can't quite find the weakpoint of [src]... Perhaps it needs to be scanned first?")) + return + to_chat(user, span_notice("You start striking [src] with your golem's fist, attempting to dredge up a boulder...")) + for(var/i in 1 to 3) + if(do_after(user, boulder_size * 1 SECONDS, src)) + user.apply_damage(20, STAMINA) + playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) + produce_boulder(TRUE) + visible_message(span_notice("You've successfully produced a boulder! Boy are your arms tired.")) + +/obj/structure/ore_vent/attack_basic_mob(mob/user, list/modifiers) + . = ..() + if(!HAS_TRAIT(user, TRAIT_BOULDER_BREAKER)) + return + produce_boulder(TRUE) + +/obj/structure/ore_vent/is_buckle_possible(mob/living/target, force, check_loc) + . = ..() + if(tapped) + return FALSE + if(istype(target, /mob/living/basic/node_drone)) + return TRUE + +/obj/structure/ore_vent/examine(mob/user) + . = ..() + if(discovered) + switch(boulder_size) + if(BOULDER_SIZE_SMALL) + . += span_notice("This vent produces [span_bold("small")] boulders containing [ore_string]") + if(BOULDER_SIZE_MEDIUM) + . += span_notice("This vent produces [span_bold("medium")] boulders containing [ore_string]") + if(BOULDER_SIZE_LARGE) + . += span_notice("This vent produces [span_bold("large")] boulders containing [ore_string]") + else + . += span_notice("This vent can be scanned with a [span_bold("Mining Scanner")].") + +/obj/structure/ore_vent/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) + if(is_type_in_list(held_item, scanning_equipment)) + context[SCREENTIP_CONTEXT_LMB] = "Scan vent" + return CONTEXTUAL_SCREENTIP_SET + + +/** + * This proc is called when the ore vent is initialized, in order to determine what minerals boulders it spawns can contain. + * The materials available are determined by SSore_generation.ore_vent_minerals, which is a list of all minerals that can be contained in ore vents for a given cave generation. + * As a result, minerals use a weighted list as seen by ore_vent_minerals_lavaland, which is then copied to ore_vent_minerals. + * Once a material is picked from the weighted list, it's removed from ore_vent_minerals, so that it can't be picked again and provided it's own internal weight used when assigning minerals to boulders spawned by this vent. + * May also be called after the fact, as seen in SSore_generation's initialize, to add more minerals to an existing vent. + * + * The above applies only when spawning in at mapload, otherwise we pick randomly from ore_vent_minerals_lavaland. + * + * @params new_minerals How many minerals should be added to this vent? Defaults to MINERAL_TYPE_OPTIONS_RANDOM, which is 4. + * @params map_loading Is this vent being spawned in at mapload? If so, we use the ore_generation subsystem's ore_vent_minerals list to pick minerals. Otherwise, we pick randomly from ore_vent_minerals_lavaland. + */ +/obj/structure/ore_vent/proc/generate_mineral_breakdown(new_minerals = MINERAL_TYPE_OPTIONS_RANDOM, map_loading = FALSE) + if(new_minerals < 1) + CRASH("generate_mineral_breakdown called with new_minerals < 1.") + var/list/available_mats = difflist(first = SSore_generation.ore_vent_minerals, second = mineral_breakdown, skiprep = 1) + for(var/i in 1 to new_minerals) + if(!length(SSore_generation.ore_vent_minerals) && map_loading) + // We should prevent this from happening in SSore_generation, but if not then we crash here + CRASH("No minerals left to pick from! We may have spawned too many ore vents in init, or the map config in seedRuins may not have enough resources for the mineral budget.") + var/datum/material/new_material + if(map_loading) + if(length(available_mats)) + new_material = pick(GLOB.ore_vent_minerals_lavaland) + var/datum/material/surrogate_mat = pick(SSore_generation.ore_vent_minerals) + available_mats -= surrogate_mat + SSore_generation.ore_vent_minerals -= surrogate_mat + else + new_material = pick(available_mats) + available_mats -= new_material + SSore_generation.ore_vent_minerals -= new_material + else + new_material = pick(GLOB.ore_vent_minerals_lavaland) + mineral_breakdown[new_material] = rand(1, 4) + + +/** + * Returns the quantity of mineral sheets in each ore vent's boulder contents roll. + * First roll can produce the most ore, with subsequent rolls scaling lower logarithmically. + * Inversely scales with ore_floor, so that the first roll is the largest, and subsequent rolls are smaller. + * (1 -> from 16 to 7 sheets of materials, and 3 -> from 8 to 6 sheets of materials on a small vent) + * This also means a large boulder can highroll a boulder with a full stack of 50 sheets of material. + * @params ore_floor The number of minerals already rolled. Used to scale the logarithmic function. + */ +/obj/structure/ore_vent/proc/ore_quantity_function(ore_floor) + return SHEET_MATERIAL_AMOUNT * round(boulder_size * (log(rand(1 + ore_floor, 4 + ore_floor)) ** -1)) + +/** + * Starts the wave defense event, which will spawn a number of lavaland mobs based on the size of the ore vent. + * Called after the vent has been tapped by a scanning device. + * Will summon a number of waves of mobs, ending in the vent being tapped after the final wave. + */ +/obj/structure/ore_vent/proc/start_wave_defense() + AddComponent(\ + /datum/component/spawner, \ + spawn_types = defending_mobs, \ + spawn_time = (10 SECONDS + (5 SECONDS * (boulder_size/5))), \ + max_spawned = 10, \ + max_spawn_per_attempt = (1 + (boulder_size/5)), \ + spawn_text = "emerges to assault", \ + spawn_distance = 4, \ + spawn_distance_exclude = 3, \ + ) + var/wave_timer = 60 SECONDS + if(boulder_size == BOULDER_SIZE_MEDIUM) + wave_timer = 90 SECONDS + else if(boulder_size == BOULDER_SIZE_LARGE) + wave_timer = 150 SECONDS + COOLDOWN_START(src, wave_cooldown, wave_timer) + addtimer(CALLBACK(src, PROC_REF(handle_wave_conclusion)), wave_timer) + spawning_mobs = TRUE + icon_state = icon_state_tapped + update_appearance(UPDATE_ICON_STATE) + +/** + * Called when the wave defense event ends, after a variable amount of time in start_wave_defense. + * + * If the node drone is still alive, the ore vent is tapped and the ore vent will begin generating boulders. + * If the node drone is dead, the ore vent is not tapped and the wave defense can be reattempted. + * + * Also gives xp and mining points to all nearby miners in equal measure. + */ +/obj/structure/ore_vent/proc/handle_wave_conclusion() + SEND_SIGNAL(src, COMSIG_SPAWNER_STOP_SPAWNING) + COOLDOWN_RESET(src, wave_cooldown) + particles = null + if(!QDELETED(node)) ///The Node Drone has survived the wave defense, and the ore vent is tapped. + tapped = TRUE + SSore_generation.processed_vents += src + balloon_alert_to_viewers("vent tapped!") + icon_state = icon_state_tapped + update_appearance(UPDATE_ICON_STATE) + else + visible_message(span_danger("\the [src] creaks and groans as the mining attempt fails, and the vent closes back up.")) + icon_state = initial(icon_state) + update_appearance(UPDATE_ICON_STATE) + return FALSE //Bad end, try again. + + for(var/mob/living/miner in range(7, src)) //Give the miners who are near the vent points and xp. + var/obj/item/card/id/user_id_card = miner.get_idcard(TRUE) + if(miner.stat <= SOFT_CRIT) + miner.mind?.adjust_experience(/datum/skill/mining, MINING_SKILL_BOULDER_SIZE_XP * boulder_size) + if(!user_id_card) + continue + var/point_reward_val = (MINER_POINT_MULTIPLIER * boulder_size) - MINER_POINT_MULTIPLIER // We remove the base value of discovering the vent + user_id_card.registered_account.mining_points += point_reward_val + user_id_card.registered_account.bank_card_talk("You have been awarded [point_reward_val] mining points for your efforts.") + node.pre_escape() //Visually show the drone is done and flies away. + add_overlay(mutable_appearance('monkestation/code/modules/factory_type_beat/icons/terrain.dmi', "well", ABOVE_MOB_LAYER, src, GAME_PLANE)) + +/** + * Called when the ore vent is tapped by a scanning device. + * Gives a readout of the ores available in the vent that gets added to the description, + * then asks the user if they want to start wave defense if it's already been discovered. + * @params user The user who tapped the vent. + * @params scan_only If TRUE, the vent will only scan, and not prompt to start wave defense. Used by the mech mineral scanner. + */ +/obj/structure/ore_vent/proc/scan_and_confirm(mob/living/user, scan_only = FALSE) + if(tapped) + balloon_alert_to_viewers("vent tapped!") + return + if(!COOLDOWN_FINISHED(src, wave_cooldown)) + balloon_alert_to_viewers("protect the node drone!") + return + if(scan_only) + discovered = TRUE + generate_description(user) + balloon_alert_to_viewers("vent scanned!") + return + if(!discovered) + balloon_alert(user, "scanning...") + playsound(src, 'sound/items/timer.ogg', 30, TRUE) + if(do_after(user, 4 SECONDS)) + discovered = TRUE + balloon_alert(user, "vent scanned!") + generate_description(user) + var/obj/item/card/id/user_id_card = user.get_idcard(TRUE) + if(isnull(user_id_card)) + return + user_id_card.registered_account.mining_points += (MINER_POINT_MULTIPLIER) + user_id_card.registered_account.bank_card_talk("You've been awarded [MINER_POINT_MULTIPLIER] mining points for discovery of an ore vent.") + return + + if(tgui_alert(user, excavation_warning, "Begin defending ore vent?", list("Yes", "No")) != "Yes") + return + if(!COOLDOWN_FINISHED(src, wave_cooldown)) + return + //This is where we start spitting out mobs. + Shake(duration = 3 SECONDS) + node = new /mob/living/basic/node_drone(loc) + node.arrive(src) + RegisterSignal(node, COMSIG_QDELETING, PROC_REF(handle_wave_conclusion)) + particles = new /particles/smoke/ash() + + for(var/i in 1 to 5) // Clears the surroundings of the ore vent before starting wave defense. + for(var/turf/closed/mineral/rock in oview(i)) + if(istype(rock, /turf/open/misc/asteroid) && prob(35)) // so it's too common + new /obj/effect/decal/cleanable/rubble(rock) + if(prob(100 - (i * 15))) + rock.gets_drilled(user, FALSE) + if(prob(50)) + new /obj/effect/decal/cleanable/rubble(rock) + sleep(0.6 SECONDS) + + start_wave_defense() + +/** + * Generates a description of the ore vent to ore_string, based on the minerals contained within it. + * Ore_string is passed to examine(). + */ +/obj/structure/ore_vent/proc/generate_description(mob/user) + for(var/mineral_count in 1 to length(mineral_breakdown)) + var/datum/material/resource = mineral_breakdown[mineral_count] + if(mineral_count == length(mineral_breakdown)) + ore_string += "and " + span_bold(initial(resource.name)) + "." + else + ore_string += span_bold(initial(resource.name)) + ", " + if(user) + ore_string += "\nThis vent was first discovered by [user]." +/** + * Adds floating temp_visual overlays to the vent, showcasing what minerals are contained within it. + * If undiscovered, adds a single overlay with the icon_state "unknown". + */ +/obj/structure/ore_vent/proc/add_mineral_overlays() + if(mineral_breakdown.len && !discovered) + var/obj/effect/temp_visual/mining_overlay/vent/new_mat = new /obj/effect/temp_visual/mining_overlay/vent(drop_location()) + new_mat.icon_state = "unknown" + return + for(var/datum/material/selected_mat as anything in mineral_breakdown) + var/obj/effect/temp_visual/mining_overlay/vent/new_mat = new /obj/effect/temp_visual/mining_overlay/vent(drop_location()) + new_mat.icon_state = selected_mat.name + +/** + * Here is where we handle producing a new boulder, based on the qualities of this ore vent. + * Returns the boulder produced. + * @params apply_cooldown Should we apply a cooldown to producing boulders? Default's false, used by manual boulder production (goldgrubs, golems, etc). + */ +/obj/structure/ore_vent/proc/produce_boulder(apply_cooldown = FALSE) + RETURN_TYPE(/obj/item/boulder) + + if(!length(mineral_breakdown)) + generate_mineral_breakdown() + //cooldown applies only for manual processing by hand + if(apply_cooldown && !COOLDOWN_FINISHED(src, manual_vent_cooldown)) + return + var/obj/item/boulder/new_rock + if(prob(artifact_chance)) + new_rock = new /obj/item/boulder/artifact(loc) + else + new_rock = new /obj/item/boulder(loc) + //decorate the boulder with materials + var/list/mats_list = list() + for(var/iteration in 1 to MINERALS_PER_BOULDER) + var/datum/material/material = pick_weight(mineral_breakdown) + mats_list[material] += ore_quantity_function(iteration) + new_rock.set_custom_materials(mats_list) + + //set size & durability + new_rock.boulder_size = boulder_size + new_rock.durability = rand(2, boulder_size) //randomize durability a bit for some flavor. + new_rock.boulder_string = boulder_icon_state + new_rock.update_appearance(UPDATE_ICON_STATE) + if(apply_cooldown) + COOLDOWN_START(src, manual_vent_cooldown, 10 SECONDS) + return new_rock + + +//comes with the station, and is already tapped. +/obj/structure/ore_vent/starter_resources + name = "active ore vent" + desc = "An ore vent, brimming with underground ore. It's already supplying the station with iron and glass." + tapped = TRUE + discovered = TRUE + unique_vent = TRUE + boulder_size = BOULDER_SIZE_SMALL + mineral_breakdown = list( + /datum/material/iron = 50, + /datum/material/glass = 50, + ) + +/obj/structure/ore_vent/random + +/obj/structure/ore_vent/random/Initialize(mapload) + . = ..() + if(!unique_vent && !mapload) + generate_mineral_breakdown(map_loading = mapload) //Default to random mineral breakdowns, unless this is a unique vent or we're still setting up default vent distribution. + generate_description() + artifact_chance = rand(0, MAX_ARTIFACT_ROLL_CHANCE) + var/string_boulder_size = pick_weight(ore_vent_options) + name = "[string_boulder_size] ore vent" + switch(string_boulder_size) + if(LARGE_VENT_TYPE) + boulder_size = BOULDER_SIZE_LARGE + if(mapload) + SSore_generation.ore_vent_sizes["large"] += 1 + if(MEDIUM_VENT_TYPE) + boulder_size = BOULDER_SIZE_MEDIUM + if(mapload) + SSore_generation.ore_vent_sizes["medium"] += 1 + if(SMALL_VENT_TYPE) + boulder_size = BOULDER_SIZE_SMALL + if(mapload) + SSore_generation.ore_vent_sizes["small"] += 1 + else + boulder_size = BOULDER_SIZE_SMALL //Might as well set a default value + name = initial(name) + + + +/obj/structure/ore_vent/random/icebox //The one that shows up on the top level of icebox + icon_state = "ore_vent_ice" + icon_state_tapped = "ore_vent_ice_active" + defending_mobs = list( + /mob/living/basic/mining/lobstrosity, + /mob/living/basic/mining/legion/snow/spawner_made, + /mob/living/simple_animal/hostile/asteroid/polarbear, + /mob/living/basic/mining/wolf, + ) + ore_vent_options = list( + SMALL_VENT_TYPE = 1, + ) + +/obj/structure/ore_vent/random/icebox/lower + defending_mobs = list( + /mob/living/basic/mining/ice_whelp, + /mob/living/basic/mining/lobstrosity, + /mob/living/basic/mining/legion/snow/spawner_made, + /mob/living/basic/mining/ice_demon, + /mob/living/simple_animal/hostile/asteroid/polarbear, + /mob/living/basic/mining/wolf, + ) + ore_vent_options = list( + SMALL_VENT_TYPE = 3, + MEDIUM_VENT_TYPE = 5, + LARGE_VENT_TYPE = 7, + ) + + +/obj/structure/ore_vent/boss + name = "menacing ore vent" + desc = "An ore vent, brimming with underground ore. This one has an evil aura about it. Better be careful." + unique_vent = TRUE + boulder_size = BOULDER_SIZE_LARGE + mineral_breakdown = list( // All the riches of the world, eeny meeny boulder room. + /datum/material/iron = 1, + /datum/material/glass = 1, + /datum/material/plasma = 1, + /datum/material/titanium = 1, + /datum/material/silver = 1, + /datum/material/gold = 1, + /datum/material/diamond = 1, + /datum/material/uranium = 1, + /datum/material/bluespace = 1, + /datum/material/plastic = 1, + ) + defending_mobs = list( + /mob/living/simple_animal/hostile/megafauna/bubblegum, + /mob/living/simple_animal/hostile/megafauna/dragon, + /mob/living/simple_animal/hostile/megafauna/colossus, + ) + excavation_warning = "Something big is nearby. Are you ABSOLUTELY ready to excavate this ore vent?" + ///What boss do we want to spawn? + var/summoned_boss = null + +/obj/structure/ore_vent/boss/Initialize(mapload) + . = ..() + summoned_boss = pick(defending_mobs) + +/obj/structure/ore_vent/boss/examine(mob/user) + . = ..() + var/boss_string = "" + switch(summoned_boss) + if(/mob/living/simple_animal/hostile/megafauna/bubblegum) + boss_string = "A giant fleshbound beast" + if(/mob/living/simple_animal/hostile/megafauna/dragon) + boss_string = "Sharp teeth and scales" + if(/mob/living/simple_animal/hostile/megafauna/colossus) + boss_string = "A giant, armored behemoth" + if(/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner) + boss_string = "A bloody drillmark" + if(/mob/living/simple_animal/hostile/megafauna/wendigo) + boss_string = "A chilling skull" + . += span_notice("[boss_string] is etched onto the side of the vent.") + +/obj/structure/ore_vent/boss/start_wave_defense() + // Completely override the normal wave defense, and just spawn the boss. + var/mob/living/simple_animal/hostile/megafauna/boss = new summoned_boss(loc) + RegisterSignal(boss, COMSIG_LIVING_DEATH, PROC_REF(handle_wave_conclusion)) + COOLDOWN_START(src, wave_cooldown, INFINITY) //Basically forever + //boss.say(boss.summon_line) //Pull their specific summon line to say. Default is meme text so make sure that they have theirs set already. + +/obj/structure/ore_vent/boss/handle_wave_conclusion() + node = new /mob/living/basic/node_drone(loc) //We're spawning the vent after the boss dies, so the player can just focus on the boss. + COOLDOWN_RESET(src, wave_cooldown) + return ..() + +/obj/structure/ore_vent/boss/icebox + icon_state = "ore_vent_ice" + icon_state_tapped = "ore_vent_ice_active" + defending_mobs = list( + /mob/living/simple_animal/hostile/megafauna/demonic_frost_miner, + /mob/living/simple_animal/hostile/megafauna/wendigo, + /mob/living/simple_animal/hostile/megafauna/colossus, + ) + +#undef MAX_ARTIFACT_ROLL_CHANCE +#undef MINERAL_TYPE_OPTIONS_RANDOM +#undef OVERLAY_OFFSET_START +#undef OVERLAY_OFFSET_EACH +#undef MINERALS_PER_BOULDER diff --git a/monkestation/code/modules/factory_type_beat/processing/bouldertech.dm b/monkestation/code/modules/factory_type_beat/processing/bouldertech.dm new file mode 100644 index 000000000000..2b6618990787 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/processing/bouldertech.dm @@ -0,0 +1,380 @@ +/obj/machinery/bouldertech + name = "bouldertech brand refining machine" + desc = "You shouldn't be seeing this! And bouldertech isn't even a real company!" + icon = 'monkestation/code/modules/factory_type_beat/icons/mining_machines.dmi' + icon_state = "ore_redemption" + anchored = TRUE + density = TRUE + + /// What is the efficiency of minerals produced by the machine? + var/refining_efficiency = 1 + /// How many boulders can we process maximum per loop? + var/boulders_processing_max = 1 + /// What boulder(s) are we holding? + var/list/boulders_contained = list() + /// How many boulders can we hold maximum? + var/boulders_held_max = 1 + /// Does this machine have a mineral storage link to the silo? + var/holds_minerals = FALSE + /// What materials do we accept and process out of boulders? Removing iron from an iron/glass boulder would leave a boulder with glass. + var/list/processable_materials = list() + /* + /// If we get a boulder with one of these inside, we'll drop it back out. + var/static/list/drop_if_contained = list( + /obj/item/relic, + ) + */ + /// What sound plays when a thing operates? + var/usage_sound = 'sound/machines/mining/wooping_teleport.ogg' + /// Cooldown associated with the usage_sound played. + COOLDOWN_DECLARE(sound_cooldown) + + /// Silo link to it's materials list. + var/datum/component/remote_materials/silo_materials + ///Does this machine hold mining points? + var/holds_mining_points = FALSE + /// Mining points held by the machine for miners. + var/points_held = 0 + ///our export side + var/export_side = EAST + ///do we allow boulders + var/allows_boulders = TRUE + var/next_allowed_process = 0 + var/process_string + +/obj/machinery/bouldertech/Initialize(mapload) + . = ..() + register_context() + if(holds_minerals) + silo_materials = AddComponent(/datum/component/remote_materials, "bouldertech", mapload, force_connect = TRUE, mat_container_flags=BREAKDOWN_FLAGS_ORM) + AddComponent(/datum/component/simple_rotation) + +/obj/machinery/bouldertech/LateInitialize() + . = ..() + if(!holds_minerals) + return + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered), + ) + AddElement(/datum/element/connect_loc, loc_connections) + +/obj/machinery/bouldertech/add_context(atom/source, list/context, obj/item/held_item, mob/user) + var/processable = "Accepts: " + if(allows_boulders) + processable += "Boulders" + if(process_string) + if(allows_boulders) + processable += ", " + processable += process_string + + context[SCREENTIP_CONTEXT_MISC] = processable + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/bouldertech/Destroy() + boulders_contained = null + silo_materials = null + return ..() + +/obj/machinery/bouldertech/update_icon_state() + . = ..() + icon_state ="[initial(icon_state)]" + +/obj/machinery/bouldertech/wrench_act(mob/living/user, obj/item/tool) + . = ..() + if(default_unfasten_wrench(user, tool, time = 1.5 SECONDS) == SUCCESSFUL_UNFASTEN) + update_appearance(UPDATE_ICON_STATE) + START_PROCESSING(SSmachines, src) + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/machinery/bouldertech/screwdriver_act(mob/living/user, obj/item/tool) + . = ..() + if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-off", initial(icon_state), tool)) + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/machinery/bouldertech/crowbar_act(mob/living/user, obj/item/tool) + . = ..() + if(default_pry_open(tool, close_after_pry = TRUE, closed_density = FALSE)) + return TOOL_ACT_TOOLTYPE_SUCCESS + if(default_deconstruction_crowbar(tool)) + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/machinery/bouldertech/attackby(obj/item/attacking_item, mob/user, params) + if(holds_minerals && istype(attacking_item, /obj/item/boulder)) + var/obj/item/boulder/my_boulder = attacking_item + update_boulder_count() + if(!accept_boulder(my_boulder)) + balloon_alert_to_viewers("full!") + return + balloon_alert_to_viewers("accepted") + START_PROCESSING(SSmachines, src) + return TRUE + if(istype(attacking_item, /obj/item/card/id) && holds_mining_points) + if(points_held <= 0) + balloon_alert_to_viewers("no points to claim!") + if(!COOLDOWN_FINISHED(src, sound_cooldown)) + return TRUE + COOLDOWN_START(src, sound_cooldown, 1.5 SECONDS) + playsound(src, 'sound/machines/buzz-sigh.ogg', 30, FALSE) + return FALSE + var/obj/item/card/id/id_card = attacking_item + var/amount = tgui_input_number(user, "How many mining points do you wish to claim? ID Balance: [id_card.registered_account.mining_points], stored mining points: [points_held]", "Transfer Points", max_value = points_held, min_value = 0, round_value = 1) + if(!amount) + return TRUE + if(amount > points_held) + amount = points_held + id_card.registered_account.mining_points += amount + points_held = round(points_held - amount) + to_chat(user, span_notice("You claim [amount] mining points from \the [src] to [id_card].")) + return TRUE + return ..() + +/obj/machinery/bouldertech/attack_hand_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + if(!anchored) + balloon_alert(user, "anchor first!") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + if(!holds_minerals) + return SECONDARY_ATTACK_CONTINUE_CHAIN + if(!length(boulders_contained)) + balloon_alert_to_viewers("No boulders to remove!") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + remove_boulder(pick(boulders_contained)) + return SECONDARY_ATTACK_CONTINUE_CHAIN + +/obj/machinery/bouldertech/deconstruct(disassembled) + . = ..() + if(length(contents)) + for(var/obj/item/boulder/boulder in contents) + remove_boulder(boulder) + +/obj/machinery/bouldertech/process() + if(!anchored) + return PROCESS_KILL + var/stop_processing_check = FALSE + var/boulders_concurrent = boulders_processing_max ///How many boulders can we touch this process() call + for(var/obj/item/potential_boulder as anything in boulders_contained) + if(QDELETED(potential_boulder)) + boulders_contained -= potential_boulder + break + if(boulders_concurrent <= 0) + break //Try again next time + + if(!istype(potential_boulder, /obj/item/boulder)) + potential_boulder.forceMove(drop_location()) + CRASH("\The [src] had a non-boulder in it's boulders contained!") + + var/obj/item/boulder/boulder = potential_boulder + if(boulder.durability < 0) + CRASH("\The [src] had a boulder with negative durability!") + if(!check_for_processable_materials(boulder.custom_materials)) //Checks for any new materials we can process. + boulders_concurrent-- //We count skipped boulders + remove_boulder(boulder) + continue + boulders_concurrent-- + boulder.durability-- //One less durability to the processed boulder. + if(COOLDOWN_FINISHED(src, sound_cooldown)) + COOLDOWN_START(src, sound_cooldown, 1.5 SECONDS) + playsound(loc, usage_sound, 29, FALSE, SHORT_RANGE_SOUND_EXTRARANGE) //This can get annoying. One play per process() call. + stop_processing_check = TRUE + if(boulder.durability <= 0) + breakdown_boulder(boulder) //Crack that bouwlder open! + continue + if(!stop_processing_check) + playsound(src.loc, 'sound/machines/ping.ogg', 50, FALSE) + return PROCESS_KILL + + +/obj/machinery/bouldertech/CanAllowThrough(atom/movable/mover, border_dir) + if(!anchored) + return FALSE + if(allows_boulders) + if(boulders_contained.len >= boulders_held_max) + return FALSE + if(istype(mover, /obj/item/boulder)) + var/obj/item/boulder/boulder = mover + return boulder.can_get_processed() + return ..() + +/obj/machinery/bouldertech/examine(mob/user) + . = ..() + if(holds_mining_points) + . += span_notice("The machine reads that it has [span_bold("[points_held] mining points")] stored. Swipe an ID to claim them.") + +/** + * Accepts a boulder into the machinery, then converts it into minerals. + * If the boulder can be fully processed by this machine, we take the materials, insert it into the silo, and destroy the boulder. + * If the boulder has materials left, we make a copy of the boulder to hold the processable materials, take the processable parts, and eject the original boulder. + * @param chosen_boulder The boulder to being breaking down into minerals. + */ +/obj/machinery/bouldertech/proc/breakdown_boulder(obj/item/boulder/chosen_boulder) + if(QDELETED(chosen_boulder)) + return FALSE + if(chosen_boulder.loc != src) + return FALSE + if(!length(chosen_boulder.custom_materials)) + qdel(chosen_boulder) + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + update_boulder_count() + return FALSE + if(isnull(silo_materials)) + return FALSE + + //here we loop through the boulder's ores + var/list/processable_ores = list() + var/tripped = FALSE + //If a material is in the boulder's custom_materials, but not in the processable_materials list, we add it to the processable_ores list to add back to a leftover boulder. + for(var/datum/material/possible_mat as anything in chosen_boulder.custom_materials) + if(!is_type_in_list(possible_mat, processable_materials)) + continue + var/quantity = chosen_boulder.custom_materials[possible_mat] + points_held = round((points_held + (quantity * possible_mat.points_per_unit * MINING_POINT_MACHINE_MULTIPLIER))) // put point total here into machine + processable_ores += possible_mat + processable_ores[possible_mat] = quantity + chosen_boulder.custom_materials -= possible_mat //Remove it from the boulder now that it's tracked + tripped = TRUE + if(!tripped) + remove_boulder(chosen_boulder) + say("Nothing to process!") + return FALSE //we shouldn't spend more time processing a boulder with contents we don't care about. + use_power(BASE_MACHINE_ACTIVE_CONSUMPTION) + check_for_boosts() //Calls the relevant behavior for boosting the machine's efficiency, if able. + var/is_artifact = (istype(chosen_boulder, /obj/item/boulder/artifact)) //We need to know if it's an artifact so we can carry it over to the new boulder. + var/obj/item/boulder/disposable_boulder = new (src) + disposable_boulder.custom_materials = processable_ores + silo_materials.mat_container.insert_item(disposable_boulder, refining_efficiency) + qdel(disposable_boulder) + + refining_efficiency = initial(refining_efficiency) //Reset refining efficiency to 100% now that we've processed any relevant ores. + if(!length(chosen_boulder.custom_materials)) + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + if(is_artifact) + points_held = round((points_held + MINER_POINT_MULTIPLIER) * MINING_POINT_MACHINE_MULTIPLIER) /// Artifacts give bonus points! + chosen_boulder.break_apart() + update_boulder_count() + return TRUE //We've processed all the materials in the boulder, so we can just destroy it in break_apart. + + chosen_boulder.restart_processing_cooldown() //So that we don't pick it back up! + chosen_boulder.durability = rand(chosen_boulder.boulder_size, chosen_boulder.boulder_size + BOULDER_SIZE_SMALL) //Reset durability to a random value between the boulder's size and a little more. + remove_boulder(chosen_boulder) + return TRUE + +/** + * Accepts a boulder into the machine. Used when a boulder is first placed into the machine. + * @param new_boulder The boulder to be accepted. + */ +/obj/machinery/bouldertech/proc/accept_boulder(obj/item/boulder/new_boulder) + if(isnull(new_boulder)) + return FALSE + if(boulders_contained.len >= boulders_held_max) //Full already + return FALSE + if(!istype(new_boulder) && !check_extras(new_boulder)) //Can't be processed + return FALSE + if(!new_boulder.custom_materials) //Shouldn't happen, but just in case. + qdel(new_boulder) + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + return FALSE + new_boulder.forceMove(src) + boulders_contained += new_boulder + SSore_generation.available_boulders -= new_boulder + START_PROCESSING(SSmachines, src) //Starts processing if we aren't already. + return TRUE + +/obj/machinery/bouldertech/proc/check_extras(obj/item/item) + return FALSE + +/** + * Ejects a boulder from the machine. Used when a boulder is finished processing, or when a boulder can't be processed. + * @param drop_turf The location to eject the boulder to. If null, it will eject to the machine's drop_location(). + * @param specific_boulder The boulder to be ejected. + */ +/obj/machinery/bouldertech/proc/remove_boulder(obj/item/boulder/specific_boulder, turf/drop_turf = null) + if(isnull(specific_boulder)) + CRASH("remove_boulder() called with no boulder!") + if(!length(specific_boulder.custom_materials)) + qdel(specific_boulder) + update_boulder_count() + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + return FALSE + specific_boulder.restart_processing_cooldown() //Reset the cooldown so we don't pick it back up by the same machine. + if(isturf(drop_turf)) + specific_boulder.forceMove(drop_turf) + else + specific_boulder.forceMove(drop_location()) + if(!update_boulder_count()) + return TRUE + STOP_PROCESSING(SSmachines, src) + balloon_alert_to_viewers("clear!") + playsound(loc, 'sound/machines/ping.ogg', 50, FALSE) + return TRUE + +/obj/machinery/bouldertech/can_drop_off() + if(length(boulders_contained) >= boulders_held_max) + return FALSE + return TRUE + +/** + * Getter proc to determine how many boulders are contained in the machine. + * Also adds their reference to the boulders_contained list. + */ +/obj/machinery/bouldertech/proc/update_boulder_count() + boulders_contained = list() + for(var/obj/item/boulder/boulder in contents) + boulders_contained += boulder + if(length(return_extras())) + boulders_contained |= return_extras() + return boulders_contained.len + +/obj/machinery/bouldertech/proc/return_extras() + return list() + +/obj/machinery/bouldertech/proc/on_entered(datum/source, atom/movable/atom_movable) + SIGNAL_HANDLER + INVOKE_ASYNC(src, PROC_REF(accept_boulder), atom_movable) + +/** + * Looks for a boost to the machine's efficiency, and applies it if found. + * Applied more on the chemistry integration but can be used for other things if desired. + */ +/obj/machinery/bouldertech/proc/check_for_boosts() + refining_efficiency = initial(refining_efficiency) //Reset refining efficiency to 100%. + +/** + * Checks if a custom_material is in a list of processable materials in the machine. + * @param list/custom_material A list of materials, presumably taken from a boulder. If a material that this machine can process is in this list, it will return true, inclusively. + */ +/obj/machinery/bouldertech/proc/check_for_processable_materials(list/boulder_mats) + for(var/material as anything in boulder_mats) + if(is_type_in_list(material, processable_materials)) + return TRUE + return FALSE + +///Beacon to launch a new mining setup when activated. For testing and speed! +/obj/item/boulder_beacon + name = "boulder beacon" + desc = "N.T. approved boulder beacon, toss it down and you will have a full bouldertech mining station." + icon = 'icons/obj/objects.dmi' + icon_state = "floor_beacon" + /// Number of activations left on this beacon. Uses will be removed as the beacon is used and each triggers a different machine to be spawned from it. + var/uses = 3 + +/obj/item/boulder_beacon/attack_self() + loc.visible_message(span_warning("\The [src] begins to beep loudly!")) + addtimer(CALLBACK(src, PROC_REF(launch_payload)), 1 SECONDS) + +/** + * Spawns a new bouldertech machine from the beacon, then removes a use from the beacon. + * Use one spawns a BRM teleporter, then a refinery, and lastly a smelter. + */ +/obj/item/boulder_beacon/proc/launch_payload() + playsound(src, SFX_SPARKS, 80, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + switch(uses) + if(3) + new /obj/machinery/bouldertech/brm(drop_location()) + if(2) + new /obj/machinery/bouldertech/refinery(drop_location()) + if(1) + new /obj/machinery/bouldertech/refinery/smelter(drop_location()) + qdel(src) + uses-- diff --git a/monkestation/code/modules/factory_type_beat/processing/brm.dm b/monkestation/code/modules/factory_type_beat/processing/brm.dm new file mode 100644 index 000000000000..2791bd39c8cb --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/processing/brm.dm @@ -0,0 +1,201 @@ +#define MANUAL_TELEPORT_SOUND 'sound/machines/mining/manual_teleport.ogg' +#define AUTO_TELEPORT_SOUND 'sound/machines/mining/auto_teleport.ogg' + +/datum/wires/brm + holder_type = /obj/machinery/bouldertech/brm + proper_name = "Boulder Retrieval Matrix" + +/datum/wires/brm/New(atom/holder) + add_duds(1) + return ..() + +/datum/wires/brm/on_pulse(wire) + var/obj/machinery/bouldertech/brm/brm_holder = holder + if(brm_holder.panel_open) + return + brm_holder.toggle_auto_on() + +/obj/machinery/bouldertech/brm + name = "boulder retrieval matrix" + desc = "A teleportation matrix used to retrieve boulders excavated by mining NODEs from ore vents." + icon_state = "brm" + circuit = /obj/item/circuitboard/machine/brm + usage_sound = MANUAL_TELEPORT_SOUND + processing_flags = START_PROCESSING_MANUALLY + boulders_held_max = 2 + /// Are we trying to actively collect boulders automatically? + var/toggled_on = FALSE + /// How long does it take to collect a boulder? + var/teleportation_time = 1.5 SECONDS + /// Cooldown used for left click teleportation. + COOLDOWN_DECLARE(manual_teleport_cooldown) + +/obj/machinery/bouldertech/brm/Initialize(mapload) + . = ..() + set_wires(new /datum/wires/brm(src)) + +/obj/machinery/bouldertech/brm/Destroy() + QDEL_NULL(wires) + return ..() + +/obj/machinery/bouldertech/brm/attack_hand(mob/living/user, list/modifiers) + . = ..() + if(!handle_teleport_conditions(user)) + return + pre_collect_boulder() + + COOLDOWN_START(src, manual_teleport_cooldown, teleportation_time) + +/obj/machinery/bouldertech/brm/attack_robot(mob/user) + if(!handle_teleport_conditions(user)) + return + pre_collect_boulder() + + COOLDOWN_START(src, manual_teleport_cooldown, teleportation_time) + +/obj/machinery/bouldertech/brm/attackby(obj/item/attacking_item, mob/user, params) + if(is_wire_tool(attacking_item) && panel_open) + wires.interact(user) + return TRUE + return ..() + +/obj/machinery/bouldertech/brm/attack_hand_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + if(!anchored) + balloon_alert(user, "anchor first!") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + toggle_auto_on(user) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/machinery/bouldertech/brm/attack_robot_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + if(!anchored) + balloon_alert(user, "anchor first!") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + toggle_auto_on(user) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/machinery/bouldertech/brm/process() + if(SSore_generation.available_boulders.len < 1) + say("No boulders to collect. Entering idle mode.") + toggled_on = FALSE + update_appearance(UPDATE_ICON_STATE) + return PROCESS_KILL + for(var/i in 1 to boulders_processing_max) + if(pre_collect_boulder()) + continue + toggled_on = FALSE + update_appearance(UPDATE_ICON_STATE) + return PROCESS_KILL + for(var/obj/item/boulder/ground_rocks in loc.contents) + boulders_contained += ground_rocks + if(boulders_contained.len < boulders_held_max) + continue + toggled_on = FALSE + boulders_contained.Cut() + update_appearance(UPDATE_ICON_STATE) + return PROCESS_KILL + +/obj/machinery/bouldertech/brm/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + context[SCREENTIP_CONTEXT_LMB] = "Teleport single boulder" + context[SCREENTIP_CONTEXT_RMB] = "Toggle automatic boulder retrieval" + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/bouldertech/brm/examine(mob/user) + . = ..() + . += span_notice("The small screen reads there are [span_boldnotice("[SSore_generation.available_boulders.len] boulders")] available to teleport.") + +/obj/machinery/bouldertech/brm/RefreshParts() + . = ..() + var/scanner_stack = 0 + var/laser_stack = 0 + for(var/datum/stock_part/scanning_module/scanner in component_parts) + scanner_stack += scanner.tier + boulders_processing_max = scanner_stack + for(var/datum/stock_part/micro_laser/laser in component_parts) + laser_stack += laser.tier + boulders_held_max = laser_stack + 1 + +/obj/machinery/bouldertech/brm/update_icon_state() + if(toggled_on && !panel_open) + icon_state = "[initial(icon_state)]-toggled" + return + return ..() + +/** + * Handles qualifiers for enabling teleportation of boulders. + * Returns TRUE if the teleportation can proceed, FALSE otherwise. + */ +/obj/machinery/bouldertech/brm/proc/handle_teleport_conditions(mob/user) + if(!COOLDOWN_FINISHED(src, manual_teleport_cooldown)) + return FALSE + if(panel_open) + balloon_alert(user, "close panel first!") + return FALSE + playsound(src, MANUAL_TELEPORT_SOUND, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + return TRUE + +/** + * Begins to collect a boulder from the available boulders list in SSore_generation. + * Boulders must not be processed by another BRM or machine, and must be in the available boulders list. + * A selected boulder is picked randomly. + * The actual movement is then handled by collect_boulder() after a timed callback. + */ +/obj/machinery/bouldertech/brm/proc/pre_collect_boulder() + if(!length(SSore_generation.available_boulders)) + playsound(loc, 'sound/machines/synth_no.ogg', 30 , TRUE) + balloon_alert_to_viewers("no boulders to collect!") + return FALSE //Nothing to collect + var/obj/item/boulder/random_boulder = pick(SSore_generation.available_boulders) + if(random_boulder.processed_by) + return FALSE + + random_boulder.processed_by = src + random_boulder.Shake(duration = 1.5 SECONDS) + SSore_generation.available_boulders -= random_boulder + addtimer(CALLBACK(src, PROC_REF(collect_boulder), random_boulder), 1.5 SECONDS) + return TRUE + +/** + * Collects a boulder from the available boulders list in SSore_generation. + * Handles the movement of the boulder as well as visual effects on the BRM. + * @param obj/item/boulder/random_boulder The boulder to collect. + */ +/obj/machinery/bouldertech/brm/proc/collect_boulder(obj/item/boulder/random_boulder) + flick("brm-flash", src) + if(QDELETED(random_boulder)) + playsound(loc, 'sound/machines/synth_no.ogg', 30 , TRUE) + balloon_alert_to_viewers("target lost!") + return FALSE + playsound(src, AUTO_TELEPORT_SOUND, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + random_boulder.forceMove(drop_location()) + random_boulder.processed_by = null + random_boulder.pixel_x = rand(-2, 2) + random_boulder.pixel_y = rand(-2, 2) + balloon_alert_to_viewers("boulder appears!") + random_boulder.visible_message(span_warning("[random_boulder] suddenly appears!")) + use_power(BASE_MACHINE_ACTIVE_CONSUMPTION * 0.1) + return TRUE + +/** + * Toggles automatic boulder retrieval on. + * Adjusts the teleportation sound, icon state, and begins processing. + * @param mob/user The user who toggled the BRM. + */ +/obj/machinery/bouldertech/brm/proc/toggle_auto_on(mob/user) + if(panel_open) + if(user) + balloon_alert(user, "close panel first!") + return + toggled_on = TRUE + START_PROCESSING(SSmachines, src) + update_appearance(UPDATE_ICON_STATE) + usage_sound = AUTO_TELEPORT_SOUND + +#undef MANUAL_TELEPORT_SOUND +#undef AUTO_TELEPORT_SOUND diff --git a/monkestation/code/modules/factory_type_beat/processing/checmial_washer.dm b/monkestation/code/modules/factory_type_beat/processing/checmial_washer.dm new file mode 100644 index 000000000000..230ba5fd34f5 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/processing/checmial_washer.dm @@ -0,0 +1,137 @@ +/obj/machinery/bouldertech/chemical_washer + name = "chemical washer" + desc = "Crushes clumps of ore into dirty dust which needs to be enriched." + icon_state = "washer" + allows_boulders = FALSE + holds_minerals = TRUE + process_string = "Water, Dirty Slurry" + processable_materials = list( + /datum/material/iron, + /datum/material/titanium, + /datum/material/silver, + /datum/material/gold, + /datum/material/uranium, + /datum/material/mythril, + /datum/material/adamantine, + /datum/material/runite, + /datum/material/glass, + /datum/material/plasma, + /datum/material/diamond, + /datum/material/bluespace, + /datum/material/bananium, + /datum/material/plastic, + ) + var/maximum_volume = 1000 + var/water_per_use = 100 + +/obj/machinery/bouldertech/chemical_washer/Initialize(mapload) + . = ..() + create_reagents(maximum_volume, TRANSPARENT) + AddComponent(/datum/component/plumbing/chemical_washer) + AddComponent(/datum/component/plumbing/chemical_washer_water) + +/obj/machinery/bouldertech/chemical_washer/process() + if(!anchored) + return + if(reagents.total_volume < water_per_use) + return + process_slurry() + + +/obj/machinery/bouldertech/chemical_washer/proc/process_slurry() + var/processed = FALSE + for(var/datum/reagent/processing/dirty_slurry/slurry as anything in reagents.reagent_list) + if(!istype(slurry)) + continue + + if(!slurry.data["materials"]) + continue + var/list/slurry_data = slurry.data + var/slurry_volume = slurry.volume + + reagents.remove_all_type(slurry.type, slurry.volume) + reagents.add_reagent(/datum/reagent/processing/clean_slurry, slurry_volume, slurry_data) + processed = TRUE + + + if(processed) + reagents.remove_all_type(/datum/reagent/water, water_per_use) + + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + update_boulder_count() + +/datum/component/plumbing/chemical_washer + demand_connects = WEST + supply_connects = EAST + +/datum/component/plumbing/chemical_washer/send_request(dir) + var/atom/movable/host = parent + + var/slurry_amount = host.reagents.get_reagent_amount(/datum/reagent/processing/dirty_slurry) + process_request(amount = max(500 - slurry_amount, 0), reagent = /datum/reagent/processing/dirty_slurry, dir = dir) + +///check who can give us what we want, and how many each of them will give us +/datum/component/plumbing/chemical_washer/process_request(amount = MACHINE_REAGENT_TRANSFER, reagent, dir) + //find the duct to take from + var/datum/ductnet/net + if(!ducts.Find(num2text(dir))) + return + net = ducts[num2text(dir)] + + var/atom/movable/host = parent + + var/datum/reagent/processing/requested_reagent + + for(var/datum/reagent/listed as anything in host.reagents.reagent_list) + if(istype(reagent, /datum/reagent/processing/clean_slurry)) + return + + for(var/datum/reagent/listed as anything in host.reagents.reagent_list) + if(!reagent) + break + if(reagent == listed.type) + requested_reagent = listed + break + //find all valid suppliers in the duct + var/list/valid_suppliers = list() + for(var/datum/component/plumbing/supplier as anything in net.suppliers) + var/failed = FALSE + if(requested_reagent) + var/atom/movable/supplier_host = supplier.parent + for(var/datum/reagent/supplier_listed as anything in supplier_host.reagents.reagent_list) + if(supplier_listed.type != reagent) + continue + if(supplier_listed.data["materials"] != requested_reagent.data["materials"]) + failed = TRUE + break + var/material = supplier_listed.data["materials"] + var/quantity = supplier_listed.data["materials"][material] + if(quantity != requested_reagent.data["materials"][material]) + failed = TRUE + break + if(failed) + continue + if(supplier.can_give(amount, reagent, net)) + valid_suppliers += supplier + var/suppliersLeft = valid_suppliers.len + if(!suppliersLeft) + return + + //take an equal amount from each supplier + var/currentRequest + var/target_volume = reagents.total_volume + amount + for(var/datum/component/plumbing/give as anything in valid_suppliers) + currentRequest = (target_volume - reagents.total_volume) / suppliersLeft + give.transfer_to(src, currentRequest, reagent, net) + suppliersLeft-- + +/datum/component/plumbing/chemical_washer_water + demand_connects = SOUTH + demand_color = COLOR_BLUE + + ducting_layer = SECOND_DUCT_LAYER + +/datum/component/plumbing/chemical_washer_water/send_request(dir) + var/atom/movable/host = parent + var/water_amount = host.reagents.get_reagent_amount(/datum/reagent/water) + process_request(amount = max(500 - water_amount, 0), reagent = /datum/reagent/water, dir = dir) diff --git a/monkestation/code/modules/factory_type_beat/processing/chemical_injector.dm b/monkestation/code/modules/factory_type_beat/processing/chemical_injector.dm new file mode 100644 index 000000000000..c193c02e516c --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/processing/chemical_injector.dm @@ -0,0 +1,165 @@ +/obj/machinery/bouldertech/chemical_injector + name = "chemical injector" + desc = "Crushes shards when infused with brine." + icon_state = "chemical_injection" + allows_boulders = FALSE + holds_minerals = TRUE + process_string = "Brine" + processable_materials = list( + /datum/material/iron, + /datum/material/titanium, + /datum/material/silver, + /datum/material/gold, + /datum/material/uranium, + /datum/material/mythril, + /datum/material/adamantine, + /datum/material/runite, + /datum/material/glass, + /datum/material/plasma, + /datum/material/diamond, + /datum/material/bluespace, + /datum/material/bananium, + /datum/material/plastic, + ) + var/maximum_volume = 1000 + var/brine_per_use = 25 + var/crystal_inside = FALSE + +/obj/machinery/bouldertech/chemical_injector/update_icon_state() + . = ..() + if(crystal_inside) + icon_state = "chemical_injection-inject" + else + icon_state = "chemical_injection" + +/obj/machinery/bouldertech/chemical_injector/update_overlays() + . = ..() + if(crystal_inside) + . += mutable_appearance(icon, "chemical_injection-crystal") + +/obj/machinery/bouldertech/chemical_injector/Initialize(mapload) + . = ..() + create_reagents(maximum_volume, TRANSPARENT) + AddComponent(/datum/component/plumbing/chemical_injector_brine) + +/obj/machinery/bouldertech/chemical_injector/process() + if(!anchored) + return PROCESS_KILL + + if(next_allowed_process > world.time) + return + + if(reagents.total_volume < brine_per_use) + return + + if(crystal_inside) + return + + var/stop_processing_check = FALSE + var/boulders_concurrent = boulders_processing_max ///How many boulders can we touch this process() call + for(var/obj/item/potential_boulder as anything in boulders_contained) + + if(istype(potential_boulder, /obj/item/processing/amalgam)) + next_allowed_process = world.time + 30 SECONDS + visible_message(span_danger("The machine gets clogged with [potential_boulder]! Disabling it for 30 Seconds.")) + + if(QDELETED(potential_boulder)) + boulders_contained -= potential_boulder + break + if(boulders_concurrent <= 0) + break //Try again next time + + if(!istype(potential_boulder, /obj/item/boulder)) + crystal_inside = TRUE + update_appearance() + addtimer(CALLBACK(src, PROC_REF(process_crystal), potential_boulder), 2.6 SECONDS) + continue + + var/obj/item/boulder/boulder = potential_boulder + if(boulder.durability < 0) + CRASH("\The [src] had a boulder with negative durability!") + if(!check_for_processable_materials(boulder.custom_materials)) //Checks for any new materials we can process. + boulders_concurrent-- //We count skipped boulders + remove_boulder(boulder) + continue + boulders_concurrent-- + boulder.durability-- //One less durability to the processed boulder. + if(COOLDOWN_FINISHED(src, sound_cooldown)) + COOLDOWN_START(src, sound_cooldown, 1.5 SECONDS) + playsound(loc, usage_sound, 29, FALSE, SHORT_RANGE_SOUND_EXTRARANGE) //This can get annoying. One play per process() call. + stop_processing_check = TRUE + if(boulder.durability <= 0) + export_shard(boulder) //Crack that bouwlder open! + continue + if(!stop_processing_check) + playsound(src.loc, 'sound/machines/ping.ogg', 50, FALSE) + return PROCESS_KILL + + +/obj/machinery/bouldertech/chemical_injector/proc/process_crystal(obj/item/processing/crystals/clump) + for(var/datum/material/material as anything in clump.custom_materials) + var/quantity = clump.custom_materials[material] + var/obj/item/processing/shards/dust = new(get_turf(src)) + dust.custom_materials = list() + dust.custom_materials += material + dust.custom_materials[material] = quantity + dust.set_colors() + dust.forceMove(get_step(src, export_side)) + + crystal_inside = FALSE + reagents.remove_all(brine_per_use) + qdel(clump) + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + update_boulder_count() + +/obj/machinery/bouldertech/chemical_injector/CanAllowThrough(atom/movable/mover, border_dir) + if(!anchored) + return FALSE + if(boulders_contained.len >= boulders_held_max) + return FALSE + if(istype(mover, /obj/item/processing/crystals)) + return TRUE + if(istype(mover, /obj/item/processing/amalgam)) + return TRUE + return ..() + +/obj/machinery/bouldertech/chemical_injector/return_extras() + var/list/boulders_contained = list() + for(var/obj/item/processing/crystals/boulder in contents) + boulders_contained += boulder + for(var/obj/item/processing/amalgam/amalgam in contents) + boulders_contained += amalgam + return boulders_contained + +/obj/machinery/bouldertech/chemical_injector/check_extras(obj/item/item) + if(istype(item, /obj/item/processing/crystals)) + return TRUE + if(istype(item, /obj/item/processing/amalgam)) + return TRUE + return FALSE + +/obj/machinery/bouldertech/chemical_injector/proc/export_shard(obj/item/boulder/boulder) + for(var/datum/material/material as anything in boulder.custom_materials) + var/quantity = boulder.custom_materials[material] + for(var/i = 1 to 4) + var/obj/item/processing/shards/dust = new(get_turf(src)) + dust.custom_materials = list() + dust.custom_materials += material + dust.custom_materials[material] = quantity + dust.set_colors() + dust.forceMove(get_step(src, export_side)) + + reagents.remove_all(brine_per_use) + qdel(boulder) + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + update_boulder_count() + + +/datum/component/plumbing/chemical_injector_brine + demand_connects = SOUTH + demand_color = COLOR_YELLOW + + ducting_layer = SECOND_DUCT_LAYER + +/datum/component/plumbing/chemical_injector_brine/send_request(dir) + process_request(amount = MACHINE_REAGENT_TRANSFER, reagent = /datum/reagent/brine, dir = dir) diff --git a/monkestation/code/modules/factory_type_beat/processing/crusher.dm b/monkestation/code/modules/factory_type_beat/processing/crusher.dm new file mode 100644 index 000000000000..3cffe8985509 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/processing/crusher.dm @@ -0,0 +1,72 @@ +/obj/machinery/bouldertech/crusher + name = "crusher" + desc = "Crushes clumps of ore into dirty dust which needs to be enriched." + icon_state = "crusher" + allows_boulders = FALSE + holds_minerals = TRUE + process_string = "Clumps" + processable_materials = list( + /datum/material/iron, + /datum/material/titanium, + /datum/material/silver, + /datum/material/gold, + /datum/material/uranium, + /datum/material/mythril, + /datum/material/adamantine, + /datum/material/runite, + /datum/material/glass, + /datum/material/plasma, + /datum/material/diamond, + /datum/material/bluespace, + /datum/material/bananium, + /datum/material/plastic, + ) + +/obj/machinery/bouldertech/crusher/process() + if(!anchored) + return PROCESS_KILL + var/boulders_concurrent = boulders_processing_max ///How many boulders can we touch this process() call + for(var/obj/item/potential_boulder as anything in boulders_contained) + if(QDELETED(potential_boulder)) + boulders_contained -= potential_boulder + break + if(boulders_concurrent <= 0) + break //Try again next time + + if(!istype(potential_boulder, /obj/item/boulder)) + process_clump(potential_boulder) + continue + +/obj/machinery/bouldertech/crusher/proc/process_clump(obj/item/processing/clumps/clump) + for(var/datum/material/material as anything in clump.custom_materials) + var/quantity = clump.custom_materials[material] + var/obj/item/processing/dirty_dust/dust = new(get_turf(src)) + dust.custom_materials = list() + dust.custom_materials += material + dust.custom_materials[material] = quantity + dust.set_colors() + dust.forceMove(get_step(src, export_side)) + + qdel(clump) + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + update_boulder_count() + +/obj/machinery/bouldertech/crusher/CanAllowThrough(atom/movable/mover, border_dir) + if(!anchored) + return FALSE + if(boulders_contained.len >= boulders_held_max) + return FALSE + if(istype(mover, /obj/item/processing/clumps)) + return TRUE + return ..() + +/obj/machinery/bouldertech/crusher/return_extras() + var/list/boulders_contained = list() + for(var/obj/item/processing/clumps/boulder in contents) + boulders_contained += boulder + return boulders_contained + +/obj/machinery/bouldertech/crusher/check_extras(obj/item/item) + if(istype(item, /obj/item/processing/clumps)) + return TRUE + return FALSE diff --git a/monkestation/code/modules/factory_type_beat/processing/crystalizer.dm b/monkestation/code/modules/factory_type_beat/processing/crystalizer.dm new file mode 100644 index 000000000000..d1ee831350d1 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/processing/crystalizer.dm @@ -0,0 +1,140 @@ +/obj/machinery/bouldertech/crystalizer + name = "crystalizer" + desc = "Crushes clumps of ore into dirty dust which needs to be enriched." + icon_state = "crystalizer" + allows_boulders = FALSE + holds_minerals = TRUE + process_string = "Clean Slurry" + processable_materials = list( + /datum/material/iron, + /datum/material/titanium, + /datum/material/silver, + /datum/material/gold, + /datum/material/uranium, + /datum/material/mythril, + /datum/material/adamantine, + /datum/material/runite, + /datum/material/glass, + /datum/material/plasma, + /datum/material/diamond, + /datum/material/bluespace, + /datum/material/bananium, + /datum/material/plastic, + ) + var/maximum_volume = 50 + var/crystalized_reagent = 50 + var/processes_left = 3 + var/crystal_in_progress = FALSE + +/obj/machinery/bouldertech/crystalizer/Initialize(mapload) + . = ..() + create_reagents(maximum_volume, TRANSPARENT) + AddComponent(/datum/component/plumbing/material_crystalizer) + +/obj/machinery/bouldertech/crystalizer/update_overlays() + . = ..() + . += mutable_appearance(icon, "crystalizer-glass", layer + 0.2, src) + + if(crystal_in_progress) + . += mutable_appearance(icon, "crystalizer-crystal", layer, src) + . += mutable_appearance(icon, "crystalizer-[processes_left]") + +/obj/machinery/bouldertech/crystalizer/process() + if(!anchored) + return + if(reagents.total_volume < crystalized_reagent) + crystal_in_progress = FALSE + return + crystal_in_progress = TRUE + if(processes_left > 0) + processes_left-- + update_appearance() + return + + processes_left = 3 + process_slurry() + reagents.remove_all_type(/datum/reagent/processing/clean_slurry, crystalized_reagent) + crystal_in_progress = FALSE + update_appearance() + + +/obj/machinery/bouldertech/crystalizer/proc/process_slurry() + for(var/datum/reagent/processing/clean_slurry/slurry as anything in reagents.reagent_list) + if(!istype(slurry)) + continue + if(!slurry.data["materials"]) + continue + for(var/item in slurry.data["materials"]) + var/material = item + var/quantity = slurry.data["materials"][material] + var/obj/item/processing/crystals/dust = new(get_turf(src)) + dust.custom_materials = list() + dust.custom_materials += material + dust.custom_materials[material] = quantity + dust.set_colors() + dust.forceMove(get_step(src, export_side)) + if(prob(15)) + new /obj/item/processing/amalgam(get_step(src, export_side)) + + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + update_boulder_count() + +/datum/component/plumbing/material_crystalizer + demand_connects = WEST + +/datum/component/plumbing/material_crystalizer/send_request(dir) + var/atom/movable/host = parent + var/reagents_left = host.reagents.maximum_volume - host.reagents.total_volume + process_request(amount = reagents_left, reagent = /datum/reagent/processing/clean_slurry, dir = dir) + +///check who can give us what we want, and how many each of them will give us +/datum/component/plumbing/material_crystalizer/process_request(amount = MACHINE_REAGENT_TRANSFER, reagent, dir) + //find the duct to take from + var/datum/ductnet/net + if(!ducts.Find(num2text(dir))) + return + net = ducts[num2text(dir)] + + var/atom/movable/host = parent + + var/datum/reagent/processing/requested_reagent + + for(var/datum/reagent/listed as anything in host.reagents.reagent_list) + if(!reagent) + break + if(reagent == listed.type) + requested_reagent = listed + break + + //find all valid suppliers in the duct + var/list/valid_suppliers = list() + for(var/datum/component/plumbing/supplier as anything in net.suppliers) + var/failed = FALSE + if(requested_reagent) + var/atom/movable/supplier_host = supplier.parent + for(var/datum/reagent/supplier_listed as anything in supplier_host.reagents.reagent_list) + if(supplier_listed.type != reagent) + continue + if(supplier_listed.data["materials"] != requested_reagent.data["materials"]) + failed = TRUE + break + var/material = supplier_listed.data["materials"] + var/quantity = supplier_listed.data["materials"][material] + if(quantity != requested_reagent.data["materials"][material]) + failed = TRUE + break + if(failed) + continue + if(supplier.can_give(amount, reagent, net)) + valid_suppliers += supplier + var/suppliersLeft = valid_suppliers.len + if(!suppliersLeft) + return + + //take an equal amount from each supplier + var/currentRequest + var/target_volume = reagents.total_volume + amount + for(var/datum/component/plumbing/give as anything in valid_suppliers) + currentRequest = (target_volume - reagents.total_volume) / suppliersLeft + give.transfer_to(src, currentRequest, reagent, net) + suppliersLeft-- diff --git a/monkestation/code/modules/factory_type_beat/processing/dissolution_chamber.dm b/monkestation/code/modules/factory_type_beat/processing/dissolution_chamber.dm new file mode 100644 index 000000000000..2f6e6c357790 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/processing/dissolution_chamber.dm @@ -0,0 +1,96 @@ +/obj/machinery/bouldertech/dissolution_chamber + name = "dissolution chamber" + desc = "Crushes shards when infused with brine." + icon_state = "dissolution" + holds_minerals = TRUE + process_string = "Sulfuric Acid" + processable_materials = list( + /datum/material/iron, + /datum/material/titanium, + /datum/material/silver, + /datum/material/gold, + /datum/material/uranium, + /datum/material/mythril, + /datum/material/adamantine, + /datum/material/runite, + /datum/material/glass, + /datum/material/plasma, + /datum/material/diamond, + /datum/material/bluespace, + /datum/material/bananium, + /datum/material/plastic, + ) + var/maximum_volume = 3000 + var/acid_per_use = 100 + +/obj/machinery/bouldertech/dissolution_chamber/Initialize(mapload) + . = ..() + create_reagents(maximum_volume, TRANSPARENT) + AddComponent(/datum/component/plumbing/dissolution_chamber) + AddComponent(/datum/component/plumbing/dissolution_chamber_output) + +/obj/machinery/bouldertech/dissolution_chamber/process() + if(!anchored) + return PROCESS_KILL + + + if(reagents.total_volume < acid_per_use) + return + + var/stop_processing_check = FALSE + var/boulders_concurrent = boulders_processing_max ///How many boulders can we touch this process() call + for(var/obj/item/potential_boulder as anything in boulders_contained) + if(QDELETED(potential_boulder)) + boulders_contained -= potential_boulder + break + if(boulders_concurrent <= 0) + break //Try again next time + + var/obj/item/boulder/boulder = potential_boulder + if(boulder.durability < 0) + CRASH("\The [src] had a boulder with negative durability!") + if(!check_for_processable_materials(boulder.custom_materials)) //Checks for any new materials we can process. + boulders_concurrent-- //We count skipped boulders + remove_boulder(boulder) + continue + boulders_concurrent-- + boulder.durability-- //One less durability to the processed boulder. + if(COOLDOWN_FINISHED(src, sound_cooldown)) + COOLDOWN_START(src, sound_cooldown, 1.5 SECONDS) + playsound(loc, usage_sound, 29, FALSE, SHORT_RANGE_SOUND_EXTRARANGE) //This can get annoying. One play per process() call. + stop_processing_check = TRUE + if(boulder.durability <= 0) + export_slurry(boulder) //Crack that bouwlder open! + reagents.remove_all_type(/datum/reagent/toxin/acid, acid_per_use) + continue + if(!stop_processing_check) + playsound(src.loc, 'sound/machines/ping.ogg', 50, FALSE) + return PROCESS_KILL + +/obj/machinery/bouldertech/dissolution_chamber/proc/export_slurry(obj/item/boulder/boulder) + for(var/datum/material/material as anything in boulder.custom_materials) + var/list/data = list() + data |= material + data[material] = boulder.custom_materials[material] + var/list/material_data = list() + material_data += "materials" + material_data["materials"] = data + reagents.add_reagent(/datum/reagent/processing/dirty_slurry, 250, material_data) + + qdel(boulder) + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + update_boulder_count() + +/datum/component/plumbing/dissolution_chamber + demand_connects = SOUTH + demand_color = COLOR_YELLOW + + ducting_layer = SECOND_DUCT_LAYER + +/datum/component/plumbing/dissolution_chamber/send_request(dir) + var/atom/movable/host = parent + var/reagents_left = host.reagents.get_reagent_amount(/datum/reagent/toxin/acid) + process_request(amount = max(2500 - reagents_left, 0), reagent = /datum/reagent/toxin/acid, dir = dir) + +/datum/component/plumbing/dissolution_chamber_output + supply_connects = EAST diff --git a/monkestation/code/modules/factory_type_beat/processing/enricher.dm b/monkestation/code/modules/factory_type_beat/processing/enricher.dm new file mode 100644 index 000000000000..7bc80bdb2e97 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/processing/enricher.dm @@ -0,0 +1,105 @@ +/obj/machinery/bouldertech/enricher + name = "enrichment chamber" + desc = "enriches boulders into dust which can then de smelted at a smelter for double the materials." + icon_state = "enricher" + holds_minerals = TRUE + process_string = "Dirty Dust" + processable_materials = list( + /datum/material/iron, + /datum/material/titanium, + /datum/material/silver, + /datum/material/gold, + /datum/material/uranium, + /datum/material/mythril, + /datum/material/adamantine, + /datum/material/runite, + /datum/material/glass, + /datum/material/plasma, + /datum/material/diamond, + /datum/material/bluespace, + /datum/material/bananium, + /datum/material/plastic, + ) + +/obj/machinery/bouldertech/enricher/process() + if(!anchored) + return PROCESS_KILL + var/stop_processing_check = FALSE + var/boulders_concurrent = boulders_processing_max ///How many boulders can we touch this process() call + for(var/obj/item/potential_boulder as anything in boulders_contained) + if(QDELETED(potential_boulder)) + boulders_contained -= potential_boulder + break + if(boulders_concurrent <= 0) + break //Try again next time + + if(!istype(potential_boulder, /obj/item/boulder)) + process_dirty_dust(potential_boulder) + continue + + var/obj/item/boulder/boulder = potential_boulder + if(boulder.durability < 0) + CRASH("\The [src] had a boulder with negative durability!") + if(!check_for_processable_materials(boulder.custom_materials)) //Checks for any new materials we can process. + boulders_concurrent-- //We count skipped boulders + remove_boulder(boulder) + continue + boulders_concurrent-- + boulder.durability-- //One less durability to the processed boulder. + if(COOLDOWN_FINISHED(src, sound_cooldown)) + COOLDOWN_START(src, sound_cooldown, 1.5 SECONDS) + playsound(loc, usage_sound, 29, FALSE, SHORT_RANGE_SOUND_EXTRARANGE) //This can get annoying. One play per process() call. + stop_processing_check = TRUE + if(boulder.durability <= 0) + export_dust(boulder) //Crack that bouwlder open! + continue + if(!stop_processing_check) + playsound(src.loc, 'sound/machines/ping.ogg', 50, FALSE) + return PROCESS_KILL + +/obj/machinery/bouldertech/enricher/proc/export_dust(obj/item/boulder/boulder) + for(var/datum/material/material as anything in boulder.custom_materials) + var/quantity = boulder.custom_materials[material] + for(var/i = 1 to 2) + var/obj/item/processing/refined_dust/dust = new(get_turf(src)) + dust.custom_materials = list() + dust.custom_materials += material + dust.custom_materials[material] = quantity + dust.set_colors() + dust.forceMove(get_step(src, export_side)) + qdel(boulder) + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + update_boulder_count() + +/obj/machinery/bouldertech/enricher/proc/process_dirty_dust(obj/item/processing/dirty_dust/dirty_dust) + for(var/datum/material/material as anything in dirty_dust.custom_materials) + var/quantity = dirty_dust.custom_materials[material] + var/obj/item/processing/refined_dust/dust = new(get_turf(src)) + dust.custom_materials = list() + dust.custom_materials += material + dust.custom_materials[material] = quantity + dust.set_colors() + dust.forceMove(get_step(src, export_side)) + qdel(dirty_dust) + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + update_boulder_count() + +/obj/machinery/bouldertech/enricher/CanAllowThrough(atom/movable/mover, border_dir) + if(!anchored) + return FALSE + if(boulders_contained.len >= boulders_held_max) + return FALSE + if(istype(mover, /obj/item/processing/dirty_dust)) + return TRUE + return ..() + +/obj/machinery/bouldertech/enricher/return_extras() + var/list/boulders_contained = list() + for(var/obj/item/processing/dirty_dust/boulder in contents) + boulders_contained += boulder + return boulders_contained + +/obj/machinery/bouldertech/enricher/check_extras(obj/item/item) + if(istype(item, /obj/item/processing/dirty_dust)) + return TRUE + return FALSE diff --git a/monkestation/code/modules/factory_type_beat/processing/holding_types.dm b/monkestation/code/modules/factory_type_beat/processing/holding_types.dm new file mode 100644 index 000000000000..2f5b06312397 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/processing/holding_types.dm @@ -0,0 +1,59 @@ +/obj/item/processing + name = "generic" + desc = "oopsie" + icon = 'monkestation/code/modules/factory_type_beat/icons/processing.dmi' + icon_state = "dust" + +/obj/item/processing/proc/set_colors() + for(var/datum/material/material as anything in custom_materials) + color = material.greyscale_colors + alpha = material.alpha + +/obj/item/processing/refined_dust + name = "refined dust" + desc = "After being enriched it has turned into some dust." + +/obj/item/processing/dirty_dust + name = "dirty dust" + desc = "After crushing some clumps we are left with this." + icon = 'monkestation/icons/obj/items/drugs.dmi' + icon_state = "crack" + +/obj/item/processing/clumps + name = "ore clumps" + desc = "After being purified we are left with some clumps of ore." + icon_state = "clump" + +/obj/item/processing/shards + name = "ore shards" + desc = "After being filled with chemicals we are left with some shards of ores." + icon_state = "shard" + +/obj/item/processing/crystals + name = "ore crystals" + desc = "After crystalizing some clean slurry we have crystals." + icon_state = "crystal" + +/datum/reagent/processing + name = "Generic Processing Reagent" + data = list("materials" = list()) + +/datum/reagent/processing/dirty_slurry + name = "Dirty Slurry" + +/datum/reagent/processing/clean_slurry + name = "Clean Slurry" + +/datum/reagent/brine + name = "Brine" + + +/obj/item/processing/amalgam + name = "ore amalgam" + desc = "Pretty useless and jams up your processing." + icon_state = "dust" + +/obj/item/processing/ruined_shard + name = "ruined shard" + desc = "Pretty useless and jams up your processing." + icon_state = "dust" diff --git a/monkestation/code/modules/factory_type_beat/processing/purification_chamber.dm b/monkestation/code/modules/factory_type_beat/processing/purification_chamber.dm new file mode 100644 index 000000000000..13e577032420 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/processing/purification_chamber.dm @@ -0,0 +1,167 @@ +#define REQUIRED_OXYGEN_MOLES 25 +/obj/machinery/bouldertech/purification_chamber + name = "purification chamber" + desc = "Uses a large amount of oxygen to purify ores into clumps." + icon_state = "purification_chamber" + holds_minerals = TRUE + process_string = "Shards" + processable_materials = list( + /datum/material/iron, + /datum/material/titanium, + /datum/material/silver, + /datum/material/gold, + /datum/material/uranium, + /datum/material/mythril, + /datum/material/adamantine, + /datum/material/runite, + /datum/material/glass, + /datum/material/plasma, + /datum/material/diamond, + /datum/material/bluespace, + /datum/material/bananium, + /datum/material/plastic, + ) + + var/oxygen_moles = 0 + var/obj/machinery/portable_atmospherics/purification_input/oxygen_input + +/obj/machinery/bouldertech/purification_chamber/AltClick(mob/user) + . = ..() + if(oxygen_input) + oxygen_input.disconnect() + QDEL_NULL(oxygen_input) + + var/side = tgui_input_list(user, "Choose a side to try and deploy the tank on", "[name]", list("North", "South")) + if(!side) + return + + var/direction = NORTH + if(side == "South") + direction = SOUTH + + if(!(locate(/obj/machinery/atmospherics/components/unary/portables_connector) in get_step(src, direction))) + return + + oxygen_input = new(get_step(src, direction)) + var/obj/machinery/atmospherics/components/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/components/unary/portables_connector) in oxygen_input.loc + if(!oxygen_input.connect(possible_port)) + QDEL_NULL(oxygen_input) + +/obj/machinery/bouldertech/purification_chamber/process() + if(!anchored) + return PROCESS_KILL + + if(oxygen_input) + oxygen_input.air_contents.assert_gas(/datum/gas/oxygen, oxygen_input.air_contents) + oxygen_moles = oxygen_input.air_contents.gases[/datum/gas/oxygen][MOLES] + + if(oxygen_moles < REQUIRED_OXYGEN_MOLES) + return + + var/stop_processing_check = FALSE + var/boulders_concurrent = boulders_processing_max ///How many boulders can we touch this process() call + for(var/obj/item/potential_boulder as anything in boulders_contained) + if(oxygen_input) + oxygen_input.air_contents.remove_specific(/datum/gas/oxygen, REQUIRED_OXYGEN_MOLES) + + if(QDELETED(potential_boulder)) + boulders_contained -= potential_boulder + break + if(boulders_concurrent <= 0) + break //Try again next time + + if(!istype(potential_boulder, /obj/item/boulder)) + process_shard(potential_boulder) + continue + + var/obj/item/boulder/boulder = potential_boulder + if(boulder.durability < 0) + CRASH("\The [src] had a boulder with negative durability!") + if(!check_for_processable_materials(boulder.custom_materials)) //Checks for any new materials we can process. + boulders_concurrent-- //We count skipped boulders + remove_boulder(boulder) + continue + boulders_concurrent-- + boulder.durability-- //One less durability to the processed boulder. + if(COOLDOWN_FINISHED(src, sound_cooldown)) + COOLDOWN_START(src, sound_cooldown, 1.5 SECONDS) + playsound(loc, usage_sound, 29, FALSE, SHORT_RANGE_SOUND_EXTRARANGE) //This can get annoying. One play per process() call. + stop_processing_check = TRUE + if(boulder.durability <= 0) + export_clump(boulder) //Crack that bouwlder open! + continue + if(!stop_processing_check) + playsound(src.loc, 'sound/machines/ping.ogg', 50, FALSE) + return PROCESS_KILL + + +/obj/machinery/bouldertech/purification_chamber/proc/process_shard(obj/item/processing/shards/shard) + for(var/datum/material/material as anything in shard.custom_materials) + var/quantity = shard.custom_materials[material] + var/obj/item/processing/clumps/dust = new(get_turf(src)) + dust.custom_materials = list() + dust.custom_materials += material + dust.custom_materials[material] = quantity + dust.set_colors() + dust.forceMove(get_step(src, export_side)) + + qdel(shard) + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + update_boulder_count() + +/obj/machinery/bouldertech/purification_chamber/proc/export_clump(obj/item/boulder/boulder) + for(var/datum/material/material as anything in boulder.custom_materials) + var/quantity = boulder.custom_materials[material] + for(var/i = 1 to 3) + var/obj/item/processing/clumps/dust = new(get_turf(src)) + dust.custom_materials = list() + dust.custom_materials += material + dust.custom_materials[material] = quantity + dust.set_colors() + dust.forceMove(get_step(src, export_side)) + + qdel(boulder) + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + update_boulder_count() + +/obj/machinery/bouldertech/purification_chamber/CanAllowThrough(atom/movable/mover, border_dir) + if(!anchored) + return FALSE + if(boulders_contained.len >= boulders_held_max) + return FALSE + if(istype(mover, /obj/item/processing/shards)) + return TRUE + return ..() + +/obj/machinery/bouldertech/purification_chamber/return_extras() + var/list/boulders_contained = list() + for(var/obj/item/processing/shards/boulder in contents) + boulders_contained += boulder + return boulders_contained + +/obj/machinery/bouldertech/purification_chamber/check_extras(obj/item/item) + if(istype(item, /obj/item/processing/shards)) + return TRUE + return FALSE + +#undef REQUIRED_OXYGEN_MOLES + +/obj/machinery/portable_atmospherics/purification_input + name = "external purification oxygen tank" + icon = 'monkestation/code/modules/factory_type_beat/icons/mining_machines.dmi' + icon_state = "air_pump" + pressure_resistance = 7 * ONE_ATMOSPHERE + volume = 2000 + density = TRUE + max_integrity = 300 + integrity_failure = 0.4 + armor_type = /datum/armor/portable_atmospherics_canister + + +/obj/machinery/portable_atmospherics/purification_input/Initialize(mapload) + . = ..() + AddElement(/datum/element/atmos_sensitive, mapload) + AddElement(/datum/element/volatile_gas_storage) + AddComponent(/datum/component/gas_leaker, leak_rate=0.01) + + SSair.start_processing_machine(src) diff --git a/monkestation/code/modules/factory_type_beat/processing/refinery.dm b/monkestation/code/modules/factory_type_beat/processing/refinery.dm new file mode 100644 index 000000000000..0908d7f21dab --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/processing/refinery.dm @@ -0,0 +1,175 @@ +/** + * Your new favorite industrial waste magnet! + * Accepts boulders and produces sheets of non-metalic materials. + * Can be upgraded with stock parts or through chemical inputs. + * When upgraded, it can hold more boulders and process more at once. + * + * Chemical inputs can be used to boost the refinery's efficiency, but produces industrial waste, which eats through the station and is generally difficult to store. + */ + +/obj/machinery/bouldertech/refinery + name = "boulder refinery" + desc = "BR for short. Accepts boulders and refines non-metallic ores into sheets using internal chemicals. Can be upgraded with stock parts or through chemical inputs." + icon_state = "stacker" + holds_minerals = TRUE + processable_materials = list( + /datum/material/glass, + /datum/material/plasma, + /datum/material/diamond, + /datum/material/bluespace, + /datum/material/bananium, + /datum/material/plastic, + ) + circuit = /obj/item/circuitboard/machine/refinery + usage_sound = 'sound/machines/mining/refinery.ogg' + holds_mining_points = TRUE + +/// okay so var that holds mining points to claim +/// add total of pts from minerals mined in parent proc +/// then, little mini UI showing points to collect? + +/obj/machinery/bouldertech/refinery/RefreshParts() + . = ..() + var/manipulator_stack = 0 + var/matter_bin_stack = 0 + for(var/datum/stock_part/manipulator/servo in component_parts) + manipulator_stack += servo.tier - 1 + boulders_processing_max = clamp(manipulator_stack, 1, 6) + for(var/datum/stock_part/matter_bin/bin in component_parts) + matter_bin_stack += bin.tier + boulders_held_max = matter_bin_stack + + +/obj/machinery/bouldertech/refinery/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + if(istype(held_item, /obj/item/boulder)) + context[SCREENTIP_CONTEXT_LMB] = "Insert boulder" + if(istype(held_item, /obj/item/card/id) && points_held > 0) + context[SCREENTIP_CONTEXT_LMB] = "Claim mining points" + context[SCREENTIP_CONTEXT_RMB] = "Remove boulder" + return CONTEXTUAL_SCREENTIP_SET + + +/** + * Your other new favorite industrial waste magnet! + * Accepts boulders and produces sheets of metalic materials. + * Can be upgraded with stock parts or through chemical inputs. + * When upgraded, it can hold more boulders and process more at once. + * + * Chemical inputs can be used to boost the refinery's efficiency, but produces industrial waste, which eats through the station and is generally difficult to store. + */ +/obj/machinery/bouldertech/refinery/smelter + name = "boulder smelter" + desc = "BS for short. Accept boulders and refines metallic ores into sheets. Can be upgraded with stock parts or through gas inputs." + icon_state = "smelter" + processable_materials = list( + /datum/material/iron, + /datum/material/titanium, + /datum/material/silver, + /datum/material/gold, + /datum/material/uranium, + /datum/material/mythril, + /datum/material/adamantine, + /datum/material/runite, + ) + light_system = OVERLAY_LIGHT + light_outer_range = 1 + light_power = 2 + light_color = "#ffaf55" + light_on = FALSE + circuit = /obj/item/circuitboard/machine/smelter + usage_sound = 'sound/machines/mining/smelter.ogg' + +/obj/machinery/bouldertech/refinery/smelter/RefreshParts() + . = ..() + light_power = boulders_processing_max + +/obj/machinery/bouldertech/refinery/smelter/accept_boulder(obj/item/boulder/new_boulder) + . = ..() + if(.) + set_light_on(TRUE) + return TRUE + + +/obj/machinery/bouldertech/refinery/smelter/process() + . = ..() + if(. == PROCESS_KILL) + set_light_on(FALSE) + +/obj/machinery/bouldertech/refinery/process() + if(!anchored) + return PROCESS_KILL + var/stop_processing_check = FALSE + var/boulders_concurrent = boulders_processing_max ///How many boulders can we touch this process() call + for(var/obj/item/potential_boulder as anything in boulders_contained) + if(QDELETED(potential_boulder)) + boulders_contained -= potential_boulder + break + if(boulders_concurrent <= 0) + break //Try again next time + + if(istype(potential_boulder, /obj/item/processing/refined_dust)) + refine_dust(potential_boulder) + + if(!istype(potential_boulder, /obj/item/boulder) && !istype(potential_boulder, /obj/item/processing/refined_dust)) + potential_boulder.forceMove(drop_location()) + CRASH("\The [src] had a non-boulder in it's boulders contained!") + + var/obj/item/boulder/boulder = potential_boulder + if(boulder.durability < 0) + CRASH("\The [src] had a boulder with negative durability!") + if(!check_for_processable_materials(boulder.custom_materials)) //Checks for any new materials we can process. + boulders_concurrent-- //We count skipped boulders + remove_boulder(boulder) + continue + boulders_concurrent-- + boulder.durability-- //One less durability to the processed boulder. + if(COOLDOWN_FINISHED(src, sound_cooldown)) + COOLDOWN_START(src, sound_cooldown, 1.5 SECONDS) + playsound(loc, usage_sound, 29, FALSE, SHORT_RANGE_SOUND_EXTRARANGE) //This can get annoying. One play per process() call. + stop_processing_check = TRUE + if(boulder.durability <= 0) + breakdown_boulder(boulder) //Crack that bouwlder open! + continue + if(!stop_processing_check) + playsound(src.loc, 'sound/machines/ping.ogg', 50, FALSE) + return PROCESS_KILL + +/obj/machinery/bouldertech/refinery/proc/refine_dust(obj/item/processing/refined_dust/dust) + use_power(BASE_MACHINE_ACTIVE_CONSUMPTION) + var/list/processable_ores = list() + for(var/datum/material/possible_mat as anything in dust.custom_materials) + if(!is_type_in_list(possible_mat, processable_materials)) + continue + var/quantity = dust.custom_materials[possible_mat] + points_held = round((points_held + (quantity * possible_mat.points_per_unit * MINING_POINT_MACHINE_MULTIPLIER))) // put point total here into machine + processable_ores += possible_mat + processable_ores[possible_mat] = quantity + dust.custom_materials -= possible_mat //Remove it from the boulder now that it's tracked + + var/obj/item/boulder/disposable_boulder = new (src) + disposable_boulder.custom_materials = processable_ores + silo_materials.mat_container.insert_item(disposable_boulder, refining_efficiency) + qdel(dust) + playsound(loc, 'sound/weapons/drill.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + update_boulder_count() + +/obj/machinery/bouldertech/refinery/CanAllowThrough(atom/movable/mover, border_dir) + if(!anchored) + return FALSE + if(boulders_contained.len >= boulders_held_max) + return FALSE + if(istype(mover, /obj/item/processing/refined_dust)) + return TRUE + return ..() + +/obj/machinery/bouldertech/refinery/return_extras() + var/list/boulders_contained = list() + for(var/obj/item/processing/refined_dust/boulder in contents) + boulders_contained += boulder + return boulders_contained + +/obj/machinery/bouldertech/refinery/check_extras(obj/item/item) + if(istype(item, /obj/item/processing/refined_dust)) + return TRUE + return FALSE diff --git a/monkestation/code/modules/factory_type_beat/readme.md b/monkestation/code/modules/factory_type_beat/readme.md new file mode 100644 index 000000000000..6c08a3c4a8fc --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/readme.md @@ -0,0 +1 @@ +This also contains the base arcmining stuff in the modular folder as its gonna get real messy diff --git a/monkestation/code/modules/factory_type_beat/ss_ore_gen.dm b/monkestation/code/modules/factory_type_beat/ss_ore_gen.dm new file mode 100644 index 000000000000..54ca83428730 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/ss_ore_gen.dm @@ -0,0 +1,94 @@ + +SUBSYSTEM_DEF(ore_generation) + name = "Ore Generation" + wait = 60 SECONDS + init_order = INIT_ORDER_DEFAULT + runlevels = RUNLEVEL_GAME + + /// All ore vents that are currently producing boulders. + var/list/obj/structure/ore_vent/processed_vents = list() + /// All the ore vents that are currently in the game, not just the ones that are producing boulders. + var/list/obj/structure/ore_vent/possible_vents = list() + /// All the boulders that have been produced by ore vents to be pulled by BRM machines. + var/list/obj/item/boulder/available_boulders = list() + /** + * Associated list of minerals to be associated with our ore vents. + * Generally Should be empty by the time initialize ends on lavaland. + * Each key value is the number of vents that will have this ore as a unique possible choice. + */ + var/static/list/ore_vent_minerals_default = list( + /datum/material/iron = 13, + /datum/material/glass = 12, + /datum/material/plasma = 9, + /datum/material/titanium = 6, + /datum/material/silver = 5, + /datum/material/gold = 5, + /datum/material/diamond = 3, + /datum/material/uranium = 3, + /datum/material/bluespace = 3, + ) + /** + * A list of all the minerals that are being mined by ore vents. We reset this list every time cave generation is done. + * Generally Should be empty by the time initialize ends on lavaland. + * Each key value is the number of vents that will have this ore as a unique possible choice. + * If we call cave_generation more than once, we copy a list from the lists in lists/ores_spawned.dm + */ + var/list/ore_vent_minerals = list() + + /// A tracker of how many of each ore vent size we have in the game. Useful for tracking purposes. + var/list/ore_vent_sizes = list( + LARGE_VENT_TYPE = 0, + MEDIUM_VENT_TYPE = 0, + SMALL_VENT_TYPE = 0, + ) + /// Ores spawned by proximity to an ore vent. Useful for logging purposes. + var/list/post_ore_random = list( + "1" = 0, + "2" = 0, + "3" = 0, + "4" = 0, + "5" = 0, + ) + /// Ores spawned randomly on the map without proximity to an ore vent. Useful for logging purposes. + var/list/post_ore_manual = list( + "1" = 0, + "2" = 0, + "3" = 0, + "4" = 0, + "5" = 0, + ) + +/datum/controller/subsystem/ore_generation/Initialize() + //Basically, we're going to round robin through the list of ore vents and assign a mineral to them until complete. + while(length(ore_vent_minerals) > 0) //Keep looping if there's more to assign + var/stallbreaker = 0 + for(var/obj/structure/ore_vent/vent as anything in possible_vents) + if(length(ore_vent_minerals) <= 0) //But break early if there's none left. + break + if(vent.unique_vent) + continue //Ya'll already got your minerals. + if(length(difflist(first = ore_vent_minerals, second = vent.mineral_breakdown, skiprep = 1))) + vent.generate_mineral_breakdown(new_minerals = 1, map_loading = TRUE) + else + stallbreaker++ + if(stallbreaker >= length(possible_vents)) + break //We've done all we can here. break inner loop + continue + if(stallbreaker >= length(possible_vents)) + break //We've done all we can here. break outer loop + + return SS_INIT_SUCCESS + +/datum/controller/subsystem/ore_generation/fire(resumed) + available_boulders.Cut() // reset upon new fire. + for(var/obj/structure/ore_vent/current_vent as anything in processed_vents) + + var/local_vent_count = 0 + for(var/obj/item/boulder/old_rock in current_vent.loc) + available_boulders += old_rock + local_vent_count++ + + if(local_vent_count >= MAX_BOULDERS_PER_VENT) + continue //We don't want to be accountable for literally hundreds of unprocessed boulders for no reason. + + available_boulders += current_vent.produce_boulder() diff --git a/monkestation/code/modules/factory_type_beat/technodes.dm b/monkestation/code/modules/factory_type_beat/technodes.dm new file mode 100644 index 000000000000..27557f460ed2 --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/technodes.dm @@ -0,0 +1,18 @@ +/datum/techweb_node/ore_processing + id = "ore_processing_nodes" + display_name = "Ore Processing Nodes" + description = "Contains all of the ore processing designs." + design_ids = list( + "brine_chamber", + "purification_chamber", + "enricher", + "crusher", + "crystalizer", + "chemical_injector", + "chemical_washer", + "dissolution_chamber", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000000000000000) // God save you + hidden = TRUE + show_on_wiki = FALSE + starting_node = TRUE diff --git a/monkestation/code/modules/factory_type_beat/yummy.dm b/monkestation/code/modules/factory_type_beat/yummy.dm new file mode 100644 index 000000000000..248f1507b34f --- /dev/null +++ b/monkestation/code/modules/factory_type_beat/yummy.dm @@ -0,0 +1,17 @@ +/obj/item/organ/internal/cyberimp/chest/gyro + name = "Gyrotron-3000" + desc = "Blood sweat and tears went into this bad boy." + encode_info = AUGMENT_NO_REQ + icon_state = "sandy" + actions_types = list(/datum/action/item_action/organ_action/sandy) + icon = 'monkestation/code/modules/cybernetics/icons/implants.dmi' + + /// The bodypart overlay datum we should apply to whatever mob we are put into + visual_implant = TRUE + bodypart_overlay = /datum/bodypart_overlay/simple/gyro + + +/datum/bodypart_overlay/simple/gyro + icon = 'monkestation/code/modules/factory_type_beat/icons/mining_machines.dmi' + icon_state = "gyrotron-3000" + layers = EXTERNAL_FRONT diff --git a/monkestation/code/modules/ghost_critters/ghost_critter_mobs/donator_mobs.dm b/monkestation/code/modules/ghost_critters/ghost_critter_mobs/donator_mobs.dm index d655ba9db7f9..0c852b29ef40 100644 --- a/monkestation/code/modules/ghost_critters/ghost_critter_mobs/donator_mobs.dm +++ b/monkestation/code/modules/ghost_critters/ghost_critter_mobs/donator_mobs.dm @@ -1,4 +1,4 @@ -/mob/living/basic/var/list/ckeywhitelist = list() +/mob/living/basic/var/list/ckeywhitelist /client/proc/return_donator_mobs() var/list/mobs = list( diff --git a/monkestation/code/modules/loadouts/items/neck.dm b/monkestation/code/modules/loadouts/items/neck.dm index 983b4245e2a8..99825e818760 100644 --- a/monkestation/code/modules/loadouts/items/neck.dm +++ b/monkestation/code/modules/loadouts/items/neck.dm @@ -289,12 +289,12 @@ GLOBAL_LIST_INIT(loadout_necks, generate_loadout_items(/datum/loadout_item/neck) restricted_roles = list(JOB_HEAD_OF_SECURITY) requires_purchase = FALSE -/* + /datum/loadout_item/neck/mantle_bs name = "Blueshield's Mantle" item_path = /obj/item/clothing/neck/mantle/bsmantle restricted_roles = list(JOB_BLUESHIELD) -*/ + /datum/loadout_item/neck/mantle_cap name = "Captain's Mantle" item_path = /obj/item/clothing/neck/mantle/capmantle diff --git a/monkestation/code/modules/mech_comp/objects/flush.dm b/monkestation/code/modules/mech_comp/objects/flush.dm index 649208b3810a..8aa0672df51f 100644 --- a/monkestation/code/modules/mech_comp/objects/flush.dm +++ b/monkestation/code/modules/mech_comp/objects/flush.dm @@ -27,6 +27,11 @@ trunk_check() if(!trunk || !COOLDOWN_FINISHED(src, flush_cd) || !input?.cmd) return + + if(QDELETED(trunk)) + trunk = null + return + var/count = 0 for(var/atom/movable/listed_movable in src.loc) if(listed_movable.anchored) diff --git a/monkestation/code/modules/mech_comp/objects/messages/button.dm b/monkestation/code/modules/mech_comp/objects/messages/button.dm index 2d6b169339d7..9dac64079b44 100644 --- a/monkestation/code/modules/mech_comp/objects/messages/button.dm +++ b/monkestation/code/modules/mech_comp/objects/messages/button.dm @@ -21,6 +21,8 @@ if(!user.dropItemToGround(src)) return + if(!user.CanReach(target)) + return forceMove(target) if(isclosedturf(target)) icon_up = "comp_switch" diff --git a/monkestation/code/modules/mob/dead/new_player/new_player.dm b/monkestation/code/modules/mob/dead/new_player/new_player.dm index 5f6d6cb8d5c0..ff657817d278 100644 --- a/monkestation/code/modules/mob/dead/new_player/new_player.dm +++ b/monkestation/code/modules/mob/dead/new_player/new_player.dm @@ -1,3 +1,8 @@ /mob/dead/new_player /// What is our temp assignment, used for round start antag calculation var/datum/job/temp_assignment + +/mob/dead/new_player/Destroy() + . = ..() + if(temp_assignment) + temp_assignment = null diff --git a/monkestation/code/modules/patches_if_they_were_cool/_base_patch_changes.dm b/monkestation/code/modules/patches_if_they_were_cool/_base_patch_changes.dm index 2271f350f103..0d831130c7d9 100644 --- a/monkestation/code/modules/patches_if_they_were_cool/_base_patch_changes.dm +++ b/monkestation/code/modules/patches_if_they_were_cool/_base_patch_changes.dm @@ -17,8 +17,9 @@ if(!isliving(target)) return - if(!do_after(user, CHEM_INTERACT_DELAY(0.1 SECONDS, user), target)) - return + if(target != user) + if(!do_after(user, CHEM_INTERACT_DELAY(3 SECONDS, user), target)) + return var/list/parameters = params2list(params) if(!LAZYACCESS(parameters, ICON_X) || !LAZYACCESS(parameters, ICON_Y)) @@ -62,8 +63,9 @@ /obj/item/reagent_containers/pill/patch/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() - if(!. && prob(15) && isliving(hit_atom)) - stick(hit_atom,rand(-7,7),rand(-7,7)) + if(!. && prob(10) && isliving(hit_atom)) + stick(hit_atom, throwingdatum.thrower, rand(-7,7), rand(-7,7)) + to_chat(attached, span_bolddanger("[src] has stuck to you.")) attached.balloon_alert_to_viewers("[src] lands on its sticky side!") ///Signal handler for COMSIG_LIVING_IGNITED, deletes this patch, if it is flammable diff --git a/monkestation/code/modules/physics/physics_component.dm b/monkestation/code/modules/physics/physics_component.dm index 185718e92802..c36ea828065d 100644 --- a/monkestation/code/modules/physics/physics_component.dm +++ b/monkestation/code/modules/physics/physics_component.dm @@ -64,6 +64,8 @@ var/datum/callback/bounce_callback /// If we have this callback, it gets invoked when stopping movement var/datum/callback/stop_callback + /// If we have this callback, it gets invoked when bumping on another atom + var/datum/callback/bump_callback /** * The cached animate_movement of the parent @@ -94,6 +96,7 @@ bounce_spin_clockwise = 0, bounce_sound, bounce_callback, + bump_callback, stop_callback, ) if(!ismovable(parent)) @@ -118,6 +121,7 @@ src.bounce_spin_clockwise = bounce_spin_clockwise src.bounce_sound = bounce_sound src.bounce_callback = bounce_callback + src.bump_callback = bump_callback src.stop_callback = stop_callback set_angle(angle) @@ -128,6 +132,7 @@ return ..() /datum/component/movable_physics/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOVABLE_NEWTONIAN_MOVE, PROC_REF(on_newtonian_move)) RegisterSignal(parent, COMSIG_MOVABLE_BUMP, PROC_REF(on_bump)) if(isitem(parent)) RegisterSignal(parent, COMSIG_ITEM_PICKUP, PROC_REF(on_item_pickup)) @@ -158,22 +163,28 @@ //this code basically only makes sense if we only move at most a single tile per tick, it is absolutely fucked otherwise while(tick_amount > 0) tick_amount-- + //we need to know if we have gravity right now to apply friction and such, yeah + var/has_gravity = moving_atom.has_gravity() + moving_atom.pixel_x = round(moving_atom.pixel_x + (horizontal_velocity * sin(angle)), MOVABLE_PHYSICS_PRECISION) moving_atom.pixel_y = round(moving_atom.pixel_y + (horizontal_velocity * cos(angle)), MOVABLE_PHYSICS_PRECISION) - moving_atom.pixel_z = round(max(z_floor, moving_atom.pixel_z + vertical_velocity), MOVABLE_PHYSICS_PRECISION) + moving_atom.pixel_z = round(clamp(moving_atom.pixel_z + vertical_velocity, z_floor, world.icon_size), MOVABLE_PHYSICS_PRECISION) moving_atom.adjust_visual_angle(round(visual_angle_velocity, 1)) - horizontal_velocity = max(0, horizontal_velocity - horizontal_friction) - // we are not on the floor, apply friction - if(moving_atom.pixel_z > z_floor) - vertical_velocity -= vertical_friction - // we are on the floor, try to bounce if we have any vertical velocity - else if(moving_atom.pixel_z <= z_floor && vertical_velocity) - z_floor_bounce(moving_atom) - - visual_angle_velocity = max(0, visual_angle_velocity - visual_angle_friction) + if(has_gravity) + visual_angle_velocity = max(0, visual_angle_velocity - visual_angle_friction) + horizontal_velocity = max(0, horizontal_velocity - horizontal_friction) + // we are not on the floor, apply friction + if(moving_atom.pixel_z > z_floor) + vertical_velocity -= vertical_friction + // we are on the floor, try to bounce if we have any vertical velocity + else if(moving_atom.pixel_z <= z_floor && vertical_velocity) + z_floor_bounce(moving_atom) + // z_floor_bounce could have deleted us + if(QDELETED(src)) + return var/move_direction = NONE var/effective_pixel_x = moving_atom.pixel_x - moving_atom.base_pixel_x @@ -257,6 +268,12 @@ /datum/component/movable_physics/proc/set_angle(new_angle) angle = SIMPLIFY_DEGREES(new_angle) +/// We do not EVER want newtonian movement while handling movement ourselves, so block it! +/datum/component/movable_physics/proc/on_newtonian_move(atom/movable/source, direction, start_delay) + SIGNAL_HANDLER + + return COMPONENT_MOVABLE_NEWTONIAN_BLOCK + /// Proc for bouncing, aka object reached z_floor on pixel_z and needs a dose of Newton's third law /datum/component/movable_physics/proc/z_floor_bounce(atom/movable/moving_atom) moving_atom.pixel_z = round(z_floor, MOVABLE_PHYSICS_PRECISION) @@ -276,6 +293,8 @@ var/incidence = GET_ANGLE_OF_INCIDENCE(face_angle, angle + 180) var/new_angle = SIMPLIFY_DEGREES(face_angle + incidence) set_angle(new_angle) + if(bump_callback) + bump_callback.Invoke(bumped_atom) if(!visual_angle_velocity) return incidence = GET_ANGLE_OF_INCIDENCE(face_angle, source.visual_angle + 180) diff --git a/monkestation/code/modules/pollution/pollution_emitter_element.dm b/monkestation/code/modules/pollution/pollution_emitter_element.dm index 69e5ea083da4..d886bd391709 100644 --- a/monkestation/code/modules/pollution/pollution_emitter_element.dm +++ b/monkestation/code/modules/pollution/pollution_emitter_element.dm @@ -35,4 +35,4 @@ PROCESSING_SUBSYSTEM_DEF(pollution_emitters) return PROCESS_KILL for(var/atom/affected_atom as anything in affected) var/turf/my_turf = get_turf(affected_atom) - my_turf.pollute_turf(pollutant_type, pollutant_amount) + my_turf?.pollute_turf(pollutant_type, pollutant_amount) diff --git a/monkestation/code/modules/reagents/chemistry/reagents/other_reagents.dm b/monkestation/code/modules/reagents/chemistry/reagents/other_reagents.dm index 6fd26f35b908..2862da172fb7 100644 --- a/monkestation/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/monkestation/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -9,8 +9,8 @@ /datum/reagent/acetone_oxide/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)//Splashing people kills people! . = ..() if(methods & TOUCH | VAPOR | INGEST) - exposed_mob.adjustFireLoss(((reac_volume * 2) / 1.65)) - exposed_mob.adjust_fire_stacks((reac_volume / 5)) + exposed_mob.adjustFireLoss(min((reac_volume * 0.5) / 1.65, 25)) + exposed_mob.adjust_fire_stacks(round(reac_volume / 50)) /datum/reagent/acetone_oxide/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) // Old acetone oxide didn't have a metabolism effect! . = ..() @@ -58,7 +58,7 @@ /datum/reagent/hydrogen_peroxide/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)//Splashing people with h2o2 can burn them ! . = ..() if(methods & TOUCH) - exposed_mob.adjustFireLoss(((reac_volume * 2) / 3)) + exposed_mob.adjustFireLoss(min((reac_volume * 0.5) / 3, 25)) /datum/reagent/hydrogen_peroxide/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) // Old h2o2 didn't have a metabolizing effect either! . = ..() diff --git a/monkestation/code/modules/smithing/ipcs/species.dm b/monkestation/code/modules/smithing/ipcs/species.dm index 101eef01e94f..00af82672889 100644 --- a/monkestation/code/modules/smithing/ipcs/species.dm +++ b/monkestation/code/modules/smithing/ipcs/species.dm @@ -22,7 +22,6 @@ TRAIT_LIMBATTACHMENT, TRAIT_LITERATE, TRAIT_REVIVES_BY_HEALING, - TRAIT_NOCRITDAMAGE, // We do our own handling of crit damage. TRAIT_NO_DNA_COPY, ) @@ -71,6 +70,7 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/robot/ipc, ) + brutemod = 1.5 coldmod = 1.2 heatmod = 2 // TWO TIMES DAMAGE FROM BEING TOO HOT?! WHAT?! No wonder lava is literal instant death for us. siemens_coeff = 1.4 // Not more because some shocks will outright crit you, which is very unfun diff --git a/monkestation/code/modules/smithing/oozelings/species.dm b/monkestation/code/modules/smithing/oozelings/species.dm index b71c429b98de..ad0e7ada02dc 100644 --- a/monkestation/code/modules/smithing/oozelings/species.dm +++ b/monkestation/code/modules/smithing/oozelings/species.dm @@ -105,6 +105,7 @@ if(core_signal) core_signal.Remove(C) ..() + C.blood_volume = BLOOD_VOLUME_SAFE /datum/species/oozeling/on_species_gain(mob/living/carbon/C, datum/species/old_species) ..() diff --git a/monkestation/code/modules/storytellers/converted_events/solo/bloodcult.dm b/monkestation/code/modules/storytellers/converted_events/solo/bloodcult.dm index 700957dff6c6..cbf469a3fb3c 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/bloodcult.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/bloodcult.dm @@ -8,6 +8,7 @@ restricted_roles = list( JOB_AI, JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_CHAPLAIN, JOB_CYBORG, JOB_DETECTIVE, diff --git a/monkestation/code/modules/storytellers/converted_events/solo/bloodsuckers.dm b/monkestation/code/modules/storytellers/converted_events/solo/bloodsuckers.dm index 1bdf4c177a0a..30ec0ef49fbf 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/bloodsuckers.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/bloodsuckers.dm @@ -4,6 +4,7 @@ antag_datum = /datum/antagonist/bloodsucker protected_roles = list( JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_HEAD_OF_PERSONNEL, JOB_CHIEF_ENGINEER, JOB_CHIEF_MEDICAL_OFFICER, diff --git a/monkestation/code/modules/storytellers/converted_events/solo/brother.dm b/monkestation/code/modules/storytellers/converted_events/solo/brother.dm index a2413bc3e608..90a6f492aba0 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/brother.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/brother.dm @@ -5,6 +5,7 @@ tags = list(TAG_COMBAT, TAG_TEAM_ANTAG) protected_roles = list( JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_HEAD_OF_PERSONNEL, JOB_CHIEF_ENGINEER, JOB_CHIEF_MEDICAL_OFFICER, diff --git a/monkestation/code/modules/storytellers/converted_events/solo/changeling.dm b/monkestation/code/modules/storytellers/converted_events/solo/changeling.dm index 39e9d605a7e4..f198a7b2e85b 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/changeling.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/changeling.dm @@ -4,6 +4,7 @@ antag_datum = /datum/antagonist/changeling protected_roles = list( JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_HEAD_OF_PERSONNEL, JOB_CHIEF_ENGINEER, JOB_CHIEF_MEDICAL_OFFICER, diff --git a/monkestation/code/modules/storytellers/converted_events/solo/clockwork_cult.dm b/monkestation/code/modules/storytellers/converted_events/solo/clockwork_cult.dm index 3f7475364bc1..d61c09ddfe94 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/clockwork_cult.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/clockwork_cult.dm @@ -8,6 +8,7 @@ restricted_roles = list( JOB_AI, JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_CHAPLAIN, JOB_CYBORG, JOB_DETECTIVE, diff --git a/monkestation/code/modules/storytellers/converted_events/solo/clown_operative.dm b/monkestation/code/modules/storytellers/converted_events/solo/clown_operative.dm index dc86d98cb9b9..65950c93feca 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/clown_operative.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/clown_operative.dm @@ -8,6 +8,7 @@ restricted_roles = list( JOB_AI, JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_CHIEF_ENGINEER, JOB_CHIEF_MEDICAL_OFFICER, JOB_CYBORG, diff --git a/monkestation/code/modules/storytellers/converted_events/solo/ghosts/nuclear_operative_ghost.dm b/monkestation/code/modules/storytellers/converted_events/solo/ghosts/nuclear_operative_ghost.dm index e9271d387ba0..54ed3b23756c 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/ghosts/nuclear_operative_ghost.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/ghosts/nuclear_operative_ghost.dm @@ -34,7 +34,7 @@ // I give up, just there should be enough heads with 35 players... min_players = 35 earliest_start = 60 MINUTES - weight = 4 + weight = 3 max_occurrences = 1 prompted_picking = TRUE diff --git a/monkestation/code/modules/storytellers/converted_events/solo/heretic.dm b/monkestation/code/modules/storytellers/converted_events/solo/heretic.dm index 726b1a809bbf..9050bbdf1941 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/heretic.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/heretic.dm @@ -4,6 +4,7 @@ antag_datum = /datum/antagonist/heretic protected_roles = list( JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_HEAD_OF_PERSONNEL, JOB_CHIEF_ENGINEER, JOB_CHIEF_MEDICAL_OFFICER, diff --git a/monkestation/code/modules/storytellers/converted_events/solo/monsterhunter.dm b/monkestation/code/modules/storytellers/converted_events/solo/monsterhunter.dm index 52f7647ae515..01441f7a84b5 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/monsterhunter.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/monsterhunter.dm @@ -8,6 +8,7 @@ antag_datum = /datum/antagonist/monsterhunter protected_roles = list( JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_HEAD_OF_PERSONNEL, JOB_CHIEF_ENGINEER, JOB_CHIEF_MEDICAL_OFFICER, diff --git a/monkestation/code/modules/storytellers/converted_events/solo/nuclear_operative.dm b/monkestation/code/modules/storytellers/converted_events/solo/nuclear_operative.dm index f2a5a12a3e14..54685b4f4871 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/nuclear_operative.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/nuclear_operative.dm @@ -8,6 +8,7 @@ restricted_roles = list( JOB_AI, JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_CHIEF_ENGINEER, JOB_CHIEF_MEDICAL_OFFICER, JOB_CYBORG, diff --git a/monkestation/code/modules/storytellers/converted_events/solo/obsessed.dm b/monkestation/code/modules/storytellers/converted_events/solo/obsessed.dm index bfb3b8294c2e..deb7b8b1e792 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/obsessed.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/obsessed.dm @@ -5,6 +5,7 @@ typepath = /datum/round_event/antagonist/solo/obsessed restricted_roles = list( JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_HEAD_OF_PERSONNEL, JOB_CHIEF_ENGINEER, JOB_CHIEF_MEDICAL_OFFICER, diff --git a/monkestation/code/modules/storytellers/converted_events/solo/revolutionary.dm b/monkestation/code/modules/storytellers/converted_events/solo/revolutionary.dm index eb8fce9f4aeb..9d9b08303e61 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/revolutionary.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/revolutionary.dm @@ -8,6 +8,7 @@ restricted_roles = list( JOB_AI, JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_CHIEF_ENGINEER, JOB_CHIEF_MEDICAL_OFFICER, JOB_CYBORG, diff --git a/monkestation/code/modules/storytellers/converted_events/solo/traitor.dm b/monkestation/code/modules/storytellers/converted_events/solo/traitor.dm index 58ed6dd76653..ede797b7be16 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/traitor.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/traitor.dm @@ -4,6 +4,7 @@ antag_datum = /datum/antagonist/traitor/infiltrator protected_roles = list( JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_HEAD_OF_PERSONNEL, JOB_CHIEF_ENGINEER, JOB_CHIEF_MEDICAL_OFFICER, diff --git a/monkestation/code/modules/storytellers/converted_events/solo/wizard.dm b/monkestation/code/modules/storytellers/converted_events/solo/wizard.dm index 70e042c70f47..b0426a0191c8 100644 --- a/monkestation/code/modules/storytellers/converted_events/solo/wizard.dm +++ b/monkestation/code/modules/storytellers/converted_events/solo/wizard.dm @@ -7,6 +7,7 @@ shared_occurence_type = SHARED_HIGH_THREAT restricted_roles = list( JOB_CAPTAIN, + JOB_BLUESHIELD, JOB_HEAD_OF_SECURITY, ) // Just to be sure that a wizard getting picked won't ever imply a Captain or HoS not getting drafted maximum_antags = 1 diff --git a/monkestation/code/modules/trading/unusual_effects/animation_housing/__spawning_component.dm b/monkestation/code/modules/trading/unusual_effects/animation_housing/__spawning_component.dm index 9ccf5603098c..a7d1df45c69a 100644 --- a/monkestation/code/modules/trading/unusual_effects/animation_housing/__spawning_component.dm +++ b/monkestation/code/modules/trading/unusual_effects/animation_housing/__spawning_component.dm @@ -6,6 +6,8 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT icon = 'monkestation/code/modules/trading/icons/particles.dmi' icon_state = "none" + underlays = null + overlays = null /datum/component/particle_spewer var/atom/source_object @@ -117,7 +119,8 @@ for(var/i = 0 to burstees) //create and assign particle its stuff - var/obj/effect/abstract/particle/spawned = new(get_turf(source_object)) + var/obj/effect/abstract/particle/spawned + spawned = new(get_turf(source_object)) if(offsets) spawned.pixel_x = offset_x spawned.pixel_y = offset_y diff --git a/monkestation/code/modules/trading/unusual_effects/animation_housing/money.dm b/monkestation/code/modules/trading/unusual_effects/animation_housing/money.dm new file mode 100644 index 000000000000..baacfb56682b --- /dev/null +++ b/monkestation/code/modules/trading/unusual_effects/animation_housing/money.dm @@ -0,0 +1,38 @@ +/datum/component/particle_spewer/cash + unusual_description = "cashflow" + icon_file = 'icons/obj/economy.dmi' + particle_state = "spacecash1" + burst_amount = 1 + duration = 2 SECONDS + random_bursts = TRUE + spawn_interval = 6 SECONDS + +/datum/component/particle_spewer/cash/animate_particle(obj/effect/abstract/particle/spawned) + var/chance = rand(1, 10) + switch(chance) + if(1 to 2) + spawned.icon_state = "spacecash1" + if(3 to 4) + spawned.icon_state = "spacecash10" + if(5 to 6) + spawned.icon_state = "spacecash50" + else + spawned.icon_state = "spacecash20" + + if(prob(65)) + spawned.layer = LOW_ITEM_LAYER + spawned.pixel_x += rand(-12, 12) + spawned.pixel_y += rand(-5, 5) + . = ..() + +/datum/component/particle_spewer/cash/adjust_animate_steps() + animate_holder.add_animation_step(list(transform = matrix(0.5, 0.5, MATRIX_SCALE), alpha = 125, time = 0)) + + animate_holder.add_animation_step(list(transform = "RANDOM", time = 2 SECONDS, pixel_y = "RANDOM", pixel_x = "RANDOM", easing = LINEAR_EASING)) + + animate_holder.set_random_var(2, "transform", list(-90, 90)) + animate_holder.set_random_var(2, "pixel_x", list(-16, 16)) + animate_holder.set_random_var(2, "pixel_y", list(-16, 16)) + animate_holder.set_transform_type(2, MATRIX_ROTATE) + + animate_holder.add_animation_step(list(alpha = 25, time = 1.5 SECONDS)) diff --git a/monkestation/code/modules/virology/disease/plague_rat/event.dm b/monkestation/code/modules/virology/disease/plague_rat/event.dm index 6217eb8d8d10..9ed00b05632a 100644 --- a/monkestation/code/modules/virology/disease/plague_rat/event.dm +++ b/monkestation/code/modules/virology/disease/plague_rat/event.dm @@ -1,11 +1,11 @@ /datum/round_event_control/plague_rat name = "Spawn Plague Rats" typepath = /datum/round_event/ghost_role/plague_rat - weight = 7 + weight = 1 max_occurrences = 1 track = EVENT_TRACK_MAJOR min_players = 30 //monke edit: 20 to 30 - earliest_start = 30 MINUTES //monke edit: 20 to 60 + earliest_start = 55 MINUTES //monke edit: 20 to 60 //dynamic_should_hijack = TRUE category = EVENT_CATEGORY_ENTITIES description = "Spawns a horde of plague rats." diff --git a/monkestation/code/modules/virology/disease/plague_rat/plague_rat.dm b/monkestation/code/modules/virology/disease/plague_rat/plague_rat.dm index 4375985d7f24..74f945c91f25 100644 --- a/monkestation/code/modules/virology/disease/plague_rat/plague_rat.dm +++ b/monkestation/code/modules/virology/disease/plague_rat/plague_rat.dm @@ -6,9 +6,17 @@ icon_living = "mouse_plague" icon_dead = "mouse_plague_dead" + maxHealth = 30 + health = 30 + melee_damage_lower = 4 melee_damage_upper = 7 chooses_bodycolor = FALSE + pass_flags = PASSTABLE|PASSGRILLE|PASSMOB|PASSDOORS + +/mob/living/basic/mouse/plague/Initialize(mapload, tame, new_body_color) + . = ..() + add_movespeed_modifier(/datum/movespeed_modifier/plague_rat) /mob/living/basic/mouse/plague/attack_hand(mob/living/carbon/human/user, list/modifiers) @@ -29,3 +37,6 @@ /mob/living/basic/mouse/attackby(obj/item/attacking_item, mob/living/user, params) . = ..() attacking_item.disease_contact(src, BODY_ZONE_CHEST) + +/datum/movespeed_modifier/plague_rat + multiplicative_slowdown = 0.5 diff --git a/monkestation/code/modules/virology/disease/symptom_cracker/cracker_puzzle.dm b/monkestation/code/modules/virology/disease/symptom_cracker/cracker_puzzle.dm index f5d0d7108999..0c62231805fe 100644 --- a/monkestation/code/modules/virology/disease/symptom_cracker/cracker_puzzle.dm +++ b/monkestation/code/modules/virology/disease/symptom_cracker/cracker_puzzle.dm @@ -17,6 +17,8 @@ var/datum/parent + var/list/plotted_points = list() + /datum/cracker_puzzle/New(grid_size = 5, difficulty = 1, datum/parent) src.grid_size = grid_size src.difficulty = difficulty @@ -47,37 +49,23 @@ var/sequence_length = 4 + difficulty - var/last_sequence_spot = null - var/last_vertical_sequence_spot = null + var/last_sequence_spot = rand(1, grid_size) + var/last_vertical_sequence_spot = rand(1, grid_size) var/vertical = FALSE for(var/i = 1 to sequence_length) if(vertical) - var/vertical_spot = rand(1, grid_size) - var/list/horizontal_cut = grid[vertical_spot] - sequence += horizontal_cut[last_vertical_sequence_spot] - var/horizontal_choice = rand(1, grid_size) - last_sequence_spot = horizontal_choice - - vertical = FALSE - + var/vertical_spot = rand(1, grid_size) // Random row (y-coordinate) + var/list/horizontal_cut_vert = grid[vertical_spot] // Get the row corresponding to vertical_spot + sequence += horizontal_cut_vert[last_sequence_spot] // Use the last x-coordinate to select the letter + last_vertical_sequence_spot = vertical_spot // Update the y-coordinate + plotted_points += "[last_sequence_spot], [last_vertical_sequence_spot]" // Log the coordinate pair + vertical = FALSE // Switch to horizontal for the next iteration else - if(!last_sequence_spot) - ///grabs the horizontal slice of the grid - var/horizontal_spot = rand(1, grid_size) - var/list/horizontal_cut = grid[horizontal_spot] - - last_sequence_spot = horizontal_spot //sets the last slice position - - var/vertical_spot = rand(1, grid_size)// we randomize the selection inside the slice - sequence += horizontal_cut[vertical_spot] - last_vertical_sequence_spot = vertical_spot //set the last vertical spot to this - else - var/list/choices = grid[last_sequence_spot] - var/grid_selection = rand(1, grid_size) - last_vertical_sequence_spot = grid_selection - sequence += choices[grid_selection] - - vertical = TRUE + var/horizontal_spot = rand(1, grid_size) // Random column (x-coordinate) + sequence += grid[last_vertical_sequence_spot][horizontal_spot] // Access the column in the current row + last_sequence_spot = horizontal_spot // Update the x-coordinate + plotted_points += "[last_sequence_spot], [last_vertical_sequence_spot]" // Log the coordinate pair + vertical = TRUE // Switch to vertical for the next iteration /datum/cracker_puzzle/proc/check_press(x, y) diff --git a/monkestation/code/modules/virology/disease/symptom_varients/base.dm b/monkestation/code/modules/virology/disease/symptom_varients/base.dm index 88e3615cef15..8a431f328336 100644 --- a/monkestation/code/modules/virology/disease/symptom_varients/base.dm +++ b/monkestation/code/modules/virology/disease/symptom_varients/base.dm @@ -46,5 +46,5 @@ COOLDOWN_START(src, host_cooldown, cooldown_time) /datum/symptom_varient/proc/Copy(datum/symptom/new_symp) - var/datum/symptom_varient/new_varient = new (new_symp) + var/datum/symptom_varient/new_varient = new new_symp return new_varient diff --git a/monkestation/code/modules/virology/disease/symtoms/restricted/stage3.dm b/monkestation/code/modules/virology/disease/symtoms/restricted/stage3.dm index 1fd8e9e54005..ebdd77b0cc58 100644 --- a/monkestation/code/modules/virology/disease/symtoms/restricted/stage3.dm +++ b/monkestation/code/modules/virology/disease/symtoms/restricted/stage3.dm @@ -45,7 +45,7 @@ if(prob(1)) mob.emote("drool") if(prob(1.5)) - mob.adjustCloneLoss(1, FALSE) + mob.adjustToxLoss(1, FALSE) if(prob(1)) to_chat(mob, span_danger("Your skin feels strange.")) @@ -56,7 +56,7 @@ mob.emote("drool") if(prob(2.5)) mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1, 170) - mob.adjustCloneLoss(2, FALSE) + mob.adjustToxLoss(2, FALSE) if(prob(7.5)) mob.adjust_stutter(6 SECONDS) if(5) @@ -67,5 +67,5 @@ if(prob(2.5)) to_chat(mob, span_danger("Your skin starts degrading!")) if(prob(5)) - mob.adjustCloneLoss(5, FALSE) + mob.adjustToxLoss(5, FALSE) mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2, 170) diff --git a/monkestation/code/modules/virology/disease/symtoms/stage2.dm b/monkestation/code/modules/virology/disease/symtoms/stage2.dm index 95136fc53d52..e00750ca7466 100644 --- a/monkestation/code/modules/virology/disease/symtoms/stage2.dm +++ b/monkestation/code/modules/virology/disease/symtoms/stage2.dm @@ -368,8 +368,8 @@ /datum/symptom/famine/activate(mob/living/mob) if(ishuman(mob)) var/mob/living/carbon/human/victim = mob - if(ispodperson(victim)) - victim.adjustCloneLoss(5 * multiplier) //Plantmen take a LOT of damag + if(ispodperson(victim)) //Plantmen take a LOT of damage + victim.adjustToxLoss(5 * multiplier) for(var/obj/item/food/grown/crop in range(2 * multiplier,mob)) crop.visible_message(span_warning("\The [crop] rots at an alarming rate!")) diff --git a/monkestation/code/modules/virology/disease/symtoms/stage3.dm b/monkestation/code/modules/virology/disease/symtoms/stage3.dm index 0086dbeb9853..05379d006233 100644 --- a/monkestation/code/modules/virology/disease/symtoms/stage3.dm +++ b/monkestation/code/modules/virology/disease/symtoms/stage3.dm @@ -65,7 +65,7 @@ GLOBAL_LIST_INIT(disease_hivemind_users, list()) var/mob/living/carbon/human/H = mob H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5, 50) else - mob.setCloneLoss(50) + mob.setToxLoss(50) /datum/symptom/hallucinations name = "Hallucinational Syndrome" @@ -451,8 +451,12 @@ GLOBAL_LIST_INIT(disease_hivemind_users, list()) desc = "Causes the infected to oversynthesize stem cells engineered towards organ generation, causing damage to the host's organs in the process. Said generated organs are expelled from the body upon completion." stage = 3 badness = EFFECT_DANGER_HARMFUL + COOLDOWN_DECLARE(organ_cooldown) /datum/symptom/teratoma/activate(mob/living/carbon/mob) + if(!COOLDOWN_FINISHED(src, organ_cooldown)) + return + COOLDOWN_START(src, organ_cooldown, 2 MINUTES) var/fail_counter = 0 var/not_passed = TRUE var/obj/item/organ/spawned_organ diff --git a/monkestation/code/modules/virology/disease/symtoms/stage4.dm b/monkestation/code/modules/virology/disease/symtoms/stage4.dm index b607c9384a1a..94354c3a3425 100644 --- a/monkestation/code/modules/virology/disease/symtoms/stage4.dm +++ b/monkestation/code/modules/virology/disease/symtoms/stage4.dm @@ -68,9 +68,9 @@ /datum/symptom/dna/activate(mob/living/carbon/mob) mob.bodytemperature = max(mob.bodytemperature, 350) - scramble_dna(mob, TRUE, TRUE, TRUE, rand(15, 45)) - if(mob.cloneloss <= 50) - mob.adjustCloneLoss(10) + scramble_dna(mob, TRUE, TRUE, TRUE, rand(15,45)) + if(mob.toxloss <= 50) + mob.adjustToxLoss(10) /datum/symptom/immortal name = "Longevity Syndrome" @@ -92,8 +92,8 @@ total_healed += heal_amt * 0.2 else total_healed += (heal_amt - current_health) * 0.2 - mob.heal_overall_damage(brute = heal_amt, burn = heal_amt, updating_health = FALSE) - mob.adjustCloneLoss(-heal_amt, updating_health = TRUE) + mob.heal_overall_damage(brute = heal_amt, burn = heal_amt) + mob.adjustToxLoss(-heal_amt) /datum/symptom/immortal/deactivate(mob/living/carbon/mob) if(ishuman(mob)) @@ -147,16 +147,28 @@ stage = 4 max_multiplier = 7 badness = EFFECT_DANGER_HARMFUL - var/spawn_type= /mob/living/basic/spider/growing/spiderling/guard - var/spawn_name="spiderling" + var/list/spawn_types= list(/mob/living/basic/spider/growing/spiderling/guard = 10) + ///what gets added based on multiplier NOT INCLUSIVE OF PREVIOUS TIERS + var/list/multipler_unlocks = list() /datum/symptom/spawn/activate(mob/living/carbon/mob) - playsound(mob.loc, 'sound/effects/splat.ogg', vol = 50, vary = TRUE) + check_unlocks() + playsound(mob.loc, 'sound/effects/splat.ogg', 50, 1) + var/atom/spawn_type = pick_weight(spawn_types) + var/spawn_name = initial(spawn_type.name) var/mob/living/spawned_mob = new spawn_type(get_turf(mob)) mob.emote("me", 1, "vomits up a live [spawn_name]!") if(multiplier < 4) addtimer(CALLBACK(src, PROC_REF(kill_mob), spawned_mob), 1 MINUTES) +/datum/symptom/spawn/proc/check_unlocks() + spawn_types = initial(spawn_types) + var/text_multi = num2text(round(multiplier)) + + if(!(text_multi in multipler_unlocks)) + return + spawn_types += multipler_unlocks[text_multi] + /datum/symptom/spawn/proc/kill_mob(mob/living/basic/mob) mob.visible_message(span_warning("The [mob] falls apart!"), span_warning("You fall apart")) mob.death() @@ -166,8 +178,13 @@ desc = "Converts the infected's stomach to begin producing creatures of the blattid variety." stage = 4 badness = EFFECT_DANGER_HINDRANCE - spawn_type = /mob/living/basic/cockroach - spawn_name = "cockroach" + spawn_types = list(/mob/living/basic/cockroach = 10) + multipler_unlocks = list( + "4" = list(/mob/living/basic/cockroach/glockroach = 3), + "5" = list(/mob/living/basic/cockroach/glockroach = 4), + "6" = list(/mob/living/basic/cockroach/glockroach = 5, /mob/living/basic/cockroach/glockroach/mobroach = 3), + "7" = list(/mob/living/basic/cockroach/glockroach = 5, /mob/living/basic/cockroach/glockroach/mobroach = 3, /mob/living/basic/cockroach/hauberoach = 3), + ) /datum/symptom/gregarious name = "Gregarious Impetus" diff --git a/monkestation/code/modules/virology/items/_base_item_additions.dm b/monkestation/code/modules/virology/items/_base_item_additions.dm index cfe80ba21362..6722945f79bc 100644 --- a/monkestation/code/modules/virology/items/_base_item_additions.dm +++ b/monkestation/code/modules/virology/items/_base_item_additions.dm @@ -5,7 +5,7 @@ GLOBAL_LIST_INIT(infected_items, list()) //how sterile an item is, not used for much atm var/sterility = 0 /obj/item - var/list/viruses = list() + var/list/viruses /obj/item/attack_hand(mob/user, list/modifiers) . = ..() diff --git a/monkestation/code/modules/virology/items/antibodyscanner.dm b/monkestation/code/modules/virology/items/antibodyscanner.dm index ec67fb48c823..8222f5bf49ee 100644 --- a/monkestation/code/modules/virology/items/antibodyscanner.dm +++ b/monkestation/code/modules/virology/items/antibodyscanner.dm @@ -154,4 +154,9 @@ var/obj/effect/abstract/blank/scan/scanline = new vis_contents += scanline - addtimer(CALLBACK(src, GLOBAL_PROC_REF(qdel), scanline), 2 SECONDS) + addtimer(CALLBACK(src, PROC_REF(remove), scanline), 2 SECONDS) + +/atom/movable/proc/remove(atom/scanline) + vis_contents -= scanline + qdel(scanline) + diff --git a/monkestation/code/modules/virology/items/extrapolator.dm b/monkestation/code/modules/virology/items/extrapolator.dm index a210c43137e4..84d7513bbbc5 100644 --- a/monkestation/code/modules/virology/items/extrapolator.dm +++ b/monkestation/code/modules/virology/items/extrapolator.dm @@ -74,18 +74,19 @@ . = ..() if(!proximity_flag && !scan) return - if(isliving(target)) + if(isliving(target) && target != usr) user_data = WEAKREF(target) if(scanner) if(!scan) if(length(stored_varient_types)) try_disease_modification(user, target) - switch(target.extrapolator_act(user, src, scan)) - if(FALSE) - if(scan) - to_chat(user, "the extrapolator fails to return any data") - if(TRUE) - to_chat(user, span_notice("You store [target]'s blood sample in [src].")) + else + switch(target.extrapolator_act(user, src, scan)) + if(FALSE) + if(scan) + to_chat(user, "the extrapolator fails to return any data") + if(TRUE) + to_chat(user, span_notice("You store [target]'s blood sample in [src].")) else to_chat(user, "the extrapolator has no scanner installed") diff --git a/monkestation/code/modules/virology/living/mouse.dm b/monkestation/code/modules/virology/living/mouse.dm index 71ba38f520bc..e1bea9307313 100644 --- a/monkestation/code/modules/virology/living/mouse.dm +++ b/monkestation/code/modules/virology/living/mouse.dm @@ -1,11 +1,15 @@ /mob/living/basic/mouse - var/disease_chance = 50 + var/disease_chance = 25 + var/diseased = TRUE + +/mob/living/basic/mouse/ratking + diseased = FALSE /mob/living/basic/mouse/Initialize(mapload, tame, new_body_color) . = ..() immune_system = new(src) - if(prob(disease_chance)) + if(prob(disease_chance) && diseased) var/virus_choice = pick(subtypesof(/datum/disease/advanced)- typesof(/datum/disease/advanced/premade)) var/list/anti = list( ANTIGEN_BLOOD = 2, @@ -23,6 +27,7 @@ ) var/datum/disease/advanced/disease = new virus_choice disease.makerandom(list(50,90),list(10,100),anti,bad,src) + disease.spread_flags &= ~DISEASE_SPREAD_AIRBORNE diseases = list() diseases += disease disease.after_add() diff --git a/monkestation/code/modules/virology/reagents/_stage_mutations.dm b/monkestation/code/modules/virology/reagents/_stage_mutations.dm index f09d300f7d55..685b44a1ff5f 100644 --- a/monkestation/code/modules/virology/reagents/_stage_mutations.dm +++ b/monkestation/code/modules/virology/reagents/_stage_mutations.dm @@ -24,12 +24,12 @@ dish.info = "OUTDATED : [dish.info]" dish.update_appearance() -/datum/reagent/toxin/plasma/plasmavirusfood/stage_disease_incubate(datum/disease/disease, list/symptoms, obj/machinery/disease2/incubator/machine) +/datum/reagent/toxin/plasma/plasmavirusfood/stage_disease_incubate(atom/movable/parent, datum/disease/disease, list/symptoms, obj/machinery/disease2/incubator/machine) disease.log += "
[ROUND_TIME()] Symptom Multiplier Increase (Virus Rations)" for(var/datum/symptom/symptom as anything in symptoms) symptom.multiplier_tweak(0.1) -/datum/reagent/medicine/antipathogenic/spaceacillin/stage_disease_incubate(datum/disease/disease, list/symptoms, obj/machinery/disease2/incubator/machine) +/datum/reagent/medicine/antipathogenic/spaceacillin/stage_disease_incubate(atom/movable/parent, datum/disease/disease, list/symptoms, obj/machinery/disease2/incubator/machine) disease.log += "
[ROUND_TIME()] Symptom Multiplier Decrease (Spaceacillin)" for(var/datum/symptom/symptom as anything in symptoms) symptom.multiplier_tweak(-0.1) diff --git a/monkestation/code/modules/virology/reagents/incubation.dm b/monkestation/code/modules/virology/reagents/incubation.dm index 362afc864361..da7ffb86fbde 100644 --- a/monkestation/code/modules/virology/reagents/incubation.dm +++ b/monkestation/code/modules/virology/reagents/incubation.dm @@ -1,7 +1,7 @@ /datum/reagent/proc/disease_incubate(atom/movable/parent, datum/disease/disease, obj/machinery/disease2/incubator/machine) return -/datum/reagent/proc/stage_disease_incubate(datum/disease/disease, list/symptoms, obj/machinery/disease2/incubator/machine) +/datum/reagent/proc/stage_disease_incubate(atom/movable/parent, datum/disease/disease, list/symptoms, obj/machinery/disease2/incubator/machine) return diff --git a/monkestation/gunning_ing/recoil.dm b/monkestation/gunning_ing/recoil.dm new file mode 100644 index 000000000000..907a7a677f18 --- /dev/null +++ b/monkestation/gunning_ing/recoil.dm @@ -0,0 +1,22 @@ +/obj/item/gun + ///a multiplier of the duration the recoil takes to go back to normal view, this is (recoil*recoil_backtime_multiplier)+1 + var/recoil_backtime_multiplier = 2 + ///this is how much deviation the gun recoil can have, recoil pushes the screen towards the reverse angle you shot + some deviation which this is the max. + var/recoil_deviation = 22.5 + +/obj/item/gun/ballistic + recoil = 1 +///Makes a recoil-like animation on the mob camera. +/proc/recoil_camera(mob/M, duration, backtime_duration, strength, angle) + if(!M || !M.client) + return + var/client/sufferer = M.client + strength *= world.icon_size + var/oldx = sufferer.pixel_x + var/oldy = sufferer.pixel_y + + //get pixels to move the camera in an angle + var/mpx = sin(angle) * strength + var/mpy = cos(angle) * strength + animate(sufferer, pixel_x = oldx+mpx, pixel_y = oldy+mpy, time = duration, flags = ANIMATION_RELATIVE) + animate(pixel_x = oldx, pixel_y = oldy, time = backtime_duration, easing = BACK_EASING) diff --git a/sound/attributions.txt b/sound/attributions.txt index 4bdcd008aa17..aaafecc9316b 100644 --- a/sound/attributions.txt +++ b/sound/attributions.txt @@ -122,3 +122,19 @@ https://freesound.org/people/vmgraw/sounds/235610/ vmgraw's "Distant Whistle" (CC 0) https://freesound.org/people/giddster/sounds/414480/ + +rock_break.ogg is taken from Bertsz's Rock Destroy from Freesound.org, CC0: +https://freesound.org/people/Bertsz/sounds/524312/ + +sonar-ping.ogg and radar-ping is taken and modified from SamsterBirdies' Sonar Ping from Freesound.org, CC0: +https://freesound.org/people/SamsterBirdies/sounds/539957/ + +manual_teleport.ogg is taken from Quetzakol's teleport from Freesound.org, CC0: +https://freesound.org/people/Quetzakol/sounds/520743/ + +auto_teleport.ogg is taken from Steaq's A teleportation from Freesound.org, CC0: +https://freesound.org/people/steaq/sounds/560124/ + +refinery.ogg, smelter.ogg, and wooping_teleport.ogg are all original works by ArcaneMusic, +with smelter.ogg using samples from rock_break alongside original sound effects from a warrior electric drill, +where refinery and wooping_teleport are modifications of that same electric drill recording. diff --git a/sound/effects/rock_break.ogg b/sound/effects/rock_break.ogg new file mode 100644 index 000000000000..09f6b1d5d33c Binary files /dev/null and b/sound/effects/rock_break.ogg differ diff --git a/sound/machines/mining/auto_teleport.ogg b/sound/machines/mining/auto_teleport.ogg new file mode 100644 index 000000000000..a8fe669e8657 Binary files /dev/null and b/sound/machines/mining/auto_teleport.ogg differ diff --git a/sound/machines/mining/manual_teleport.ogg b/sound/machines/mining/manual_teleport.ogg new file mode 100644 index 000000000000..b011ef91e65a Binary files /dev/null and b/sound/machines/mining/manual_teleport.ogg differ diff --git a/sound/machines/mining/refinery.ogg b/sound/machines/mining/refinery.ogg new file mode 100644 index 000000000000..fdae21f9a301 Binary files /dev/null and b/sound/machines/mining/refinery.ogg differ diff --git a/sound/machines/mining/smelter.ogg b/sound/machines/mining/smelter.ogg new file mode 100644 index 000000000000..b1d65f3bd203 Binary files /dev/null and b/sound/machines/mining/smelter.ogg differ diff --git a/sound/machines/mining/wooping_teleport.ogg b/sound/machines/mining/wooping_teleport.ogg new file mode 100644 index 000000000000..edf5eb57b432 Binary files /dev/null and b/sound/machines/mining/wooping_teleport.ogg differ diff --git a/sound/machines/radar-ping.ogg b/sound/machines/radar-ping.ogg new file mode 100644 index 000000000000..d6fd0000d1a5 Binary files /dev/null and b/sound/machines/radar-ping.ogg differ diff --git a/sound/machines/sonar-ping.ogg b/sound/machines/sonar-ping.ogg new file mode 100644 index 000000000000..c69d43520958 Binary files /dev/null and b/sound/machines/sonar-ping.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 7d63f0cf86bd..7140b7485cc9 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -158,6 +158,7 @@ #include "code\__DEFINES\melee.dm" #include "code\__DEFINES\memory_defines.dm" #include "code\__DEFINES\mergers.dm" +#include "code\__DEFINES\mining.dm" #include "code\__DEFINES\mob_spawn.dm" #include "code\__DEFINES\mobfactions.dm" #include "code\__DEFINES\mobs.dm" @@ -406,7 +407,9 @@ #include "code\__DEFINES\~monkestation\blackboard.dm" #include "code\__DEFINES\~monkestation\blueshift.dm" #include "code\__DEFINES\~monkestation\botany.dm" +#include "code\__DEFINES\~monkestation\cargo.dm" #include "code\__DEFINES\~monkestation\chat.dm" +#include "code\__DEFINES\~monkestation\chewin.dm" #include "code\__DEFINES\~monkestation\clock_cult.dm" #include "code\__DEFINES\~monkestation\colors.dm" #include "code\__DEFINES\~monkestation\combat.dm" @@ -439,6 +442,7 @@ #include "code\__DEFINES\~monkestation\oozeling.dm" #include "code\__DEFINES\~monkestation\optfor.dm" #include "code\__DEFINES\~monkestation\overwatch.dm" +#include "code\__DEFINES\~monkestation\pain.dm" #include "code\__DEFINES\~monkestation\particles.dm" #include "code\__DEFINES\~monkestation\physics.dm" #include "code\__DEFINES\~monkestation\power.dm" @@ -612,6 +616,7 @@ #include "code\_globalvars\lists\mobs.dm" #include "code\_globalvars\lists\names.dm" #include "code\_globalvars\lists\objects.dm" +#include "code\_globalvars\lists\ores_spawned.dm" #include "code\_globalvars\lists\poll_ignore.dm" #include "code\_globalvars\lists\quirks.dm" #include "code\_globalvars\lists\rtd.dm" @@ -5947,6 +5952,12 @@ #include "monkestation\code\game\turfs\open\water.dm" #include "monkestation\code\game\turfs\open\floor\misc_floor.dm" #include "monkestation\code\modules\_paperwork\paper_premade.dm" +#include "monkestation\code\modules\a_ship_in_need_of_breaking\area.dm" +#include "monkestation\code\modules\a_ship_in_need_of_breaking\scrap.dm" +#include "monkestation\code\modules\a_ship_in_need_of_breaking\machines\console.dm" +#include "monkestation\code\modules\a_ship_in_need_of_breaking\machines\recycler.dm" +#include "monkestation\code\modules\a_ship_in_need_of_breaking\ships\_base_ship.dm" +#include "monkestation\code\modules\a_ship_in_need_of_breaking\ships\robotics.dm" #include "monkestation\code\modules\abberant_organs\organ_process.dm" #include "monkestation\code\modules\abberant_organs\components\abberant_organ.dm" #include "monkestation\code\modules\abberant_organs\custom_organs\drunkards_liver.dm" @@ -6169,22 +6180,6 @@ #include "monkestation\code\modules\antagonists\heretic\knowledge\sacrifice_knowledge\sacrifice_buff.dm" #include "monkestation\code\modules\antagonists\nukeop\nukeop.dm" #include "monkestation\code\modules\antagonists\nukeop\equipment\nuclear_bomb\bee_nuke.dm" -#include "monkestation\code\modules\antagonists\slasher\__base_slasher_additions.dm" -#include "monkestation\code\modules\antagonists\slasher\ghost_role.dm" -#include "monkestation\code\modules\antagonists\slasher\slasher_datum.dm" -#include "monkestation\code\modules\antagonists\slasher\slasher_punishment.dm" -#include "monkestation\code\modules\antagonists\slasher\abilities\_slasher_base.dm" -#include "monkestation\code\modules\antagonists\slasher\abilities\blood_walk.dm" -#include "monkestation\code\modules\antagonists\slasher\abilities\incorporealize.dm" -#include "monkestation\code\modules\antagonists\slasher\abilities\recall_machette.dm" -#include "monkestation\code\modules\antagonists\slasher\abilities\slasher_regenerate.dm" -#include "monkestation\code\modules\antagonists\slasher\abilities\soul_steal.dm" -#include "monkestation\code\modules\antagonists\slasher\abilities\stalk_target.dm" -#include "monkestation\code\modules\antagonists\slasher\abilities\terror_screech.dm" -#include "monkestation\code\modules\antagonists\slasher\components\team_monitor.dm" -#include "monkestation\code\modules\antagonists\slasher\slasher_outfit\slasher_footwear.dm" -#include "monkestation\code\modules\antagonists\slasher\slasher_outfit\slasher_headgear.dm" -#include "monkestation\code\modules\antagonists\slasher\slasher_outfit\slasher_middlewear.dm" #include "monkestation\code\modules\antagonists\space_ninja\space_ninja.dm" #include "monkestation\code\modules\antagonists\traitor\traitor_objective.dm" #include "monkestation\code\modules\antagonists\traitor\uplink_handler.dm" @@ -6283,6 +6278,22 @@ #include "monkestation\code\modules\ballpit\ballpit.dm" #include "monkestation\code\modules\bitrunners\code\ability_disks.dm" #include "monkestation\code\modules\bitrunners\code\combat_gear_disks.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\fly_away.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\particle.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\__base_slasher_additions.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\ghost_role.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\slasher_datum.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\abilities\_slasher_base.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\abilities\blood_walk.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\abilities\envelope_darkness.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\abilities\recall_machette.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\abilities\slasher_regenerate.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\abilities\soul_steal.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\abilities\stalk_target.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\abilities\terror_screech.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\components\see_as_something.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\components\team_monitor.dm" +#include "monkestation\code\modules\blood_for_the_blood_gods\slasher\slasher_outfit\slasher_clothing.dm" #include "monkestation\code\modules\bloodsuckers\bloodsucker_assets.dm" #include "monkestation\code\modules\bloodsuckers\bloodsucker\bloodsucker_conversion.dm" #include "monkestation\code\modules\bloodsuckers\bloodsucker\bloodsucker_datum.dm" @@ -6365,6 +6376,18 @@ #include "monkestation\code\modules\bloodsuckers\vassals\vassal_pinpointer.dm" #include "monkestation\code\modules\bloodsuckers\vassals\types\favorite.dm" #include "monkestation\code\modules\bloodsuckers\vassals\types\revenge.dm" +#include "monkestation\code\modules\blueshield\areas.dm" +#include "monkestation\code\modules\blueshield\closet.dm" +#include "monkestation\code\modules\blueshield\clothing.dm" +#include "monkestation\code\modules\blueshield\gun.dm" +#include "monkestation\code\modules\blueshield\job.dm" +#include "monkestation\code\modules\blueshield\landmarks.dm" +#include "monkestation\code\modules\blueshield\radio.dm" +#include "monkestation\code\modules\blueshield\trim.dm" +#include "monkestation\code\modules\blueshield\devices\crew_monitor.dm" +#include "monkestation\code\modules\blueshield\devices\sensor.dm" +#include "monkestation\code\modules\blueshield\modsuit\suit.dm" +#include "monkestation\code\modules\blueshield\modsuit\theme.dm" #include "monkestation\code\modules\blueshift\shuttles.dm" #include "monkestation\code\modules\blueshift\appliances\colony.dm" #include "monkestation\code\modules\blueshift\appliances\multi_charger.dm" @@ -6400,7 +6423,6 @@ #include "monkestation\code\modules\blueshift\cargo\deforest.dm" #include "monkestation\code\modules\blueshift\cargo\flatpacks.dm" #include "monkestation\code\modules\blueshift\cargo\specialist_armor.dm" -#include "monkestation\code\modules\blueshift\clothing\blueshield.dm" #include "monkestation\code\modules\blueshift\clothing\dogginos.dm" #include "monkestation\code\modules\blueshift\clothing\kahraman.dm" #include "monkestation\code\modules\blueshift\clothing\nova_armorsuit.dm" @@ -6633,11 +6655,89 @@ #include "monkestation\code\modules\botany\species\apid\hive\area.dm" #include "monkestation\code\modules\botany\species\apid\hive\hive_object.dm" #include "monkestation\code\modules\botany\species\apid\hive\hive_turfs.dm" +#include "monkestation\code\modules\brewin_and_chewin\cargo_exports.dm" +#include "monkestation\code\modules\brewin_and_chewin\uniqueness.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\bottler.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\bottles.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\designs.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\fermintation_keg.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\reagents.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\recipe_card.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\recipes\_base.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\recipes\beers.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\recipes\custom.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\recipes\liquors.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\recipes\meads.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\recipes\misc.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\recipes\rums.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\recipes\vinegars.dm" +#include "monkestation\code\modules\brewin_and_chewin\brewing\recipes\wines.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\cooking_containers.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\food_additons.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\fryer_overhaul.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\global_creation.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\items.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\oven_overrides.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\tracker.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\food_effects\food_posioning.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\_base.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\add_item.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\add_produce.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\add_produce_choice.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\add_reagent.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\add_reagent_choice.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\recipe_start.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\use_fryer.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\use_grill.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\use_item.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\use_oven.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\use_stove.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipe_steps\use_tool.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipes\black_eggs.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipes\example_recipe.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipes\french_fries.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipes\fried_blood_sausage.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipes\fried_rice.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipes\katsu_curry.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipes\kimchi.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipes\lizard_dumplings.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipes\oven_bread.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipes\recipe_crafting_helper_generator.dm" +#include "monkestation\code\modules\brewin_and_chewin\chewing\recipes\sandwhich_test.dm" #include "monkestation\code\modules\buckshotroulette\projectiles\ammunition\ballistic\shotgun.dm" #include "monkestation\code\modules\buckshotroulette\projectiles\boxes_magazines\internal\shotgun.dm" #include "monkestation\code\modules\buckshotroulette\projectiles\guns\ballistic\shotgun.dm" #include "monkestation\code\modules\bunny_wizard\outfits.dm" #include "monkestation\code\modules\bunny_wizard\wizard_items.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\subsystem.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\components\make_item_slow.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\elements\temperature_pack.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\_base.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\bodyparts.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\effects.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\helpers.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\item_helpers.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\modifiers.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\pain_assistance_tools.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\pain_goodies.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\preferences.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\shock.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\species.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\traits.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\causes\generic.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\causes\opiods.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\causes\surgery.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\reagents\modified_reagents.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\reagents\painkiller_related.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\reagents\painkillers.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\status_effects\anesthetics.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\status_effects\fire_pain.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\status_effects\low_blood_pressure.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\status_effects\min_pain.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\status_effects\pain_limp.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\status_effects\sharp_pain.dm" +#include "monkestation\code\modules\can_spessmen_feel_pain\pain\status_effects\temp_pack.dm" #include "monkestation\code\modules\cargo\bounties\pathology.dm" #include "monkestation\code\modules\cargo\crates\costumes_toys.dm" #include "monkestation\code\modules\cargo\crates\emergency.dm" @@ -6836,6 +6936,41 @@ #include "monkestation\code\modules\events\summon_wizard_event.dm" #include "monkestation\code\modules\events\ghost_role\drifting_contractor.dm" #include "monkestation\code\modules\events\wizard\summon_gifts.dm" +#include "monkestation\code\modules\factory_type_beat\boulder.dm" +#include "monkestation\code\modules\factory_type_beat\circuits.dm" +#include "monkestation\code\modules\factory_type_beat\debug.dm" +#include "monkestation\code\modules\factory_type_beat\designs.dm" +#include "monkestation\code\modules\factory_type_beat\effects.dm" +#include "monkestation\code\modules\factory_type_beat\flatpacks.dm" +#include "monkestation\code\modules\factory_type_beat\map_templates.dm" +#include "monkestation\code\modules\factory_type_beat\ore_vent.dm" +#include "monkestation\code\modules\factory_type_beat\ss_ore_gen.dm" +#include "monkestation\code\modules\factory_type_beat\technodes.dm" +#include "monkestation\code\modules\factory_type_beat\yummy.dm" +#include "monkestation\code\modules\factory_type_beat\ai_behaviours\latch_onto.dm" +#include "monkestation\code\modules\factory_type_beat\machinery\assembler.dm" +#include "monkestation\code\modules\factory_type_beat\machinery\brine_chamber.dm" +#include "monkestation\code\modules\factory_type_beat\machinery\grabber.dm" +#include "monkestation\code\modules\factory_type_beat\machinery\splitter.dm" +#include "monkestation\code\modules\factory_type_beat\machinery\test_boulder_spawner.dm" +#include "monkestation\code\modules\factory_type_beat\machinery\atmos_chem\chemical_infuser.dm" +#include "monkestation\code\modules\factory_type_beat\machinery\atmos_chem\pressurized_reaction_chamber.dm" +#include "monkestation\code\modules\factory_type_beat\machinery\atmos_chem\chemical_infuser_recipes\_base.dm" +#include "monkestation\code\modules\factory_type_beat\machinery\atmos_chem\chemical_infuser_recipes\sulfur.dm" +#include "monkestation\code\modules\factory_type_beat\machinery\atmos_chem\pressurised_reactions\_base.dm" +#include "monkestation\code\modules\factory_type_beat\machinery\atmos_chem\pressurised_reactions\sulfur.dm" +#include "monkestation\code\modules\factory_type_beat\mobs\node_drone.dm" +#include "monkestation\code\modules\factory_type_beat\processing\bouldertech.dm" +#include "monkestation\code\modules\factory_type_beat\processing\brm.dm" +#include "monkestation\code\modules\factory_type_beat\processing\checmial_washer.dm" +#include "monkestation\code\modules\factory_type_beat\processing\chemical_injector.dm" +#include "monkestation\code\modules\factory_type_beat\processing\crusher.dm" +#include "monkestation\code\modules\factory_type_beat\processing\crystalizer.dm" +#include "monkestation\code\modules\factory_type_beat\processing\dissolution_chamber.dm" +#include "monkestation\code\modules\factory_type_beat\processing\enricher.dm" +#include "monkestation\code\modules\factory_type_beat\processing\holding_types.dm" +#include "monkestation\code\modules\factory_type_beat\processing\purification_chamber.dm" +#include "monkestation\code\modules\factory_type_beat\processing\refinery.dm" #include "monkestation\code\modules\flavor_text\flavor_examine.dm" #include "monkestation\code\modules\flavor_text\flavor_helpers.dm" #include "monkestation\code\modules\flavor_text\flavor_hrefs.dm" @@ -6900,7 +7035,6 @@ #include "monkestation\code\modules\job_xp\milestones\botany_milestones.dm" #include "monkestation\code\modules\job_xp\preferences\base_preferences.dm" #include "monkestation\code\modules\job_xp\preferences\xp_handlers.dm" -#include "monkestation\code\modules\jobs\job_types\blueshield.dm" #include "monkestation\code\modules\jobs\job_types\brig_physician.dm" #include "monkestation\code\modules\jobs\job_types\candysalesman.dm" #include "monkestation\code\modules\jobs\job_types\chaplain.dm" @@ -7719,6 +7853,7 @@ #include "monkestation\code\modules\trading\unusual_effects\animation_housing\fire.dm" #include "monkestation\code\modules\trading\unusual_effects\animation_housing\galaxies.dm" #include "monkestation\code\modules\trading\unusual_effects\animation_housing\holy_steps.dm" +#include "monkestation\code\modules\trading\unusual_effects\animation_housing\money.dm" #include "monkestation\code\modules\trading\unusual_effects\animation_housing\music.dm" #include "monkestation\code\modules\trading\unusual_effects\animation_housing\rain.dm" #include "monkestation\code\modules\trading\unusual_effects\animation_housing\shooting_stars.dm" @@ -7878,4 +8013,5 @@ #include "monkestation\code\random_rooms\engines\kilostation.dm" #include "monkestation\code\random_rooms\engines\metastation.dm" #include "monkestation\code\random_rooms\engines\tramstation.dm" +#include "monkestation\gunning_ing\recoil.dm" // END_INCLUDE diff --git a/tgui/packages/tgui/components/Collapsible.jsx b/tgui/packages/tgui/components/Collapsible.jsx index 7d59a11417cc..944b517b57f8 100644 --- a/tgui/packages/tgui/components/Collapsible.jsx +++ b/tgui/packages/tgui/components/Collapsible.jsx @@ -20,7 +20,14 @@ export class Collapsible extends Component { render() { const { props } = this; const { open } = this.state; - const { children, color = 'default', title, buttons, ...rest } = props; + const { + children, + color = 'default', + title, + buttons, + contentStyle, + ...rest + } = props; return (
@@ -39,7 +46,11 @@ export class Collapsible extends Component {
{buttons}
)}
- {open && {children}} + {open && ( + + {children} + + )}
); } diff --git a/tgui/packages/tgui/components/ImageButton.js b/tgui/packages/tgui/components/ImageButton.js new file mode 100644 index 000000000000..2b7258497fa6 --- /dev/null +++ b/tgui/packages/tgui/components/ImageButton.js @@ -0,0 +1,234 @@ +/** + * @file + * @copyright 2024 Aylong (https://github.com/AyIong) + * @license MIT + */ + +import { resolveAsset } from '../assets'; +import { classes, pureComponentHooks } from 'common/react'; +import { computeBoxClassName, computeBoxProps } from './Box'; +import { Icon } from './Icon'; +import { Tooltip } from './Tooltip'; + +export const ImageButton = (props) => { + const { + className, + asset, + color, + title, + vertical, + content, + selected, + disabled, + disabledContent, + image, + imageUrl, + imageAsset, + imageSize, + tooltip, + tooltipPosition, + ellipsis, + children, + onClick, + ...rest + } = props; + rest.onClick = (e) => { + if (!disabled && onClick) { + onClick(e); + } + }; + let buttonContent = ( +
+
+ {asset ? ( +
+ ) : ( + + )} +
+ {content && + (vertical ? ( +
+ {disabled && disabledContent ? disabledContent : content} +
+ ) : ( +
+ {title && ( +
+ {title} +
+
+ )} +
+ {content} +
+
+ ))} +
+ ); + + if (tooltip) { + buttonContent = ( + + {buttonContent} + + ); + } + + return ( +
+ {buttonContent} + {children} +
+ ); +}; + +ImageButton.defaultHooks = pureComponentHooks; + +/** + * That's VERY fucking expensive thing! + * Use it only in places, where it really needed. + * Otherwise, the window opening time may increase by a third! + * Most of the blame is on Icon. + * Maybe it's also because I'm a bit crooked. + * (с) Aylong + */ +export const ImageButtonItem = (props) => { + const { + className, + color, + content, + horizontal, + selected, + disabled, + disabledContent, + tooltip, + tooltipPosition, + icon, + iconColor, + iconPosition, + iconRotation, + iconSize, + onClick, + children, + ...rest + } = props; + rest.onClick = (e) => { + if (!disabled && onClick) { + onClick(e); + } + }; + let itemContent = ( +
+
+
+ {icon && (iconPosition === 'top' || iconPosition === 'left') && ( + + )} +
+ {disabled && disabledContent ? disabledContent : content} + {children} +
+ {icon && !(iconPosition === 'top' || iconPosition === 'left') && ( + + )} +
+
+
+ ); + if (tooltip) { + itemContent = ( + + {itemContent} + + ); + } + + return itemContent; +}; + +ImageButton.Item = ImageButtonItem; diff --git a/tgui/packages/tgui/components/index.jsx b/tgui/packages/tgui/components/index.jsx index fefd280a590c..95780c83b46e 100644 --- a/tgui/packages/tgui/components/index.jsx +++ b/tgui/packages/tgui/components/index.jsx @@ -22,6 +22,7 @@ export { Flex } from './Flex'; export { FitText } from './FitText'; export { Grid } from './Grid'; export { Icon } from './Icon'; +export { ImageButton } from './ImageButton'; export { InfinitePlane } from './InfinitePlane'; export { Interactive } from './Interactive'; export { Input } from './Input'; diff --git a/tgui/packages/tgui/interfaces/BigManipulator.tsx b/tgui/packages/tgui/interfaces/BigManipulator.tsx new file mode 100644 index 000000000000..6a5501b56647 --- /dev/null +++ b/tgui/packages/tgui/interfaces/BigManipulator.tsx @@ -0,0 +1,30 @@ +import { BooleanLike } from 'common/react'; + +import { useBackend } from '../backend'; +import { Button, Section, Stack } from '../components'; +import { Window } from '../layouts'; + +type ManipulatorData = { + active: BooleanLike; +}; + +export const BigManipulator = (props) => { + const { data, act } = useBackend(); + const { active } = data; + return ( + + +
+ +
+
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/CrewConsoleNovaBlueshield.jsx b/tgui/packages/tgui/interfaces/CrewConsoleNovaBlueshield.jsx new file mode 100644 index 000000000000..a939e3a4d076 --- /dev/null +++ b/tgui/packages/tgui/interfaces/CrewConsoleNovaBlueshield.jsx @@ -0,0 +1,201 @@ +// THIS IS A NOVA SECTOR UI FILE +import { sortBy } from 'common/collections'; + +import { useBackend } from '../backend'; +import { Box, Button, Icon, Section, Table } from '../components'; +import { COLORS } from '../constants'; +import { Window } from '../layouts'; + +const HEALTH_COLOR_BY_LEVEL = [ + '#17d568', + '#c4cf2d', + '#e67e22', + '#ed5100', + '#e74c3c', + '#801308', +]; +const HEALTH_ICON_BY_LEVEL = [ + 'heart', + 'heart', + 'heart', + 'heart', + 'heartbeat', + 'skull', +]; +const jobIsHead = (jobId) => jobId % 10 === 0; + +const jobToColor = (jobId) => { + if (jobId === 0) { + return COLORS.department.captain; + } + if (jobId >= 10 && jobId < 20) { + return COLORS.department.security; + } + if (jobId >= 20 && jobId < 30) { + return COLORS.department.medbay; + } + if (jobId >= 30 && jobId < 40) { + return COLORS.department.science; + } + if (jobId >= 40 && jobId < 50) { + return COLORS.department.engineering; + } + if (jobId >= 50 && jobId < 60) { + return COLORS.department.cargo; + } + if (jobId >= 60 && jobId < 80) { + return COLORS.department.service; + } + if (jobId >= 200 && jobId < 240) { + return COLORS.department.centcom; + } + return COLORS.department.other; +}; + +const healthToAttribute = (oxy, tox, burn, brute, attributeList) => { + const healthSum = oxy + tox + burn + brute; + const level = Math.min(Math.max(Math.ceil(healthSum / 50), 0), 5); + // 200 Default Health, Sum Divided by 50, 6 Health States + return attributeList[level]; +}; + +const HealthStat = (props) => { + const { type, value } = props; + return ( + + {value} + + ); +}; + +// all of this just to change the name +export const CrewConsoleNovaBlueshield = () => { + return ( + + +
+ +
+
+
+ ); +}; + +const CrewTable = (props) => { + const { act, data } = useBackend(); + const sensors = sortBy((s) => s.ijob)(data.sensors ?? []); + return ( + + + + Name + + + Status + + + Vitals + + + Position + + + {sensors.map((sensor) => ( + + ))} +
+ ); +}; + +const CrewTableEntry = (props) => { + const { act, data } = useBackend(); + const { link_allowed } = data; + const { sensor_data } = props; + const { + name, + assignment, + ijob, + is_robot, + life_status, + oxydam, + toxdam, + burndam, + brutedam, + area, + can_track, + } = sensor_data; + + return ( + + + {name} + {assignment !== undefined ? ` (${assignment})` : ''} + + + {is_robot ? : ''} + + + {oxydam !== undefined && life_status ? ( + + ) : life_status ? ( + + ) : ( + + )} + + + {oxydam !== undefined ? ( + + + {'/'} + + {'/'} + + {'/'} + + + ) : life_status ? ( + 'Alive' + ) : ( + 'Dead' + )} + + + {area !== undefined ? ( + area + ) : ( + + )} + + {!!link_allowed && ( + +