diff --git a/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_arena.dmm b/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_arena.dmm index 47fd82ad043..a062f3cc436 100644 --- a/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_arena.dmm +++ b/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_arena.dmm @@ -115,7 +115,7 @@ }, /mob/living/basic/mining/hivelord/no_wander{ color = "red"; - name = "gate guardian"; + name = "gate guardian" }, /turf/open/lava/smooth/lava_land_surface{ slowdown = 0 @@ -309,7 +309,7 @@ }, /mob/living/basic/mining/hivelord/no_wander{ color = "red"; - name = "gate guardian"; + name = "gate guardian" }, /turf/open/lava/smooth/lava_land_surface{ slowdown = 0 @@ -627,7 +627,7 @@ }, /mob/living/basic/mining/hivelord/no_wander{ color = "red"; - name = "gate guardian"; + name = "gate guardian" }, /turf/open/indestructible/boss, /area/lavaland/surface/outdoors) @@ -777,7 +777,7 @@ }, /mob/living/basic/mining/hivelord/no_wander{ color = "red"; - name = "gate guardian"; + name = "gate guardian" }, /turf/open/indestructible/boss, /area/lavaland/surface/outdoors) diff --git a/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_syndicate_base1_skyrat.dmm b/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_syndicate_base1_skyrat.dmm index 957a669e53c..b9f9c542350 100644 --- a/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_syndicate_base1_skyrat.dmm +++ b/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_syndicate_base1_skyrat.dmm @@ -1741,6 +1741,8 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/structure/table/reinforced, +/obj/item/storage/backpack/duffelbag/synth_treatment_kit/trauma/advanced/unzipped, /turf/open/floor/iron/white, /area/ruin/syndicate_lava_base/medbay) "rQ" = ( diff --git a/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm b/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm index b621fef4d28..2383c4688e3 100644 --- a/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm +++ b/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm @@ -1984,10 +1984,7 @@ /obj/effect/decal/cleanable/glass, /obj/item/shard, /obj/item/stack/sheet/iron, -/mob/living/simple_animal/hostile/heretic_summon/rust_spirit{ - AIStatus = 1; - stop_automated_movement = 0 - }, +/mob/living/basic/heretic_summon/rust_walker, /turf/open/floor/plating/rust, /area/ruin/space/has_grav/dangerous_research/lab) "zR" = ( @@ -3717,10 +3714,7 @@ /turf/open/floor/engine/airless, /area/ruin/space/has_grav/dangerous_research/maint) "Xh" = ( -/mob/living/simple_animal/hostile/heretic_summon/rust_spirit{ - AIStatus = 1; - stop_automated_movement = 0 - }, +/mob/living/basic/heretic_summon/rust_walker, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, @@ -3862,10 +3856,7 @@ /turf/open/floor/iron/white, /area/ruin/space/has_grav/dangerous_research/medical) "YZ" = ( -/mob/living/simple_animal/hostile/heretic_summon/rust_spirit{ - AIStatus = 1; - stop_automated_movement = 0 - }, +/mob/living/basic/heretic_summon/rust_walker, /turf/open/floor/plating/rust, /area/ruin/space/has_grav/dangerous_research/lab) "Zc" = ( diff --git a/_maps/RandomRuins/SpaceRuins/skyrat/clothing_facility.dmm b/_maps/RandomRuins/SpaceRuins/skyrat/clothing_facility.dmm index a1f3c7868b8..b8c0a4e576c 100644 --- a/_maps/RandomRuins/SpaceRuins/skyrat/clothing_facility.dmm +++ b/_maps/RandomRuins/SpaceRuins/skyrat/clothing_facility.dmm @@ -57,14 +57,14 @@ /turf/open/floor/engine, /area/ruin/space/has_grav/powered/skyrat/clothing_facility) "n" = ( -/obj/item/card/id/advanced/colourable{ - pixel_y = 6 - }, +/obj/item/card/id/advanced/silver/generic, /obj/structure/rack, -/obj/item/card/id/advanced/colourable{ +/obj/item/card/id/advanced/silver/generic{ pixel_y = 3 }, -/obj/item/card/id/advanced/colourable, +/obj/item/card/id/advanced/silver/generic{ + pixel_y = 6 + }, /turf/open/floor/engine, /area/ruin/space/has_grav/powered/skyrat/clothing_facility) "o" = ( diff --git a/_maps/RandomRuins/SpaceRuins/skyrat/interdynefob.dmm b/_maps/RandomRuins/SpaceRuins/skyrat/interdynefob.dmm index 464498600fd..0e37692de27 100644 --- a/_maps/RandomRuins/SpaceRuins/skyrat/interdynefob.dmm +++ b/_maps/RandomRuins/SpaceRuins/skyrat/interdynefob.dmm @@ -1891,6 +1891,8 @@ /obj/effect/turf_decal/trimline/dark_blue/filled/line, /obj/effect/turf_decal/siding/dark, /obj/structure/extinguisher_cabinet/directional/west, +/obj/structure/table/glass, +/obj/item/storage/backpack/duffelbag/synth_treatment_kit/trauma/advanced/unzipped, /turf/open/floor/iron/white/diagonal, /area/ruin/space/has_grav/skyrat/interdynefob/medbay) "hZ" = ( diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index b6f8d1a4da2..0711e8dc96a 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -26928,7 +26928,7 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/holopad, -/mob/living/simple_animal/sloth/citrus, +/mob/living/basic/sloth/citrus, /turf/open/floor/iron, /area/station/cargo/storage) "jHE" = ( @@ -32991,15 +32991,10 @@ /turf/open/floor/iron, /area/station/security/checkpoint/escape) "lLq" = ( -/obj/effect/turf_decal/box/corners{ - dir = 1 - }, -/obj/effect/turf_decal/box/corners{ - dir = 4 - }, /obj/machinery/firealarm/directional/east, /obj/effect/decal/cleanable/oil, -/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/machinery/byteforge, +/obj/effect/turf_decal/box, /turf/open/floor/iron/dark/smooth_large, /area/station/bitrunning/den) "lLr" = ( @@ -37938,13 +37933,10 @@ /turf/open/floor/circuit/telecomms/mainframe, /area/station/science/xenobiology) "nyf" = ( -/obj/effect/turf_decal/box/corners{ - dir = 8 - }, -/obj/effect/turf_decal/box/corners, /obj/machinery/camera/autoname/directional/east, /obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/structure/table, +/obj/item/food/cornchips/green, /turf/open/floor/iron/dark/smooth_large, /area/station/bitrunning/den) "nyi" = ( @@ -54250,9 +54242,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/mob/living/simple_animal/hostile/retaliate/goat{ - name = "Pete" - }, +/mob/living/basic/goat/pete, /obj/machinery/duct, /turf/open/floor/iron/freezer, /area/station/service/kitchen/coldroom) diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 610855acbaf..7ab412a4f3d 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -2745,6 +2745,11 @@ /obj/item/toy/figure/chef, /turf/open/floor/iron/dark, /area/station/service/kitchen) +"aHw" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "aHC" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/status_display/evac/directional/east, @@ -10094,6 +10099,17 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/iron, /area/station/security/prison/safe) +"cvc" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/department/science) "cvo" = ( /obj/machinery/power/apc/auto_name/directional/west, /obj/structure/cable, @@ -10135,12 +10151,9 @@ /turf/open/floor/iron/dark, /area/station/command/heads_quarters/hop) "cwd" = ( -/obj/effect/turf_decal/box/corners, -/obj/effect/turf_decal/box/corners{ - dir = 4 - }, /obj/machinery/light/directional/south, -/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/machinery/byteforge, +/obj/effect/turf_decal/box, /turf/open/floor/iron/dark/smooth_large, /area/station/bitrunning/den) "cwe" = ( @@ -13064,18 +13077,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"dhA" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/duct, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron, -/area/station/maintenance/department/chapel) "dhM" = ( /obj/machinery/holopad, /obj/effect/turf_decal/bot, @@ -18647,13 +18648,6 @@ /obj/effect/turf_decal/tile/neutral/full, /turf/open/floor/iron/large, /area/station/hallway/secondary/exit/departure_lounge) -"eEG" = ( -/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/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "eEH" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -20399,15 +20393,6 @@ /obj/effect/turf_decal/tile/brown/anticorner/contrasted, /turf/open/floor/iron, /area/station/cargo/sorting) -"eZb" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/obj/effect/turf_decal/tile/red/fourcorners, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron, -/area/station/service/kitchen/abandoned) "eZe" = ( /obj/machinery/vending/wardrobe/viro_wardrobe, /obj/structure/sign/poster/official/cleanliness/directional/west, @@ -23794,6 +23779,16 @@ "fSW" = ( /turf/closed/indestructible/opshuttle, /area/station/science/ordnance/bomb) +"fTh" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/blobstart, +/obj/effect/turf_decal/tile/red/opposingcorners, +/obj/effect/turf_decal/tile/yellow/opposingcorners{ + dir = 1 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron, +/area/station/service/kitchen/abandoned) "fTw" = ( /obj/machinery/portable_atmospherics/canister/oxygen, /obj/effect/turf_decal/bot, @@ -24349,17 +24344,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/atmos/project) -"fZC" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/department/science) "fZG" = ( /obj/effect/turf_decal/stripes/corner, /obj/effect/turf_decal/stripes/corner{ @@ -24460,14 +24444,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/medical/chemistry) -"gaE" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/visible, -/obj/effect/spawner/random/engineering/tracking_beacon, -/obj/effect/mapping_helpers/burnt_floor, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron, -/area/station/maintenance/department/electrical) "gaG" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -27250,12 +27226,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/ce) -"gHA" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron, -/area/station/science/research/abandoned) "gHE" = ( /obj/machinery/requests_console/directional/north{ department = "Chapel"; @@ -27794,6 +27764,11 @@ }, /turf/open/floor/iron, /area/station/security/prison) +"gOH" = ( +/obj/effect/landmark/blobstart, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/solars/starboard/fore) "gOR" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -30095,6 +30070,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/mapping_helpers/burnt_floor, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron, +/area/station/maintenance/department/electrical) "huX" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/disposalpipe/segment{ @@ -33851,6 +33834,13 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/maintenance/port/fore) +"itC" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/turf/open/floor/iron/dark, +/area/station/maintenance/starboard/aft) "itF" = ( /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ dir = 6 @@ -37861,13 +37851,6 @@ /obj/effect/turf_decal/tile/neutral/half/contrasted, /turf/open/floor/iron, /area/station/commons/dorms) -"jrN" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/port) "jsa" = ( /obj/item/storage/box/rxglasses, /obj/structure/table/reinforced/rglass, @@ -38966,16 +38949,6 @@ }, /turf/open/floor/iron/white, /area/station/science/lab) -"jFV" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/blobstart, -/obj/effect/turf_decal/tile/red/opposingcorners, -/obj/effect/turf_decal/tile/yellow/opposingcorners{ - dir = 1 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron, -/area/station/service/kitchen/abandoned) "jGl" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, @@ -39310,15 +39283,15 @@ /turf/open/floor/iron/white, /area/station/command/heads_quarters/cmo) "jKY" = ( -/obj/effect/turf_decal/box/corners{ - dir = 8 - }, -/obj/effect/turf_decal/box/corners{ - dir = 1 - }, /obj/effect/decal/cleanable/oil/streak, /obj/machinery/camera/directional/south, -/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/structure/table, +/obj/item/storage/toolbox/mechanical{ + pixel_y = 7 + }, +/obj/item/reagent_containers/cup/soda_cans/space_mountain_wind{ + pixel_x = 5 + }, /turf/open/floor/iron/dark/smooth_large, /area/station/bitrunning/den) "jLa" = ( @@ -43993,6 +43966,15 @@ }, /turf/open/floor/iron, /area/station/maintenance/port/aft) +"kVw" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red/fourcorners, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron, +/area/station/service/kitchen/abandoned) "kVx" = ( /obj/machinery/door/airlock/highsecurity{ name = "Emergency Access" @@ -44725,11 +44707,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/engineering/atmos/project) -"leY" = ( -/obj/effect/landmark/blobstart, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/solars/starboard/fore) "lfm" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -45843,6 +45820,16 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/maintenance/department/science) +"ltg" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/department/chapel) "ltr" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -47103,13 +47090,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"lId" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/station/maintenance/starboard/aft) "lIe" = ( /obj/effect/landmark/blobstart, /obj/structure/disposalpipe/segment{ @@ -48111,6 +48091,12 @@ /obj/effect/turf_decal/tile/neutral/full, /turf/open/floor/iron/large, /area/station/medical/paramedic) +"lUW" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/tile/red/fourcorners, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron, +/area/station/service/kitchen/abandoned) "lVi" = ( /obj/structure/closet/l3closet/virology, /obj/effect/turf_decal/bot, @@ -58021,12 +58007,6 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/station/maintenance/solars/starboard/aft) -"oBN" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/tile/red/fourcorners, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron, -/area/station/service/kitchen/abandoned) "oBX" = ( /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, /obj/item/kirbyplants/random, @@ -63262,6 +63242,13 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/science/robotics/lab) +"pRp" = ( +/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/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "pRy" = ( /obj/effect/turf_decal/siding/green, /obj/structure/window/reinforced/spawner/directional/south, @@ -67987,16 +67974,6 @@ /obj/effect/turf_decal/trimline/blue/end, /turf/open/floor/iron/dark/textured, /area/station/engineering/atmos/project) -"raE" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/department/chapel) "raI" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -69336,6 +69313,14 @@ }, /turf/open/floor/iron, /area/station/science/xenobiology) +"rqN" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/port) "rqV" = ( /obj/machinery/dna_infuser, /obj/item/infuser_book, @@ -69774,14 +69759,6 @@ /obj/machinery/light/directional/east, /turf/open/floor/iron/dark, /area/station/service/kitchen) -"rxO" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/port) "rxT" = ( /obj/structure/table/reinforced, /obj/item/paper_bin{ @@ -75223,6 +75200,18 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/engineering/main) +"sNP" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/duct, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron, +/area/station/maintenance/department/chapel) "sOi" = ( /obj/machinery/portable_atmospherics/pump, /obj/effect/turf_decal/bot, @@ -75559,6 +75548,12 @@ /obj/effect/spawner/random/trash/graffiti, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"sSx" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/delivery, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron, +/area/station/science/research/abandoned) "sSH" = ( /obj/effect/turf_decal/tile/green/half/contrasted{ dir = 8 @@ -78952,11 +78947,6 @@ /obj/effect/turf_decal/tile/neutral/full, /turf/open/floor/iron/half, /area/station/security/range) -"tLz" = ( -/obj/effect/landmark/blobstart, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/solars/starboard/aft) "tLC" = ( /obj/structure/sign/warning/radiation, /turf/closed/wall/r_wall, @@ -80141,9 +80131,7 @@ /obj/structure/disposalpipe/segment, /obj/effect/decal/cleanable/dirt, /obj/machinery/duct, -/mob/living/simple_animal/hostile/retaliate/goat{ - name = "Pete" - }, +/mob/living/basic/goat/pete, /turf/open/floor/iron/freezer, /area/station/service/kitchen/coldroom) "uaE" = ( @@ -81329,6 +81317,18 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) +"upq" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron, +/area/station/maintenance/starboard/aft) "upv" = ( /obj/machinery/navbeacon{ codes_txt = "delivery;dir=4"; @@ -84874,6 +84874,11 @@ /obj/structure/cable, /turf/open/floor/iron/grimy, /area/station/service/bar/backroom) +"vhK" = ( +/obj/effect/landmark/blobstart, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/solars/starboard/aft) "vhW" = ( /obj/item/kirbyplants/random, /obj/structure/sign/warning/pods/directional/south{ @@ -86566,10 +86571,6 @@ dir = 1 }, /obj/effect/decal/cleanable/dirt/dust, -/obj/item/storage/toolbox/mechanical{ - pixel_x = -8; - pixel_y = 17 - }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, /obj/machinery/holopad, @@ -88288,18 +88289,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, /turf/open/floor/iron, /area/station/science/xenobiology) -"wcb" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron, -/area/station/maintenance/starboard/aft) "wcd" = ( /obj/structure/chair/wood, /obj/effect/decal/cleanable/dirt, @@ -89285,11 +89274,6 @@ /obj/item/screwdriver, /turf/open/floor/plating, /area/station/maintenance/department/crew_quarters/bar) -"wnO" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "wnQ" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -94131,6 +94115,13 @@ "xzJ" = ( /turf/open/floor/iron, /area/station/security/execution/transfer) +"xzL" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/port) "xzO" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/medical/glass{ @@ -95384,7 +95375,7 @@ /obj/structure/disposalpipe/segment{ dir = 10 }, -/mob/living/simple_animal/sloth/citrus, +/mob/living/basic/sloth/citrus, /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/command/heads_quarters/qm) @@ -121762,7 +121753,7 @@ lAs trG fnq uKY -jrN +xzL mYM pTC eSu @@ -121784,7 +121775,7 @@ vSX nEc tFP oMV -gHA +sSx cHU eKz qel @@ -124871,7 +124862,7 @@ aJX fSw fTA jkC -fZC +cvc jUx wEI qYo @@ -126635,7 +126626,7 @@ ikf vcB vcB jPf -rxO +rqN sIe bTe jTw @@ -127709,7 +127700,7 @@ bvd wJJ wEI dnV -wnO +aHw gFO qQM isR @@ -128105,7 +128096,7 @@ azA oYs bEs bEs -eEG +pRp tQY ltr qRN @@ -139644,7 +139635,7 @@ aad aad csz jSE -leY +gOH wFz xrr aaa @@ -141203,11 +141194,11 @@ aeF vno nNs ffk -jFV +fTh egs vno rJN -oBN +lUW pGy vno kvs @@ -141826,7 +141817,7 @@ bRZ qMf jfW gUF -raE +ltg xeX qkj qMf @@ -142749,7 +142740,7 @@ aad aad vno iJj -eZb +kVw acU vno aad @@ -142854,7 +142845,7 @@ pPl vPf qMf rPf -dhA +sNP ovf qkj ygf @@ -144143,7 +144134,7 @@ xPK wZE eSU haQ -gaE +huS pdb hnH nvM @@ -149270,7 +149261,7 @@ ouy geH nXH gWF -wcb +upq jix nmD gQK @@ -150047,7 +150038,7 @@ nXH aad nXH uFH -lId +itC udQ cun kOR @@ -150315,7 +150306,7 @@ hrt wZV vNa cPU -tLz +vhK oBM pWe aad diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index ef2790cb69a..172a001020e 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -237,6 +237,13 @@ /obj/structure/cable, /turf/open/floor/iron, /area/mine/production) +"afn" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "afp" = ( /obj/machinery/air_sensor/nitrogen_tank, /turf/open/floor/engine/n2, @@ -652,11 +659,6 @@ }, /turf/open/floor/plating, /area/mine/storage) -"ama" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/solars/port/fore) "amg" = ( /obj/machinery/door/poddoor/shutters/window/preopen{ dir = 4; @@ -761,12 +763,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/carpet, /area/station/command/heads_quarters/captain) -"anI" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "anK" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 4 @@ -922,15 +918,6 @@ }, /turf/open/floor/iron, /area/station/command/gateway) -"apL" = ( -/obj/effect/turf_decal/trimline/green/filled/corner, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/maintenance/starboard/aft) "apS" = ( /obj/structure/cable, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, @@ -988,6 +975,12 @@ }, /turf/open/floor/iron, /area/station/command/bridge) +"aqK" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 8 + }, +/turf/open/floor/plating, +/area/station/maintenance/aft/lesser) "aqQ" = ( /obj/structure/table, /obj/item/stack/package_wrap, @@ -1312,6 +1305,14 @@ }, /turf/open/floor/wood, /area/station/hallway/secondary/service) +"auX" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/maintenance/department/chapel) "avb" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, @@ -1714,6 +1715,19 @@ /obj/machinery/light/cold/directional/south, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/cmo) +"aBx" = ( +/obj/effect/decal/cleanable/plasma, +/obj/effect/landmark/blobstart, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) +"aBQ" = ( +/obj/effect/landmark/blobstart, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron, +/area/station/maintenance/port/aft) "aBR" = ( /turf/open/genturf/blue, /area/icemoon/surface/outdoors/noruins) @@ -1765,15 +1779,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) -"aCt" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_smooth, -/area/station/maintenance/fore/lesser) "aCA" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 10 @@ -1969,12 +1974,6 @@ }, /turf/open/floor/iron/white, /area/station/science/xenobiology) -"aGi" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/central) "aGr" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/camera/directional/east{ @@ -2340,13 +2339,6 @@ }, /turf/open/floor/iron, /area/station/tcommsat/computer) -"aMB" = ( -/obj/effect/decal/cleanable/plasma, -/obj/effect/landmark/blobstart, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "aME" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -2363,13 +2355,6 @@ /obj/effect/turf_decal/tile/yellow, /turf/open/floor/iron/white, /area/station/medical/pharmacy) -"aMR" = ( -/obj/structure/cable, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/fore) "aMX" = ( /obj/machinery/light/small/directional/south, /obj/structure/cable, @@ -2412,10 +2397,6 @@ /obj/machinery/portable_atmospherics/canister/oxygen, /turf/open/floor/plating, /area/mine/eva/lower) -"aNC" = ( -/obj/item/food/fried_chicken, -/turf/open/floor/plating/snowed/smoothed, -/area/station/maintenance/fore/lesser) "aNR" = ( /obj/machinery/smartfridge, /obj/machinery/door/firedoor, @@ -2461,11 +2442,6 @@ /obj/effect/mapping_helpers/airlock/access/all/supply/mining_station, /turf/open/floor/iron/smooth_large, /area/station/cargo/warehouse) -"aOG" = ( -/obj/item/trash/raisins, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "aOS" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -3432,6 +3408,17 @@ "bcN" = ( /turf/closed/wall/r_wall, /area/station/hallway/primary/central) +"bcQ" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Firefighting Equipment" + }, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 4 + }, +/obj/effect/mapping_helpers/airlock/access/any/science/maintenance, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "bcT" = ( /obj/structure/extinguisher_cabinet/directional/north, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -3479,15 +3466,6 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/external, /turf/open/floor/plating, /area/station/maintenance/aft/greater) -"bdA" = ( -/obj/machinery/door/airlock/maintenance, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 4 - }, -/obj/effect/mapping_helpers/airlock/access/any/medical/maintenance, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "bdJ" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -3966,6 +3944,14 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/service) +"bkw" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/maintenance/starboard/upper) "bkC" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -4427,11 +4413,6 @@ /obj/machinery/status_display/evac/directional/west, /turf/open/floor/iron, /area/station/hallway/primary/central) -"brq" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "brt" = ( /obj/machinery/portable_atmospherics/canister/nitrous_oxide, /turf/open/floor/iron/dark, @@ -5596,11 +5577,6 @@ }, /turf/open/floor/iron, /area/station/maintenance/disposal/incinerator) -"bHB" = ( -/obj/effect/spawner/random/structure/steam_vent, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/aft/lesser) "bHF" = ( /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plating, @@ -5696,11 +5672,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/disposal) -"bIr" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "bIt" = ( /obj/structure/rack, /obj/effect/decal/cleanable/cobweb/cobweb2, @@ -5735,6 +5706,11 @@ /obj/effect/turf_decal/tile/blue/half/contrasted, /turf/open/floor/iron, /area/station/command/bridge) +"bIS" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "bIU" = ( /obj/structure/table, /obj/item/stack/sheet/glass/fifty, @@ -5979,11 +5955,6 @@ }, /turf/open/floor/iron/dark, /area/station/service/chapel) -"bMi" = ( -/obj/structure/grille/broken, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "bMu" = ( /obj/structure/table/reinforced, /obj/machinery/door/window/left/directional/north{ @@ -6222,6 +6193,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/construction) +"bPy" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "bPz" = ( /obj/effect/landmark/blobstart, /turf/open/floor/plating, @@ -6608,15 +6585,6 @@ /obj/machinery/light/floor, /turf/open/floor/iron, /area/station/engineering/atmos) -"bWD" = ( -/obj/machinery/door/airlock/engineering{ - name = "Port Bow Solar Access" - }, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/solars/port/fore) "bWK" = ( /turf/open/floor/iron/dark, /area/station/engineering/atmos/project) @@ -6885,6 +6853,11 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"cat" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/solars/port/fore) "caC" = ( /obj/machinery/door/window/right/directional/south{ dir = 8; @@ -6950,14 +6923,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/hallway/primary/starboard) -"cbt" = ( -/obj/structure/chair/plastic{ - dir = 8 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) "cbz" = ( /obj/machinery/light/small/directional/south, /turf/open/floor/iron/dark/textured, @@ -7609,13 +7574,6 @@ /obj/effect/spawner/random/engineering/tracking_beacon, /turf/open/floor/engine, /area/station/science/xenobiology) -"cky" = ( -/obj/structure/railing{ - dir = 1 - }, -/obj/structure/reagent_dispensers/fueltank, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/central) "ckN" = ( /obj/structure/cable, /obj/machinery/newscaster/directional/south, @@ -8327,13 +8285,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/hallway/primary/starboard) -"cvt" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/aft/lesser) "cvz" = ( /obj/machinery/duct, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -8466,18 +8417,6 @@ /obj/machinery/status_display/evac/directional/west, /turf/open/floor/circuit, /area/station/ai_monitored/turret_protected/ai) -"cxo" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Firefighting Equipment" - }, -/obj/effect/mapping_helpers/airlock/abandoned, -/obj/effect/mapping_helpers/airlock/access/any/service/maintenance, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "cxp" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/closet/secure_closet/personal{ @@ -8528,12 +8467,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply, /turf/open/floor/iron/white, /area/station/medical/virology) -"cxS" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "cyh" = ( /obj/structure/cable, /obj/effect/spawner/structure/window/reinforced, @@ -8664,6 +8597,13 @@ }, /turf/open/floor/iron, /area/station/cargo/storage) +"czx" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "czz" = ( /obj/machinery/computer/pod/old/mass_driver_controller/trash{ pixel_x = -24; @@ -8861,6 +8801,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/aft/greater) +"cBw" = ( +/obj/effect/spawner/random/structure/steam_vent, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "cBD" = ( /obj/effect/turf_decal/siding/wood/corner{ dir = 4 @@ -9671,6 +9616,10 @@ }, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) +"cNG" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/plating, +/area/station/maintenance/aft/lesser) "cNI" = ( /obj/machinery/door/poddoor/preopen{ id = "xenobio7"; @@ -9798,11 +9747,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/prison/work) -"cQg" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/solars/port/aft) "cQh" = ( /obj/structure/chair/office{ dir = 1 @@ -10147,15 +10091,10 @@ /area/mine/laborcamp) "cWa" = ( /obj/machinery/light_switch/directional/west, -/obj/effect/turf_decal/box/corners{ - dir = 1 - }, -/obj/effect/turf_decal/box/corners{ - dir = 4 - }, /obj/effect/decal/cleanable/cobweb, /obj/effect/decal/cleanable/dirt/dust, -/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/machinery/byteforge, +/obj/effect/turf_decal/box, /turf/open/floor/iron/dark/smooth_large, /area/station/bitrunning/den) "cWq" = ( @@ -10737,12 +10676,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"dex" = ( -/obj/effect/landmark/blobstart, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron, -/area/station/maintenance/port/aft) "deD" = ( /obj/machinery/modular_computer/preset/id{ dir = 4 @@ -11822,6 +11755,12 @@ dir = 1 }, /area/mine/eva) +"dva" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "dvf" = ( /obj/machinery/light/directional/south, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -12141,6 +12080,13 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/engineering/lobby) +"dAq" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/turf/open/floor/plating, +/area/station/maintenance/aft/lesser) "dAt" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -12282,13 +12228,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/commons/fitness) -"dDk" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "dDm" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/on{ dir = 1 @@ -12646,18 +12585,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/hallway/secondary/service) -"dIp" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Research Delivery Access" - }, -/obj/effect/mapping_helpers/airlock/abandoned, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 1 - }, -/obj/effect/mapping_helpers/airlock/access/any/science/maintenance, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "dIx" = ( /obj/effect/spawner/random/structure/grille, /turf/open/floor/plating, @@ -13385,9 +13312,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/commons/locker) -"dVj" = ( -/turf/open/floor/iron/dark, -/area/station/medical/morgue) "dVq" = ( /obj/machinery/space_heater, /obj/structure/sign/poster/random/directional/east, @@ -13429,11 +13353,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth, /area/station/engineering/lobby) -"dVP" = ( -/obj/effect/mapping_helpers/broken_floor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "dVX" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/sign/poster/contraband/random/directional/east, @@ -13646,13 +13565,6 @@ dir = 8 }, /area/mine/eva) -"dZx" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/turf/open/floor/plating, -/area/station/maintenance/solars/starboard/aft) "dZB" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -13730,6 +13642,12 @@ /obj/item/radio/intercom/directional/east, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"eae" = ( +/obj/structure/sign/poster/contraband/random/directional/north, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/port/greater) "eag" = ( /obj/structure/chair/stool/directional/north, /obj/effect/landmark/start/scientist, @@ -13801,6 +13719,13 @@ }, /turf/open/floor/iron/smooth, /area/mine/mechbay) +"ebw" = ( +/obj/effect/turf_decal/trimline/green/filled/line{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/maintenance/starboard/aft) "ebB" = ( /turf/open/misc/dirt{ initial_gas_mix = "ICEMOON_ATMOS" @@ -14010,16 +13935,6 @@ /obj/machinery/iv_drip, /turf/open/floor/iron/dark, /area/station/medical/morgue) -"efu" = ( -/obj/machinery/door/airlock/maintenance, -/obj/effect/mapping_helpers/airlock/abandoned, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "efv" = ( /obj/item/toy/snowball{ pixel_x = -6; @@ -14810,6 +14725,12 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron, /area/station/cargo/storage) +"erU" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/plating, +/area/station/maintenance/department/crew_quarters/bar) "erY" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -14820,11 +14741,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/command/teleporter) -"esb" = ( -/obj/effect/spawner/random/structure/steam_vent, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "esc" = ( /obj/machinery/computer/order_console/mining, /obj/effect/turf_decal/tile/brown/half/contrasted{ @@ -15079,12 +14995,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/cargo/storage) -"ewv" = ( -/obj/structure/plasticflaps, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/fore) "ewz" = ( /obj/structure/window/reinforced/spawner/directional/east, /obj/structure/window/reinforced/spawner/directional/north, @@ -15652,12 +15562,6 @@ /obj/structure/sign/poster/official/report_crimes, /turf/closed/wall/ice, /area/icemoon/underground/explored) -"eFH" = ( -/obj/structure/cable, -/obj/effect/mapping_helpers/broken_floor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/fore) "eFS" = ( /obj/machinery/door/airlock/maintenance{ name = "Mech Bay Maintenance" @@ -15757,13 +15661,6 @@ /obj/item/clothing/under/costume/jabroni, /turf/open/floor/iron, /area/station/maintenance/starboard/fore) -"eHA" = ( -/obj/effect/turf_decal/trimline/green/filled/line{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron, -/area/station/maintenance/starboard/aft) "eHT" = ( /obj/structure/cable, /obj/effect/spawner/random/structure/steam_vent, @@ -15814,11 +15711,6 @@ /obj/machinery/light/small/directional/west, /turf/open/floor/wood, /area/station/service/library) -"eIo" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "eIC" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/disposalpipe/segment{ @@ -16338,6 +16230,11 @@ }, /turf/open/floor/iron, /area/station/command/heads_quarters/hop) +"eSg" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/solars/port/fore) "eSn" = ( /obj/structure/chair/office, /obj/effect/landmark/start/assistant, @@ -16417,11 +16314,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/large, /area/station/engineering/main) -"eTB" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/solars/starboard/fore) "eTC" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -16980,6 +16872,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/science/ordnance) +"fcs" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/solars/port/aft) "fcu" = ( /obj/machinery/power/apc/auto_name/directional/east, /obj/structure/chair, @@ -17095,14 +16992,6 @@ "feJ" = ( /turf/closed/wall/r_wall, /area/station/ai_monitored/security/armory/upper) -"feP" = ( -/obj/structure/cable, -/obj/machinery/power/apc/auto_name/directional/west, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/smooth, -/area/station/maintenance/fore/lesser) "feQ" = ( /obj/machinery/portable_atmospherics/canister/air, /turf/open/floor/plating, @@ -17262,11 +17151,6 @@ }, /turf/open/floor/iron, /area/station/engineering/lobby) -"fif" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/aft/lesser) "fij" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -17662,6 +17546,13 @@ }, /turf/open/floor/iron/dark, /area/station/medical/storage) +"foo" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/aft/lesser) "foy" = ( /obj/item/radio/intercom/directional/south, /obj/machinery/vending/wardrobe/science_wardrobe, @@ -18241,7 +18132,7 @@ /area/station/maintenance/starboard/aft) "fya" = ( /obj/structure/cable, -/mob/living/simple_animal/sloth/paperwork, +/mob/living/basic/sloth/paperwork, /turf/open/floor/iron, /area/station/cargo/storage) "fyc" = ( @@ -18322,6 +18213,14 @@ /obj/machinery/light/directional/north, /turf/open/floor/iron, /area/station/hallway/primary/central) +"fzA" = ( +/obj/effect/spawner/random/maintenance, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "fzD" = ( /obj/structure/disposalpipe/segment, /obj/item/radio/intercom/directional/east, @@ -18331,12 +18230,6 @@ /obj/effect/turf_decal/tile/red, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"fzF" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 8 - }, -/turf/open/floor/plating, -/area/station/maintenance/aft/lesser) "fzG" = ( /obj/structure/closet{ name = "evidence closet 5" @@ -18492,6 +18385,13 @@ }, /turf/open/floor/cult, /area/station/service/chapel/office) +"fCA" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/solars/port/aft) "fCM" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -18857,6 +18757,16 @@ /obj/machinery/light/small/directional/west, /turf/open/floor/iron/white, /area/station/maintenance/port/fore) +"fIL" = ( +/obj/machinery/door/airlock{ + name = "Observatory Access" + }, +/obj/effect/mapping_helpers/airlock/abandoned, +/obj/effect/mapping_helpers/airlock/unres, +/obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance/departmental, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "fJd" = ( /obj/item/kirbyplants/random, /obj/structure/sign/warning/pods/directional/west, @@ -19329,6 +19239,13 @@ /obj/structure/cable/layer3, /turf/open/floor/iron/grimy, /area/station/ai_monitored/turret_protected/aisat_interior) +"fQx" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 8 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "fQz" = ( /obj/effect/landmark/start/hangover, /turf/open/floor/carpet, @@ -19354,14 +19271,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/pink, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"fRn" = ( -/obj/effect/turf_decal/trimline/green/filled/line{ - dir = 9 - }, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron, -/area/station/maintenance/starboard/aft) "fRv" = ( /obj/machinery/light/small/directional/north, /turf/open/floor/engine, @@ -19974,6 +19883,11 @@ }, /turf/open/floor/iron, /area/station/command/gateway) +"gbf" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "gbh" = ( /obj/machinery/light/small/directional/south, /turf/open/floor/engine, @@ -21221,11 +21135,6 @@ dir = 9 }, /area/station/science/research) -"gwo" = ( -/obj/effect/mapping_helpers/broken_floor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "gwp" = ( /obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral/full, @@ -21384,6 +21293,11 @@ }, /turf/open/floor/grass, /area/station/service/hydroponics) +"gyC" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/aft/lesser) "gyH" = ( /obj/machinery/light/directional/north, /obj/machinery/vending/coffee, @@ -21819,12 +21733,6 @@ dir = 5 }, /area/station/hallway/secondary/entry) -"gFP" = ( -/obj/item/trash/popcorn, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/plating, -/area/station/maintenance/fore) "gFR" = ( /obj/structure/table/reinforced, /obj/item/clothing/suit/utility/radiation, @@ -21968,6 +21876,11 @@ }, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"gHv" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/solars/starboard/fore) "gHA" = ( /mob/living/simple_animal/hostile/asteroid/polarbear{ move_force = 999; @@ -22434,15 +22347,6 @@ dir = 8 }, /area/station/science/research) -"gPG" = ( -/obj/structure/chair/plastic{ - dir = 1 - }, -/obj/effect/decal/cleanable/blood/splatter, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron, -/area/station/maintenance/starboard/fore) "gPR" = ( /obj/effect/turf_decal/trimline/green/filled/warning, /obj/machinery/duct, @@ -22900,12 +22804,6 @@ dir = 8 }, /area/station/maintenance/department/medical/central) -"gXn" = ( -/obj/machinery/space_heater, -/obj/effect/mapping_helpers/broken_floor, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/turf/open/floor/plating, -/area/station/maintenance/fore/lesser) "gXp" = ( /obj/structure/table/wood, /obj/item/folder/yellow, @@ -23224,13 +23122,6 @@ /obj/structure/grille, /turf/open/floor/plating, /area/station/maintenance/port/greater) -"hcb" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/chair/stool/directional/south, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "hce" = ( /obj/machinery/door/airlock{ id_tag = "AuxToilet3"; @@ -23277,13 +23168,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/engineering/storage/tech) -"hcO" = ( -/obj/structure/sign/warning/cold_temp/directional/east, -/obj/effect/mapping_helpers/broken_floor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "hdb" = ( /obj/machinery/shower/directional/south, /turf/open/floor/iron/smooth, @@ -23429,6 +23313,11 @@ /obj/effect/turf_decal/tile/blue/half/contrasted, /turf/open/floor/iron, /area/station/command/bridge) +"heW" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "heX" = ( /obj/structure/cable, /turf/open/floor/wood, @@ -23638,13 +23527,6 @@ "hjM" = ( /turf/closed/wall/r_wall, /area/station/maintenance/department/medical/morgue) -"hjO" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "hjQ" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 @@ -24689,13 +24571,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/science/genetics) -"hAW" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/solars/port/aft) "hBc" = ( /obj/effect/turf_decal/siding/white{ dir = 1 @@ -24896,12 +24771,6 @@ /obj/structure/closet/emcloset, /turf/open/floor/iron/dark, /area/mine/eva) -"hEC" = ( -/obj/structure/sign/poster/contraband/random/directional/north, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/port/greater) "hEG" = ( /obj/machinery/door/airlock/security/glass{ name = "Brig Control" @@ -25055,6 +24924,13 @@ }, /turf/open/floor/iron, /area/station/commons/fitness) +"hHs" = ( +/obj/structure/cable, +/obj/structure/sign/warning/gas_mask/directional/south, +/obj/machinery/light/small/dim/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "hHu" = ( /obj/structure/disposalpipe/segment, /obj/structure/extinguisher_cabinet/directional/west, @@ -26966,6 +26842,12 @@ /obj/effect/spawner/random/structure/steam_vent, /turf/open/floor/plating, /area/station/maintenance/department/medical/morgue) +"imu" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/turf/open/floor/plating, +/area/station/maintenance/aft/lesser) "imy" = ( /obj/machinery/airalarm/directional/east, /turf/open/floor/iron/dark, @@ -27010,6 +26892,15 @@ /obj/structure/falsewall, /turf/open/floor/plating, /area/station/maintenance/port/lesser) +"inw" = ( +/obj/machinery/door/airlock/engineering{ + name = "Port Bow Solar Access" + }, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/all/engineering/general, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/solars/port/fore) "inE" = ( /turf/open/floor/iron/corner, /area/station/engineering/lobby) @@ -27193,13 +27084,6 @@ /obj/structure/cable, /turf/open/floor/plating/snowed/icemoon, /area/icemoon/surface/outdoors/nospawn) -"ipS" = ( -/obj/machinery/door/airlock/maintenance, -/obj/effect/mapping_helpers/airlock/abandoned, -/obj/effect/mapping_helpers/airlock/access/any/science/maintenance, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "iqn" = ( /obj/structure/rack, /obj/effect/spawner/random/clothing/costume, @@ -27513,13 +27397,6 @@ /obj/machinery/airalarm/directional/north, /turf/open/floor/glass/reinforced, /area/station/ai_monitored/security/armory/upper) -"ivf" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/random/trash/grille_or_waste, -/obj/machinery/duct, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "ivi" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/yellow, @@ -27662,12 +27539,6 @@ }, /turf/open/floor/wood/parquet, /area/station/service/bar/atrium) -"ixW" = ( -/obj/structure/sign/warning/gas_mask/directional/south, -/obj/effect/spawner/random/trash/grille_or_waste, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "ixZ" = ( /obj/machinery/door/airlock/command/glass{ name = "Chief Engineer" @@ -28116,12 +27987,6 @@ /obj/item/kirbyplants/random, /turf/open/floor/wood, /area/station/security/prison/rec) -"iDv" = ( -/obj/structure/sign/poster/random/directional/east, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron/smooth, -/area/station/maintenance/fore/lesser) "iDG" = ( /obj/machinery/door/window/left/directional/north{ dir = 4; @@ -28232,17 +28097,6 @@ }, /turf/open/floor/iron, /area/station/command/bridge) -"iFu" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Firefighting Equipment" - }, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 4 - }, -/obj/effect/mapping_helpers/airlock/access/any/science/maintenance, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "iFL" = ( /obj/structure/bed/dogbed/renault, /mob/living/basic/pet/fox/renault, @@ -28918,6 +28772,16 @@ /obj/item/flashlight, /turf/open/floor/plating, /area/station/construction) +"iRd" = ( +/obj/machinery/door/airlock/maintenance, +/obj/effect/mapping_helpers/airlock/abandoned, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "iRo" = ( /turf/closed/wall, /area/station/security/checkpoint/customs/auxiliary) @@ -29599,11 +29463,6 @@ /obj/machinery/airalarm/directional/north, /turf/open/floor/iron/dark/textured, /area/station/security/prison/rec) -"jbt" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/solars/port/fore) "jbu" = ( /obj/structure/railing/corner, /turf/open/floor/iron/dark/side{ @@ -29716,6 +29575,11 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) +"jdP" = ( +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "jdQ" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -30151,11 +30015,6 @@ }, /turf/open/floor/iron/grimy, /area/station/service/chapel/office) -"jnB" = ( -/obj/structure/cable, -/obj/machinery/light/floor, -/turf/open/floor/plating, -/area/station/engineering/storage/tech) "jnR" = ( /obj/effect/spawner/structure/window/hollow/reinforced/middle{ dir = 4 @@ -30659,16 +30518,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/treatment_center) -"juL" = ( -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/effect/mapping_helpers/burnt_floor, -/obj/machinery/airalarm/directional/north, -/obj/effect/decal/cleanable/dirt/dust, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/port/lesser) "juQ" = ( /obj/structure/rack, /obj/item/stack/rods/fifty, @@ -30887,16 +30736,6 @@ /obj/structure/closet/secure_closet/captains, /turf/open/floor/carpet, /area/station/command/heads_quarters/captain) -"jzt" = ( -/obj/machinery/door/airlock/maintenance, -/obj/effect/mapping_helpers/airlock/abandoned, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 1 - }, -/obj/effect/mapping_helpers/airlock/access/any/medical/maintenance, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "jzy" = ( /obj/machinery/computer/exodrone_control_console{ dir = 1 @@ -31016,6 +30855,11 @@ /obj/structure/flora/bush/jungle/a/style_random, /turf/open/floor/grass, /area/station/service/hydroponics) +"jBr" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "jBB" = ( /obj/structure/kitchenspike, /turf/open/floor/plating/snowed/coldroom, @@ -31794,6 +31638,11 @@ }, /turf/open/floor/carpet/blue, /area/station/hallway/secondary/entry) +"jNS" = ( +/obj/effect/mapping_helpers/burnt_floor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "jNZ" = ( /obj/effect/turf_decal/weather/snow/corner{ dir = 9 @@ -32403,11 +32252,6 @@ }, /turf/open/floor/carpet, /area/station/command/heads_quarters/hop) -"jWR" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/solars/starboard/aft) "jXc" = ( /obj/structure/sign/poster/official/help_others, /turf/closed/wall/ice, @@ -32696,14 +32540,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood, /area/station/maintenance/fore) -"kbQ" = ( -/obj/structure/chair, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "kbU" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -33708,6 +33544,14 @@ }, /turf/open/floor/iron/smooth, /area/station/security/holding_cell) +"kpu" = ( +/obj/effect/spawner/random/trash/mess, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "kpC" = ( /turf/closed/wall/r_wall, /area/station/engineering/atmos/mix) @@ -34038,14 +33882,6 @@ /obj/effect/turf_decal/tile/blue/opposingcorners, /turf/open/floor/iron/dark, /area/station/command/gateway) -"ksZ" = ( -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/turf/open/floor/plating, -/area/station/maintenance/department/chapel) "kta" = ( /turf/closed/wall, /area/station/commons/storage/mining) @@ -34100,6 +33936,12 @@ /obj/effect/spawner/random/trash/hobo_squat, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) +"ktC" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/smooth, +/area/station/maintenance/fore/lesser) "ktD" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 4 @@ -34131,15 +33973,6 @@ /obj/machinery/newscaster/directional/east, /turf/open/floor/iron/dark, /area/station/service/chapel) -"kuc" = ( -/obj/machinery/door/airlock/engineering{ - name = "Port Quarter Solar Access" - }, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/solars/port/aft) "kum" = ( /obj/structure/table, /obj/item/trash/can/food/beans, @@ -34826,6 +34659,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/security/prison/visit) +"kEo" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/plating, +/area/station/maintenance/fore) "kEq" = ( /obj/effect/spawner/random/structure/crate, /turf/open/floor/plating, @@ -35359,14 +35197,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/medical/cryo) -"kNd" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron/cafeteria{ - dir = 5 - }, -/area/station/maintenance/port/aft) "kNi" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -35389,6 +35219,13 @@ /obj/structure/cable, /turf/open/floor/iron/dark/telecomms, /area/station/tcommsat/server) +"kNz" = ( +/obj/structure/cable, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/fore) "kNA" = ( /obj/structure/disposalpipe/segment, /obj/structure/girder, @@ -35681,6 +35518,15 @@ /obj/structure/bookcase, /turf/open/floor/iron, /area/mine/laborcamp) +"kRr" = ( +/obj/machinery/door/airlock/engineering{ + name = "Port Quarter Solar Access" + }, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/all/engineering/general, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/solars/port/aft) "kRw" = ( /obj/machinery/portable_atmospherics/scrubber, /obj/effect/turf_decal/stripes/line{ @@ -35887,6 +35733,12 @@ "kUD" = ( /turf/open/openspace, /area/mine/eva) +"kUG" = ( +/obj/item/trash/popcorn, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/plating, +/area/station/maintenance/fore) "kUJ" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/built/directional/south, @@ -35948,6 +35800,12 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron, /area/station/engineering/lobby) +"kVW" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/central) "kWa" = ( /obj/structure/fireplace, /turf/open/floor/plating, @@ -36236,6 +36094,14 @@ "kZu" = ( /turf/closed/wall, /area/mine/production) +"kZw" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "kZz" = ( /obj/machinery/computer/order_console/cook{ dir = 1 @@ -36586,6 +36452,12 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/underground/explored) +"lge" = ( +/obj/structure/sign/poster/contraband/random/directional/east, +/obj/machinery/light/small/dim/directional/west, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "lgk" = ( /obj/effect/turf_decal/trimline/blue/filled/corner{ dir = 4 @@ -36924,6 +36796,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/science/xenobiology) +"llC" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/wood, +/area/station/maintenance/port/aft) "llD" = ( /obj/structure/table/wood, /obj/item/paper_bin/carbon, @@ -37046,6 +36923,11 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/commons/storage/tools) +"lnd" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/port/greater) "lnk" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 4 @@ -37160,6 +37042,15 @@ /obj/item/screwdriver, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/cmo) +"loQ" = ( +/obj/effect/turf_decal/trimline/green/filled/corner, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/maintenance/starboard/aft) "loV" = ( /obj/machinery/atmospherics/pipe/smart/simple/dark/visible{ dir = 4 @@ -37212,14 +37103,6 @@ "lpM" = ( /turf/closed/wall/r_wall, /area/station/command/heads_quarters/captain) -"lpR" = ( -/obj/machinery/door/airlock/maintenance, -/obj/effect/mapping_helpers/airlock/abandoned, -/obj/effect/mapping_helpers/airlock/unres, -/obj/effect/mapping_helpers/airlock/access/any/science/maintenance, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "lpS" = ( /obj/machinery/disposal/bin, /obj/structure/disposalpipe/trunk, @@ -37300,6 +37183,13 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/aft) +"lqP" = ( +/obj/effect/decal/cleanable/insectguts, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "lqU" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -37357,11 +37247,6 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/station/science/robotics/lab) -"lsd" = ( -/obj/effect/spawner/random/trash/mess, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "lsi" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -37473,6 +37358,13 @@ }, /turf/open/floor/iron/white/side, /area/station/science/ordnance/office) +"luK" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/turf/open/floor/plating, +/area/station/maintenance/solars/starboard/aft) "lva" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, @@ -37674,13 +37566,6 @@ /obj/machinery/atmospherics/pipe/bridge_pipe/cyan/visible, /turf/open/floor/iron, /area/station/engineering/atmos) -"lxI" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/blobstart, -/obj/effect/turf_decal/tile/yellow/opposingcorners, -/turf/open/floor/iron/white, -/area/station/maintenance/port/fore) "lxT" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/effect/decal/cleanable/dirt, @@ -38117,12 +38002,6 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/station/medical/cryo) -"lDO" = ( -/obj/structure/sign/poster/contraband/random/directional/east, -/obj/machinery/light/small/dim/directional/west, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "lDX" = ( /obj/structure/railing/corner{ dir = 1 @@ -38770,14 +38649,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/service) -"lPd" = ( -/obj/effect/spawner/random/trash/mess, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "lPh" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -39294,6 +39165,13 @@ }, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) +"lXm" = ( +/obj/item/trash/pistachios, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/turf/open/floor/plating, +/area/station/maintenance/aft/greater) "lXn" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -39582,17 +39460,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/smooth_large, /area/station/command/heads_quarters/hos) -"mcP" = ( -/obj/machinery/door/airlock/maintenance, -/obj/effect/mapping_helpers/airlock/abandoned, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/any/service/maintenance, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/department/crew_quarters/bar) "mcW" = ( /turf/open/floor/iron/white, /area/station/medical/medbay/central) @@ -40161,11 +40028,6 @@ }, /turf/open/floor/iron/textured_half, /area/station/hallway/secondary/service) -"mnm" = ( -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/wood, -/area/station/maintenance/port/aft) "mnu" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 @@ -40407,10 +40269,6 @@ /obj/structure/sign/warning/gas_mask/directional/south, /turf/open/floor/plating, /area/station/maintenance/fore/lesser) -"mrj" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/plating, -/area/station/maintenance/aft/lesser) "mro" = ( /obj/structure/curtain/cloth, /obj/effect/turf_decal/tile/yellow/opposingcorners, @@ -40563,6 +40421,11 @@ /obj/machinery/requests_console/auto_name/directional/south, /turf/open/floor/plating, /area/station/engineering/storage/tech) +"mtm" = ( +/obj/effect/spawner/random/structure/steam_vent, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/aft/lesser) "mtn" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -40659,9 +40522,22 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/wood, /area/station/command/heads_quarters/captain) +"mvf" = ( +/obj/machinery/door/airlock/maintenance, +/obj/effect/mapping_helpers/airlock/abandoned, +/obj/effect/mapping_helpers/airlock/access/any/science/maintenance, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "mvl" = ( /turf/closed/wall/r_wall, /area/station/security/interrogation) +"mvp" = ( +/obj/machinery/space_heater, +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/turf/open/floor/plating, +/area/station/maintenance/fore/lesser) "mvv" = ( /turf/open/floor/wood, /area/station/security/courtroom) @@ -40728,13 +40604,6 @@ /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) -"mwB" = ( -/obj/item/trash/pistachios, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 1 - }, -/turf/open/floor/plating, -/area/station/maintenance/aft/greater) "mwQ" = ( /obj/structure/tank_holder/extinguisher, /turf/open/floor/plating, @@ -41241,11 +41110,6 @@ /obj/item/weldingtool, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"mFC" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/port/greater) "mFE" = ( /turf/closed/wall, /area/station/medical/surgery/aft) @@ -41392,14 +41256,6 @@ /obj/machinery/power/apc/auto_name/directional/west, /turf/open/floor/iron, /area/station/maintenance/disposal/incinerator) -"mIG" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "mIT" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -41507,15 +41363,6 @@ /obj/machinery/light/small/directional/north, /turf/open/floor/iron/dark/textured_edge, /area/station/security/evidence) -"mKJ" = ( -/obj/machinery/door/airlock/engineering{ - name = "Starboard Bow Solar Access" - }, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/solars/starboard/fore) "mLa" = ( /obj/item/kirbyplants/random, /turf/open/floor/plating, @@ -41837,6 +41684,13 @@ }, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"mRu" = ( +/obj/structure/railing{ + dir = 1 + }, +/obj/structure/reagent_dispensers/fueltank, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/central) "mRG" = ( /obj/structure/table, /obj/item/book/manual/wiki/atmospherics, @@ -41966,6 +41820,14 @@ /obj/machinery/light/directional/south, /turf/open/floor/plating, /area/station/engineering/supermatter/room) +"mUt" = ( +/obj/machinery/door/airlock/maintenance, +/obj/effect/mapping_helpers/airlock/abandoned, +/obj/effect/mapping_helpers/airlock/unres, +/obj/effect/mapping_helpers/airlock/access/any/science/maintenance, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "mUz" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -42178,6 +42040,15 @@ /obj/structure/cable, /turf/open/floor/iron/white, /area/station/science/ordnance/office) +"mXf" = ( +/obj/machinery/door/airlock/maintenance, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 4 + }, +/obj/effect/mapping_helpers/airlock/access/any/medical/maintenance, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "mXi" = ( /obj/machinery/ai_slipper{ uses = 10 @@ -42251,6 +42122,11 @@ }, /turf/open/floor/plating, /area/station/hallway/secondary/entry) +"mYc" = ( +/obj/effect/mapping_helpers/burnt_floor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "mYd" = ( /obj/machinery/air_sensor/ordnance_burn_chamber, /turf/open/floor/engine/vacuum, @@ -42816,13 +42692,6 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/engine_smes) -"neJ" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "neM" = ( /obj/machinery/hydroponics/soil, /turf/open/misc/asteroid/snow/icemoon, @@ -42975,11 +42844,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"nhF" = ( -/obj/effect/mapping_helpers/burnt_floor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "nhI" = ( /obj/machinery/camera/directional/east{ c_tag = "Research Division Genetics Monkey Pen"; @@ -43047,6 +42911,21 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/science/xenobiology) +"niB" = ( +/obj/structure/cable, +/obj/machinery/button/door/directional/west{ + id = "maint2"; + name = "Blast Door Control B"; + pixel_y = 4 + }, +/obj/machinery/button/door/directional/west{ + id = "maint1"; + name = "Blast Door Control A"; + pixel_y = -6 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "niC" = ( /obj/structure/cable, /obj/structure/sign/warning/secure_area/directional/east, @@ -43467,10 +43346,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/department/chapel) -"noC" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "noF" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -44341,14 +44216,6 @@ /obj/structure/lattice/catwalk, /turf/open/openspace/icemoon/keep_below, /area/station/maintenance/port/lesser) -"nAq" = ( -/obj/effect/spawner/random/maintenance, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 4 - }, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "nAr" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/plating, @@ -44934,6 +44801,11 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/aft) +"nIa" = ( +/obj/structure/cable, +/obj/machinery/light/floor, +/turf/open/floor/plating, +/area/station/engineering/storage/tech) "nId" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -46153,6 +46025,11 @@ }, /turf/open/floor/iron/dark, /area/station/science/robotics/lab) +"oef" = ( +/obj/structure/grille/broken, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "oeh" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 @@ -46328,6 +46205,10 @@ }, /turf/open/floor/plating/snowed/icemoon, /area/icemoon/surface/outdoors/nospawn) +"ohM" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "ohS" = ( /obj/structure/railing{ dir = 8 @@ -46420,6 +46301,11 @@ dir = 4 }, /area/station/hallway/secondary/entry) +"oiH" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "oiK" = ( /obj/machinery/door/airlock{ id_tag = "commissarydoor"; @@ -46546,6 +46432,11 @@ }, /turf/open/floor/iron/dark, /area/station/medical/morgue) +"okg" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/solars/starboard/aft) "okk" = ( /obj/structure/cable, /obj/structure/sign/departments/aisat/directional/east, @@ -47158,6 +47049,18 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/station/maintenance/aft/greater) +"osq" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Firefighting Equipment" + }, +/obj/effect/mapping_helpers/airlock/abandoned, +/obj/effect/mapping_helpers/airlock/access/any/service/maintenance, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "osr" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 1 @@ -47773,6 +47676,12 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/solars/starboard/fore) +"oCl" = ( +/obj/structure/cable, +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/fore) "oCs" = ( /obj/structure/table, /obj/item/toy/figure/virologist{ @@ -48492,6 +48401,14 @@ "oMT" = ( /turf/open/floor/iron, /area/station/command/heads_quarters/rd) +"oNp" = ( +/obj/effect/turf_decal/trimline/green/filled/line{ + dir = 9 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/maintenance/starboard/aft) "oNA" = ( /obj/effect/turf_decal/bot, /turf/open/floor/plating/snowed/smoothed/icemoon, @@ -49248,6 +49165,17 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai_upload) +"oYx" = ( +/obj/machinery/door/airlock/maintenance, +/obj/effect/mapping_helpers/airlock/abandoned, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/any/service/maintenance, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/department/crew_quarters/bar) "oYH" = ( /obj/effect/turf_decal/siding/wideplating/dark, /obj/effect/landmark/start/botanist, @@ -49505,12 +49433,6 @@ /obj/item/coin/silver, /turf/open/floor/iron, /area/station/commons/dorms) -"pcX" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "pdc" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, @@ -51432,6 +51354,12 @@ /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"pGM" = ( +/obj/structure/girder, +/obj/structure/grille, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "pGQ" = ( /obj/machinery/atmospherics/pipe/smart/simple/orange/visible, /turf/closed/wall, @@ -51462,6 +51390,15 @@ }, /turf/open/floor/iron/dark, /area/station/security/checkpoint/science) +"pHd" = ( +/obj/machinery/door/airlock/engineering{ + name = "Starboard Bow Solar Access" + }, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/all/engineering/general, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/solars/starboard/fore) "pHy" = ( /obj/structure/rack, /obj/item/clothing/mask/breath, @@ -51829,12 +51766,6 @@ "pMF" = ( /turf/open/floor/iron/white, /area/station/science/xenobiology) -"pMP" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/obj/structure/cable, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/plating, -/area/station/maintenance/department/crew_quarters/bar) "pMY" = ( /obj/effect/spawner/structure/window, /turf/open/floor/plating, @@ -51889,17 +51820,18 @@ }, /turf/open/floor/iron/dark/airless, /area/station/science/ordnance/freezerchamber) -"pNI" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/department/crew_quarters/bar) "pNK" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 4 }, /turf/open/floor/iron/large, /area/station/commons/storage/tools) +"pNM" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "pNO" = ( /obj/machinery/duct, /obj/structure/disposalpipe/segment, @@ -52855,14 +52787,6 @@ /obj/machinery/microwave, /turf/open/floor/stone, /area/mine/eva/lower) -"qet" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/turf/open/floor/plating, -/area/station/maintenance/starboard/upper) "qeF" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -52877,6 +52801,15 @@ dir = 4 }, /area/station/hallway/secondary/entry) +"qeJ" = ( +/obj/structure/chair/plastic{ + dir = 1 + }, +/obj/effect/decal/cleanable/blood/splatter, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron, +/area/station/maintenance/starboard/fore) "qeL" = ( /obj/structure/lattice/catwalk, /obj/structure/railing{ @@ -53205,12 +53138,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/security/lockers) -"qkP" = ( -/obj/effect/mapping_helpers/broken_floor, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/smooth, -/area/station/maintenance/fore/lesser) "qkT" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -53637,6 +53564,11 @@ /obj/effect/spawner/random/trash/mess, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"qqC" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/department/crew_quarters/bar) "qqJ" = ( /obj/machinery/navbeacon{ codes_txt = "delivery;dir=8"; @@ -54033,6 +53965,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/commons/fitness) +"qxa" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/chair/stool/directional/south, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "qxb" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/effect/turf_decal/tile/brown/half/contrasted{ @@ -55376,6 +55315,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/wood, /area/station/command/meeting_room) +"qRt" = ( +/obj/effect/spawner/random/trash/mess, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "qRv" = ( /obj/structure/railing, /obj/structure/marker_beacon/cerulean, @@ -55515,6 +55459,12 @@ /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"qTe" = ( +/obj/structure/railing/corner/end/flip{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/central) "qTj" = ( /obj/effect/turf_decal/tile/blue{ dir = 8 @@ -56687,6 +56637,11 @@ /obj/structure/sign/warning/no_smoking/circle/directional/west, /turf/open/floor/iron/white, /area/station/maintenance/port/fore) +"rmh" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/showroomfloor, +/area/station/maintenance/department/medical/morgue) "rmn" = ( /obj/structure/chair/stool/directional/north, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -57281,6 +57236,13 @@ /obj/item/clothing/suit/apron/chef, /turf/open/floor/plating, /area/station/maintenance/department/medical/morgue) +"rwG" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "rwR" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/status_display/evac/directional/west, @@ -58390,6 +58352,14 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron/dark, /area/station/engineering/lobby) +"rOX" = ( +/obj/structure/chair, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "rPe" = ( /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/structure/closet/toolcloset, @@ -59282,6 +59252,13 @@ /obj/effect/turf_decal/tile/neutral/half/contrasted, /turf/open/floor/iron/dark, /area/station/ai_monitored/command/storage/eva) +"sez" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/turf/open/floor/plating, +/area/station/maintenance/aft/greater) "seA" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -59523,6 +59500,14 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron/sepia, /area/station/service/library) +"sin" = ( +/obj/machinery/door/poddoor/preopen{ + id = "maint3" + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "siu" = ( /obj/structure/table, /obj/item/storage/toolbox/emergency, @@ -60061,13 +60046,6 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/commons/dorms/laundry) -"sqe" = ( -/obj/structure/cable, -/obj/structure/sign/warning/gas_mask/directional/south, -/obj/machinery/light/small/dim/directional/south, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "sqn" = ( /obj/machinery/computer/records/security{ dir = 1 @@ -62115,11 +62093,7 @@ /turf/open/floor/plating/snowed/icemoon, /area/icemoon/underground/explored) "sVW" = ( -/obj/effect/turf_decal/box/corners{ - dir = 8 - }, -/obj/effect/turf_decal/box/corners, -/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/dark/smooth_large, /area/station/bitrunning/den) "sWl" = ( @@ -62150,6 +62124,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/aft/greater) +"sWv" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_smooth, +/area/station/maintenance/fore/lesser) "sWB" = ( /obj/machinery/door/airlock/mining/glass{ name = "Mining Smeltery" @@ -62655,6 +62638,18 @@ /obj/structure/reagent_dispensers/watertank, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) +"tgw" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Research Delivery Access" + }, +/obj/effect/mapping_helpers/airlock/abandoned, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 1 + }, +/obj/effect/mapping_helpers/airlock/access/any/science/maintenance, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "tgx" = ( /obj/structure/lattice/catwalk, /obj/structure/railing{ @@ -62772,6 +62767,11 @@ dir = 8 }, /area/mine/eva) +"tip" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/solars/starboard/fore) "tis" = ( /obj/structure/window/reinforced/fulltile, /obj/structure/transit_tube/horizontal, @@ -63132,14 +63132,6 @@ /obj/effect/turf_decal/siding/yellow, /turf/open/floor/iron, /area/station/engineering/storage) -"tou" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/confetti, -/obj/effect/turf_decal/tile/yellow/opposingcorners, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron/white, -/area/station/maintenance/port/fore) "toG" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 6 @@ -63701,6 +63693,13 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/entry) +"txe" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/blobstart, +/obj/effect/turf_decal/tile/yellow/opposingcorners, +/turf/open/floor/iron/white, +/area/station/maintenance/port/fore) "txj" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 8 @@ -63720,11 +63719,6 @@ /obj/machinery/firealarm/directional/south, /turf/open/floor/plating, /area/station/medical/treatment_center) -"txv" = ( -/obj/effect/decal/cleanable/oil, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "txE" = ( /obj/item/cigbutt, /obj/effect/decal/cleanable/dirt, @@ -65331,11 +65325,6 @@ /obj/machinery/light/directional/north, /turf/open/floor/iron, /area/station/security/prison/garden) -"tYK" = ( -/obj/effect/mapping_helpers/burnt_floor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "tYZ" = ( /obj/machinery/door/airlock/external{ name = "External Airlock" @@ -65386,13 +65375,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/engineering/atmos/storage) -"tZM" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/turf/open/floor/plating, -/area/station/maintenance/aft/greater) "tZO" = ( /obj/machinery/modular_computer/preset/civilian{ dir = 8 @@ -66922,6 +66904,11 @@ /obj/structure/cable, /turf/open/floor/iron/dark/textured, /area/station/security/range) +"uAF" = ( +/obj/effect/decal/cleanable/oil, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "uAJ" = ( /obj/machinery/space_heater, /turf/open/floor/plating, @@ -68024,17 +68011,6 @@ /obj/effect/turf_decal/tile/yellow/opposingcorners, /turf/open/floor/iron/white, /area/station/maintenance/port/fore) -"uSj" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/plating, -/area/station/maintenance/aft/lesser) -"uSm" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "uSo" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -68045,14 +68021,6 @@ dir = 1 }, /area/station/engineering/main) -"uSp" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "uSq" = ( /obj/machinery/atmospherics/pipe/smart/manifold/purple/visible{ dir = 4 @@ -68533,11 +68501,6 @@ /obj/structure/cable, /turf/open/floor/circuit/telecomms/mainframe, /area/station/tcommsat/server) -"vbr" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/showroomfloor, -/area/station/maintenance/department/medical/morgue) "vbz" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -68904,16 +68867,22 @@ /obj/effect/mapping_helpers/airlock/abandoned, /turf/open/floor/plating, /area/station/maintenance/port/greater) +"vhg" = ( +/obj/structure/sign/poster/random/directional/east, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron/smooth, +/area/station/maintenance/fore/lesser) "vhm" = ( /obj/structure/sign/poster/random/directional/west, /obj/machinery/firealarm/directional/north, /turf/open/floor/iron/dark, /area/station/service/chapel) "vhr" = ( -/mob/living/simple_animal/hostile/retaliate/goat{ - atmos_requirements = list("min_oxy"=1,"max_oxy"=0,"min_plas"=0,"max_plas"=1,"min_co2"=0,"max_co2"=5,"min_n2"=0,"max_n2"=0); +/mob/living/basic/goat/pete{ desc = "Not known for their pleasant disposition. This one seems a bit more hardy to the cold."; - minbodytemp = 150; + habitable_atmos = list("min_oxy"=1,"max_oxy"=0,"min_plas"=0,"max_plas"=1,"min_co2"=0,"max_co2"=5,"min_n2"=0,"max_n2"=0); + minimum_survivable_temperature = 150; name = "Snowy Pete" }, /turf/open/misc/asteroid/snow/coldroom, @@ -68949,11 +68918,6 @@ dir = 6 }, /area/station/science/research) -"vis" = ( -/obj/machinery/duct, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "viH" = ( /obj/machinery/power/emitter/welded{ dir = 4 @@ -68978,11 +68942,6 @@ dir = 1 }, /area/station/command/gateway) -"viZ" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/solars/starboard/fore) "vja" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/mapping_helpers/broken_floor, @@ -69364,14 +69323,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/hallway/secondary/service) -"voP" = ( -/obj/machinery/door/poddoor/preopen{ - id = "maint3" - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "voY" = ( /obj/structure/cable, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -70563,13 +70514,6 @@ }, /turf/open/floor/iron/white/smooth_large, /area/station/medical/chemistry) -"vIb" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/plating, -/area/station/maintenance/aft/lesser) "vIe" = ( /obj/item/soap/deluxe, /obj/item/bikehorn/rubberducky, @@ -70666,6 +70610,14 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/service) +"vKo" = ( +/obj/structure/railing{ + dir = 1 + }, +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/light/small/dim/directional/east, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "vKq" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -70735,6 +70687,16 @@ /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/station/service/bar) +"vLY" = ( +/obj/machinery/door/airlock/maintenance, +/obj/effect/mapping_helpers/airlock/abandoned, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 1 + }, +/obj/effect/mapping_helpers/airlock/access/any/medical/maintenance, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "vMa" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/airalarm/directional/south, @@ -70822,13 +70784,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark/textured, /area/station/hallway/secondary/entry) -"vNr" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 8 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "vNs" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -70889,6 +70844,13 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"vOI" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/grille_or_waste, +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "vPh" = ( /obj/machinery/light/directional/north, /obj/machinery/digital_clock/directional/north, @@ -70984,16 +70946,6 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron, /area/station/cargo/lobby) -"vRh" = ( -/obj/machinery/door/airlock{ - name = "Observatory Access" - }, -/obj/effect/mapping_helpers/airlock/abandoned, -/obj/effect/mapping_helpers/airlock/unres, -/obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance/departmental, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "vRo" = ( /obj/machinery/shower/directional/north, /obj/effect/turf_decal/trimline/blue/line{ @@ -71173,6 +71125,15 @@ /obj/item/radio/intercom/directional/south, /turf/open/floor/iron, /area/station/hallway/primary/fore) +"vTl" = ( +/obj/machinery/door/airlock/engineering{ + name = "Starboard Quarter Solar Access" + }, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/all/engineering/general, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/solars/starboard/aft) "vTo" = ( /obj/structure/disposalpipe/sorting/mail{ dir = 1 @@ -71568,6 +71529,14 @@ }, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"vZq" = ( +/obj/structure/chair/plastic{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/department/cargo) "vZt" = ( /obj/machinery/atmospherics/pipe/smart/manifold/scrubbers/visible{ dir = 8 @@ -72350,12 +72319,6 @@ /mob/living/carbon/human/species/monkey, /turf/open/floor/grass, /area/station/medical/virology) -"wlK" = ( -/obj/structure/railing/corner/end/flip{ - dir = 4 - }, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/central) "wlR" = ( /obj/structure/closet/boxinggloves, /turf/open/floor/iron, @@ -72522,6 +72485,10 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/security/brig) +"wog" = ( +/obj/item/food/fried_chicken, +/turf/open/floor/plating/snowed/smoothed, +/area/station/maintenance/fore/lesser) "wol" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/extinguisher_cabinet/directional/east, @@ -73239,15 +73206,6 @@ }, /turf/open/floor/iron/dark/textured_half, /area/station/service/bar/atrium) -"wyR" = ( -/obj/machinery/door/airlock/engineering{ - name = "Starboard Quarter Solar Access" - }, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/solars/starboard/aft) "wzc" = ( /obj/machinery/power/apc/auto_name/directional/north, /obj/structure/cable, @@ -74777,6 +74735,14 @@ /obj/effect/spawner/random/structure/tank_holder, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"wWm" = ( +/obj/item/trash/raisins, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) +"wWJ" = ( +/turf/open/floor/iron/dark, +/area/station/medical/morgue) "wWM" = ( /obj/machinery/atmospherics/pipe/smart/simple/orange/visible{ dir = 4 @@ -74806,6 +74772,18 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/mine/laborcamp) +"wXc" = ( +/obj/structure/sign/warning/cold_temp/directional/east, +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) +"wXf" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/starboard/aft) "wXh" = ( /obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/co2{ dir = 8 @@ -74829,6 +74807,12 @@ /obj/effect/turf_decal/tile/brown/half/contrasted, /turf/open/floor/iron, /area/station/cargo/office) +"wXW" = ( +/obj/structure/sign/warning/gas_mask/directional/south, +/obj/effect/spawner/random/trash/grille_or_waste, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "wXX" = ( /obj/machinery/door/window/left/directional/north{ base_state = "right"; @@ -75551,6 +75535,16 @@ }, /turf/open/floor/iron/dark/textured_edge, /area/station/security/prison) +"xgM" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/effect/mapping_helpers/burnt_floor, +/obj/machinery/airalarm/directional/north, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/port/lesser) "xgO" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/trimline/yellow/corner{ @@ -75567,6 +75561,14 @@ }, /turf/open/floor/iron/smooth_large, /area/station/cargo/drone_bay) +"xgQ" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "xgX" = ( /obj/structure/table/wood, /obj/effect/spawner/random/entertainment/deck{ @@ -75774,6 +75776,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/wood, /area/station/commons/dorms) +"xkG" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/confetti, +/obj/effect/turf_decal/tile/yellow/opposingcorners, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron/white, +/area/station/maintenance/port/fore) "xkH" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -76212,6 +76222,14 @@ /obj/machinery/light/blacklight/directional/east, /turf/open/floor/wood, /area/station/service/library) +"xsm" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron/cafeteria{ + dir = 5 + }, +/area/station/maintenance/port/aft) "xss" = ( /obj/machinery/light/directional/south, /obj/effect/turf_decal/tile/yellow/half/contrasted, @@ -76719,14 +76737,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/mine/laborcamp/security) -"xzt" = ( -/obj/structure/railing{ - dir = 1 - }, -/obj/effect/mapping_helpers/broken_floor, -/obj/machinery/light/small/dim/directional/east, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "xzO" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/maintenance/three, @@ -77166,12 +77176,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) -"xGk" = ( -/obj/structure/girder, -/obj/structure/grille, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/aft) "xGp" = ( /obj/structure/table/reinforced, /obj/machinery/door/window/left/directional/north{ @@ -77504,11 +77508,6 @@ }, /turf/open/floor/iron/cafeteria, /area/station/security/prison/work) -"xMf" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/plating, -/area/station/maintenance/fore) "xMh" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/bridge_pipe/cyan/visible, @@ -77640,21 +77639,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/aft) -"xPz" = ( -/obj/structure/cable, -/obj/machinery/button/door/directional/west{ - id = "maint2"; - name = "Blast Door Control B"; - pixel_y = 4 - }, -/obj/machinery/button/door/directional/west{ - id = "maint1"; - name = "Blast Door Control A"; - pixel_y = -6 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/starboard/fore) "xPF" = ( /obj/structure/fence{ dir = 4 @@ -77962,13 +77946,6 @@ }, /turf/open/floor/wood/tile, /area/station/service/theater) -"xUr" = ( -/obj/effect/decal/cleanable/insectguts, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/port/aft) "xUw" = ( /obj/structure/sign/departments/maint/directional/west, /turf/open/floor/plating/snowed/smoothed/icemoon, @@ -78476,6 +78453,12 @@ dir = 1 }, /area/station/maintenance/department/cargo) +"ycc" = ( +/obj/structure/plasticflaps, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/fore) "ych" = ( /obj/item/chair/wood/wings, /obj/effect/turf_decal/bot_red, @@ -78851,6 +78834,14 @@ dir = 4 }, /area/station/hallway/secondary/entry) +"ykn" = ( +/obj/structure/cable, +/obj/machinery/power/apc/auto_name/directional/west, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/smooth, +/area/station/maintenance/fore/lesser) "ykw" = ( /turf/closed/wall/r_wall, /area/station/security/processing) @@ -160309,7 +160300,7 @@ thA thA thA iLh -juL +xgM mLm dxE ccB @@ -164720,7 +164711,7 @@ nWH nWH nWH xjC -cbt +vZq cZO gnh iDt @@ -166711,10 +166702,10 @@ ucN iDt iDt qQf -gXn -iDv -qkP -feP +mvp +vhg +ktC +ykn pFV jPs qQf @@ -166971,7 +166962,7 @@ qQf qQf qQf fro -aCt +sWv tym jur vqi @@ -167225,7 +167216,7 @@ ucN iDt iDt qQf -aNC +wog qQf uxZ dBp @@ -179622,7 +179613,7 @@ aJw sBJ qpD nxM -ixW +wXW nxM nxM pBW @@ -179876,10 +179867,10 @@ pHD jKG hjM xDU -aMB -vbr -jzt -noC +aBx +rmh +vLY +ohM bHF eos jol @@ -180871,9 +180862,9 @@ uRz aak dMS vJL -pMP -pNI -mcP +erU +qqC +oYx nCJ dMS fuH @@ -181164,7 +181155,7 @@ qmK nxM lAA nxM -ivf +vOI nxM qqv xzO @@ -181421,7 +181412,7 @@ lAA nxM scw ilN -vis +jdP nxM bgd kmM @@ -181678,10 +181669,10 @@ scw deN iDt nxM -vis -vis -vis -esb +jdP +jdP +jdP +cBw oiT xUe hjM @@ -181938,7 +181929,7 @@ nxM myP nxM nxM -bdA +mXf nxM nxM hjM @@ -182169,7 +182160,7 @@ wvL jnY cWJ dYX -dVj +wWJ aRQ ako rjr @@ -182450,9 +182441,9 @@ xMq xMq nxM bvS -xzt +vKo owG -hjO +rwG cmQ skJ owG @@ -185040,7 +185031,7 @@ nsp fWO tRd tRd -bHB +mtm tRd tRd alM @@ -185556,7 +185547,7 @@ tRd alM alM fuD -vIb +dAq eEY oxO fWO @@ -186310,7 +186301,7 @@ oxO oxO oxO oxO -fif +gyC tRd tRd nPI @@ -188569,7 +188560,7 @@ tBs nHQ oik oFl -ksZ +auX uDl feQ tBs @@ -190407,7 +190398,7 @@ alM alM alM oxO -mrj +cNG tNJ tNJ nyJ @@ -190669,11 +190660,11 @@ oLa pvh oxO oxO -fzF +aqK oxO -cvt +foo oxO -uSj +imu oxO oxO oxO @@ -225341,7 +225332,7 @@ stP dVX oLo tKI -hEC +eae bCQ tKI tKI @@ -226329,9 +226320,9 @@ izw pVN kJe pVN -jbt -ama -bWD +eSg +cat +inw rgs eUf eUf @@ -227370,7 +227361,7 @@ qDI lJO lJO lJO -anI +dva lFq dix lJO @@ -227878,7 +227869,7 @@ qDI pWb okU rSe -lxI +txe rSe hRt lJO @@ -229163,7 +229154,7 @@ lJO unq mZn uSd -tou +xkG tIh lJO ovt @@ -229451,7 +229442,7 @@ uKO juq tKI xqX -mFC +lnd wBb tKI veh @@ -229492,12 +229483,12 @@ bln pRj mVN hUI -xUr +lqP qAI snw mNY kkp -hAW +fCA ipE glh bln @@ -229754,7 +229745,7 @@ mXN vUz mNY qIf -cQg +fcs czR glh bln @@ -230011,7 +230002,7 @@ lDh pRj mNY bCc -kuc +kRr mNY glh bln @@ -230514,7 +230505,7 @@ thW pRj uhX dnM -dex +aBQ wEW hjH eMT @@ -230782,7 +230773,7 @@ cjL gfC pRj daS -sqe +hHs pRj pRj pRj @@ -231023,7 +231014,7 @@ bln pRj jzk kYF -mnm +llC qzM pRj dOH @@ -231034,12 +231025,12 @@ hjH pRj nDy hUI -kNd +xsm nVR iWZ bse xHe -hcO +wXc lPE daS nNr @@ -232564,7 +232555,7 @@ bln bln ptf jYS -pcX +pNM jSe oxB jQC @@ -233866,17 +233857,17 @@ pRj pRj pRj poc -bMi -aOG -txv +oef +wWm +uAF pXv -lDO +lge pXv -nhF +mYc pXv -vRh +fIL pXv -kbQ +rOX nkO ptf bln @@ -234125,7 +234116,7 @@ blO xHe pRj glX -uSp +xgQ kNZ pRj lDF @@ -234817,7 +234808,7 @@ sDl hEI iwj kEB -lPd +kpu rtq lJO lJO @@ -234896,7 +234887,7 @@ gob hwn cAe mXa -nAq +fzA mXa mXa qCl @@ -236668,7 +236659,7 @@ paM sqq nBk nBk -jnB +nIa nBk nBk aCX @@ -243351,7 +243342,7 @@ cvS sxu kwX pNq -aGi +kVW gDp rxa qgm @@ -243548,9 +243539,9 @@ bln fsm bUx cCC -xMf -aMR -eFH +kEo +kNz +oCl skl iHz jOQ @@ -243807,10 +243798,10 @@ bUx wnq dqv cKn -eFH +oCl skl -gFP -eFH +kUG +oCl skl gmW gmW @@ -244064,7 +244055,7 @@ skl skl skl skl -ewv +ycc skl byP eXY @@ -247729,7 +247720,7 @@ kRP kRP kRP vpR -wlK +qTe uep cvS lUU @@ -247986,7 +247977,7 @@ iHZ uOg kRP pAN -cky +mRu uep vsZ hnd @@ -251261,13 +251252,13 @@ rUR kxv fIs kxv -viZ -eTB -mKJ -uSm -uSm -uSm -uSm +gHv +tip +pHd +gbf +gbf +gbf +gbf kKL gAt orf @@ -251335,7 +251326,7 @@ vIe sZF xsA wRr -mwB +lXm sKf tfG eZu @@ -251524,7 +251515,7 @@ pDQ xBL wJM wJM -uSm +gbf kKL dnL orf @@ -251592,7 +251583,7 @@ sZF sZF hEZ mlo -tZM +sez sKf sZF sZF @@ -251781,7 +251772,7 @@ mHB pVl kKL bqe -uSm +gbf kKL hOu orf @@ -252038,7 +252029,7 @@ cvF lli kKL mwu -uSm +gbf kKL kKL lAG @@ -252295,7 +252286,7 @@ oCv gGF kKL qqB -uSm +gbf kKL weF orf @@ -252552,7 +252543,7 @@ sRI lli kKL hJx -efu +iRd kKL hOu orf @@ -252809,7 +252800,7 @@ rSq raH kKL lli -uSm +gbf kKL kKL orf @@ -253066,9 +253057,9 @@ kKL kKL kKL xcp -uSm -voP -xPz +gbf +sin +niB iOc uDW xlN @@ -253323,7 +253314,7 @@ sRI jwF kKL lli -tYK +jNS paT lli lli @@ -253576,11 +253567,11 @@ bln bln kKL cjO -gPG -gwo -cxo +qeJ +heW +osq tDy -lsd +qRt kKL kKL kKL @@ -255129,7 +255120,7 @@ wsO bcC bcC bcC -neJ +czx unu kKL hno @@ -255386,7 +255377,7 @@ bcC lli hJx weF -cxS +bPy aME kKL qLf @@ -255633,7 +255624,7 @@ iyY kbn rCf vZa -hcb +qxa sxO ijb kKL @@ -255725,7 +255716,7 @@ vzD vzD vzD uZc -mIG +kZw sGZ gQw bln @@ -255976,13 +255967,13 @@ fxV rEU rEU rEU -dVP +bIS rEU -dVP +bIS rEU -lpR -bIr -bIr +mUt +wXf +wXf fNa gQw bln @@ -256486,10 +256477,10 @@ vzD vzD fxT jOj -xGk -ipS -fRn -eHA +pGM +mvf +oNp +ebw cAK szD xYw @@ -256746,7 +256737,7 @@ jOj axu vzD pPB -apL +loQ fwD too mHw @@ -259048,7 +259039,7 @@ rDZ rDZ bgx qUY -dDk +afn juQ vzD geJ @@ -259563,8 +259554,8 @@ rDZ bgx vzb rEU -dVP -dIp +bIS +tgw pTW vzD bgx @@ -260080,10 +260071,10 @@ jCl axu jCl geJ -eIo -wyR -jWR -dZx +oiH +vTl +okg +luK xCz qYP xCz @@ -260563,7 +260554,7 @@ elw elw elw rft -qet +bkw idt fMq pSz @@ -260576,7 +260567,7 @@ hyV bgx gti bhk -vNr +fQx jCl jCl jCl @@ -260590,7 +260581,7 @@ vzD vzD vzD vzD -iFu +bcQ vzD vzD vzD @@ -261103,7 +261094,7 @@ tKN qZh vzD twZ -brq +jBr rEU vXd jCl diff --git a/_maps/map_files/KiloStation2/KiloStation2.dmm b/_maps/map_files/KiloStation2/KiloStation2.dmm index b02882b427f..631c0163eff 100644 --- a/_maps/map_files/KiloStation2/KiloStation2.dmm +++ b/_maps/map_files/KiloStation2/KiloStation2.dmm @@ -4863,6 +4863,7 @@ /obj/machinery/power/apc/auto_name/directional/north, /obj/structure/cable, /obj/effect/decal/cleanable/oil, +/obj/machinery/byteforge, /turf/open/floor/catwalk_floor, /area/station/bitrunning/den) "bFu" = ( @@ -7084,7 +7085,7 @@ /turf/closed/wall/r_wall, /area/space/nearstation) "cox" = ( -/mob/living/simple_animal/sloth/citrus, +/mob/living/basic/sloth/citrus, /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 1 }, @@ -9590,7 +9591,7 @@ /obj/structure/window/reinforced/spawner/directional/north, /obj/structure/window/reinforced/spawner/directional/east, /obj/structure/rack/gunrack, -/obj/effect/spawner/armory_spawn/cmg, +/obj/effect/spawner/armory_spawn/smg, /turf/open/floor/iron/showroomfloor, /area/station/ai_monitored/security/armory) "dix" = ( @@ -13762,7 +13763,7 @@ dir = 8 }, /obj/effect/decal/cleanable/blood/old, -/mob/living/simple_animal/hostile/retaliate/goat{ +/mob/living/basic/goat/pete{ name = "Pete" }, /turf/open/floor/iron/freezer, @@ -28897,14 +28898,11 @@ /turf/open/floor/iron/dark, /area/station/maintenance/department/bridge) "jgI" = ( -/obj/effect/landmark/bitrunning/station_reward_spawn, -/obj/effect/turf_decal/box/corners{ - dir = 1 - }, -/obj/effect/turf_decal/box/corners{ - dir = 4 - }, /obj/machinery/light/directional/east, +/obj/effect/decal/cleanable/dirt, +/obj/structure/chair/sofa/corp/right{ + dir = 8 + }, /turf/open/floor/iron/dark/textured_large, /area/station/bitrunning/den) "jgN" = ( @@ -45699,11 +45697,10 @@ /turf/open/floor/plating, /area/station/engineering/supermatter/room) "oQt" = ( -/obj/effect/landmark/bitrunning/station_reward_spawn, -/obj/effect/turf_decal/box/corners{ +/obj/effect/decal/cleanable/dirt, +/obj/structure/chair/sofa/corp/left{ dir = 8 }, -/obj/effect/turf_decal/box/corners, /turf/open/floor/iron/dark/textured_large, /area/station/bitrunning/den) "oQv" = ( @@ -50019,9 +50016,6 @@ dir = 8 }, /obj/machinery/newscaster/directional/south, -/obj/structure/chair{ - pixel_y = -2 - }, /obj/effect/landmark/start/bitrunner, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 6c0ec1a6e79..c4a4756f915 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -3343,16 +3343,9 @@ /turf/open/floor/iron, /area/station/hallway/primary/starboard) "bje" = ( -/obj/effect/turf_decal/box/corners{ - dir = 8 - }, -/obj/effect/turf_decal/box/corners{ - dir = 1 - }, /obj/effect/decal/cleanable/oil/streak, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/structure/extinguisher_cabinet/directional/north, -/obj/effect/landmark/bitrunning/station_reward_spawn, /turf/open/floor/iron/dark/smooth_large, /area/station/bitrunning/den) "bjl" = ( @@ -18234,9 +18227,7 @@ /area/station/science/xenobiology/hallway) "gLF" = ( /obj/structure/sink/kitchen/directional/west, -/mob/living/simple_animal/hostile/retaliate/goat{ - name = "Pete" - }, +/mob/living/basic/goat/pete, /turf/open/floor/iron/kitchen_coldroom/freezerfloor, /area/station/service/kitchen/coldroom) "gLI" = ( @@ -18505,6 +18496,7 @@ /obj/structure/disposalpipe/sorting/mail/flip{ dir = 1 }, +/obj/effect/mapping_helpers/mail_sorting/supply/disposals, /turf/open/floor/plating, /area/station/maintenance/port/fore) "gQw" = ( @@ -25337,7 +25329,7 @@ dir = 4 }, /obj/structure/disposalpipe/segment, -/mob/living/simple_animal/sloth/citrus, +/mob/living/basic/sloth/citrus, /turf/open/floor/iron, /area/station/cargo/storage) "jhD" = ( @@ -29713,14 +29705,11 @@ /turf/open/floor/engine, /area/station/science/explab) "kHU" = ( -/obj/effect/turf_decal/box/corners, -/obj/effect/turf_decal/box/corners{ - dir = 4 - }, /obj/effect/decal/cleanable/dirt/dust, /obj/machinery/light_switch/directional/north, /obj/effect/decal/cleanable/dirt/dust, -/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/machinery/byteforge, +/obj/effect/turf_decal/box, /turf/open/floor/iron/dark/smooth_large, /area/station/bitrunning/den) "kIG" = ( diff --git a/_maps/map_files/NSSJourney/NSSJourney.dmm b/_maps/map_files/NSSJourney/NSSJourney.dmm index eac9b009558..c233c8cefd9 100644 --- a/_maps/map_files/NSSJourney/NSSJourney.dmm +++ b/_maps/map_files/NSSJourney/NSSJourney.dmm @@ -8863,7 +8863,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ dir = 8 }, -/mob/living/simple_animal/hostile/retaliate/goat{ +/mob/living/basic/goat/pete{ name = "Pete" }, /turf/open/floor/iron/kitchen_coldroom/freezerfloor, @@ -25135,16 +25135,11 @@ /area/station/engineering/gravity_generator) "bPZ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/bitrunning/station_reward_spawn, /obj/structure/sign/poster/random/directional/south, /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/directional/south, -/obj/effect/turf_decal/box/corners{ - dir = 1 - }, -/obj/effect/turf_decal/box/corners{ - dir = 8 - }, +/obj/machinery/byteforge, +/obj/effect/turf_decal/box, /turf/open/floor/iron/dark/textured_large, /area/station/bitrunning/den) "bQa" = ( @@ -37154,7 +37149,7 @@ /area/station/security/office) "fpc" = ( /obj/structure/cable, -/mob/living/simple_animal/sloth/paperwork, +/mob/living/basic/sloth/paperwork, /turf/open/floor/iron, /area/station/cargo/storage) "fph" = ( @@ -37533,8 +37528,8 @@ /turf/open/floor/plating, /area/station/maintenance/starboard/aft) "fFF" = ( -/obj/structure/closet/secure_closet/smartgun, /obj/effect/turf_decal/delivery/blue, +/obj/structure/closet/secure_closet/armory_kiboko, /turf/open/floor/iron/smooth, /area/station/ai_monitored/security/armory) "fFP" = ( @@ -45919,7 +45914,7 @@ "mQS" = ( /obj/structure/rack/gunrack, /obj/effect/turf_decal/delivery/red, -/obj/effect/spawner/armory_spawn/cmg, +/obj/effect/spawner/armory_spawn/smg, /turf/open/floor/iron/smooth, /area/station/ai_monitored/security/armory) "mRk" = ( @@ -47396,11 +47391,11 @@ "ofd" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/bitrunning/station_reward_spawn, -/obj/effect/turf_decal/box/corners, -/obj/effect/turf_decal/box/corners{ - dir = 4 - }, +/obj/structure/rack, +/obj/item/food/cornchips/random, +/obj/item/food/cornchips/random, +/obj/item/reagent_containers/cup/soda_cans/random, +/obj/item/reagent_containers/cup/soda_cans/random, /turf/open/floor/iron/dark/textured_large, /area/station/bitrunning/den) "ofM" = ( diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index cc842a66084..60ccea505c0 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -182,6 +182,15 @@ }, /turf/open/floor/plating, /area/station/engineering/atmos/project) +"abJ" = ( +/obj/machinery/light_switch/directional/north, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/turf/open/floor/wood, +/area/station/maintenance/floor3/starboard/aft) "abP" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -295,11 +304,6 @@ /obj/effect/turf_decal/trimline/blue/line, /turf/open/floor/carpet/blue, /area/station/command/meeting_room) -"acX" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron/kitchen, -/area/station/service/kitchen/abandoned) "adk" = ( /obj/structure/grille, /obj/structure/sign/directions/medical/directional/north, @@ -566,6 +570,13 @@ /obj/effect/spawner/random/maintenance/two, /turf/open/floor/pod/light, /area/station/maintenance/floor2/port) +"agW" = ( +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark, +/area/station/medical/morgue) "ahd" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -1783,12 +1794,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/pod/light, /area/station/maintenance/floor4/starboard/fore) -"awK" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/pod/light, -/area/station/maintenance/floor4/port) "awR" = ( /obj/structure/flora/bush/flowers_br/style_random, /obj/machinery/light/directional/west, @@ -2519,6 +2524,14 @@ /obj/item/radio/intercom/directional/west, /turf/open/floor/iron, /area/station/cargo/storage) +"aHf" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/pod/light, +/area/station/maintenance/solars/port/aft) "aHk" = ( /turf/closed/wall, /area/station/medical/medbay/lobby) @@ -5553,6 +5566,12 @@ dir = 1 }, /area/station/bitrunning/den) +"brM" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/floor4/port/fore) "brN" = ( /obj/effect/spawner/structure/window/hollow/reinforced/directional, /obj/structure/disposalpipe/segment, @@ -7281,13 +7300,6 @@ /obj/effect/spawner/random/maintenance/two, /turf/open/floor/pod/light, /area/station/maintenance/floor4/starboard) -"bOM" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/airalarm/directional/east, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/wood/parquet, -/area/station/maintenance/floor2/port/aft) "bOZ" = ( /obj/effect/turf_decal/tile/red/half, /obj/structure/disposalpipe/segment, @@ -11630,6 +11642,17 @@ }, /turf/open/floor/iron/white, /area/station/science/robotics/lab) +"cVU" = ( +/obj/machinery/door/airlock/hatch{ + name = "Wine Cellar" + }, +/obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/pod/light, +/area/station/maintenance/floor3/starboard/aft) "cVX" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -12020,6 +12043,16 @@ /obj/structure/cable, /turf/open/floor/pod/light, /area/station/maintenance/floor1/port/fore) +"dad" = ( +/obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/airlock/hatch{ + name = "Emergency Power" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/pod/dark, +/area/station/maintenance/floor4/port/fore) "daf" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, @@ -13046,6 +13079,12 @@ /obj/machinery/light/broken/directional/south, /turf/open/floor/plating, /area/station/medical/abandoned) +"dqJ" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/pod/light, +/area/station/maintenance/floor2/port/aft) "dqQ" = ( /turf/closed/wall/r_wall, /area/station/security/medical) @@ -13155,6 +13194,13 @@ /obj/item/flamethrower, /turf/open/floor/iron, /area/station/maintenance/floor4/starboard) +"dsw" = ( +/obj/structure/chair/office{ + dir = 8 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/wood, +/area/station/maintenance/floor2/starboard) "dsz" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -14906,16 +14952,6 @@ dir = 1 }, /area/station/hallway/floor1/aft) -"dRp" = ( -/obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/airlock/hatch{ - name = "Emergency Power" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/pod/dark, -/area/station/maintenance/floor4/port/fore) "dRs" = ( /obj/machinery/camera/autoname/directional/north, /turf/open/floor/iron/dark, @@ -15705,6 +15741,10 @@ }, /turf/open/floor/engine/hull, /area/space/nearstation) +"ebC" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/catwalk_floor, +/area/station/maintenance/floor1/starboard) "ebE" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -17121,9 +17161,6 @@ /obj/item/cigbutt/cigarbutt{ pixel_x = 7 }, -/obj/effect/turf_decal/stripes{ - dir = 8 - }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 }, @@ -18128,11 +18165,6 @@ dir = 4 }, /area/station/command/bridge) -"eId" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/pod/light, -/area/station/maintenance/floor4/port/fore) "eIq" = ( /obj/structure/chair/stool/directional/west, /obj/effect/turf_decal/trimline/red/warning{ @@ -18523,14 +18555,6 @@ /obj/structure/cable, /turf/open/floor/catwalk_floor, /area/station/maintenance/floor1/port/fore) -"ePr" = ( -/obj/effect/turf_decal/stripes/corner, -/obj/effect/turf_decal/stripes/corner{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/pod/light, -/area/station/maintenance/floor4/port/fore) "ePv" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -21647,12 +21671,6 @@ }, /turf/open/floor/iron/dark, /area/station/hallway/secondary/service) -"fKz" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/pod/light, -/area/station/maintenance/floor4/port/fore) "fKC" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, @@ -23529,10 +23547,6 @@ }, /turf/open/floor/iron, /area/station/cargo/storage) -"gki" = ( -/obj/effect/baseturf_helper/reinforced_plating/ceiling, -/turf/open/floor/iron, -/area/station/maintenance/disposal/incinerator) "gkq" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 @@ -23664,6 +23678,12 @@ /obj/machinery/newscaster/directional/west, /turf/open/floor/iron/dark, /area/station/hallway/secondary/service) +"gmg" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/pod/light, +/area/station/maintenance/floor4/port/fore) "gmj" = ( /obj/structure/chair/office{ dir = 1 @@ -23734,15 +23754,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/pod/light, /area/station/maintenance/floor3/starboard/aft) -"gmM" = ( -/obj/machinery/light_switch/directional/north, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/turf/open/floor/wood, -/area/station/maintenance/floor3/starboard/aft) "gmO" = ( /obj/machinery/camera/autoname/directional/west, /turf/open/floor/catwalk_floor, @@ -24463,13 +24474,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/pod/light, /area/station/maintenance/floor2/port/aft) -"gwV" = ( -/obj/structure/chair/office{ - dir = 8 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/wood, -/area/station/maintenance/floor2/starboard) "gxb" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable/multilayer/multiz, @@ -27273,11 +27277,6 @@ /obj/machinery/light/directional/west, /turf/open/floor/iron/dark/smooth_large, /area/station/science/robotics/mechbay) -"hiO" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/floor4/port/fore) "hiQ" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -29640,12 +29639,6 @@ /obj/structure/disposalpipe/trunk, /turf/open/floor/carpet, /area/station/service/lawoffice) -"hNZ" = ( -/obj/structure/chair/wood, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/carpet/green, -/area/station/service/abandoned_gambling_den) "hOs" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -30715,7 +30708,7 @@ /turf/open/floor/plating, /area/station/maintenance/floor3/starboard/fore) "idf" = ( -/mob/living/simple_animal/sloth/paperwork, +/mob/living/basic/sloth/paperwork, /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/brown{ dir = 4 @@ -30886,12 +30879,6 @@ }, /turf/open/floor/iron/white, /area/station/science/circuits) -"ifE" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/mapping_helpers/broken_floor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/wood, -/area/station/maintenance/floor3/starboard/aft) "ifG" = ( /obj/item/kirbyplants/random, /turf/open/floor/iron/dark/side{ @@ -31803,6 +31790,10 @@ /obj/item/radio/intercom/directional/east, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"irp" = ( +/obj/effect/baseturf_helper/reinforced_plating/ceiling, +/turf/open/floor/iron, +/area/station/maintenance/disposal/incinerator) "irx" = ( /obj/machinery/door/window/left/directional/south{ name = "Robotics Lab"; @@ -32657,11 +32648,6 @@ /obj/effect/mapping_helpers/airlock/unres, /turf/open/floor/catwalk_floor, /area/station/maintenance/floor1/port) -"iCI" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/maintenance/floor2/starboard/aft) "iCJ" = ( /obj/effect/turf_decal/stripes/corner{ dir = 8 @@ -33735,6 +33721,11 @@ /obj/item/radio/intercom/directional/north, /turf/open/floor/iron/dark, /area/station/service/library/lounge) +"iRo" = ( +/obj/machinery/firealarm/directional/north, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/catwalk_floor, +/area/station/maintenance/floor1/starboard) "iRr" = ( /obj/effect/turf_decal/siding/wideplating_new{ dir = 10 @@ -34106,11 +34097,6 @@ }, /turf/open/floor/iron/white, /area/station/command/heads_quarters/rd) -"iXb" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/pod/light, -/area/station/maintenance/floor4/starboard/fore) "iXe" = ( /obj/item/restraints/legcuffs/beartrap/prearmed, /turf/open/floor/pod/light, @@ -34855,12 +34841,10 @@ /turf/open/floor/pod/light, /area/station/maintenance/floor1/starboard/fore) "jhP" = ( -/obj/effect/turf_decal/box/corners, -/obj/effect/turf_decal/box/corners{ - dir = 4 - }, /obj/effect/decal/cleanable/dirt/dust, -/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/effect/turf_decal/stripes{ + dir = 8 + }, /turf/open/floor/iron/dark/smooth_large, /area/station/bitrunning/den) "jhU" = ( @@ -35511,6 +35495,12 @@ /obj/structure/reagent_dispensers/watertank, /turf/open/floor/iron, /area/station/maintenance/floor1/starboard/fore) +"jsb" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/wood, +/area/station/maintenance/floor3/starboard/aft) "jse" = ( /obj/machinery/door/airlock{ name = "Bartender's Backroom" @@ -38198,6 +38188,16 @@ /obj/item/radio/intercom/directional/north, /turf/open/floor/iron/grimy, /area/station/security/detectives_office) +"kbW" = ( +/obj/machinery/door/airlock/hatch{ + name = "Maintenance Access" + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance, +/obj/structure/barricade/wooden/crude, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/pod/light, +/area/station/maintenance/floor1/starboard) "kca" = ( /turf/closed/wall/r_wall, /area/station/service/library/lounge) @@ -39155,10 +39155,6 @@ /obj/structure/extinguisher_cabinet/directional/west, /turf/open/floor/iron/white/textured, /area/station/medical/office) -"kof" = ( -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/medical/abandoned) "kok" = ( /obj/effect/turf_decal/trimline/dark_blue/line{ dir = 6 @@ -39721,14 +39717,6 @@ }, /turf/open/floor/wood/parquet, /area/station/service/lawoffice) -"kvr" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/pod/light, -/area/station/maintenance/solars/port/aft) "kvw" = ( /obj/machinery/igniter/incinerator_ordmix, /turf/open/floor/engine/vacuum, @@ -39984,12 +39972,6 @@ "kyR" = ( /turf/closed/wall, /area/station/hallway/floor1/fore) -"kzf" = ( -/obj/effect/spawner/random/trash/grime, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/plating, -/area/station/medical/abandoned) "kzj" = ( /obj/effect/turf_decal/tile/red{ dir = 4 @@ -43425,6 +43407,11 @@ /obj/structure/cable/multilayer/multiz, /turf/open/floor/plating, /area/station/maintenance/floor2/port) +"lrM" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/pod/light, +/area/station/maintenance/solars/starboard/aft) "lrN" = ( /obj/machinery/portable_atmospherics/canister/nitrogen, /obj/machinery/atmospherics/components/unary/portables_connector{ @@ -44511,10 +44498,6 @@ /obj/effect/spawner/random/structure/closet_maintenance, /turf/open/floor/pod/light, /area/station/maintenance/floor3/port/fore) -"lGN" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/catwalk_floor, -/area/station/maintenance/floor1/starboard) "lGX" = ( /obj/structure/flora/bush/sparsegrass/style_random, /obj/structure/sign/poster/official/random/directional/north, @@ -45424,12 +45407,6 @@ "lRY" = ( /turf/closed/wall, /area/station/commons/vacant_room/office) -"lSd" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/pod/light, -/area/station/maintenance/floor1/port/fore) "lSt" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/trash/grime, @@ -47720,11 +47697,6 @@ }, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"mvl" = ( -/obj/machinery/firealarm/directional/north, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/catwalk_floor, -/area/station/maintenance/floor1/starboard) "mvs" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -51003,9 +50975,6 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/turf_decal/trimline/brown/line, -/obj/effect/turf_decal/stripes/corner{ - dir = 8 - }, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -51255,6 +51224,12 @@ }, /turf/open/floor/catwalk_floor, /area/station/maintenance/floor4/port/aft) +"noF" = ( +/obj/effect/spawner/random/trash/grime, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/medical/abandoned) "noM" = ( /obj/machinery/atmospherics/pipe/smart/simple/dark/visible/layer2{ dir = 4 @@ -51502,6 +51477,14 @@ }, /turf/open/floor/iron, /area/station/commons/fitness/recreation) +"nry" = ( +/obj/effect/turf_decal/stripes/corner, +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/pod/light, +/area/station/maintenance/floor4/port/fore) "nrB" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -52344,11 +52327,6 @@ /obj/structure/sign/departments/security, /turf/closed/wall/r_wall, /area/station/security/checkpoint/first) -"nCt" = ( -/obj/effect/landmark/blobstart, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/grass/fairy, -/area/station/maintenance/floor2/port/fore) "nCA" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/pod/dark, @@ -54247,11 +54225,6 @@ /obj/structure/window/spawner/directional/south, /turf/open/floor/grass, /area/station/hallway/secondary/exit/departure_lounge) -"ocr" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/pod, -/area/station/maintenance/floor4/starboard/aft) "oct" = ( /obj/machinery/camera/directional/south{ c_tag = "Security - Exterior" @@ -54680,6 +54653,12 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/hos) +"oiv" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/pod/light, +/area/station/maintenance/floor1/starboard) "oiw" = ( /obj/structure/cable, /obj/machinery/door/airlock/grunge{ @@ -55661,11 +55640,13 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, -/obj/effect/turf_decal/stripes, /obj/effect/turf_decal/trimline/brown/line, /obj/structure/disposalpipe/segment{ dir = 5 }, +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, /turf/open/floor/iron/dark/smooth_half, /area/station/bitrunning/den) "owo" = ( @@ -57681,12 +57662,6 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/carpet/green, /area/station/commons/dorms/apartment1) -"oYH" = ( -/obj/machinery/airalarm/directional/south, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/catwalk_floor/iron_dark, -/area/station/maintenance/floor3/starboard) "oYI" = ( /obj/effect/turf_decal/stripes{ dir = 4 @@ -58397,11 +58372,6 @@ /obj/structure/disposalpipe/trunk, /turf/open/floor/iron/dark, /area/station/service/hydroponics) -"pjq" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/pod/light, -/area/station/maintenance/floor1/starboard) "pjs" = ( /obj/machinery/vending/hydronutrients, /obj/machinery/light/small/directional/north, @@ -58623,9 +58593,7 @@ "pmG" = ( /obj/machinery/power/apc/auto_name/directional/west, /obj/structure/cable, -/mob/living/simple_animal/hostile/retaliate/goat{ - name = "Pete" - }, +/mob/living/basic/goat/pete, /turf/open/floor/iron/kitchen_coldroom/freezerfloor, /area/station/service/kitchen/coldroom) "pmO" = ( @@ -58695,16 +58663,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/miningdock) -"pnv" = ( -/obj/machinery/door/airlock/hatch{ - name = "Maintenance Access" - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance, -/obj/structure/barricade/wooden/crude, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/pod/light, -/area/station/maintenance/floor1/starboard) "pnw" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/sign/poster/official/random/directional/south, @@ -59713,6 +59671,11 @@ /obj/effect/mapping_helpers/airlock/unres, /turf/open/floor/pod/light, /area/station/maintenance/floor3/starboard/aft) +"pAv" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/pod/light, +/area/station/maintenance/floor4/port/fore) "pAy" = ( /obj/structure/window/reinforced/spawner/directional/south, /obj/structure/flora/bush/snow/style_random, @@ -59930,6 +59893,13 @@ }, /turf/open/floor/iron, /area/station/hallway/floor3/fore) +"pDB" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/airalarm/directional/east, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/wood/parquet, +/area/station/maintenance/floor2/port/aft) "pDK" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -62320,6 +62290,10 @@ /obj/structure/cable, /turf/open/floor/carpet/neon/simple/white, /area/station/commons/dorms/room3) +"qna" = ( +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/medical/abandoned) "qnc" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -65557,6 +65531,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/catwalk_floor/iron, /area/station/engineering/lobby) +"rce" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/pod/light, +/area/station/maintenance/floor4/starboard/fore) "rci" = ( /obj/structure/closet/emcloset, /obj/effect/turf_decal/trimline/purple/filled/line{ @@ -66469,12 +66448,6 @@ /obj/structure/closet/firecloset, /turf/open/floor/pod/light, /area/station/maintenance/floor2/port/fore) -"roL" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/pod/light, -/area/station/maintenance/floor2/port/aft) "roZ" = ( /obj/machinery/light/floor, /turf/open/floor/iron, @@ -66905,6 +66878,11 @@ }, /turf/open/floor/plating, /area/station/cargo/storage) +"rvh" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/plating, +/area/station/maintenance/floor2/starboard/aft) "rvD" = ( /obj/structure/sink/directional/south, /obj/structure/mirror/directional/north, @@ -67798,16 +67776,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/medical/virology) -"rIr" = ( -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 8 - }, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/turf/open/floor/pod/light, -/area/station/maintenance/floor3/starboard/fore) "rIt" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/pod/dark, @@ -71511,6 +71479,12 @@ /obj/machinery/light/cold/directional/east, /turf/open/floor/iron/dark/textured, /area/station/medical/office) +"sKg" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/pod/light, +/area/station/maintenance/floor4/port) "sKm" = ( /turf/closed/wall, /area/station/medical/virology/isolation) @@ -72931,17 +72905,6 @@ /obj/effect/landmark/start/warden, /turf/open/floor/iron/dark, /area/station/security/warden) -"tcr" = ( -/obj/machinery/door/airlock/hatch{ - name = "Wine Cellar" - }, -/obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/pod/light, -/area/station/maintenance/floor3/starboard/aft) "tcA" = ( /obj/machinery/telecomms/server/presets/engineering, /turf/open/floor/circuit/telecomms, @@ -73382,6 +73345,12 @@ /obj/machinery/telecomms/broadcaster/preset_left, /turf/open/floor/circuit/green/telecomms, /area/station/tcommsat/server) +"tiC" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/oil, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/pod/light, +/area/station/maintenance/floor1/port/fore) "tiX" = ( /obj/effect/turf_decal/trimline/green/warning{ dir = 10 @@ -74777,12 +74746,6 @@ /obj/machinery/vending/cola/starkist, /turf/open/floor/wood, /area/station/command/meeting_room) -"tAJ" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/floor4/port/fore) "tAL" = ( /obj/structure/railing{ dir = 4 @@ -75012,6 +74975,11 @@ /obj/machinery/light/cold/directional/north, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"tEb" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron/textured_large, +/area/station/maintenance/solars/starboard/fore) "tEc" = ( /obj/machinery/door/airlock/external{ name = "External Airlock" @@ -75251,6 +75219,11 @@ }, /turf/open/floor/iron/cafeteria, /area/station/security/prison) +"tIa" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/floor4/port/fore) "tIc" = ( /obj/structure/chair/comfy/black{ dir = 8 @@ -78238,13 +78211,6 @@ /obj/machinery/newscaster/directional/west, /turf/open/floor/iron/dark, /area/station/engineering/atmos/office) -"uyz" = ( -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/dark, -/area/station/medical/morgue) "uyD" = ( /turf/closed/wall/r_wall, /area/station/engineering/supermatter) @@ -78268,6 +78234,12 @@ initial_gas_mix = "TEMP=2.7" }, /area/station/science/ordnance/bomb) +"uyS" = ( +/obj/machinery/airalarm/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/maintenance/floor3/starboard) "uyX" = ( /obj/effect/turf_decal/tile/red/half/contrasted, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -78285,11 +78257,6 @@ /obj/machinery/camera/autoname/directional/east, /turf/open/floor/iron/dark, /area/station/command/teleporter) -"uzf" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/iron/textured_large, -/area/station/maintenance/solars/starboard/fore) "uzl" = ( /obj/structure/table, /obj/effect/turf_decal/trimline/red/filled/line{ @@ -78546,16 +78513,11 @@ /turf/open/floor/iron, /area/station/hallway/floor2/aft) "uDm" = ( -/obj/effect/turf_decal/box/corners{ - dir = 8 - }, -/obj/effect/turf_decal/box/corners{ - dir = 1 - }, /obj/machinery/firealarm/directional/south, /obj/machinery/light/directional/south, /obj/effect/decal/cleanable/oil/streak, -/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/machinery/byteforge, +/obj/effect/turf_decal/box, /turf/open/floor/iron/dark/smooth_large, /area/station/bitrunning/den) "uDr" = ( @@ -78565,6 +78527,11 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron/dark, /area/station/maintenance/floor1/port) +"uDx" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/iron/kitchen, +/area/station/service/kitchen/abandoned) "uDA" = ( /obj/structure/chair/sofa/corp{ dir = 8 @@ -80674,6 +80641,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/wood, /area/station/service/kitchen/diner) +"vej" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/pod/light, +/area/station/maintenance/floor4/port/fore) "veA" = ( /obj/structure/railing{ dir = 8 @@ -83228,12 +83201,6 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/plating, /area/station/maintenance/floor2/starboard/aft) -"vMV" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/generic_maintenance_landmark, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/pod/light, -/area/station/maintenance/floor1/starboard) "vNa" = ( /obj/effect/decal/cleanable/blood/drip, /turf/open/floor/iron/chapel{ @@ -83460,6 +83427,11 @@ /obj/effect/spawner/structure/window/hollow/reinforced/directional, /turf/open/floor/plating, /area/station/service/chapel/office) +"vPC" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/pod/light, +/area/station/maintenance/floor1/starboard) "vPE" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -83568,6 +83540,16 @@ /obj/machinery/light/red/dim/directional/west, /turf/open/floor/catwalk_floor, /area/station/maintenance/floor4/port/aft) +"vRb" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 8 + }, +/obj/effect/landmark/generic_maintenance_landmark, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/turf/open/floor/pod/light, +/area/station/maintenance/floor3/starboard/fore) "vRj" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/wood, @@ -84381,11 +84363,6 @@ }, /turf/open/space/openspace, /area/space) -"wch" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/floor/pod/light, -/area/station/maintenance/solars/starboard/aft) "wci" = ( /obj/effect/turf_decal/siding/wood/corner{ dir = 4 @@ -85521,12 +85498,6 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/security/holding_cell) -"wpX" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/stripes/line, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/pod/light, -/area/station/maintenance/floor4/port/fore) "wpY" = ( /obj/machinery/light/red/dim/directional/east, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -87340,6 +87311,11 @@ }, /turf/open/floor/iron, /area/station/science/auxlab) +"wLy" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/pod, +/area/station/maintenance/floor4/starboard/aft) "wLC" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 1 @@ -90874,6 +90850,12 @@ "xHe" = ( /turf/closed/wall, /area/station/maintenance/floor4/starboard/fore) +"xHf" = ( +/obj/structure/chair/wood, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/carpet/green, +/area/station/service/abandoned_gambling_den) "xHg" = ( /obj/structure/window/reinforced/spawner/directional/east, /turf/open/floor/engine/hull/reinforced, @@ -92757,6 +92739,11 @@ }, /turf/open/floor/wood/large, /area/station/service/library/artgallery) +"yiV" = ( +/obj/effect/landmark/blobstart, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/floor/grass/fairy, +/area/station/maintenance/floor2/port/fore) "yiZ" = ( /obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, @@ -113941,7 +113928,7 @@ vIx hJy rXp oZW -lSd +tiC ifx hJy htg @@ -127014,10 +127001,10 @@ bdC ddv mST dui -vMV -pjq -pnv -lGN +oiv +vPC +kbW +ebC wsE whV lYR @@ -127274,7 +127261,7 @@ dui rxJ jVW whV -lGN +ebC jFT whV whV @@ -127531,7 +127518,7 @@ whV whV whV whV -lGN +ebC yfi wJB eFY @@ -127788,7 +127775,7 @@ whV mWJ qKt whV -mvl +iRo jQG eFY qfr @@ -128045,7 +128032,7 @@ nho qKt aqd whV -lGN +ebC yfi vqN eFY @@ -128302,7 +128289,7 @@ whV whV whV whV -lGN +ebC bCT nSv vWS @@ -130868,7 +130855,7 @@ rIS fXy ihH gok -gki +irp kxq nJK nBx @@ -176368,7 +176355,7 @@ knP cpW qtf bQv -uzf +tEb rYw uUG wpa @@ -182058,7 +182045,7 @@ bSb clJ kEf ejl -acX +uDx rGP cfU pkr @@ -185397,7 +185384,7 @@ uXA hLz hZP pJf -nCt +yiV uJr pJf owM @@ -193324,7 +193311,7 @@ wJI wJI qvk sff -gwV +dsw erN wGl wGl @@ -197471,7 +197458,7 @@ rlB wLV uMK aZs -uyz +agW aKF vrA ffA @@ -205149,7 +205136,7 @@ oyh dEt dEt exc -iCI +rvh bwK tHn qWS @@ -206466,7 +206453,7 @@ dVH jtf nlN usq -bOM +pDB wWf xui mvS @@ -208006,7 +207993,7 @@ nlN mbe mbe rcp -roL +dqJ oin jtL cCq @@ -208269,7 +208256,7 @@ xRo cCq iDm xrj -kvr +aHf bIm hMs qCt @@ -242161,7 +242148,7 @@ kVp wRJ wRJ eCP -rIr +vRb wPF xkX ooF @@ -254265,7 +254252,7 @@ eDe xGx diU ufs -kof +qna dDu ufs uZc @@ -257092,7 +257079,7 @@ ykZ ybK iuo wcC -kzf +noF hiu uZc gYj @@ -259113,7 +259100,7 @@ bof bof lDD xRM -oYH +uyS qrd sSB jpz @@ -268409,7 +268396,7 @@ sOD pOn mVR piR -hNZ +xHf cBq rsz mnY @@ -268637,7 +268624,7 @@ pwA rlX xLO kRw -gmM +abJ sBE kRw upo @@ -268894,7 +268881,7 @@ xJM hCJ vXH kRw -ifE +jsb iMM kRw cpa @@ -269151,7 +269138,7 @@ kRw kRw kRw kRw -tcr +cVU kRw kRw fpp @@ -269397,7 +269384,7 @@ rCv snd wVu pUC -wch +lrM qON snd tat @@ -307954,7 +307941,7 @@ ucA xHe xHe ioM -iXb +rce xjQ iqD euv @@ -311840,10 +311827,10 @@ uIx aaO xFo lBG -wpX -hiO -tAJ -dRp +gmg +tIa +brM +dad qlh nDu nDu @@ -312095,9 +312082,9 @@ xMF kBi uIx rao -fKz -eId -ePr +vej +pAv +nry eiO wkF voT @@ -314413,7 +314400,7 @@ owb fXs dIh wtL -awK +sKg bAG wtL fXs @@ -320545,7 +320532,7 @@ kDq dlW xrY xdm -ocr +wLy vJf rVI oih diff --git a/_maps/map_files/VoidRaptor/VoidRaptor.dmm b/_maps/map_files/VoidRaptor/VoidRaptor.dmm index 143300c080a..2a630d0d647 100644 --- a/_maps/map_files/VoidRaptor/VoidRaptor.dmm +++ b/_maps/map_files/VoidRaptor/VoidRaptor.dmm @@ -1873,7 +1873,6 @@ "aAN" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ - dir = 8; id = "chemistry_shutters"; name = "Pharmacy Shutters" }, @@ -3372,7 +3371,7 @@ anchored = 1; name = "Citrus's bed" }, -/mob/living/simple_animal/sloth/citrus, +/mob/living/basic/sloth/citrus, /turf/open/floor/iron/dark/smooth_large, /area/station/command/heads_quarters/qm) "aWY" = ( @@ -3484,9 +3483,9 @@ pixel_y = 16 }, /obj/machinery/door/poddoor/shutters/window/preopen{ - dir = 4; id = "paramed_dispatch_desk"; - name = "Desk Shutters" + name = "Desk Shutters"; + dir = 8 }, /obj/item/paper_bin{ pixel_y = 4 @@ -11920,7 +11919,6 @@ "dAP" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ - dir = 4; id = "genetics_shutters"; name = "Genetics Shutters" }, @@ -13944,7 +13942,6 @@ /obj/item/reagent_containers/syringe/epinephrine, /obj/effect/turf_decal/tile/yellow/fourcorners, /obj/machinery/door/poddoor/shutters/preopen{ - dir = 8; id = "chemistry_shutters"; name = "Pharmacy Shutters" }, @@ -18259,9 +18256,9 @@ req_access = list("medical") }, /obj/machinery/door/poddoor/shutters/window/preopen{ - dir = 4; id = "paramed_dispatch_desk"; - name = "Desk Shutters" + name = "Desk Shutters"; + dir = 8 }, /turf/open/floor/iron/white/smooth_large, /area/station/medical/medbay/lobby) @@ -18729,7 +18726,7 @@ /turf/open/floor/iron/smooth, /area/station/maintenance/disposal/incinerator) "fth" = ( -/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/machinery/byteforge, /obj/effect/turf_decal/box/corners{ dir = 8 }, @@ -22906,7 +22903,7 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/mob/living/simple_animal/hostile/retaliate/goat{ +/mob/living/basic/goat/pete{ name = "Pete" }, /obj/effect/turf_decal/weather/snow, @@ -24383,7 +24380,6 @@ /area/station/engineering/atmos) "haE" = ( /obj/machinery/door/poddoor/shutters/preopen{ - dir = 8; id = "hop"; name = "Privacy Shutters" }, @@ -29278,7 +29274,8 @@ /obj/effect/turf_decal/caution/stand_clear, /obj/machinery/door/poddoor/shutters{ id = "mechbay"; - name = "Mech Bay Shutters" + name = "Mech Bay Shutters"; + dir = 4 }, /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -36933,7 +36930,6 @@ req_access = list("pharmacy") }, /obj/machinery/door/poddoor/shutters/preopen{ - dir = 4; id = "chemistry_shutters"; name = "Pharmacy Shutters" }, @@ -39446,7 +39442,6 @@ /area/station/hallway/primary/fore) "lfY" = ( /obj/machinery/door/poddoor/shutters/preopen{ - dir = 8; id = "hopqueue"; name = "HoP Queue Shutters" }, @@ -40600,7 +40595,6 @@ pixel_y = 9 }, /obj/machinery/door/poddoor/shutters/preopen{ - dir = 4; id = "genetics_shutters"; name = "Genetics Shutters" }, @@ -44465,9 +44459,9 @@ /obj/item/stack/medical/mesh, /obj/item/stack/medical/suture, /obj/machinery/door/poddoor/shutters/window/preopen{ - dir = 4; id = "paramed_dispatch_desk"; - name = "Desk Shutters" + name = "Desk Shutters"; + dir = 8 }, /turf/open/floor/iron/white/smooth_large, /area/station/medical/medbay/lobby) @@ -50365,6 +50359,11 @@ "ogb" = ( /obj/machinery/smartfridge, /obj/effect/turf_decal/bot, +/obj/machinery/door/firedoor, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchen_service"; + name = "Service Shutter" + }, /turf/open/floor/iron/large, /area/station/service/kitchen) "ogc" = ( @@ -50697,7 +50696,8 @@ }, /obj/machinery/door/poddoor/shutters/preopen{ id = "roboticsprivacy"; - name = "Robotics Shutters" + name = "Robotics Shutters"; + dir = 4 }, /turf/open/floor/iron/dark/smooth_large, /area/station/science/robotics/lab) @@ -55225,9 +55225,9 @@ req_access = list("medical") }, /obj/machinery/door/poddoor/shutters/window/preopen{ - dir = 4; id = "paramed_dispatch_desk"; - name = "Desk Shutters" + name = "Desk Shutters"; + dir = 8 }, /obj/item/storage/box/bandages{ pixel_y = 15 @@ -58109,7 +58109,6 @@ req_access = list("hop") }, /obj/machinery/door/poddoor/shutters/preopen{ - dir = 8; id = "hop"; name = "Privacy Shutters" }, @@ -58171,11 +58170,23 @@ /turf/open/floor/catwalk_floor, /area/station/hallway/secondary/exit/departure_lounge) "qhU" = ( -/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/structure/table, +/obj/item/food/cornchips/blue{ + pixel_x = 9; + pixel_y = 4 + }, +/obj/item/reagent_containers/cup/soda_cans/space_mountain_wind{ + pixel_x = -7; + pixel_y = -1 + }, /obj/effect/turf_decal/box/corners, /obj/effect/turf_decal/box/corners{ dir = 4 }, +/obj/item/food/cornchips/red{ + pixel_x = 3; + pixel_y = 6 + }, /turf/open/floor/engine, /area/station/bitrunning/den) "qhX" = ( @@ -58318,7 +58329,6 @@ }, /obj/machinery/door/firedoor, /obj/machinery/door/poddoor/shutters/preopen{ - dir = 4; id = "rndlab1"; name = "Research and Development Shutter" }, @@ -59608,7 +59618,6 @@ "qDW" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ - dir = 4; id = "rndlab1"; name = "Research and Development Shutter" }, @@ -61138,6 +61147,11 @@ /area/station/maintenance/aft/upper) "qZl" = ( /obj/machinery/smartfridge/chemistry/preloaded, +/obj/machinery/door/firedoor, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "chemistry_shutters"; + name = "Pharmacy Shutters" + }, /turf/open/floor/iron/freezer, /area/station/medical/pharmacy) "qZz" = ( @@ -64224,7 +64238,6 @@ /area/station/service/cafeteria) "rUf" = ( /obj/machinery/door/poddoor/shutters/preopen{ - dir = 1; id = "chemistry_shutters"; name = "Pharmacy Shutters" }, @@ -66444,7 +66457,6 @@ req_access = list("pharmacy") }, /obj/machinery/door/poddoor/shutters/preopen{ - dir = 1; id = "chemistry_shutters"; name = "Pharmacy Shutters" }, @@ -69158,7 +69170,8 @@ /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ id = "roboticsprivacy"; - name = "Robotics Shutters" + name = "Robotics Shutters"; + dir = 8 }, /turf/open/floor/plating/airless, /area/station/science/robotics/lab) @@ -76768,7 +76781,8 @@ /obj/effect/turf_decal/caution/stand_clear, /obj/machinery/door/poddoor/shutters{ id = "mechbay"; - name = "Mech Bay Shutters" + name = "Mech Bay Shutters"; + dir = 4 }, /obj/machinery/button/door/directional/north{ id = "mechbay"; @@ -83926,6 +83940,11 @@ /area/station/security/checkpoint/engineering) "xnP" = ( /obj/machinery/smartfridge/chemistry/preloaded, +/obj/machinery/door/firedoor, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "chemistry_shutters"; + name = "Pharmacy Shutters" + }, /turf/open/floor/iron/dark/smooth_large, /area/station/medical/pharmacy) "xnR" = ( @@ -87204,13 +87223,13 @@ /turf/open/floor/iron/smooth_large, /area/station/engineering/atmos) "ykT" = ( -/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/smartfridge/chemistry/preloaded, /obj/machinery/door/poddoor/shutters/preopen{ - dir = 1; id = "chemistry_shutters"; name = "Pharmacy Shutters" }, -/turf/open/floor/plating/airless, +/obj/machinery/door/firedoor, +/turf/open/floor/iron/dark/smooth_large, /area/station/medical/pharmacy) "ylg" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ @@ -119292,7 +119311,7 @@ rFl xgy uQf jLi -ykT +aAN gut uMt sLk @@ -119549,7 +119568,7 @@ gLN dRX jQm tJU -xnP +ykT vVO twU wwr diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm index c1740dd6338..b287fefce3e 100644 --- a/_maps/map_files/debug/runtimestation.dmm +++ b/_maps/map_files/debug/runtimestation.dmm @@ -1989,6 +1989,10 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/medical/chemistry) +"vZ" = ( +/obj/machinery/byteforge, +/turf/open/floor/circuit/green, +/area/station/bitrunning/den) "wb" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 4 @@ -2442,10 +2446,6 @@ /obj/item/healthanalyzer/advanced, /turf/open/floor/iron, /area/station/medical/medbay) -"UM" = ( -/obj/effect/landmark/bitrunning/station_reward_spawn, -/turf/open/floor/circuit/green, -/area/station/bitrunning/den) "Va" = ( /obj/machinery/power/smes{ charge = 5e+006 @@ -3196,7 +3196,7 @@ aa aa aa Yn -UM +AR AR Ma Fk @@ -3288,8 +3288,8 @@ aa aa aa Yn -UM AR +vZ Ma Fk Yn diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index 9b6c1b6d5d5..b0de40dcde2 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -2,6 +2,15 @@ "aa" = ( /turf/open/space/basic, /area/space) +"ab" = ( +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 1 + }, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 1 + }, +/turf/open/floor/iron/white/side, +/area/centcom/central_command_areas/evacuation) "ad" = ( /turf/open/space, /area/space) @@ -313,6 +322,21 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/control) +"bu" = ( +/obj/effect/turf_decal/siding/dark_blue{ + dir = 9 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) +"bv" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/siding/dark_blue{ + dir = 8 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "bx" = ( /turf/open/floor/iron/goonplaque{ desc = "This is a plaque commemorating the thunderdome and all those who have died at its pearly blast doors." @@ -422,6 +446,10 @@ /obj/effect/light_emitter/thunderdome, /turf/open/floor/iron, /area/centcom/tdome/arena) +"bS" = ( +/obj/structure/sign/poster/contraband/syndicate_recruitment/directional/north, +/turf/open/indestructible/dark, +/area/centcom/central_command_areas/admin) "bV" = ( /obj/structure/table/reinforced, /obj/machinery/computer/records/medical/laptop, @@ -656,15 +684,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/tdome/observation) -"cX" = ( -/obj/structure/table/reinforced, -/turf/open/floor/iron, -/area/centcom/central_command_areas/supplypod) -"cY" = ( -/obj/machinery/icecream_vat, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/centcom/tdome/observation) "cZ" = ( /obj/effect/turf_decal/tile/green/half/contrasted{ dir = 1 @@ -679,6 +698,13 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/briefing) +"dc" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/yellow/corner{ + dir = 8 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supply) "dd" = ( /obj/structure/reagent_dispensers/watertank, /obj/effect/turf_decal/stripes/line{ @@ -690,13 +716,6 @@ /obj/effect/landmark/start/new_player, /turf/closed/indestructible/start_area, /area/misc/start) -"dh" = ( -/obj/effect/turf_decal/tile/blue/half/contrasted{ - dir = 8 - }, -/obj/machinery/light/floor, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "di" = ( /obj/structure/table/reinforced, /obj/machinery/door/firedoor, @@ -726,6 +745,16 @@ /obj/effect/light_emitter/thunderdome, /turf/open/floor/iron, /area/centcom/tdome/arena) +"dm" = ( +/obj/structure/table/reinforced, +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/bot, +/obj/item/food/mint{ + pixel_x = 6; + pixel_y = -4 + }, +/turf/open/floor/iron, +/area/centcom/tdome/observation) "dn" = ( /obj/effect/turf_decal/siding/wood{ dir = 4 @@ -975,6 +1004,19 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/admin) +"eC" = ( +/obj/structure/table, +/obj/item/toy/sword{ + pixel_y = 8; + pixel_x = 14 + }, +/obj/item/gun/ballistic/shotgun/toy/crossbow{ + pixel_y = 11; + pixel_x = -2 + }, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "eD" = ( /obj/machinery/door/airlock/centcom{ name = "Administrative Office" @@ -997,6 +1039,28 @@ "eF" = ( /turf/open/floor/iron/grimy, /area/centcom/central_command_areas/briefing) +"eG" = ( +/obj/machinery/computer/auxiliary_base/directional/north, +/obj/structure/table/reinforced, +/obj/item/clipboard{ + pixel_y = 4; + pixel_x = 2 + }, +/obj/item/folder/yellow{ + pixel_y = 7; + pixel_x = 5 + }, +/obj/item/pen/red{ + pixel_y = 2; + pixel_x = 3 + }, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/item/paper_bin{ + pixel_x = -15; + pixel_y = 7 + }, +/turf/open/floor/iron/dark, +/area/centcom/central_command_areas/supply) "eH" = ( /obj/structure/flora/bush/sparsegrass/style_random, /obj/structure/flora/bush/lavendergrass/style_random, @@ -1142,6 +1206,27 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/centcom/central_command_areas/evacuation) +"fs" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/siding/dark_blue/corner, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) +"ft" = ( +/obj/structure/table/wood, +/obj/item/lighter{ + pixel_x = -6; + pixel_y = -2 + }, +/obj/item/crowbar/power{ + pixel_y = 15 + }, +/turf/open/floor/iron/dark, +/area/centcom/central_command_areas/supplypod) "fw" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, @@ -1206,6 +1291,17 @@ }, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/evacuation/ship) +"fJ" = ( +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 4 + }, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 4 + }, +/turf/open/floor/iron/white/side{ + dir = 8 + }, +/area/centcom/central_command_areas/evacuation) "fM" = ( /obj/structure/filingcabinet/medical, /obj/machinery/firealarm/directional/west, @@ -1422,9 +1518,30 @@ /obj/machinery/light/directional/south, /turf/open/floor/iron, /area/centcom/central_command_areas/control) +"gM" = ( +/obj/structure/table, +/obj/item/paper_bin{ + pixel_y = 7; + pixel_x = -4 + }, +/obj/item/pen{ + pixel_x = -5; + pixel_y = 9 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "gO" = ( /turf/closed/indestructible/riveted, /area/centcom/central_command_areas/briefing) +"gQ" = ( +/obj/effect/turf_decal/siding/dark_blue{ + dir = 6 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "gR" = ( /obj/item/wrench, /obj/item/restraints/handcuffs, @@ -1515,17 +1632,23 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/briefing) -"hv" = ( -/obj/structure/table/reinforced, -/obj/machinery/microwave{ - desc = "Cooks and boils stuff, somehow."; - pixel_x = -3; - pixel_y = 5 - }, -/obj/machinery/barsign/all_access/directional/south, +"hq" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/centcom/tdome/observation) +/obj/effect/turf_decal/siding/yellow{ + dir = 1 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supply) +"hs" = ( +/obj/item/kirbyplants/organic/plant22, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/siding/dark_blue{ + dir = 4 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "hx" = ( /obj/machinery/photocopier, /turf/open/floor/iron/grimy, @@ -2005,13 +2128,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron, /area/centcom/central_command_areas/supply) -"jq" = ( -/obj/item/stack/package_wrap, -/obj/item/hand_labeler, -/obj/structure/table, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron, -/area/centcom/central_command_areas/supply) "jr" = ( /obj/machinery/door/airlock/external/ruin{ name = "Supply Shuttle" @@ -2186,12 +2302,17 @@ }, /turf/open/floor/iron, /area/centcom/central_command_areas/supply) -"jQ" = ( -/obj/structure/closet/secure_closet/quartermaster, -/obj/machinery/airalarm/directional/east, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron, -/area/centcom/central_command_areas/supply) +"jS" = ( +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 8 + }, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 8 + }, +/turf/open/floor/iron/white/side{ + dir = 4 + }, +/area/centcom/central_command_areas/evacuation) "jU" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/computer, @@ -2205,10 +2326,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/tdome/administration) -"kh" = ( -/obj/machinery/telecomms/allinone/nuclear, -/turf/open/indestructible/hierophant, -/area/centcom/central_command_areas/admin) "ki" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/structure/filingcabinet{ @@ -2481,6 +2598,26 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/supplypod) +"lH" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/table/reinforced, +/obj/machinery/reagentgrinder{ + desc = "Used to grind things up into raw materials and liquids."; + pixel_y = 5 + }, +/obj/item/reagent_containers/condiment/saltshaker{ + pixel_x = -8; + pixel_y = 5 + }, +/obj/item/reagent_containers/condiment/peppermill{ + pixel_x = -8 + }, +/obj/item/knife/kitchen{ + pixel_x = 11; + pixel_y = -12 + }, +/turf/open/floor/iron/dark, +/area/centcom/tdome/observation) "lJ" = ( /obj/machinery/door/airlock/centcom{ name = "Shuttle Control Office" @@ -2578,10 +2715,6 @@ }, /turf/open/floor/iron/grimy, /area/centcom/central_command_areas/courtroom) -"lZ" = ( -/obj/machinery/light/floor, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "mc" = ( /obj/effect/light_emitter/podbay, /turf/open/floor/iron, @@ -2645,11 +2778,27 @@ /obj/structure/table/wood, /turf/open/floor/iron/grimy, /area/centcom/central_command_areas/courtroom) +"mr" = ( +/obj/effect/turf_decal/tile/dark_blue/fourcorners, +/obj/effect/turf_decal/tile/dark_blue/fourcorners, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "ms" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/machinery/light/floor, /turf/open/floor/iron, /area/centcom/central_command_areas/supplypod/loading/ert) +"mv" = ( +/obj/machinery/airalarm/directional/east, +/obj/effect/turf_decal/bot, +/obj/structure/closet/wardrobe/cargotech, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supply) +"mB" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/yellow, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supply) "mC" = ( /obj/structure/window/reinforced/spawner/directional/east, /obj/machinery/computer/operating, @@ -3019,6 +3168,17 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/centcom/central_command_areas/ferry) +"og" = ( +/obj/machinery/status_display/evac/directional/west, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/table/reinforced, +/obj/machinery/microwave{ + desc = "Cooks and boils stuff, somehow."; + pixel_x = -3; + pixel_y = 5 + }, +/turf/open/floor/iron/dark, +/area/centcom/tdome/observation) "oh" = ( /obj/structure/table/wood, /obj/item/paper_bin, @@ -3259,17 +3419,6 @@ /obj/structure/sign/nanotrasen, /turf/closed/indestructible/riveted, /area/centcom/central_command_areas/courtroom) -"pd" = ( -/obj/item/clipboard, -/obj/item/stamp/denied{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/stamp, -/obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/centcom/central_command_areas/supply) "pf" = ( /obj/structure/table/reinforced, /obj/item/crowbar/red, @@ -3639,6 +3788,18 @@ /obj/effect/mapping_helpers/airlock/access/all/admin/captain, /turf/open/floor/iron, /area/centcom/central_command_areas/prison) +"qN" = ( +/obj/structure/table/wood, +/obj/item/storage/box/drinkingglasses{ + pixel_y = 14; + pixel_x = -4 + }, +/obj/item/reagent_containers/cup/glass/shaker{ + pixel_y = -8; + pixel_x = -10 + }, +/turf/open/floor/iron/dark, +/area/centcom/central_command_areas/supplypod) "qO" = ( /obj/effect/turf_decal/tile/red{ dir = 8 @@ -3707,6 +3868,11 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/prison) +"rj" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/closet/secure_closet/quartermaster, +/turf/open/floor/iron/dark, +/area/centcom/central_command_areas/supply) "rk" = ( /turf/open/floor/wood, /area/centcom/central_command_areas/courtroom) @@ -3724,11 +3890,6 @@ }, /turf/open/floor/iron, /area/centcom/central_command_areas/ferry) -"rq" = ( -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/machinery/light/floor, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "rs" = ( /obj/effect/landmark/prisonwarp, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -3780,6 +3941,12 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/briefing) +"rC" = ( +/obj/effect/turf_decal/siding/dark_blue/corner{ + dir = 1 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "rF" = ( /obj/structure/flora/bush/sparsegrass/style_random, /obj/structure/flora/bush/grassy/style_random, @@ -3891,12 +4058,6 @@ }, /turf/open/floor/iron/white, /area/centcom/tdome/observation) -"sa" = ( -/obj/structure/table/wood, -/obj/item/lighter, -/obj/item/crowbar/power, -/turf/open/floor/iron/dark, -/area/centcom/central_command_areas/supplypod) "sb" = ( /obj/machinery/vending/snack, /turf/open/floor/iron, @@ -3928,6 +4089,10 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/tdome/administration) +"sl" = ( +/obj/effect/turf_decal/siding/dark_blue/corner, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "sn" = ( /obj/machinery/door/airlock/centcom{ name = "CentCom Security" @@ -4086,15 +4251,6 @@ }, /turf/open/floor/iron, /area/centcom/central_command_areas/evacuation) -"sP" = ( -/obj/structure/table, -/obj/item/paper_bin, -/obj/item/pen, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "sQ" = ( /obj/structure/chair, /obj/effect/turf_decal/stripes/line{ @@ -4110,15 +4266,6 @@ /obj/machinery/light/directional/north, /turf/open/floor/iron, /area/centcom/central_command_areas/evacuation) -"sS" = ( -/obj/structure/table, -/obj/item/toy/katana, -/obj/item/toy/plush/carpplushie, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "sT" = ( /obj/effect/turf_decal/stripes/line{ dir = 5 @@ -4228,6 +4375,14 @@ /obj/effect/mapping_helpers/airlock/access/all/admin/general, /turf/open/floor/iron, /area/centcom/central_command_areas/ferry) +"tx" = ( +/obj/structure/table/reinforced, +/obj/item/paper_bin{ + pixel_y = 8; + pixel_x = -4 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supplypod) "ty" = ( /obj/structure/filingcabinet/security, /obj/machinery/status_display/evac/directional/south, @@ -4303,12 +4458,6 @@ /obj/machinery/status_display/evac/directional/west, /turf/open/floor/iron, /area/centcom/central_command_areas/prison) -"tT" = ( -/obj/effect/turf_decal/siding/yellow{ - dir = 1 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "tU" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -4319,9 +4468,9 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron, /area/centcom/central_command_areas/evacuation) -"tW" = ( -/turf/open/indestructible/hierophant/two, -/area/centcom/central_command_areas/admin) +"tY" = ( +/turf/open/floor/iron/white, +/area/centcom/central_command_areas/evacuation) "ub" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/centcom{ @@ -4389,10 +4538,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/control) -"us" = ( -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "ut" = ( /obj/docking_port/stationary{ dir = 8; @@ -4428,15 +4573,6 @@ }, /turf/open/space, /area/space) -"uA" = ( -/obj/structure/chair{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "uE" = ( /obj/effect/light_emitter/thunderdome, /turf/closed/indestructible/fakeglass, @@ -4451,10 +4587,6 @@ /obj/machinery/light/directional/east, /turf/open/floor/grass, /area/centcom/tdome/observation) -"uG" = ( -/obj/effect/turf_decal/siding/yellow, -/turf/open/floor/iron, -/area/centcom/central_command_areas/supply) "uM" = ( /obj/machinery/chem_master/condimaster{ name = "HoochMaster 2000" @@ -4489,6 +4621,18 @@ /obj/machinery/light/floor, /turf/open/floor/iron, /area/centcom/central_command_areas/evacuation/ship) +"uS" = ( +/obj/structure/table/reinforced, +/obj/item/reagent_containers/cup/glass/bottle/whiskey{ + pixel_y = 19; + pixel_x = 7 + }, +/obj/item/clothing/mask/cigarette/cigar/havana{ + pixel_x = -6; + pixel_y = 5 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supplypod) "uX" = ( /obj/machinery/shower/directional/east, /obj/effect/turf_decal/tile/green{ @@ -4557,20 +4701,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron, /area/centcom/central_command_areas/control) -"ve" = ( -/obj/effect/turf_decal/tile/blue, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) -"vf" = ( -/obj/effect/turf_decal/tile/blue/half/contrasted, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) -"vg" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "vm" = ( /obj/effect/turf_decal/delivery, /obj/machinery/light/directional/south, @@ -4729,18 +4859,6 @@ }, /turf/open/floor/iron, /area/centcom/central_command_areas/evacuation) -"vW" = ( -/obj/effect/turf_decal/tile/neutral/anticorner/contrasted{ - dir = 8 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) -"vX" = ( -/obj/effect/turf_decal/tile/blue/anticorner/contrasted{ - dir = 4 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "vY" = ( /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 4 @@ -4748,18 +4866,6 @@ /obj/machinery/light/directional/east, /turf/open/floor/iron, /area/centcom/central_command_areas/supply) -"vZ" = ( -/obj/effect/turf_decal/tile/blue/half/contrasted{ - dir = 4 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) -"wa" = ( -/obj/effect/turf_decal/tile/blue/half/contrasted{ - dir = 8 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "wb" = ( /obj/effect/turf_decal/tile/green/half/contrasted{ dir = 1 @@ -4829,6 +4935,13 @@ /obj/effect/light_emitter/thunderdome, /turf/open/floor/iron, /area/centcom/tdome/arena) +"wn" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/yellow{ + dir = 8 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supply) "wq" = ( /obj/structure/chair/comfy/black{ dir = 1 @@ -4954,16 +5067,6 @@ }, /turf/open/floor/iron, /area/centcom/central_command_areas/evacuation) -"wK" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) -"wL" = ( -/obj/effect/turf_decal/tile/blue/anticorner/contrasted, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "wN" = ( /obj/effect/turf_decal/siding/wood{ dir = 6 @@ -5074,20 +5177,10 @@ /obj/effect/turf_decal/tile/green, /turf/open/floor/iron, /area/centcom/central_command_areas/control) -"xr" = ( -/obj/structure/chair{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/machinery/status_display/evac/directional/west, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) -"xt" = ( -/obj/effect/turf_decal/tile/neutral/anticorner/contrasted{ - dir = 4 - }, +"xq" = ( +/obj/effect/turf_decal/tile/dark_blue/fourcorners, +/obj/effect/turf_decal/tile/dark_blue/fourcorners, +/obj/machinery/light/floor, /turf/open/floor/iron, /area/centcom/central_command_areas/evacuation) "xv" = ( @@ -5112,6 +5205,24 @@ /obj/structure/cable, /turf/open/floor/iron, /area/centcom/central_command_areas/admin/storage) +"xA" = ( +/obj/structure/table/reinforced, +/obj/machinery/door/firedoor, +/obj/item/reagent_containers/condiment/saltshaker{ + pixel_x = -8; + pixel_y = 5 + }, +/obj/item/reagent_containers/condiment/peppermill{ + pixel_x = -8 + }, +/obj/item/reagent_containers/cup/glass/mug/britcup, +/obj/effect/turf_decal/bot, +/obj/item/clothing/head/utility/chefhat{ + pixel_y = 11; + pixel_x = 5 + }, +/turf/open/floor/iron, +/area/centcom/tdome/observation) "xD" = ( /obj/machinery/computer/security{ dir = 1 @@ -5187,18 +5298,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/courtroom) -"xY" = ( -/obj/effect/turf_decal/tile/blue/anticorner/contrasted{ - dir = 1 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) -"xZ" = ( -/obj/effect/turf_decal/tile/blue/anticorner/contrasted{ - dir = 8 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "yb" = ( /obj/item/kirbyplants/organic/plant21, /obj/effect/turf_decal/tile/green{ @@ -5313,12 +5412,6 @@ /obj/effect/light_emitter/thunderdome, /turf/open/floor/iron, /area/centcom/tdome/arena) -"yB" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "yC" = ( /obj/structure/filingcabinet/security, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -5342,6 +5435,27 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/briefing) +"yN" = ( +/obj/machinery/keycard_auth/directional/south, +/obj/structure/table/reinforced, +/obj/item/stack/package_wrap{ + pixel_y = 11; + pixel_x = -16 + }, +/obj/item/stack/cable_coil{ + pixel_y = 4; + pixel_x = -10 + }, +/obj/item/hand_labeler{ + pixel_y = 1 + }, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/item/hand_labeler_refill{ + pixel_x = 8; + pixel_y = 12 + }, +/turf/open/floor/iron/dark, +/area/centcom/central_command_areas/supply) "yO" = ( /obj/machinery/computer/communications, /obj/machinery/status_display/evac/directional/north, @@ -5462,18 +5576,6 @@ /obj/effect/mapping_helpers/airlock/access/all/admin/medical, /turf/open/floor/iron, /area/centcom/central_command_areas/control) -"zl" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) -"zm" = ( -/obj/effect/turf_decal/tile/blue/half/contrasted{ - dir = 1 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "zn" = ( /obj/machinery/light/directional/north, /obj/structure/table/reinforced, @@ -5513,6 +5615,11 @@ }, /turf/open/floor/iron, /area/centcom/tdome/observation) +"zv" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/griddle, +/turf/open/floor/iron/dark, +/area/centcom/tdome/observation) "zw" = ( /obj/structure/sign/nanotrasen, /turf/closed/indestructible/riveted, @@ -5629,6 +5736,16 @@ }, /turf/open/floor/iron, /area/centcom/central_command_areas/supplypod/loading/two) +"zN" = ( +/obj/effect/turf_decal/siding/dark_blue, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) +"zP" = ( +/obj/effect/turf_decal/siding/dark_blue{ + dir = 10 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "zR" = ( /obj/structure/closet/secure_closet/personal, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -5644,6 +5761,22 @@ /obj/machinery/light/directional/south, /turf/open/misc/asteroid, /area/centcom/tdome/administration) +"zT" = ( +/obj/item/clipboard{ + pixel_y = 4; + pixel_x = -2 + }, +/obj/item/stamp/denied{ + pixel_x = -2; + pixel_y = 12 + }, +/obj/item/stamp{ + pixel_y = 7 + }, +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/turf/open/floor/iron/dark, +/area/centcom/central_command_areas/supply) "zU" = ( /obj/item/kirbyplants/organic/plant22, /obj/machinery/light_switch/directional/south, @@ -5748,10 +5881,6 @@ }, /turf/open/floor/iron/white, /area/centcom/central_command_areas/control) -"At" = ( -/obj/effect/turf_decal/siding/yellow, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "Av" = ( /obj/item/kirbyplants/organic/plant21, /obj/effect/turf_decal/tile/green{ @@ -5861,13 +5990,6 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron, /area/centcom/central_command_areas/evacuation) -"AX" = ( -/obj/structure/table, -/obj/item/toy/sword, -/obj/item/gun/ballistic/shotgun/toy/crossbow, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "AY" = ( /obj/structure/chair{ dir = 1 @@ -5940,14 +6062,6 @@ }, /turf/open/floor/iron/grimy, /area/centcom/central_command_areas/admin) -"Bs" = ( -/obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/item/storage/bag/tray, -/obj/item/kitchen/fork, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron, -/area/centcom/tdome/observation) "Bu" = ( /obj/item/kirbyplants/organic/plant21, /obj/machinery/status_display/evac/directional/west, @@ -6178,6 +6292,19 @@ /obj/machinery/light/directional/south, /turf/open/floor/grass, /area/centcom/central_command_areas/evacuation) +"Ce" = ( +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 8 + }, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 8 + }, +/obj/effect/turf_decal/tile/dark_blue, +/obj/effect/turf_decal/tile/dark_blue, +/turf/open/floor/iron/white/corner{ + dir = 4 + }, +/area/centcom/central_command_areas/evacuation) "Cf" = ( /obj/effect/turf_decal/tile/red/half/contrasted{ dir = 1 @@ -6193,19 +6320,6 @@ }, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/evacuation) -"Ci" = ( -/obj/structure/table/reinforced, -/obj/item/surgery_tray/full{ - pixel_y = 10; - pixel_x = 2 - }, -/obj/item/storage/box/masks{ - pixel_x = -6; - pixel_y = 4 - }, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/iron/white, -/area/centcom/central_command_areas/evacuation/ship) "Co" = ( /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 4 @@ -6243,6 +6357,26 @@ }, /turf/open/floor/iron, /area/centcom/tdome/observation) +"CB" = ( +/obj/effect/turf_decal/tile/dark_blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/dark_blue{ + dir = 4 + }, +/turf/open/floor/iron/white/side{ + dir = 10 + }, +/area/centcom/central_command_areas/evacuation) +"CC" = ( +/obj/machinery/light/directional/north, +/obj/structure/table/wood, +/obj/structure/reagent_dispensers/beerkeg{ + pixel_y = 6; + pixel_x = 5 + }, +/turf/open/floor/iron/dark, +/area/centcom/central_command_areas/supplypod) "CE" = ( /obj/item/clipboard, /obj/item/folder/red, @@ -6374,6 +6508,12 @@ }, /turf/open/floor/iron, /area/centcom/central_command_areas/control) +"Dg" = ( +/obj/machinery/light/floor, +/obj/effect/turf_decal/tile/dark_blue/fourcorners, +/obj/effect/turf_decal/tile/dark_blue/fourcorners, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "Di" = ( /turf/closed/indestructible/riveted, /area/centcom/ai_multicam_room) @@ -6394,6 +6534,32 @@ /obj/machinery/light/directional/east, /turf/open/floor/iron, /area/centcom/central_command_areas/control) +"Dn" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/siding/dark_blue/corner{ + dir = 4 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) +"Do" = ( +/obj/structure/table/reinforced, +/obj/machinery/status_display/evac/directional/west, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/item/clothing/suit/apron/chef, +/obj/item/kitchen/rollingpin{ + pixel_y = 2 + }, +/obj/item/reagent_containers/condiment/enzyme{ + pixel_y = 15; + pixel_x = -7 + }, +/turf/open/floor/iron/dark, +/area/centcom/tdome/observation) "Dp" = ( /obj/machinery/status_display/evac/directional/west, /obj/effect/turf_decal/tile/green{ @@ -6409,6 +6575,17 @@ /obj/effect/mapping_helpers/airlock/access/all/admin/general, /turf/open/floor/iron, /area/centcom/central_command_areas/control) +"Dr" = ( +/obj/effect/turf_decal/tile/dark_blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/dark_blue{ + dir = 8 + }, +/turf/open/floor/iron/white/side{ + dir = 5 + }, +/area/centcom/central_command_areas/evacuation) "Ds" = ( /obj/effect/turf_decal/tile/red/half/contrasted{ dir = 4 @@ -6827,6 +7004,13 @@ /obj/effect/light_emitter/thunderdome, /turf/open/floor/iron, /area/centcom/tdome/arena) +"FM" = ( +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 4 + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supply) "FO" = ( /obj/structure/table/reinforced, /obj/item/computer_disk/quartermaster, @@ -6838,6 +7022,15 @@ }, /turf/open/floor/iron, /area/centcom/central_command_areas/supply) +"FP" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/siding/dark_blue/corner{ + dir = 8 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "FR" = ( /obj/effect/light_emitter/podbay, /turf/open/floor/iron, @@ -6867,6 +7060,13 @@ /obj/effect/light_emitter/thunderdome, /turf/closed/indestructible/fakeglass, /area/centcom/tdome/observation) +"Gc" = ( +/obj/structure/table/reinforced, +/obj/item/storage/fancy/donut_box{ + pixel_y = 13 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supplypod) "Gf" = ( /obj/machinery/firealarm/directional/east, /obj/machinery/atmospherics/components/unary/vent_pump{ @@ -6921,6 +7121,15 @@ /obj/machinery/light/directional/north, /turf/open/floor/iron, /area/centcom/central_command_areas/admin/storage) +"Gw" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/siding/dark_blue{ + dir = 4 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "GB" = ( /obj/machinery/power/apc/auto_name/directional/west, /obj/effect/turf_decal/stripes/line, @@ -6994,6 +7203,12 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/courtroom) +"GU" = ( +/obj/effect/turf_decal/siding/dark_blue/corner{ + dir = 4 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "GX" = ( /obj/item/kirbyplants/organic/plant22, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -7135,6 +7350,15 @@ /obj/machinery/status_display/evac/directional/south, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/courtroom) +"HQ" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/siding/dark_blue/corner{ + dir = 1 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "HR" = ( /obj/structure/bed/medical/emergency, /obj/machinery/iv_drip, @@ -7182,6 +7406,9 @@ }, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/evacuation/ship) +"Ib" = ( +/turf/closed/indestructible/riveted, +/area/space) "Ic" = ( /obj/machinery/door/poddoor{ id = "thunderdomehea"; @@ -7191,24 +7418,6 @@ /obj/effect/light_emitter/thunderdome, /turf/open/floor/iron, /area/centcom/tdome/arena) -"Id" = ( -/obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/item/reagent_containers/condiment/saltshaker{ - pixel_x = -8; - pixel_y = 5 - }, -/obj/item/reagent_containers/condiment/peppermill{ - pixel_x = -8 - }, -/obj/item/reagent_containers/cup/glass/mug/britcup, -/obj/effect/turf_decal/bot, -/turf/open/floor/iron, -/area/centcom/tdome/observation) -"Ie" = ( -/obj/structure/sign/poster/contraband/syndicate_recruitment, -/turf/closed/indestructible/riveted, -/area/centcom/central_command_areas/admin) "If" = ( /obj/machinery/newscaster{ pixel_x = -32 @@ -7246,6 +7455,13 @@ }, /turf/open/floor/iron, /area/centcom/central_command_areas/ferry) +"Iu" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/yellow{ + dir = 4 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supply) "Iv" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -7283,6 +7499,32 @@ /obj/machinery/light/directional/south, /turf/open/floor/grass, /area/centcom/tdome/administration) +"IW" = ( +/obj/item/stack/package_wrap, +/obj/item/hand_labeler{ + pixel_y = 13; + pixel_x = 1 + }, +/obj/structure/table, +/obj/effect/turf_decal/bot, +/obj/item/hand_labeler_refill{ + pixel_x = -8; + pixel_y = 6 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supply) +"Ja" = ( +/obj/structure/table/reinforced, +/obj/machinery/door/firedoor, +/obj/structure/noticeboard/directional/south, +/obj/effect/turf_decal/bot, +/obj/item/storage/bag/tray, +/obj/item/kitchen/fork{ + pixel_x = -7; + pixel_y = 2 + }, +/turf/open/floor/iron, +/area/centcom/tdome/observation) "Jb" = ( /turf/closed/indestructible/riveted, /area/centcom/central_command_areas/prison/cells) @@ -7338,6 +7580,17 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/tdome/administration) +"JK" = ( +/obj/structure/table/wood, +/obj/item/storage/box/donkpockets{ + pixel_y = 19; + pixel_x = 5 + }, +/obj/item/storage/fancy/cigarettes/cigars/cohiba{ + pixel_y = 6 + }, +/turf/open/floor/iron/dark, +/area/centcom/central_command_areas/supplypod) "JO" = ( /obj/machinery/modular_computer/preset/id/centcom, /obj/machinery/computer/security/telescreen{ @@ -7348,16 +7601,6 @@ }, /turf/open/floor/iron/grimy, /area/centcom/central_command_areas/admin) -"JU" = ( -/obj/structure/chair{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/machinery/light/directional/west, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "JV" = ( /obj/structure/table/wood, /obj/machinery/chem_dispenser/drinks/beer{ @@ -7372,6 +7615,9 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/briefing) +"JX" = ( +/turf/open/indestructible/dark, +/area/centcom/central_command_areas/admin) "Kd" = ( /obj/effect/turf_decal/tile/red/opposingcorners, /obj/effect/turf_decal/tile/yellow/opposingcorners{ @@ -7440,6 +7686,11 @@ "KH" = ( /turf/closed/wall/mineral/titanium, /area/centcom/central_command_areas/evacuation/ship) +"KJ" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/yellow/corner, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supply) "KK" = ( /obj/structure/reagent_dispensers/fueltank, /obj/effect/turf_decal/stripes/line{ @@ -7482,6 +7733,19 @@ /obj/machinery/vending/cigarette, /turf/open/floor/iron/dark/textured_large, /area/centcom/central_command_areas/evacuation/ship) +"KP" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/light/directional/west, +/obj/effect/turf_decal/siding/dark_blue{ + dir = 4 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "KQ" = ( /turf/open/floor/plating, /area/centcom/central_command_areas/evacuation/ship) @@ -7519,6 +7783,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/evacuation/ship) +"La" = ( +/obj/effect/turf_decal/tile/dark_blue/half/contrasted, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted, +/turf/open/floor/iron/white/side{ + dir = 1 + }, +/area/centcom/central_command_areas/evacuation) "Lb" = ( /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/effect/turf_decal/tile/neutral/opposingcorners, @@ -7556,6 +7827,21 @@ /obj/structure/marker_beacon/burgundy, /turf/open/floor/catwalk_floor, /area/centcom/central_command_areas/evacuation/ship) +"Lh" = ( +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 8 + }, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 8 + }, +/obj/effect/turf_decal/tile/dark_blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/dark_blue{ + dir = 4 + }, +/turf/open/floor/iron/white/corner, +/area/centcom/central_command_areas/evacuation) "Li" = ( /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/effect/turf_decal/tile/neutral/opposingcorners, @@ -7888,12 +8174,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark/herringbone, /area/centcom/central_command_areas/evacuation/ship) -"MI" = ( -/obj/machinery/light/directional/north, -/obj/structure/table/wood, -/obj/structure/reagent_dispensers/beerkeg, -/turf/open/floor/iron/dark, -/area/centcom/central_command_areas/supplypod) "MJ" = ( /obj/structure/chair/office, /obj/effect/landmark/ert_spawn, @@ -7966,16 +8246,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/control) -"Nh" = ( -/obj/structure/table/wood, -/obj/item/storage/box/drinkingglasses, -/obj/item/reagent_containers/cup/glass/shaker, -/turf/open/floor/iron/dark, -/area/centcom/central_command_areas/supplypod) -"Nk" = ( -/obj/structure/sign/poster/contraband/syndicate_pistol, -/turf/closed/indestructible/riveted, -/area/centcom/central_command_areas/admin) "Nm" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 4 @@ -8050,15 +8320,6 @@ /obj/effect/mapping_helpers/airlock/access/all/admin/general, /turf/open/floor/iron, /area/centcom/central_command_areas/control) -"NH" = ( -/obj/structure/table/reinforced, -/obj/item/food/mint, -/obj/item/reagent_containers/condiment/enzyme{ - pixel_y = 5 - }, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/centcom/tdome/observation) "NI" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -8198,6 +8459,13 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/admin/storage) +"Os" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/yellow/corner{ + dir = 1 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supply) "Ot" = ( /obj/structure/table/reinforced, /obj/machinery/door/firedoor, @@ -8299,20 +8567,6 @@ /obj/item/kirbyplants/organic/plant21, /turf/open/floor/iron/dark/herringbone, /area/centcom/central_command_areas/evacuation/ship) -"OM" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/centcom/central_command_areas/supply) -"OO" = ( -/obj/structure/table/reinforced, -/obj/machinery/reagentgrinder{ - desc = "Used to grind things up into raw materials and liquids."; - pixel_y = 5 - }, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/centcom/tdome/observation) "OP" = ( /obj/effect/turf_decal/delivery, /turf/open/floor/iron, @@ -8379,6 +8633,10 @@ /obj/machinery/light/directional/north, /turf/open/misc/asteroid, /area/centcom/tdome/observation) +"Pa" = ( +/obj/machinery/light/floor, +/turf/open/floor/iron/white, +/area/centcom/central_command_areas/evacuation) "Pc" = ( /obj/structure/fans/tiny, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -8408,15 +8666,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/courtroom) -"Pg" = ( -/obj/machinery/computer/auxiliary_base/directional/north, -/obj/structure/table/reinforced, -/obj/item/clipboard, -/obj/item/folder/yellow, -/obj/item/pen/red, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/centcom/central_command_areas/supply) "Pk" = ( /obj/structure/table/wood, /obj/item/storage/fancy/donut_box, @@ -8522,13 +8771,6 @@ /obj/structure/sign/nanotrasen, /turf/closed/indestructible/riveted, /area/centcom/central_command_areas/admin) -"PG" = ( -/obj/effect/turf_decal/tile/blue/half/contrasted{ - dir = 4 - }, -/obj/machinery/light/floor, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "PH" = ( /obj/machinery/firealarm/directional/south, /obj/structure/closet/crate/bin, @@ -8715,12 +8957,6 @@ }, /turf/open/floor/iron, /area/centcom/tdome/observation) -"Qx" = ( -/obj/effect/turf_decal/siding/yellow{ - dir = 1 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/supply) "Qy" = ( /obj/machinery/shower/directional/west, /obj/effect/turf_decal/tile/green/anticorner/contrasted{ @@ -8767,6 +9003,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark/textured_large, /area/centcom/central_command_areas/evacuation/ship) +"QL" = ( +/obj/machinery/telecomms/allinone/nuclear, +/obj/structure/sign/poster/contraband/syndicate_pistol/directional/north, +/turf/open/indestructible/dark, +/area/centcom/central_command_areas/admin) "QM" = ( /obj/effect/turf_decal/tile/brown/anticorner/contrasted{ dir = 8 @@ -8779,6 +9020,23 @@ }, /turf/open/floor/iron, /area/centcom/central_command_areas/supplypod) +"QQ" = ( +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 4 + }, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 4 + }, +/obj/effect/turf_decal/tile/dark_blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/dark_blue{ + dir = 8 + }, +/turf/open/floor/iron/white/corner{ + dir = 1 + }, +/area/centcom/central_command_areas/evacuation) "QR" = ( /obj/structure/chair/office/light{ dir = 8 @@ -8861,10 +9119,9 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/briefing) -"Rf" = ( -/obj/item/kirbyplants/organic/plant22, -/obj/effect/turf_decal/stripes/line{ - dir = 8 +"Re" = ( +/obj/effect/turf_decal/siding/dark_blue{ + dir = 5 }, /turf/open/floor/iron, /area/centcom/central_command_areas/evacuation) @@ -8921,14 +9178,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/admin) -"Ro" = ( -/obj/structure/table/wood, -/obj/item/storage/box/donkpockets, -/obj/item/storage/fancy/cigarettes/cigars/cohiba{ - pixel_y = 3 - }, -/turf/open/floor/iron/dark, -/area/centcom/central_command_areas/supplypod) "Rp" = ( /obj/machinery/computer/communications, /turf/open/floor/iron/dark/herringbone, @@ -8956,20 +9205,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/tdome/administration) -"Rx" = ( -/obj/structure/table/reinforced, -/obj/item/reagent_containers/condiment/saltshaker{ - pixel_x = -8; - pixel_y = 5 - }, -/obj/item/reagent_containers/condiment/peppermill{ - pixel_x = -8 - }, -/obj/item/knife/kitchen, -/obj/machinery/newscaster/directional/west, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/centcom/tdome/observation) "Ry" = ( /obj/item/storage/medkit/fire, /obj/item/storage/medkit/regular{ @@ -9220,6 +9455,15 @@ /obj/machinery/computer/shuttle, /turf/open/floor/iron/dark/herringbone, /area/centcom/central_command_areas/evacuation/ship) +"SZ" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/item/papercutter{ + pixel_y = 6; + pixel_x = 2 + }, +/turf/open/floor/iron/dark, +/area/centcom/central_command_areas/supply) "Tb" = ( /obj/structure/railing/corner{ dir = 8 @@ -9265,16 +9509,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/admin) -"Tj" = ( -/obj/structure/table/reinforced, -/obj/item/reagent_containers/cup/glass/bottle/whiskey{ - pixel_y = 5 - }, -/obj/item/clothing/mask/cigarette/cigar/havana{ - pixel_x = 2 - }, -/turf/open/floor/iron, -/area/centcom/central_command_areas/supplypod) "Tl" = ( /obj/structure/table/wood, /obj/structure/plaque/static_plaque/thunderdome{ @@ -9297,14 +9531,6 @@ }, /turf/open/floor/iron/grimy, /area/centcom/central_command_areas/admin) -"Tp" = ( -/obj/structure/table/reinforced, -/obj/item/clothing/suit/apron/chef, -/obj/item/kitchen/rollingpin, -/obj/machinery/status_display/evac/directional/west, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/centcom/tdome/observation) "Tq" = ( /obj/structure/filingcabinet/filingcabinet, /obj/machinery/status_display/evac/directional/south, @@ -9324,6 +9550,13 @@ }, /turf/open/floor/iron, /area/centcom/tdome/administration) +"Tu" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/yellow/corner{ + dir = 4 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/supply) "Tv" = ( /obj/structure/table/wood, /obj/structure/window/spawner/directional/south, @@ -9392,15 +9625,6 @@ /obj/effect/light_emitter/thunderdome, /turf/open/floor/iron, /area/centcom/tdome/arena) -"TO" = ( -/obj/machinery/keycard_auth/directional/south, -/obj/structure/table/reinforced, -/obj/item/stack/package_wrap, -/obj/item/stack/cable_coil, -/obj/item/hand_labeler, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/centcom/central_command_areas/supply) "TS" = ( /obj/structure/table/wood, /obj/item/dice/d20{ @@ -9415,11 +9639,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/admin) -"TT" = ( -/obj/structure/table/reinforced, -/obj/item/storage/fancy/donut_box, -/turf/open/floor/iron, -/area/centcom/central_command_areas/supplypod) "TU" = ( /obj/machinery/computer/security{ dir = 8 @@ -9461,6 +9680,12 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/evacuation) +"Ug" = ( +/obj/machinery/barsign/all_access/directional/south, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/griddle, +/turf/open/floor/iron/dark, +/area/centcom/tdome/observation) "Uh" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 8 @@ -9547,9 +9772,6 @@ /obj/machinery/light/directional/west, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/supplypod) -"Ux" = ( -/turf/open/indestructible/hierophant, -/area/centcom/central_command_areas/admin) "Uz" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -9650,10 +9872,6 @@ /obj/effect/decal/cleanable/vomit/old, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/control) -"Vd" = ( -/obj/effect/turf_decal/tile/blue/fourcorners, -/turf/open/floor/iron, -/area/centcom/central_command_areas/evacuation) "Vf" = ( /obj/item/kirbyplants/organic/plant21{ pixel_x = -3; @@ -9679,6 +9897,19 @@ }, /turf/open/floor/iron, /area/centcom/central_command_areas/armory) +"Vh" = ( +/obj/structure/table/reinforced, +/obj/item/surgery_tray/full{ + pixel_y = 10; + pixel_x = 2 + }, +/obj/item/storage/box/masks{ + pixel_x = -6; + pixel_y = 4 + }, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/iron/white, +/area/centcom/central_command_areas/evacuation/ship) "Vi" = ( /obj/item/book/manual/wiki/security_space_law, /obj/structure/table/wood, @@ -9786,6 +10017,17 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/control) +"VE" = ( +/obj/structure/table, +/obj/item/toy/katana{ + pixel_y = 8 + }, +/obj/item/toy/plush/carpplushie, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "VF" = ( /obj/machinery/computer/crew{ dir = 4 @@ -9827,15 +10069,6 @@ /obj/effect/turf_decal/tile/brown/anticorner/contrasted, /turf/open/floor/iron, /area/centcom/central_command_areas/supplypod/loading/four) -"VT" = ( -/obj/structure/rack, -/obj/item/storage/box/donkpockets, -/obj/item/storage/box/donkpockets, -/obj/item/clothing/head/utility/chefhat, -/obj/machinery/status_display/evac/directional/west, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/centcom/tdome/observation) "VY" = ( /obj/machinery/computer/records/security{ dir = 8 @@ -9893,6 +10126,12 @@ /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/floor/iron, /area/centcom/tdome/observation) +"Wi" = ( +/obj/machinery/newscaster/directional/west, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/icecream_vat, +/turf/open/floor/iron/dark, +/area/centcom/tdome/observation) "Wl" = ( /obj/structure/table/wood, /obj/machinery/recharger, @@ -9917,6 +10156,12 @@ /obj/effect/turf_decal/tile/brown/half/contrasted, /turf/open/floor/iron, /area/centcom/central_command_areas/supplypod/loading/four) +"Wu" = ( +/obj/effect/turf_decal/siding/dark_blue/corner{ + dir = 8 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "Wv" = ( /obj/structure/chair, /obj/effect/landmark/thunderdome/observe, @@ -10353,6 +10598,19 @@ /obj/effect/mapping_helpers/airlock/access/all/admin/general, /turf/open/floor/iron/dark, /area/centcom/central_command_areas/control) +"YD" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/status_display/evac/directional/west, +/obj/effect/turf_decal/siding/dark_blue{ + dir = 4 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "YG" = ( /obj/structure/closet/emcloset, /obj/item/tank/internals/emergency_oxygen/engi, @@ -10408,6 +10666,12 @@ }, /turf/open/floor/iron/grimy, /area/centcom/central_command_areas/admin) +"YS" = ( +/obj/effect/turf_decal/siding/dark_blue{ + dir = 1 + }, +/turf/open/floor/iron, +/area/centcom/central_command_areas/evacuation) "YT" = ( /obj/structure/table/wood, /obj/structure/plaque/static_plaque/thunderdome{ @@ -10454,6 +10718,28 @@ /obj/structure/sign/nanotrasen, /turf/closed/indestructible/riveted, /area/centcom/central_command_areas/fore) +"Zc" = ( +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 4 + }, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 4 + }, +/obj/effect/turf_decal/tile/dark_blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/dark_blue{ + dir = 1 + }, +/turf/open/floor/iron/white/corner{ + dir = 8 + }, +/area/centcom/central_command_areas/evacuation) +"Zd" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/oven/range, +/turf/open/floor/iron/dark, +/area/centcom/tdome/observation) "Ze" = ( /obj/effect/turf_decal/tile/red, /turf/open/floor/iron, @@ -37631,7 +37917,7 @@ Lt aa aa Lt -Ci +Vh LI CH CH @@ -49390,9 +49676,9 @@ aa aa aa aa -Ie -tW -Ux +On +bS +JX On yO To @@ -49647,9 +49933,9 @@ aa aa aa aa -Nk -kh -tW +On +QL +JX On On Oc @@ -50160,10 +50446,10 @@ aa aa aa iX -OM +SZ mG nl -pd +zT On Rn EJ @@ -50417,10 +50703,10 @@ iX iX iN iF -Pg +eG mH nm -TO +yN On Ui JC @@ -51172,20 +51458,20 @@ aa aa aa aa -aa +Ib iF iQ -oJ -oJ -oJ -oJ -oJ -oJ -oJ -oJ -oJ -oJ -oJ +KJ +Iu +Iu +Iu +Iu +Iu +Iu +Iu +Iu +Iu +Tu ln iN zn @@ -51229,11 +51515,11 @@ oi QC aM BW -Rx -NH -Tp -OO -VT +Wi +Zd +Do +lH +og BY QC bR @@ -51429,20 +51715,20 @@ aa aa aa aa -aa +Ib iG iR -oJ -Qx +mB iO -oJ iO oJ iO oJ iO -uG oJ +iO +iO +hq lo lJ hz @@ -51491,7 +51777,7 @@ bi eI bi eI -hv +Ug QC bR KL @@ -51686,23 +51972,23 @@ aa aa aa aa -aa +Ib iG iR -oJ -Qx +mB jp -oJ jp oJ jp oJ jp -uG oJ +jp +jp +hq lo iF -XA +rj mJ lq XK @@ -51748,7 +52034,7 @@ Wf bi eI bi -cY +zv QC EI CW @@ -51943,20 +52229,20 @@ aa aa aa aa -aa +Ib iF iR -oJ -Qx +mB jp -oJ jp oJ jp oJ jp -uG oJ +jp +jp +hq EK iF iF @@ -52002,9 +52288,9 @@ Zj bi eI zw -Id -Bs -di +xA +dm +Ja QC QC xv @@ -52200,20 +52486,20 @@ aa aa aa aa -aa +Ib iG iR -oJ -Qx +mB jp -oJ jp oJ jp oJ jp -uG oJ +jp +jp +hq lp iF mi @@ -52457,20 +52743,20 @@ aa aa aa aa -aa +Ib iG iR -oJ -oJ -oJ -oJ -oJ -oJ -oJ -oJ -oJ -oJ -oJ +dc +wn +wn +wn +wn +wn +wn +wn +wn +wn +Os lo lK iR @@ -52714,20 +53000,20 @@ aa aa aa aa -aa +Ib iF iS iZ -iZ -jq +FM +IW ju eq vY jN -jQ +mv jN -iZ -iZ +FM +FM lq iF mj @@ -59169,15 +59455,15 @@ qz cg sN bL -uA -JU -xr -wK -Rf -wK -xr -JU -uA +fs +KP +YD +Gw +hs +Gw +YD +KP +Dn bL AV cg @@ -59198,7 +59484,7 @@ NO Uw NO ly -cX +tx Yn OZ HE @@ -59425,17 +59711,17 @@ qz qy cg sO -tT -us -us -us -us -us -us -us -us -us -At +sl +gQ +mr +mr +mr +mr +mr +mr +mr +Re +GU AW cg qz @@ -59455,7 +59741,7 @@ NO NO NO ly -TT +Gc Yn Yn Yn @@ -59681,19 +59967,19 @@ Hv qA qy fm -sP -tT -us -ve -vW -us -us -us -us -us -us -At -AX +gM +zN +mr +Lh +mr +mr +mr +mr +mr +mr +mr +YS +eC fm Cd cg @@ -59939,17 +60225,17 @@ qy qz cg fE -tT -us -vf -vX -vW -us -us -us -us -us -At +zN +mr +ab +Dr +mr +xq +mr +mr +mr +mr +YS aP cg qy @@ -60196,17 +60482,17 @@ qy qz cg sQ -tT -us -vf -Vd -vX -vW -us -us -us -us -At +zN +mr +ab +tY +Dr +mr +mr +mr +mr +mr +YS AY cg fm @@ -60453,17 +60739,17 @@ cg fm cg sQ -tT -us -ve -vZ -vZ -PG -vZ -vZ -yB -us -At +zN +mr +Lh +jS +jS +jS +jS +jS +Ce +mr +YS AY cg pg @@ -60710,17 +60996,17 @@ qB qW rT sO -tT -us -vg -Vd -Vd -Vd -xY -wa -zl -us -At +zN +mr +Zc +CB +tY +tY +fJ +fJ +QQ +mr +YS AW BN Cf @@ -60967,17 +61253,17 @@ qC qX rU sO -tT -us -lZ -vg -Vd -Vd -Vd -yB -lZ -us -At +zN +mr +Dg +mr +CB +Pa +Dr +mr +Dg +mr +YS DU BO Cg @@ -61224,17 +61510,17 @@ qD qY rV sO -tT -us -ve -vZ -wL -Vd -Vd -Vd -yB -us -At +zN +mr +Lh +jS +jS +tY +tY +Dr +Ce +mr +YS AW BP Cf @@ -61481,17 +61767,17 @@ cg fm cg sQ -tT -us -vg -wa -wa -dh -wa -wa -zl -us -At +zN +mr +Zc +fJ +fJ +fJ +fJ +fJ +QQ +mr +YS AY cg VY @@ -61738,17 +62024,17 @@ qz qy cg sR -tT -us -us -us -us -xt -xZ -Vd -zm -us -At +zN +mr +mr +mr +mr +mr +CB +tY +La +mr +YS AZ cg fm @@ -61995,23 +62281,23 @@ qy qz cg fE -tT -us -us -us -us -us -xt -xZ -zm -us -At +zN +mr +mr +mr +mr +mr +mr +CB +La +mr +YS aP cg qz cg -Nh -Ro +qN +JK Yn Se MP @@ -62251,23 +62537,23 @@ Hv qA qy fm -sS -tT -us -us -us -us -rq -us -xt -zl -us -At +VE +zN +mr +mr +mr +mr +Dg +mr +mr +QQ +mr +YS Bb fm Cd cg -MI +CC NO Yn Se @@ -62509,17 +62795,17 @@ qz qy cg sO -tT -us -us -us -us -us -us -us -us -us -At +Wu +zP +mr +mr +mr +mr +mr +mr +mr +bu +rC AW cg qy @@ -62767,21 +63053,21 @@ qy cg sT tU -tU -tU -tU -tU -tU -tU -tU -tU -tU +FP +bv +bv +bv +bv +bv +bv +bv +HQ tU Bc cg qz cg -sa +ft NO Yn Se @@ -63038,7 +63324,7 @@ tV cg cg cg -Tj +uS Su Yn Vk diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index d912a6ff9d6..9ce8d37d988 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -18358,9 +18358,7 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 }, -/mob/living/simple_animal/hostile/retaliate/goat{ - name = "Pete" - }, +/mob/living/basic/goat/pete, /turf/open/floor/iron/kitchen_coldroom, /area/station/service/kitchen/coldroom) "fvn" = ( @@ -19931,14 +19929,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/science/ordnance) -"gaR" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/light/small/directional/south{ - dir = 1 - }, -/turf/open/floor/plating, -/area/station/science/ordnance) "gaY" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -26377,6 +26367,16 @@ }, /turf/open/floor/iron, /area/station/cargo/miningdock) +"iyC" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 8 + }, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/security/evidence) "iyK" = ( /obj/machinery/telecomms/bus/preset_two, /turf/open/floor/iron/dark/telecomms, @@ -42017,14 +42017,9 @@ /turf/open/floor/iron/white, /area/station/science/lobby) "nUF" = ( -/obj/effect/turf_decal/box/corners, -/obj/effect/turf_decal/box/corners{ - dir = 4 - }, /obj/effect/decal/cleanable/dirt/dust, /obj/machinery/light/directional/north, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/obj/effect/landmark/bitrunning/station_reward_spawn, /turf/open/floor/iron/dark/smooth_large, /area/station/bitrunning/den) "nUM" = ( @@ -43433,6 +43428,14 @@ }, /turf/open/floor/glass/reinforced, /area/station/science/research) +"ovK" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small/directional/south{ + dir = 1 + }, +/turf/open/floor/plating, +/area/station/science/ordnance) "ovL" = ( /turf/open/floor/iron, /area/station/hallway/secondary/service) @@ -43615,6 +43618,12 @@ }, /turf/open/space/openspace, /area/station/solars/starboard/fore) +"ozB" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/cargo/miningdock) "ozM" = ( /obj/structure/table/wood/poker, /obj/item/storage/dice, @@ -45377,17 +45386,12 @@ /turf/open/floor/plating, /area/station/commons/vacant_room) "plH" = ( -/obj/effect/turf_decal/box/corners{ - dir = 8 - }, -/obj/effect/turf_decal/box/corners{ - dir = 1 - }, /obj/effect/decal/cleanable/oil/streak, /obj/structure/sign/poster/random/directional/north, /obj/machinery/power/apc/auto_name/directional/west, /obj/structure/cable, -/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/machinery/byteforge, +/obj/effect/turf_decal/box, /turf/open/floor/iron/dark/smooth_large, /area/station/bitrunning/den) "plQ" = ( @@ -53423,16 +53427,6 @@ /obj/effect/decal/cleanable/food/flour, /turf/open/floor/iron/cafeteria, /area/station/service/kitchen) -"sdO" = ( -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 8 - }, -/obj/structure/cable, -/turf/open/floor/iron/dark, -/area/station/security/evidence) "sed" = ( /obj/effect/turf_decal/trimline/dark_green/filled/line{ dir = 10 @@ -53573,7 +53567,7 @@ /turf/open/floor/iron/white, /area/station/science/lower) "sha" = ( -/mob/living/simple_animal/sloth/paperwork, +/mob/living/basic/sloth/paperwork, /turf/open/floor/glass, /area/station/cargo/storage) "shw" = ( @@ -65020,6 +65014,16 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) +"vZc" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red/opposingcorners, +/obj/effect/turf_decal/tile/blue/opposingcorners{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/service/theater) "vZB" = ( /obj/machinery/airalarm/directional/north, /turf/open/floor/wood/large, @@ -68534,12 +68538,6 @@ }, /turf/open/floor/iron, /area/station/security/brig) -"xuo" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/cargo/miningdock) "xuq" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 4 @@ -69834,16 +69832,6 @@ /obj/machinery/light/small/dim/directional/south, /turf/open/floor/iron, /area/station/maintenance/tram/mid) -"xVb" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red/opposingcorners, -/obj/effect/turf_decal/tile/blue/opposingcorners{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/service/theater) "xVp" = ( /obj/structure/cable, /turf/open/floor/wood, @@ -119253,7 +119241,7 @@ aac aac pCL rci -xuo +ozB iyq pCL aac @@ -123418,7 +123406,7 @@ qAl nMB ryI frV -gaR +ovK lwt gaO mWp @@ -159069,7 +159057,7 @@ abM tFJ voL mNy -sdO +iyC dGn jKq wqu @@ -170397,7 +170385,7 @@ abM abM lZW eDV -xVb +vZc iZn dME evW diff --git a/_maps/shuttles/pirate_geode.dmm b/_maps/shuttles/pirate_geode.dmm index d2e8f034f48..693b7c8635f 100644 --- a/_maps/shuttles/pirate_geode.dmm +++ b/_maps/shuttles/pirate_geode.dmm @@ -127,21 +127,19 @@ }, /turf/open/floor/plating, /area/shuttle/pirate) +"iG" = ( +/obj/effect/spawner/structure/window/hollow/survival_pod, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "geodebridge"; + dir = 4 + }, +/turf/open/misc/dirt/station, +/area/shuttle/pirate) "jh" = ( /turf/open/floor/catwalk_floor, /area/shuttle/pirate) -"jt" = ( -/obj/machinery/power/terminal{ - dir = 8 - }, -/turf/closed/mineral/random/jungle{ - baseturfs = /turf/open/misc/dirt - }, -/area/shuttle/pirate) "jx" = ( -/turf/closed/mineral/random/jungle{ - baseturfs = /turf/open/misc/dirt - }, +/turf/closed/mineral/random/jungle/space_safe, /area/shuttle/pirate) "jD" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -465,7 +463,6 @@ /turf/open/floor/plating, /area/shuttle/pirate) "xg" = ( -/obj/structure/grille, /obj/effect/spawner/structure/window/hollow/survival_pod, /obj/structure/barricade/wooden/crude, /turf/open/misc/dirt/station, @@ -515,11 +512,6 @@ /obj/structure/reagent_dispensers/watertank, /turf/open/misc/dirt/station, /area/shuttle/pirate) -"At" = ( -/turf/closed/mineral/random/jungle{ - baseturfs = null - }, -/area/shuttle/pirate) "AT" = ( /obj/effect/turf_decal/lunar_sand/plating, /obj/docking_port/mobile/pirate{ @@ -864,14 +856,6 @@ }, /turf/open/misc/dirt/station, /area/shuttle/pirate) -"Qg" = ( -/obj/structure/grille, -/obj/effect/spawner/structure/window/hollow/survival_pod, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "geodebridge" - }, -/turf/open/misc/dirt/station, -/area/shuttle/pirate) "Qo" = ( /turf/open/floor/iron/stairs{ dir = 1 @@ -948,7 +932,6 @@ /obj/effect/turf_decal/lunar_sand/plating, /obj/structure/barricade/wooden/crude, /obj/effect/spawner/structure/window/hollow/survival_pod, -/obj/structure/grille, /turf/open/floor/plating, /area/shuttle/pirate) "Un" = ( @@ -963,7 +946,6 @@ /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/shuttle/pirate) "UM" = ( -/obj/structure/grille, /obj/effect/spawner/structure/window/hollow/survival_pod, /turf/open/misc/dirt/station, /area/shuttle/pirate) @@ -1050,11 +1032,11 @@ mv Od Pq Pq -At +jx Pq Pq Pq -At +jx Pq Pq Od @@ -1066,8 +1048,8 @@ lt (3,1,1) = {" lt lt -At -At +jx +jx Od Uf Uf @@ -1079,8 +1061,8 @@ Od Uf Uf Od -At -At +jx +jx lt lt "} @@ -1212,7 +1194,7 @@ jx "} (10,1,1) = {" lt -jt +jx Od DT ZF @@ -1407,9 +1389,9 @@ jx jx Od Od -Qg -Qg -Qg +iG +iG +iG Od Od Od diff --git a/_maps/virtual_domains/beach_bar.dmm b/_maps/virtual_domains/beach_bar.dmm index 408d3c0cda1..29fe04d8283 100644 --- a/_maps/virtual_domains/beach_bar.dmm +++ b/_maps/virtual_domains/beach_bar.dmm @@ -159,7 +159,7 @@ pixel_x = -8; pixel_y = -1 }, -/obj/item/reagent_containers/cup/glass/drinkingglass/virtual_domain{ +/obj/item/reagent_containers/cup/glass/drinkingglass/filled/virtual_domain{ pixel_y = 8; pixel_x = 5 }, @@ -424,8 +424,8 @@ /area/virtual_domain/powered) "uq" = ( /obj/structure/table/wood, -/obj/item/reagent_containers/cup/glass/drinkingglass/virtual_domain, -/obj/item/reagent_containers/cup/glass/drinkingglass/virtual_domain{ +/obj/item/reagent_containers/cup/glass/drinkingglass/filled/virtual_domain, +/obj/item/reagent_containers/cup/glass/drinkingglass/filled/virtual_domain{ pixel_x = -4; pixel_y = 8 }, @@ -878,11 +878,11 @@ /area/virtual_domain/powered) "Mp" = ( /obj/structure/table/wood, -/obj/item/reagent_containers/cup/glass/drinkingglass/virtual_domain{ +/obj/item/reagent_containers/cup/glass/drinkingglass/filled/virtual_domain{ pixel_y = 7; pixel_x = 4 }, -/obj/item/reagent_containers/cup/glass/drinkingglass/virtual_domain, +/obj/item/reagent_containers/cup/glass/drinkingglass/filled/virtual_domain, /turf/open/floor/wood, /area/virtual_domain/powered) "Mw" = ( diff --git a/code/__DEFINES/ai/ai.dm b/code/__DEFINES/ai/ai.dm index 467fc9d7c0f..83d7e7f6a5f 100644 --- a/code/__DEFINES/ai/ai.dm +++ b/code/__DEFINES/ai/ai.dm @@ -32,6 +32,8 @@ #define CAN_ACT_WHILE_DEAD (1<<1) /// Stop processing while in a progress bar #define PAUSE_DURING_DO_AFTER (1<<2) +/// Continue processing while in stasis +#define CAN_ACT_IN_STASIS (1<<3) //Base Subtree defines diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index 24ecf0a19f6..3877bc689d5 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -54,6 +54,9 @@ /// Generic key for a non-specific action #define BB_GENERIC_ACTION "BB_generic_action" +/// Generic key for a shapeshifting action +#define BB_SHAPESHIFT_ACTION "BB_shapeshift_action" + ///How long have we spent with no target? #define BB_TARGETLESS_TIME "BB_targetless_time" @@ -77,8 +80,8 @@ ///List of mobs who have damaged us #define BB_BASIC_MOB_RETALIATE_LIST "BB_basic_mob_shitlist" -/// Flag to set on or off if you want your mob to prioritise running away -#define BB_BASIC_MOB_FLEEING "BB_basic_fleeing" +/// Flag to set on if you want your mob to STOP running away +#define BB_BASIC_MOB_STOP_FLEEING "BB_basic_stop_fleeing" ///list of foods this mob likes #define BB_BASIC_FOODS "BB_basic_foods" diff --git a/code/__DEFINES/ai/monsters.dm b/code/__DEFINES/ai/monsters.dm index be9a4be34cd..89670d4f346 100644 --- a/code/__DEFINES/ai/monsters.dm +++ b/code/__DEFINES/ai/monsters.dm @@ -147,6 +147,22 @@ /// key holds the tray we will beam #define BB_BEAMABLE_HYDROPLANT_TARGET "beamable_hydroplant_target" +//ice demons +///the list of items we are afraid of +#define BB_LIST_SCARY_ITEMS "list_scary_items" +///our teleportation ability +#define BB_DEMON_TELEPORT_ABILITY "demon_teleport_ability" +///the destination of our teleport ability +#define BB_TELEPORT_DESTINATION "teleport_destination" +///the ability to clone ourself +#define BB_DEMON_CLONE_ABILITY "demon_clone_ability" +///our slippery ice ability +#define BB_DEMON_SLIP_ABILITY "demon_slip_ability" +///the turf we are escaping too +#define BB_ESCAPE_DESTINATION "escape_destination" +///how far away we will be from our target before teleporting +#define BB_MINIMUM_DISTANCE_RANGE "minimum_distance_range" + /// Corpse we have consumed #define BB_LEGION_CORPSE "legion_corpse" /// Things our target recently said diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index caff9c319e2..cc9412208fb 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -274,6 +274,8 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define BODY_ZONE_L_LEG "l_leg" #define BODY_ZONE_R_LEG "r_leg" +GLOBAL_LIST_INIT(arm_zones, list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + #define BODY_ZONE_PRECISE_EYES "eyes" #define BODY_ZONE_PRECISE_MOUTH "mouth" #define BODY_ZONE_PRECISE_GROIN "groin" diff --git a/code/__DEFINES/configuration.dm b/code/__DEFINES/configuration.dm index 81965514fcb..477bed243c1 100644 --- a/code/__DEFINES/configuration.dm +++ b/code/__DEFINES/configuration.dm @@ -20,3 +20,11 @@ #define KEY_MODE_TEXT 0 #define KEY_MODE_TYPE 1 + +// Flags for respawn config +/// Respawn not allowed +#define RESPAWN_FLAG_DISABLED 0 +/// Respawn as much as you'd like +#define RESPAWN_FLAG_FREE 1 +/// Can respawn, but not as the same character +#define RESPAWN_FLAG_NEW_CHARACTER 2 diff --git a/code/__DEFINES/dcs/signals/signals_bitrunning.dm b/code/__DEFINES/dcs/signals/signals_bitrunning.dm index 3d008449ee7..957e61ae303 100644 --- a/code/__DEFINES/dcs/signals/signals_bitrunning.dm +++ b/code/__DEFINES/dcs/signals/signals_bitrunning.dm @@ -29,3 +29,6 @@ /// from /obj/machinery/quantum_server/refreshParts(): (servo rating) #define COMSIG_BITRUNNER_SERVER_UPGRADED "bitrunner_server_upgraded" + +/// from /obj/machinery/quantum_server/scrub_vdom() +#define COMSIG_BITRUNNER_DOMAIN_SCRUBBED "bitrunner_domain_scrubbed" diff --git a/code/__DEFINES/dcs/signals/signals_fish.dm b/code/__DEFINES/dcs/signals/signals_fish.dm index 90e580e9166..a40e731fc7b 100644 --- a/code/__DEFINES/dcs/signals/signals_fish.dm +++ b/code/__DEFINES/dcs/signals/signals_fish.dm @@ -31,3 +31,6 @@ /// Sent when the challenge is to be interrupted: (reason) #define COMSIG_FISHING_SOURCE_INTERRUPT_CHALLENGE "fishing_spot_interrupt_challenge" + +/// From /obj/item/fish_analyzer/proc/analyze_status: (fish, user) +#define COMSIG_FISH_ANALYZER_ANALYZE_STATUS "fish_analyzer_analyze_status" diff --git a/code/__DEFINES/dcs/signals/signals_global.dm b/code/__DEFINES/dcs/signals/signals_global.dm index c75b169b90d..9ccd3fd7267 100644 --- a/code/__DEFINES/dcs/signals/signals_global.dm +++ b/code/__DEFINES/dcs/signals/signals_global.dm @@ -77,8 +77,8 @@ /// global signal sent when a nuclear device is detonating (/obj/machinery/nuclearbomb/nuke/exploding_nuke) #define COMSIG_GLOB_NUKE_DEVICE_DETONATING "!nuclear_device_detonating" -/// Global signal sent when a light mechanism is completed (try_id) -#define COMSIG_GLOB_LIGHT_MECHANISM_COMPLETED "!light_mechanism_completed" +/// Global signal sent when a puzzle piece is completed (light mechanism, etc.) (try_id) +#define COMSIG_GLOB_PUZZLE_COMPLETED "!puzzle_completed" /// Global signal called after the station changes its name. /// (new_name, old_name) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm index c96d21b7163..ad0e6e359b1 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -36,6 +36,9 @@ #define COMSIG_BODYPART_ATTACHED "bodypart_removed" ///from base of /obj/item/bodypart/proc/try_attach_limb(): (new_limb, special) #define COMSIG_CARBON_POST_ATTACH_LIMB "carbon_post_attach_limb" +///from /obj/item/bodypart/proc/receive_damage, sent from the limb owner (limb, brute, burn) +#define COMSIG_CARBON_LIMB_DAMAGED "carbon_limb_damaged" + #define COMPONENT_PREVENT_LIMB_DAMAGE (1 << 0) /// from /obj/item/bodypart/proc/apply_gauze(/obj/item/stack/gauze): (/obj/item/stack/medical/gauze/applied_gauze, /obj/item/stack/medical/gauze/stack_used) #define COMSIG_BODYPART_GAUZED "bodypart_gauzed" /// from /obj/item/stack/medical/gauze/Destroy(): (/obj/item/stack/medical/gauze/removed_gauze) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index 273b9f216c7..a6c5fdbf793 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -55,6 +55,35 @@ ///from base of element/bane/activate(): (item/weapon, mob/user) #define COMSIG_OBJECT_ON_BANING "obj_on_baning" +// adjust_x_loss messages sent from /mob/living/proc/adjust[x]Loss +/// Returned from all the following messages if you actually aren't going to apply any change +#define COMPONENT_IGNORE_CHANGE (1<<0) +// Each of these messages sends the damagetype even though it is inferred by the signal so you can pass all of them to the same proc if required +/// Send when bruteloss is modified (type, amount, forced) +#define COMSIG_LIVING_ADJUST_BRUTE_DAMAGE "living_adjust_brute_damage" +/// Send when fireloss is modified (type, amount, forced) +#define COMSIG_LIVING_ADJUST_BURN_DAMAGE "living_adjust_burn_damage" +/// Send when oxyloss is modified (type, amount, forced) +#define COMSIG_LIVING_ADJUST_OXY_DAMAGE "living_adjust_oxy_damage" +/// Send when toxloss is modified (type, amount, forced) +#define COMSIG_LIVING_ADJUST_TOX_DAMAGE "living_adjust_tox_damage" +/// Send when cloneloss is modified (type, amount, forced) +#define COMSIG_LIVING_ADJUST_CLONE_DAMAGE "living_adjust_clone_damage" +/// Send when staminaloss is modified (type, amount, forced) +#define COMSIG_LIVING_ADJUST_STAMINA_DAMAGE "living_adjust_stamina_damage" + +/// List of signals sent when you receive any damage except stamina +#define COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES list(\ + COMSIG_LIVING_ADJUST_BRUTE_DAMAGE,\ + COMSIG_LIVING_ADJUST_BURN_DAMAGE,\ + COMSIG_LIVING_ADJUST_CLONE_DAMAGE,\ + COMSIG_LIVING_ADJUST_OXY_DAMAGE,\ + COMSIG_LIVING_ADJUST_TOX_DAMAGE,\ +) +/// List of signals sent when you receive any kind of damage at all +#define COMSIG_LIVING_ADJUST_ALL_DAMAGE_TYPES (COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES + COMSIG_LIVING_ADJUST_STAMINA_DAMAGE) + + /// from base of mob/living/updatehealth() #define COMSIG_LIVING_HEALTH_UPDATE "living_health_update" ///from base of mob/living/death(): (gibbed) @@ -179,3 +208,10 @@ /// From /datum/ai/behavior/climb_tree/perform() : (mob/living/basic/living_pawn) #define COMSIG_LIVING_CLIMB_TREE "living_climb_tree" + +/// Sent on a mob from /datum/component/mob_chain when component is attached with it as the "front" : (mob/living/basic/tail) +#define COMSIG_MOB_GAINED_CHAIN_TAIL "living_gained_chain_tail" +/// Sent on a mob from /datum/component/mob_chain when component is detached from it as the "front" : (mob/living/basic/tail) +#define COMSIG_MOB_LOST_CHAIN_TAIL "living_detached_chain_tail" +/// Sent from a 'contract chain' button on a mob chain +#define COMSIG_MOB_CHAIN_CONTRACT "living_chain_contracted" diff --git a/code/__DEFINES/footsteps.dm b/code/__DEFINES/footsteps.dm index d77a0e1cab3..c8b89b082a4 100644 --- a/code/__DEFINES/footsteps.dm +++ b/code/__DEFINES/footsteps.dm @@ -25,6 +25,7 @@ #define FOOTSTEP_MOB_SHOE "footstep_shoe" #define FOOTSTEP_MOB_HUMAN "footstep_human" //Warning: Only works on /mob/living/carbon/human #define FOOTSTEP_MOB_SLIME "footstep_slime" +#define FOOTSTEP_MOB_RUST "footstep_rust" #define FOOTSTEP_OBJ_MACHINE "footstep_machine" #define FOOTSTEP_OBJ_ROBOT "footstep_robot" diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index b775b948c87..901e3c4d90f 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -12,7 +12,7 @@ #define isweakref(D) (istype(D, /datum/weakref)) GLOBAL_VAR_INIT(magic_appearance_detecting_image, new /image) // appearances are awful to detect safely, but this seems to be the best way ~ninjanomnom -#define isappearance(thing) (!ispath(thing) && istype(GLOB.magic_appearance_detecting_image, thing)) +#define isappearance(thing) (!istype(thing, /image) && !ispath(thing) && istype(GLOB.magic_appearance_detecting_image, thing)) #define isgenerator(A) (istype(A, /generator)) @@ -181,7 +181,7 @@ GLOBAL_LIST_INIT(turfs_pass_meteor, typecacheof(list( #define isclown(A) (istype(A, /mob/living/basic/clown)) -#define isspider(A) (istype(A, /mob/living/basic/spider/giant)) +#define isspider(A) (istype(A, /mob/living/basic/spider)) //Misc mobs diff --git a/code/__DEFINES/reagents.dm b/code/__DEFINES/reagents.dm index dda31ee2adc..3fb32011a1d 100644 --- a/code/__DEFINES/reagents.dm +++ b/code/__DEFINES/reagents.dm @@ -85,12 +85,8 @@ #define DEFAULT_REAGENT_TEMPERATURE 300 //Used in holder.dm/equlibrium.dm to set values and volume limits -///stops floating point errors causing issues with checking reagent amounts +///the minimum volume of reagents than can be operated on. #define CHEMICAL_QUANTISATION_LEVEL 0.0001 -///The smallest amount of volume allowed - prevents tiny numbers -#define CHEMICAL_VOLUME_MINIMUM 0.001 -///Round to this, to prevent extreme decimal magic and to keep reagent volumes in line with perceived values. -#define CHEMICAL_VOLUME_ROUNDING 0.01 ///Default pH for reagents datum #define CHEMICAL_NORMAL_PH 7.000 ///The maximum temperature a reagent holder can attain diff --git a/code/__DEFINES/research/anomalies.dm b/code/__DEFINES/research/anomalies.dm index 911a2958d89..12a114439c7 100644 --- a/code/__DEFINES/research/anomalies.dm +++ b/code/__DEFINES/research/anomalies.dm @@ -32,6 +32,7 @@ GLOBAL_LIST_INIT(bioscrambler_parts_blacklist, typecacheof(list( GLOBAL_LIST_INIT(bioscrambler_organs_blacklist, typecacheof(list ( /obj/item/organ/external/pod_hair, /obj/item/organ/external/spines, + /obj/item/organ/external/wings, /obj/item/organ/external/wings/functional, /obj/item/organ/internal/alien, /obj/item/organ/internal/brain, diff --git a/code/__DEFINES/text.dm b/code/__DEFINES/text.dm index 751fe7c2b58..a0df5e24eb7 100644 --- a/code/__DEFINES/text.dm +++ b/code/__DEFINES/text.dm @@ -84,6 +84,10 @@ #define FLESH_SCAR_FILE "wounds/flesh_scar_desc.json" /// File location for bone wound descriptions #define BONE_SCAR_FILE "wounds/bone_scar_desc.json" +// SKYRAT EDIT ADDITION BEGIN - SYNTH WOUNDS +/// File location for metalic wound descriptions +#define METAL_SCAR_FILE "wounds/metal_scar_desc.json" +// SKYRAT EDIT ADDITION END /// File location for scar wound descriptions #define SCAR_LOC_FILE "wounds/scar_loc.json" /// File location for exodrone descriptions diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm index 19ccd843dd4..14067fbcd6a 100644 --- a/code/__DEFINES/wounds.dm +++ b/code/__DEFINES/wounds.dm @@ -124,10 +124,15 @@ GLOBAL_LIST_INIT(bio_state_anatomy, list( /// Generic loss wounds. See loss.dm #define WOUND_SERIES_LOSS_BASIC "wound_series_loss_basic" -// SKYRAT EDIT ADDITION BEGIN - MUSCLE WOUNDS +// SKYRAT EDIT ADDITION BEGIN - MUSCLE AND SYNTH WOUNDS // Have to put it here so I can use it in the global list of wound series -/// See muscle.dm -#define WOUND_SERIES_MUSCLE_DAMAGE "skyrat_wound_series_muscle_damage" // We use a super high number as realistically speaking TG will never increment to this amount of wound series +/// See muscle.dm and robotic_blunt.dm +#define WOUND_SERIES_MUSCLE_DAMAGE "skyrat_wound_series_muscle_damage" + +#define WOUND_SERIES_METAL_BLUNT_BASIC "wound_series_metal_blunt_basic" +#define WOUND_SERIES_METAL_BURN_OVERHEAT "wound_series_metal_burn_basic" +#define WOUND_SERIES_WIRE_SLASH_ELECTRICAL_DAMAGE "wound_series_metal_slash_electrical_damage_basic" +#define WOUND_SERIES_WIRE_PIERCE_ELECTRICAL_DAMAGE "wound_series_metal_pierce_electrical_damage_basic" // SKYRAT EDIT ADDITION END /// A assoc list of (wound typepath -> wound_pregen_data instance). Every wound should have a pregen data. @@ -203,17 +208,23 @@ GLOBAL_LIST_INIT(wounding_types_to_series, list( WOUND_BLUNT = list( WOUND_SERIES_BONE_BLUNT_BASIC, WOUND_SERIES_MUSCLE_DAMAGE, // SKYRAT EDIT -- MUSCLE WOUNDS + WOUND_SERIES_METAL_BLUNT_BASIC, // SKYRAT EDIT ADDITION - SYNTH WOUNDS + ), WOUND_SLASH = list( WOUND_SERIES_FLESH_SLASH_BLEED, - WOUND_SERIES_MUSCLE_DAMAGE, // SKYRAT EDIT -- MUSCLE WOUNDS + WOUND_SERIES_MUSCLE_DAMAGE, // SKYRAT EDIT ADDITION - MUSCLE WOUNDS + WOUND_SERIES_WIRE_SLASH_ELECTRICAL_DAMAGE, // SKYRAT EDIT ADDITION - SYNTH WOUNDS + ), WOUND_BURN = list( WOUND_SERIES_FLESH_BURN_BASIC, + WOUND_SERIES_METAL_BURN_OVERHEAT, // SKYRAT EDIT ADDITION - SYNTH WOUNDS ), WOUND_PUNCTURE = list( WOUND_SERIES_FLESH_PUNCTURE_BLEED, - WOUND_SERIES_MUSCLE_DAMAGE, // SKYRAT EDIT -- MUSCLE WOUNDS + WOUND_SERIES_MUSCLE_DAMAGE, // SKYRAT EDIT ADDITION - MUSCLE WOUNDS + WOUND_SERIES_WIRE_PIERCE_ELECTRICAL_DAMAGE, // SKYRAT EDIT ADDITION - SYNTH WOUNDS ), )) @@ -284,7 +295,8 @@ GLOBAL_LIST_INIT(wounding_types_to_series, list( /// Assoc list of biotype -> ideal scar file to be used and grab stuff from. GLOBAL_LIST_INIT(biotypes_to_scar_file, list( "[BIO_FLESH]" = FLESH_SCAR_FILE, - "[BIO_BONE]" = BONE_SCAR_FILE + "[BIO_BONE]" = BONE_SCAR_FILE, + "[BIO_METAL]" = METAL_SCAR_FILE // SKYRAT EDIT ADDITION - METAL SCARS (see robotic_blunt.dm) )) // ~burn wound infection defines diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 2fd384e69a9..8239dc29231 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -31,19 +31,6 @@ GLOBAL_LIST_EMPTY(deliverybeacontags) /// List of all singularity components that exist GLOBAL_LIST_EMPTY_TYPED(singularities, /datum/component/singularity) -/// list of all /datum/chemical_reaction datums indexed by their typepath. Use this for general lookup stuff -GLOBAL_LIST(chemical_reactions_list) -/// list of all /datum/chemical_reaction datums. Used during chemical reactions. Indexed by REACTANT types -GLOBAL_LIST(chemical_reactions_list_reactant_index) -/// list of all /datum/chemical_reaction datums. Used for the reaction lookup UI. Indexed by PRODUCT type -GLOBAL_LIST(chemical_reactions_list_product_index) /// list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff -GLOBAL_LIST_INIT(chemical_reagents_list, init_chemical_reagent_list()) -/// names of reagents used by plumbing UI. -GLOBAL_LIST_INIT(chemical_name_list, init_chemical_name_list()) -/// List of all reactions with their associated product and result ids. Used for reaction lookups -GLOBAL_LIST(chemical_reactions_results_lookup_list) -/// List of all reagents that are parent types used to define a bunch of children - but aren't used themselves as anything. -GLOBAL_LIST(fake_reagent_blacklist) /// list of all /datum/tech datums indexed by id. GLOBAL_LIST_EMPTY(tech_list) /// list of all surgeries by name, associated with their path. diff --git a/code/_globalvars/lists/reagents.dm b/code/_globalvars/lists/reagents.dm new file mode 100644 index 00000000000..dec2724cfeb --- /dev/null +++ b/code/_globalvars/lists/reagents.dm @@ -0,0 +1,154 @@ +/// list of all /datum/chemical_reaction datums indexed by their typepath. Use this for general lookup stuff +GLOBAL_LIST(chemical_reactions_list) +/// list of all /datum/chemical_reaction datums. Used during chemical reactions. Indexed by REACTANT types +GLOBAL_LIST(chemical_reactions_list_reactant_index) +/// list of all /datum/chemical_reaction datums. Used for the reaction lookup UI. Indexed by PRODUCT type +GLOBAL_LIST(chemical_reactions_list_product_index) +/// list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff +GLOBAL_LIST_INIT(chemical_reagents_list, init_chemical_reagent_list()) +/// list of all reactions with their associated product and result ids. Used for reaction lookups +GLOBAL_LIST(chemical_reactions_results_lookup_list) +/// list of all reagents that are parent types used to define a bunch of children - but aren't used themselves as anything. +GLOBAL_LIST(fake_reagent_blacklist) +/// Turfs metalgen cant touch +GLOBAL_LIST_INIT(blacklisted_metalgen_types, typecacheof(list( + /turf/closed/indestructible, //indestructible turfs should be indestructible, metalgen transmutation to plasma allows them to be destroyed + /turf/open/indestructible +))) +/// Names of human readable reagents used by plumbing UI. +GLOBAL_LIST_INIT(chemical_name_list, init_chemical_name_list()) +/// Map of reagent names to its datum path +GLOBAL_LIST_INIT(name2reagent, build_name2reagentlist()) + +/// Initialises all /datum/reagent into a list indexed by reagent id +/proc/init_chemical_reagent_list() + var/list/reagent_list = list() + + for(var/datum/reagent/path as anything in subtypesof(/datum/reagent)) + if(path in GLOB.fake_reagent_blacklist) + continue + var/datum/reagent/target_object = new path() + target_object.mass = rand(10, 800) + reagent_list[path] = target_object + + return reagent_list + +/// Creates an list which is indexed by reagent name . used by plumbing reaction chamber and chemical filter UI +/proc/init_chemical_name_list() + var/list/name_list = list() + + for(var/X in GLOB.chemical_reagents_list) + var/datum/reagent/Reagent = GLOB.chemical_reagents_list[X] + name_list += Reagent.name + + return sort_list(name_list) + +/** + * Chemical Reactions - Initialises all /datum/chemical_reaction into a list + * It is filtered into multiple lists within a list. + * For example: + * chemical_reactions_list_reactant_index[/datum/reagent/toxin/plasma] is a list of all reactions relating to plasma + * For chemical reaction list product index - indexes reactions based off the product reagent type - see get_recipe_from_reagent_product() in helpers + * For chemical reactions list lookup list - creates a bit list of info passed to the UI. This is saved to reduce lag from new windows opening, since it's a lot of data. + */ +/proc/build_chemical_reactions_lists() + if(GLOB.chemical_reactions_list_reactant_index) + return + + //Prevent these reactions from appearing in lookup tables (UI code) + var/list/blacklist = typecacheof(/datum/chemical_reaction/randomized) + + //Randomized need to go last since they need to check against conflicts with normal recipes + var/paths = subtypesof(/datum/chemical_reaction) - typesof(/datum/chemical_reaction/randomized) + subtypesof(/datum/chemical_reaction/randomized) + GLOB.chemical_reactions_list = list() //typepath to reaction list + GLOB.chemical_reactions_list_reactant_index = list() //reagents to reaction list + GLOB.chemical_reactions_results_lookup_list = list() //UI glob + GLOB.chemical_reactions_list_product_index = list() //product to reaction list + + var/list/datum/chemical_reaction/reactions = list() + for(var/path in paths) + var/datum/chemical_reaction/reaction = new path() + reactions += reaction + + // Ok so we're gonna do a thingTM here + // I want to distribute all our reactions such that each reagent id links to as few as possible + // I get the feeling there's a canonical way of doing this, but I don't know it + // So instead, we're gonna wing it + var/list/reagent_to_react_count = list() + for(var/datum/chemical_reaction/reaction as anything in reactions) + for(var/reagent_id as anything in reaction.required_reagents) + reagent_to_react_count[reagent_id] += 1 + + var/list/reaction_lookup = GLOB.chemical_reactions_list_reactant_index + // Create filters based on a random reagent id in the required reagents list - this is used to speed up handle_reactions() + // Basically, we only really need to care about ONE reagent, at least when initially filtering, since any others are ignorable + // Doing this separately because it relies on the loop above, and this is easier to parse + for(var/datum/chemical_reaction/reaction as anything in reactions) + var/preferred_id = null + for(var/reagent_id as anything in reaction.required_reagents) + if(isnull(preferred_id)) + preferred_id = reagent_id + continue + // If we would have less then they would, take it + if(length(reaction_lookup[reagent_id]) < length(reaction_lookup[preferred_id])) + preferred_id = reagent_id + continue + // If they potentially have more then us, we take it + if(reagent_to_react_count[reagent_id] < reagent_to_react_count[preferred_id]) + preferred_id = reagent_id + continue + if (!isnull(preferred_id)) + if(!reaction_lookup[preferred_id]) + reaction_lookup[preferred_id] = list() + reaction_lookup[preferred_id] += reaction + + for(var/datum/chemical_reaction/reaction as anything in reactions) + var/list/product_ids = list() + var/list/reagents = list() + var/list/product_names = list() + var/bitflags = reaction.reaction_tags + + if(!length(reaction.required_reagents)) //Skip impossible reactions + continue + + GLOB.chemical_reactions_list[reaction.type] = reaction + + for(var/reagent_path in reaction.required_reagents) + var/datum/reagent/reagent = find_reagent_object_from_type(reagent_path) + if(!istype(reagent)) + stack_trace("Invalid reagent found in [reaction] required_reagents: [reagent_path]") + continue + reagents += list(list("name" = reagent.name, "id" = reagent.type)) + + for(var/product in reaction.results) + var/datum/reagent/reagent = find_reagent_object_from_type(product) + if(!istype(reagent)) + stack_trace("Invalid reagent found in [reaction] results: [product]") + continue + product_names += reagent.name + product_ids += product + + var/product_name + if(!length(product_names)) + var/list/names = splittext("[reaction.type]", "/") + product_name = names[names.len] + else + product_name = product_names[1] + + if(!is_type_in_typecache(reaction.type, blacklist)) + //Master list of ALL reactions that is used in the UI lookup table. This is expensive to make, and we don't want to lag the server by creating it on UI request, so it's cached to send to UIs instantly. + GLOB.chemical_reactions_results_lookup_list += list(list("name" = product_name, "id" = reaction.type, "bitflags" = bitflags, "reactants" = reagents)) + + // Create filters based on each reagent id in the required reagents list - this is specifically for finding reactions from product(reagent) ids/typepaths. + for(var/id in product_ids) + if(!GLOB.chemical_reactions_list_product_index[id]) + GLOB.chemical_reactions_list_product_index[id] = list() + GLOB.chemical_reactions_list_product_index[id] += reaction + +/// Builds map of reagent name to its datum path +/proc/build_name2reagentlist() + . = list() + for (var/datum/reagent/R as anything in subtypesof(/datum/reagent)) + var/name = initial(R.name) + if (length(name)) + .[ckey(name)] = R diff --git a/code/_globalvars/phobias.dm b/code/_globalvars/phobias.dm index a913410214d..f9a878c3da9 100644 --- a/code/_globalvars/phobias.dm +++ b/code/_globalvars/phobias.dm @@ -72,7 +72,6 @@ GLOBAL_LIST_INIT(phobia_mobs, list( "doctors" = typecacheof(list(/mob/living/simple_animal/bot/medbot)), "heresy" = typecacheof(list( /mob/living/basic/heretic_summon, - /mob/living/simple_animal/hostile/heretic_summon, )), "insects" = typecacheof(list( /mob/living/basic/cockroach, @@ -99,7 +98,6 @@ GLOBAL_LIST_INIT(phobia_mobs, list( /mob/living/simple_animal/bot/mulebot/paranormal, /mob/living/simple_animal/hostile/construct, /mob/living/simple_animal/hostile/dark_wizard, - /mob/living/simple_animal/hostile/heretic_summon, /mob/living/simple_animal/hostile/skeleton, /mob/living/simple_animal/hostile/wizard, /mob/living/simple_animal/hostile/zombie, diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 95697862b3c..3d632a99f73 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -73,10 +73,6 @@ if(world.time <= next_move) return - if(aicamera.in_camera_mode) - aicamera.toggle_camera_mode(sound = FALSE) - aicamera.captureimage(pixel_turf, usr) - return if(waypoint_mode) waypoint_mode = 0 set_waypoint(A) diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index 92340c59bc9..8cc8603f552 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -48,11 +48,6 @@ face_atom(A) // change direction to face what you clicked on - if(aicamera.in_camera_mode) //Cyborg picture taking - aicamera.toggle_camera_mode(sound = FALSE) - aicamera.captureimage(A, usr) - return - var/obj/item/W = get_active_held_item() if(!W && get_dist(src,A) <= interaction_range) diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index b5fc855da31..16791b7fd7e 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -262,10 +262,25 @@ /datum/config_entry/string/hostedby -/datum/config_entry/flag/norespawn - +/// Determines if a player can respawn after dying. +/// 0 / RESPAWN_FLAG_DISABLED = Cannot respawn (default) +/// 1 / RESPAWN_FLAG_FREE = Can respawn +/// 2 / RESPAWN_FLAG_NEW_CHARACTER = Can respawn if choosing a different character +/datum/config_entry/flag/allow_respawn + default = RESPAWN_FLAG_DISABLED + +/datum/config_entry/flag/allow_respawn/ValidateAndSet(str_val) + if(!VASProcCallGuard(str_val)) + return FALSE + var/val_as_num = text2num(str_val) + if(val_as_num in list(RESPAWN_FLAG_DISABLED, RESPAWN_FLAG_FREE, RESPAWN_FLAG_NEW_CHARACTER)) + config_entry_value = val_as_num + return TRUE + return FALSE + +/// Determines how long (in deciseconds) before a player is allowed to respawn. /datum/config_entry/number/respawn_delay - default = 0 + default = 0 SECONDS /datum/config_entry/flag/usewhitelist diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index 488debb48e5..1de3f900c8c 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -452,7 +452,7 @@ SUBSYSTEM_DEF(air) border += item net.air.volume += item.volume - item.parent = net + item.replace_pipenet(item.parent, net) if(item.air_temporary) net.air.merge(item.air_temporary) diff --git a/code/controllers/subsystem/processing/quirks.dm b/code/controllers/subsystem/processing/quirks.dm index 6e6fc6547e2..c34d97b28f9 100644 --- a/code/controllers/subsystem/processing/quirks.dm +++ b/code/controllers/subsystem/processing/quirks.dm @@ -15,7 +15,7 @@ GLOBAL_LIST_INIT_TYPED(quirk_blacklist, /list/datum/quirk, list( list(/datum/quirk/prosthetic_limb, /datum/quirk/quadruple_amputee, /datum/quirk/body_purist), list(/datum/quirk/prosthetic_organ, /datum/quirk/tin_man, /datum/quirk/body_purist), list(/datum/quirk/quadruple_amputee, /datum/quirk/paraplegic, /datum/quirk/hemiplegic), - list(/datum/quirk/quadruple_amputee, /datum/quirk/frail), + //list(/datum/quirk/quadruple_amputee, /datum/quirk/frail), // SKYRAT EDIT REMOVAL- Since we have synth wounds now, frail has a large downside for prosthetics and such list(/datum/quirk/social_anxiety, /datum/quirk/mute), list(/datum/quirk/mute, /datum/quirk/softspoken), list(/datum/quirk/poor_aim, /datum/quirk/bighands), diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm index 7f0b52d471b..1cc3468fb7d 100644 --- a/code/controllers/subsystem/research.dm +++ b/code/controllers/subsystem/research.dm @@ -313,6 +313,8 @@ SUBSYSTEM_DEF(research) */ /datum/controller/subsystem/research/proc/get_available_servers(turf/location) var/list/local_servers = list() + if(!location) + return local_servers for (var/datum/techweb/individual_techweb as anything in techwebs) var/list/servers = find_valid_servers(location, individual_techweb) if(length(servers)) diff --git a/code/datums/ai/basic_mobs/base_basic_controller.dm b/code/datums/ai/basic_mobs/base_basic_controller.dm index 3eb79a815ad..cd025b28bcb 100644 --- a/code/datums/ai/basic_mobs/base_basic_controller.dm +++ b/code/datums/ai/basic_mobs/base_basic_controller.dm @@ -18,7 +18,10 @@ if(!isliving(pawn)) return var/mob/living/living_pawn = pawn - if(!(ai_traits & CAN_ACT_WHILE_DEAD) && IS_DEAD_OR_INCAP(living_pawn)) + var/incap_flags = NONE + if (ai_traits & CAN_ACT_IN_STASIS) + incap_flags |= IGNORE_STASIS + if(!(ai_traits & CAN_ACT_WHILE_DEAD) && (living_pawn.incapacitated(incap_flags) || living_pawn.stat)) return FALSE if(ai_traits & PAUSE_DURING_DO_AFTER && LAZYLEN(living_pawn.do_afters)) return FALSE diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm index bd86260ee89..551cb12f3b1 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm @@ -19,13 +19,13 @@ /datum/ai_behavior/run_away_from_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hiding_location_key) . = ..() - if (!controller.blackboard[BB_BASIC_MOB_FLEEING]) + if (controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) return var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] if (QDELETED(target) || !can_see(controller.pawn, target, run_distance)) finish_action(controller, succeeded = TRUE, target_key = target_key, hiding_location_key = hiding_location_key) return - if (get_dist(controller.pawn, controller.current_movement_target) >= required_distance) + if (get_dist(controller.pawn, controller.current_movement_target) > required_distance) return // Still heading over if (plot_path_away_from(controller, target)) return diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm index 04cb9b171dd..ba167b34f29 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm @@ -11,7 +11,8 @@ finish_action(controller, FALSE, ability_key, target_key) return var/mob/pawn = controller.pawn - var/result = ability.InterceptClickOn(pawn, null, target) + pawn.face_atom(target) + var/result = ability.Trigger(target = target) finish_action(controller, result, ability_key, target_key) /datum/ai_behavior/targeted_mob_ability/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm index 0b9e31db667..376f62a5855 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm @@ -23,7 +23,8 @@ var/aggro_range = controller.blackboard[aggro_range_key] || vision_range controller.clear_blackboard_key(target_key) - var/list/potential_targets = hearers(aggro_range, controller.pawn) - living_mob //Remove self, so we don't suicide + + var/list/potential_targets = hearers(aggro_range, get_turf(controller.pawn)) - living_mob //Remove self, so we don't suicide for(var/HM in typecache_filter_list(range(aggro_range, living_mob), hostile_machines)) //Can we see any hostile machines? if(can_see(living_mob, HM, aggro_range)) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/climb_tree.dm b/code/datums/ai/basic_mobs/basic_subtrees/climb_tree.dm index 1beab6ec907..bad349030f1 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/climb_tree.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/climb_tree.dm @@ -1,4 +1,5 @@ /datum/ai_planning_subtree/climb_trees + operational_datums = list(/datum/component/tree_climber) ///chance to climb a tree var/climb_chance = 35 diff --git a/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm index 8d1391f7c7d..4f901745eee 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm @@ -10,7 +10,7 @@ /datum/ai_planning_subtree/flee_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() var/atom/flee_from = controller.blackboard[target_key] - if (!controller.blackboard[BB_BASIC_MOB_FLEEING] || QDELETED(flee_from)) + if (controller.blackboard[BB_BASIC_MOB_STOP_FLEEING] || QDELETED(flee_from)) return var/flee_distance = controller.blackboard[BB_BASIC_MOB_FLEE_DISTANCE] || DEFAULT_BASIC_FLEE_DISTANCE if (get_dist(controller.pawn, flee_from) >= flee_distance) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm b/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm index c09e7cdbf75..2a85e9e902b 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm @@ -8,6 +8,8 @@ var/maximum_distance = 6 /// How far do we look for our target? var/view_distance = 10 + /// the run away behavior we will use + var/run_away_behavior = /datum/ai_behavior/step_away /datum/ai_planning_subtree/maintain_distance/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() @@ -16,12 +18,15 @@ return // Don't run away from cucumbers, they're not snakes var/range = get_dist(controller.pawn, target) if (range < minimum_distance) - controller.queue_behavior(/datum/ai_behavior/step_away, target_key) + controller.queue_behavior(run_away_behavior, target_key, minimum_distance) return if (range > maximum_distance) controller.queue_behavior(/datum/ai_behavior/pursue_to_range, target_key, maximum_distance) return +/datum/ai_planning_subtree/maintain_distance/cover_minimum_distance + run_away_behavior = /datum/ai_behavior/cover_minimum_distance + /// Take one step away /datum/ai_behavior/step_away behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION @@ -80,3 +85,32 @@ if (!QDELETED(current_target) && get_dist(controller.pawn, current_target) > range) return finish_action(controller, succeeded = TRUE) + +///instead of taking a single step, we cover the entire distance +/datum/ai_behavior/cover_minimum_distance + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + required_distance = 0 + action_cooldown = 0.2 SECONDS + +/datum/ai_behavior/cover_minimum_distance/setup(datum/ai_controller/controller, target_key, minimum_distance) + . = ..() + var/atom/target = controller.blackboard[target_key] + if(QDELETED(target)) + return FALSE + var/required_distance = minimum_distance - get_dist(controller.pawn, target) //the distance we need to move + var/distance = 0 + var/turf/chosen_turf + for(var/turf/open/potential_turf in oview(required_distance, controller.pawn)) + var/new_distance_from_target = get_dist(potential_turf, target) + if(potential_turf.is_blocked_turf()) + continue + if(new_distance_from_target > distance) + chosen_turf = potential_turf + distance = new_distance_from_target + if(isnull(chosen_turf)) + return FALSE + set_movement_target(controller, target = chosen_turf) + +/datum/ai_behavior/cover_minimum_distance/perform(seconds_per_tick, datum/ai_controller/controller, target_key) + . = ..() + finish_action(controller, succeeded = TRUE) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm b/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm index 1ff752d925f..be395f3dfe4 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm @@ -4,28 +4,28 @@ /// Blackboard key holding target atom var/target_key = BB_BASIC_MOB_CURRENT_TARGET /// What AI behaviour do we actually run? - var/datum/ai_behavior/ranged_skirmish/attack_behavior = /datum/ai_behavior/ranged_skirmish + var/attack_behavior = /datum/ai_behavior/ranged_skirmish + /// If target is further away than this we don't fire + var/max_range = 9 + /// If target is closer than this we don't fire + var/min_range = 2 /datum/ai_planning_subtree/ranged_skirmish/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() if(!controller.blackboard_key_exists(target_key)) return - controller.queue_behavior(attack_behavior, target_key, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + controller.queue_behavior(attack_behavior, target_key, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION, max_range, min_range) /// How often will we try to perform our ranged attack? /datum/ai_behavior/ranged_skirmish action_cooldown = 1 SECONDS - /// If target is further away than this we don't fire - var/max_range = 9 - /// If target is closer than this we don't fire - var/min_range = 2 -/datum/ai_behavior/ranged_skirmish/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/ranged_skirmish/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key, max_range, min_range) . = ..() var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] return !QDELETED(target) -/datum/ai_behavior/ranged_skirmish/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) +/datum/ai_behavior/ranged_skirmish/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key, max_range, min_range) . = ..() var/atom/target = controller.blackboard[target_key] if (QDELETED(target)) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/shapechange_ambush.dm b/code/datums/ai/basic_mobs/basic_subtrees/shapechange_ambush.dm new file mode 100644 index 00000000000..ff01eb804ff --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/shapechange_ambush.dm @@ -0,0 +1,41 @@ +/// Shapeshift when we have no target, until someone has been nearby for long enough +/datum/ai_planning_subtree/shapechange_ambush + operational_datums = list(/datum/component/ai_target_timer) + /// Key where we keep our ability + var/ability_key = BB_SHAPESHIFT_ACTION + /// Key where we keep our target + var/target_key = BB_BASIC_MOB_CURRENT_TARGET + /// How long to lull our target into a false sense of security + var/minimum_target_time = 8 SECONDS + +/datum/ai_planning_subtree/shapechange_ambush/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/mob/living/living_pawn = controller.pawn + var/is_shifted = ismob(living_pawn.loc) + var/has_target = controller.blackboard_key_exists(target_key) + var/datum/action/cooldown/using_action = controller.blackboard[ability_key] + + if (!is_shifted) + if (has_target) + return // We're busy + + if (using_action?.IsAvailable()) + controller.queue_behavior(/datum/ai_behavior/use_mob_ability/shapeshift, BB_SHAPESHIFT_ACTION) // Shift + return SUBTREE_RETURN_FINISH_PLANNING + + if (!has_target || !using_action?.IsAvailable()) + return SUBTREE_RETURN_FINISH_PLANNING // Lie in wait + var/time_on_target = controller.blackboard[BB_BASIC_MOB_HAS_TARGET_TIME] || 0 + if (time_on_target < minimum_target_time) + return // Wait a bit longer + controller.queue_behavior(/datum/ai_behavior/use_mob_ability/shapeshift, BB_SHAPESHIFT_ACTION) // Surprise! + +/// Selects a random shapeshift ability before shifting +/datum/ai_behavior/use_mob_ability/shapeshift + +/datum/ai_behavior/use_mob_ability/shapeshift/setup(datum/ai_controller/controller, ability_key) + var/datum/action/cooldown/spell/shapeshift/using_action = controller.blackboard[ability_key] + if (!using_action?.IsAvailable()) + return FALSE + if (isnull(using_action.shapeshift_type)) // If we don't have a shape then pick one, AI can't use context wheels + using_action.shapeshift_type = pick(using_action.possible_shapes) + return ..() diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_nearest_target_to_flee.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_nearest_target_to_flee.dm index 42a361c25cd..3fe1ada33ba 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_nearest_target_to_flee.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_nearest_target_to_flee.dm @@ -3,7 +3,7 @@ /datum/ai_planning_subtree/simple_find_nearest_target_to_flee/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() - if (!controller.blackboard[BB_BASIC_MOB_FLEEING]) + if (controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) return controller.queue_behavior(/datum/ai_behavior/find_potential_targets/nearest, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) @@ -13,7 +13,7 @@ /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() - if (!controller.blackboard[BB_BASIC_MOB_FLEEING]) + if (controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) return controller.queue_behavior(/datum/ai_behavior/target_from_retaliate_list/nearest, BB_BASIC_MOB_RETALIATE_LIST, BB_BASIC_MOB_CURRENT_TARGET, targeting_key, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/teleport_away_from_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/teleport_away_from_target.dm new file mode 100644 index 00000000000..dadba992e9f --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/teleport_away_from_target.dm @@ -0,0 +1,56 @@ +///behavior to activate ability to escape from target +/datum/ai_planning_subtree/teleport_away_from_target + ///minimum distance away from the target before we execute behavior + var/minimum_distance = 2 + ///the ability we will execute + var/ability_key + +/datum/ai_planning_subtree/teleport_away_from_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + if(!controller.blackboard_key_exists(BB_BASIC_MOB_CURRENT_TARGET)) + return + var/atom/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + var/distance_from_target = get_dist(target, controller.pawn) + if(distance_from_target >= minimum_distance) + controller.clear_blackboard_key(BB_ESCAPE_DESTINATION) + return + var/datum/action/cooldown/ability = controller.blackboard[ability_key] + if(!ability?.IsAvailable()) + return + var/turf/location_turf = controller.blackboard[BB_ESCAPE_DESTINATION] + + if(isnull(location_turf)) + controller.queue_behavior(/datum/ai_behavior/find_furthest_turf_from_target, BB_BASIC_MOB_CURRENT_TARGET, BB_ESCAPE_DESTINATION, minimum_distance) + return SUBTREE_RETURN_FINISH_PLANNING + + if(get_dist(location_turf, target) < minimum_distance || !can_see(controller.pawn, location_turf)) //target moved close too close or we moved too far since finding the target turf + controller.clear_blackboard_key(BB_ESCAPE_DESTINATION) + return + + controller.queue_behavior(/datum/ai_behavior/targeted_mob_ability/and_clear_target, ability_key, BB_ESCAPE_DESTINATION) + +///find furtherst turf target so we may teleport to it +/datum/ai_behavior/find_furthest_turf_from_target + +/datum/ai_behavior/find_furthest_turf_from_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key, set_key, range) + var/mob/living/living_target = controller.blackboard[target_key] + if(QDELETED(living_target)) + return + + var/distance = 0 + var/turf/chosen_turf + for(var/turf/open/potential_destination in oview(range, living_target)) + if(potential_destination.is_blocked_turf()) + continue + var/new_distance_to_target = get_dist(potential_destination, living_target) + if(new_distance_to_target > distance) + chosen_turf = potential_destination + distance = new_distance_to_target + if(distance == range) + break //we have already found the max distance + + if(isnull(chosen_turf)) + finish_action(controller, FALSE) + return + + controller.set_blackboard_key(set_key, chosen_turf) + finish_action(controller, TRUE) diff --git a/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm b/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm index 570088ce4d6..978d7b7f8a7 100644 --- a/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm +++ b/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm @@ -26,7 +26,7 @@ if(isnull(our_controller)) return FALSE - if(isturf(the_target) || !the_target) // bail out on invalids + if(isturf(the_target) || isnull(the_target)) // bail out on invalids return FALSE if(isobj(the_target.loc)) @@ -35,6 +35,8 @@ return FALSE if(ismob(the_target)) //Target is in godmode, ignore it. + if(living_mob.loc == the_target) + return FALSE // We've either been eaten or are shapeshifted, let's assume the latter because we're still alive var/mob/M = the_target if(M.status_flags & GODMODE) return FALSE @@ -45,7 +47,7 @@ if(living_mob.see_invisible < the_target.invisibility) //Target's invisible to us, forget it return FALSE - if(isturf(the_target.loc) && living_mob.z != the_target.z) // z check will always fail if target is in a mech + if(isturf(living_mob.loc) && isturf(the_target.loc) && living_mob.z != the_target.z) // z check will always fail if target is in a mech or pawn is shapeshifted or jaunting return FALSE if(isliving(the_target)) //Targeting vs living mobs diff --git a/code/datums/ai/basic_mobs/targetting_datums/with_object.dm b/code/datums/ai/basic_mobs/targetting_datums/with_object.dm new file mode 100644 index 00000000000..039027b6aa5 --- /dev/null +++ b/code/datums/ai/basic_mobs/targetting_datums/with_object.dm @@ -0,0 +1,39 @@ +/** + * Find mobs who are holding the configurable object type + * + * This is an extension of basic targeting behaviour, that allows you to + * only target the mob if they have a specific item in their hand. + * + */ +/datum/targetting_datum/basic/holding_object + // We will find mobs who are holding this object in their hands + var/object_type_path = null + +/** + * Create an instance of the holding object targeting datum + * + * * object_type_path Pass an object type path, this will be compared to the items + * in targets hands to filter the target list. + */ +/datum/targetting_datum/basic/holding_object/New(object_type_path) + if (!ispath(object_type_path)) + stack_trace("trying to create an item targeting datum with no valid typepath") + // Leaving object type as null will make this basically a noop + return + src.object_type_path = object_type_path + +///Returns true or false depending on if the target can be attacked by the mob +/datum/targetting_datum/basic/holding_object/can_attack(mob/living/living_mob, atom/target, vision_range, check_faction = FALSE) + if (object_type_path == null) + return FALSE // no op + if(!ismob(target)) + return FALSE // no hands no problems + + // Look at me, type casting like a grown up + var/mob/targetmob = target + // Check if our parent behaviour agrees we can attack this target (we ignore faction by default) + var/can_attack = ..() + if(can_attack && targetmob.is_holding_item_of_type(object_type_path)) + return TRUE // they have the item + // No valid target + return FALSE diff --git a/code/datums/ai/dog/dog_controller.dm b/code/datums/ai/dog/dog_controller.dm index 5a42cb43a1e..6883642b689 100644 --- a/code/datums/ai/dog/dog_controller.dm +++ b/code/datums/ai/dog/dog_controller.dm @@ -20,6 +20,8 @@ BB_DOG_HARASS_HARM = TRUE, BB_VISION_RANGE = AI_DOG_VISION_RANGE, BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/not_friends(), + // Find nearby mobs with tongs in hand. + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/holding_object(/obj/item/kitchen/tongs), BB_BABIES_PARTNER_TYPES = list(/mob/living/basic/pet/dog), BB_BABIES_CHILD_TYPES = list(/mob/living/basic/pet/dog/corgi/puppy = 95, /mob/living/basic/pet/dog/corgi/puppy/void = 5), ) @@ -29,6 +31,10 @@ /datum/ai_planning_subtree/make_babies, // Ian WILL prioritise sex over following your instructions /datum/ai_planning_subtree/pet_planning, /datum/ai_planning_subtree/dog_harassment, + // Find targets to run away from (uses the targetting datum from above) + /datum/ai_planning_subtree/simple_find_target, + // Flee from that target + /datum/ai_planning_subtree/flee_target, ) /datum/ai_controller/basic_controller/dog/corgi/get_access() diff --git a/code/datums/ai/hunting_behavior/hunting_behaviors.dm b/code/datums/ai/hunting_behavior/hunting_behaviors.dm index ba7c7f2ffba..468cfed33fb 100644 --- a/code/datums/ai/hunting_behavior/hunting_behaviors.dm +++ b/code/datums/ai/hunting_behavior/hunting_behaviors.dm @@ -94,8 +94,6 @@ var/atom/hunted = controller.blackboard[hunting_target_key] if(QDELETED(hunted)) - //Target is gone for some reason. forget about this task! - controller[hunting_target_key] = null finish_action(controller, FALSE, hunting_target_key) else target_caught(hunter, hunted) @@ -136,7 +134,7 @@ /datum/ai_behavior/hunt_target/use_ability_on_target/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, hunting_cooldown_key) var/datum/action/cooldown/ability = controller.blackboard[ability_key] - if(QDELETED(ability) || !ability.IsAvailable()) + if(!ability?.IsAvailable()) finish_action(controller, FALSE, hunting_target_key) return ..() diff --git a/code/datums/alarm.dm b/code/datums/alarm.dm index b266362f3ca..e25f96b95a5 100644 --- a/code/datums/alarm.dm +++ b/code/datums/alarm.dm @@ -201,4 +201,5 @@ for(var/area_name as anything in alarms_of_type) var/list/alarm_packet = alarms_of_type[area_name] var/list/cameras = alarm_packet[2] - cameras -= source // REF FOUND AND CLEARED BOYSSSS + if(cameras) + cameras -= source // REF FOUND AND CLEARED BOYSSSS diff --git a/code/datums/components/bakeable.dm b/code/datums/components/bakeable.dm index 537ae62ddbe..b4cde3c5752 100644 --- a/code/datums/components/bakeable.dm +++ b/code/datums/components/bakeable.dm @@ -14,7 +14,10 @@ /// REF() to the mind which placed us in an oven var/who_baked_us -/datum/component/bakeable/Initialize(bake_result, required_bake_time, positive_result, use_large_steam_sprite) + /// Reagents that should be added to the result + var/list/added_reagents + +/datum/component/bakeable/Initialize(bake_result, required_bake_time, positive_result, use_large_steam_sprit, list/added_reagents) . = ..() if(!isitem(parent)) //Only items support baking at the moment return COMPONENT_INCOMPATIBLE @@ -22,6 +25,7 @@ src.bake_result = bake_result src.required_bake_time = required_bake_time src.positive_result = positive_result + src.added_reagents = added_reagents // Inherit the new values passed to the component /datum/component/bakeable/InheritComponent(datum/component/bakeable/new_comp, original, bake_result, required_bake_time, positive_result, use_large_steam_sprite) @@ -67,9 +71,11 @@ var/atom/original_object = parent var/obj/item/plate/oven_tray/used_tray = original_object.loc var/atom/baked_result = new bake_result(used_tray) - if(baked_result.reagents) //make space and tranfer reagents if it has any + if(baked_result.reagents && positive_result) //make space and tranfer reagents if it has any & the resulting item isn't bad food or other bad baking result baked_result.reagents.clear_reagents() original_object.reagents.trans_to(baked_result, original_object.reagents.total_volume) + if(added_reagents) // Add any new reagents that should be added + baked_result.reagents.add_reagent_list(added_reagents) if(who_baked_us) ADD_TRAIT(baked_result, TRAIT_FOOD_CHEF_MADE, who_baked_us) diff --git a/code/datums/components/crafting/ranged_weapon.dm b/code/datums/components/crafting/ranged_weapon.dm index a8d631c6266..94a943b42c8 100644 --- a/code/datums/components/crafting/ranged_weapon.dm +++ b/code/datums/components/crafting/ranged_weapon.dm @@ -222,18 +222,19 @@ time = 30 SECONDS //contemplate for a bit category = CAT_WEAPON_RANGED -/datum/crafting_recipe/deagle_prime //When you factor in the makarov (7 tc), the toolbox (1 tc), and the emag (3 tc), this comes to a total of 17 TC or thereabouts. Igorning the 20k pricetag, obviously. +/datum/crafting_recipe/deagle_prime //When you factor in the makarov (7 tc), the toolbox (1 tc), and the emag (3 tc), this comes to a total of 18 TC or thereabouts. Igorning the 20k pricetag, obviously. name = "Regal Condor" always_available = FALSE - result = /obj/item/gun/ballistic/automatic/pistol/deagle/regal/no_mag + result = /obj/item/gun/ballistic/automatic/pistol/deagle/regal reqs = list( /obj/item/gun/ballistic/automatic/pistol = 1, /obj/item/stack/sheet/mineral/gold = 25, /obj/item/stack/sheet/mineral/silver = 25, /obj/item/food/donkpocket = 1, - /obj/item/stack/telecrystal = 3, + /obj/item/stack/telecrystal = 4, /obj/item/clothing/head/costume/crown/fancy = 1, //the captain's crown /obj/item/storage/toolbox/syndicate = 1, + /obj/item/stack/sheet/iron = 10, ) tool_behaviors = list(TOOL_SCREWDRIVER) tool_paths = list( @@ -249,18 +250,22 @@ blacklist += subtypesof(/obj/item/gun/ballistic/automatic/pistol) /datum/crafting_recipe/deagle_prime_mag - name = "Regal Condor Magazine (10mm)" + name = "Regal Condor Magazine (10mm Reaper)" always_available = FALSE - result = /obj/item/ammo_box/magazine/r10mm/empty + result = /obj/item/ammo_box/magazine/r10mm reqs = list( /obj/item/stack/sheet/iron = 10, - /obj/item/stack/telecrystal = 2, + /obj/item/stack/sheet/mineral/gold = 10, + /obj/item/stack/sheet/mineral/silver = 10, + /obj/item/stack/sheet/mineral/plasma = 10, + /obj/item/food/donkpocket = 1, //Station mass murder, as sponsored by Donk Co. ) tool_behaviors = list(TOOL_SCREWDRIVER, TOOL_WELDER) tool_paths = list( /obj/item/clothing/under/syndicate, /obj/item/clothing/mask/gas/syndicate, - /obj/item/card/emag + /obj/item/card/emag, + /obj/item/gun/ballistic/automatic/pistol/deagle/regal ) time = 5 SECONDS category = CAT_WEAPON_RANGED diff --git a/code/datums/components/cult_ritual_item.dm b/code/datums/components/cult_ritual_item.dm index 561789d1b6d..13d1ab8d921 100644 --- a/code/datums/components/cult_ritual_item.dm +++ b/code/datums/components/cult_ritual_item.dm @@ -304,7 +304,7 @@ ) if(cultist.blood_volume) - cultist.apply_damage(initial(rune_to_scribe.scribe_damage), BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM), wound_bonus = CANT_WOUND) // *cuts arm* *bone explodes* ever have one of those days? + cultist.apply_damage(initial(rune_to_scribe.scribe_damage), BRUTE, pick(GLOB.arm_zones), wound_bonus = CANT_WOUND) // *cuts arm* *bone explodes* ever have one of those days? var/scribe_mod = initial(rune_to_scribe.scribe_delay) if(!initial(rune_to_scribe.no_scribe_boost) && (our_turf.type in turfs_that_boost_us)) diff --git a/code/datums/components/fullauto.dm b/code/datums/components/fullauto.dm index d02f090ae20..8663de5adc6 100644 --- a/code/datums/components/fullauto.dm +++ b/code/datums/components/fullauto.dm @@ -8,8 +8,12 @@ var/turf/target_loc //For dealing with locking on targets due to BYOND engine limitations (the mouse input only happening when mouse moves). var/autofire_stat = AUTOFIRE_STAT_IDLE var/mouse_parameters - var/autofire_shot_delay = 0.3 SECONDS //Time between individual shots. - var/mouse_status = AUTOFIRE_MOUSEUP //This seems hacky but there can be two MouseDown() without a MouseUp() in between if the user holds click and uses alt+tab, printscreen or similar. + /// Time between individual shots. + var/autofire_shot_delay = 0.3 SECONDS + /// This seems hacky but there can be two MouseDown() without a MouseUp() in between if the user holds click and uses alt+tab, printscreen or similar. + var/mouse_status = AUTOFIRE_MOUSEUP + /// Should dual wielding be allowed? + var/allow_akimbo ///windup autofire vars ///Whether the delay between shots increases over time, simulating a spooling weapon @@ -26,7 +30,7 @@ var/timerid COOLDOWN_DECLARE(next_shot_cd) -/datum/component/automatic_fire/Initialize(autofire_shot_delay, windup_autofire, windup_autofire_reduction_multiplier, windup_autofire_cap, windup_spindown) +/datum/component/automatic_fire/Initialize(autofire_shot_delay, windup_autofire, windup_autofire_reduction_multiplier, windup_autofire_cap, windup_spindown, allow_akimbo = TRUE) . = ..() if(!isgun(parent)) return COMPONENT_INCOMPATIBLE @@ -34,6 +38,7 @@ RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(wake_up)) if(autofire_shot_delay) src.autofire_shot_delay = autofire_shot_delay + src.allow_akimbo = allow_akimbo if(windup_autofire) src.windup_autofire = windup_autofire src.windup_autofire_reduction_multiplier = windup_autofire_reduction_multiplier @@ -256,7 +261,7 @@ if(HAS_TRAIT(shooter, TRAIT_DOUBLE_TAP)) next_delay = round(next_delay * 0.5) COOLDOWN_START(src, next_shot_cd, next_delay) - if(SEND_SIGNAL(parent, COMSIG_AUTOFIRE_SHOT, target, shooter, mouse_parameters) & COMPONENT_AUTOFIRE_SHOT_SUCCESS) + if(SEND_SIGNAL(parent, COMSIG_AUTOFIRE_SHOT, target, shooter, allow_akimbo, mouse_parameters) & COMPONENT_AUTOFIRE_SHOT_SUCCESS) return TRUE stop_autofiring() return FALSE @@ -288,21 +293,21 @@ return COMPONENT_AUTOFIRE_ONMOUSEDOWN_BYPASS -/obj/item/gun/proc/do_autofire(datum/source, atom/target, mob/living/shooter, params) +/obj/item/gun/proc/do_autofire(datum/source, atom/target, mob/living/shooter, allow_akimbo, params) SIGNAL_HANDLER if(semicd || shooter.incapacitated()) return NONE if(!can_shoot()) shoot_with_empty_chamber(shooter) return NONE - INVOKE_ASYNC(src, PROC_REF(do_autofire_shot), source, target, shooter, params) + INVOKE_ASYNC(src, PROC_REF(do_autofire_shot), source, target, shooter, allow_akimbo, params) return COMPONENT_AUTOFIRE_SHOT_SUCCESS //All is well, we can continue shooting. -/obj/item/gun/proc/do_autofire_shot(datum/source, atom/target, mob/living/shooter, params) +/obj/item/gun/proc/do_autofire_shot(datum/source, atom/target, mob/living/shooter, allow_akimbo, params) var/obj/item/gun/akimbo_gun = shooter.get_inactive_held_item() var/bonus_spread = 0 - if(istype(akimbo_gun) && weapon_weight < WEAPON_MEDIUM) + if(istype(akimbo_gun) && weapon_weight < WEAPON_MEDIUM && allow_akimbo) if(akimbo_gun.weapon_weight < WEAPON_MEDIUM && akimbo_gun.can_trigger_gun(shooter)) bonus_spread = dual_wield_spread addtimer(CALLBACK(akimbo_gun, TYPE_PROC_REF(/obj/item/gun, process_fire), target, shooter, TRUE, params, null, bonus_spread), 1) diff --git a/code/datums/components/grillable.dm b/code/datums/components/grillable.dm index f1fe80fe9fb..72c2e75e8cb 100644 --- a/code/datums/components/grillable.dm +++ b/code/datums/components/grillable.dm @@ -12,11 +12,10 @@ var/use_large_steam_sprite = FALSE /// REF() to the mind which placed us on the griddle var/who_placed_us + /// Reagents that should be added to the result + var/list/added_reagents - /// What type of pollutant we spread around as we are grilleed, can be none // SKYRAT EDIT ADDITION - var/pollutant_type // SKYRAT EDIT ADDITION - -/datum/component/grillable/Initialize(cook_result, required_cook_time, positive_result, use_large_steam_sprite, pollutant_type) //SKYRAT EDIT CHANGE +/datum/component/grillable/Initialize(cook_result, required_cook_time, positive_result, use_large_steam_sprite, list/added_reagents) . = ..() if(!isitem(parent)) //Only items support grilling at the moment return COMPONENT_INCOMPATIBLE @@ -25,7 +24,7 @@ src.required_cook_time = required_cook_time src.positive_result = positive_result src.use_large_steam_sprite = use_large_steam_sprite - src.pollutant_type = pollutant_type //SKYRAT EDIT ADDITION + src.added_reagents = added_reagents /datum/component/grillable/RegisterWithParent() RegisterSignal(parent, COMSIG_ITEM_GRILL_PLACED, PROC_REF(on_grill_placed)) @@ -108,10 +107,12 @@ if(original_object.custom_materials) grilled_result.set_custom_materials(original_object.custom_materials) - if(IsEdible(grilled_result)) + if(IsEdible(grilled_result) && positive_result) BLACKBOX_LOG_FOOD_MADE(grilled_result.type) grilled_result.reagents.clear_reagents() original_object.reagents?.trans_to(grilled_result, original_object.reagents.total_volume) + if(added_reagents) // Add any new reagents that should be added + grilled_result.reagents.add_reagent_list(added_reagents) SEND_SIGNAL(parent, COMSIG_ITEM_GRILLED, grilled_result) if(who_placed_us) diff --git a/code/datums/components/joint_damage.dm b/code/datums/components/joint_damage.dm new file mode 100644 index 00000000000..5397bd307ca --- /dev/null +++ b/code/datums/components/joint_damage.dm @@ -0,0 +1,35 @@ +/* + * A component given to mobs to damage a linked mob + */ +/datum/component/joint_damage + ///the mob we will damage + var/datum/weakref/overlord_mob + ///our last health count + var/previous_health_count + +/datum/component/joint_damage/Initialize(mob/overlord_mob) + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + var/mob/living/parent_mob = parent + previous_health_count = parent_mob.health + if(overlord_mob) + src.overlord_mob = WEAKREF(overlord_mob) + +/datum/component/joint_damage/RegisterWithParent() + RegisterSignal(parent, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(damage_overlord)) + RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(damage_overlord)) + +/datum/component/joint_damage/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_LIVING_HEALTH_UPDATE, COMSIG_LIVING_DEATH)) + +/datum/component/joint_damage/Destroy() + overlord_mob = null + return ..() + +/datum/component/joint_damage/proc/damage_overlord(mob/living/source) + SIGNAL_HANDLER + + var/mob/living/overlord_to_damage = overlord_mob?.resolve() + if(!isnull(overlord_to_damage)) + overlord_to_damage.adjustBruteLoss(previous_health_count - source.health) ///damage or heal overlord + previous_health_count = source.health diff --git a/code/datums/components/mob_chain.dm b/code/datums/components/mob_chain.dm new file mode 100644 index 00000000000..8312d9d5504 --- /dev/null +++ b/code/datums/components/mob_chain.dm @@ -0,0 +1,224 @@ +/** + * Component allowing you to create a linked list of mobs. + * These mobs will follow each other and attack as one, as well as sharing damage taken. + */ +/datum/component/mob_chain + + /// If true then damage we take is passed backwards along the line + var/pass_damage_back + /// If true then we will set our icon state based on line position + var/vary_icon_state + + /// Mob in front of us in the chain + var/mob/living/front + /// Mob behind us in the chain + var/mob/living/back + +/datum/component/mob_chain/Initialize(mob/living/front, pass_damage_back = TRUE, vary_icon_state = FALSE) + . = ..() + if (!isliving(parent)) + return COMPONENT_INCOMPATIBLE + + src.front = front + src.pass_damage_back = pass_damage_back + src.vary_icon_state = vary_icon_state + if (!isnull(front)) + SEND_SIGNAL(front, COMSIG_MOB_GAINED_CHAIN_TAIL, parent) + parent.AddComponent(/datum/component/leash, owner = front, distance = 1) // Handles catching up gracefully + var/mob/living/living_parent = parent + living_parent.set_glide_size(front.glide_size) + +/datum/component/mob_chain/Destroy(force, silent) + if (!isnull(front)) + SEND_SIGNAL(front, COMSIG_MOB_LOST_CHAIN_TAIL, parent) + front = null + back = null + return ..() + +/datum/component/mob_chain/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOB_GAINED_CHAIN_TAIL, PROC_REF(on_gained_tail)) + RegisterSignal(parent, COMSIG_MOB_LOST_CHAIN_TAIL, PROC_REF(on_lost_tail)) + RegisterSignal(parent, COMSIG_MOB_CHAIN_CONTRACT, PROC_REF(on_contracted)) + RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(on_death)) + RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(on_deletion)) + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) + RegisterSignal(parent, COMSIG_ATOM_CAN_BE_PULLED, PROC_REF(on_pulled)) + RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, COMSIG_MOB_ATTACK_RANGED), PROC_REF(on_attack)) + RegisterSignal(parent, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, PROC_REF(on_glide_size_changed)) + if (vary_icon_state) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_ICON_STATE, PROC_REF(on_update_icon_state)) + update_mob_appearance() + if (pass_damage_back) + RegisterSignals(parent, COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES, PROC_REF(on_adjust_damage)) + RegisterSignal(parent, COMSIG_LIVING_ADJUST_STAMINA_DAMAGE, PROC_REF(on_adjust_stamina)) + RegisterSignal(parent, COMSIG_CARBON_LIMB_DAMAGED, PROC_REF(on_limb_damage)) + + var/datum/action/cooldown/worm_contract/shrink = new(parent) + shrink.Grant(parent) + +/datum/component/mob_chain/UnregisterFromParent() + UnregisterSignal(parent, list( + COMSIG_ATOM_CAN_BE_PULLED, + COMSIG_ATOM_UPDATE_ICON_STATE, + COMSIG_CARBON_LIMB_DAMAGED, + COMSIG_HUMAN_EARLY_UNARMED_ATTACK, + COMSIG_LIVING_ADJUST_BRUTE_DAMAGE, + COMSIG_LIVING_ADJUST_BURN_DAMAGE, + COMSIG_LIVING_ADJUST_CLONE_DAMAGE, + COMSIG_LIVING_DEATH, + COMSIG_LIVING_ADJUST_OXY_DAMAGE, + COMSIG_LIVING_ADJUST_STAMINA_DAMAGE, + COMSIG_LIVING_ADJUST_TOX_DAMAGE, + COMSIG_LIVING_UNARMED_ATTACK, + COMSIG_MOB_ATTACK_RANGED, + COMSIG_MOB_CHAIN_CONTRACT, + COMSIG_MOB_GAINED_CHAIN_TAIL, + COMSIG_MOB_LOST_CHAIN_TAIL, + COMSIG_MOVABLE_MOVED, + COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, + COMSIG_QDELETING, + )) + qdel(parent.GetComponent(/datum/component/leash)) + var/mob/living/living_parent = parent + var/datum/action/cooldown/worm_contract/shrink = locate() in living_parent.actions + qdel(shrink) + +/// Update how we look +/datum/component/mob_chain/proc/update_mob_appearance() + if (!vary_icon_state) + return + var/mob/living/body = parent + body.update_appearance(UPDATE_ICON_STATE) + +/// Called when something sets us as IT'S front +/datum/component/mob_chain/proc/on_gained_tail(mob/living/body, mob/living/tail) + SIGNAL_HANDLER + back = tail + update_mob_appearance() + +/// Called when our tail loses its chain component +/datum/component/mob_chain/proc/on_lost_tail() + SIGNAL_HANDLER + back = null + update_mob_appearance() + +/// Called when our tail gets pulled up to our body +/datum/component/mob_chain/proc/on_contracted(mob/living/shrinking) + SIGNAL_HANDLER + if (isnull(back)) + return + back.forceMove(shrinking.loc) + var/datum/action/cooldown/worm_contract/shrink = locate() in back.actions + if (isnull(shrink)) + return + INVOKE_ASYNC(shrink, TYPE_PROC_REF(/datum/action, Trigger)) + +/// If we die so does the guy behind us, then stop following the leader +/datum/component/mob_chain/proc/on_death() + SIGNAL_HANDLER + back?.death() + qdel(src) + +/// If we get deleted so does the guy behind us +/datum/component/mob_chain/proc/on_deletion() + SIGNAL_HANDLER + QDEL_NULL(back) + front?.update_appearance(UPDATE_ICON) + +/// Pull our tail behind us when we move +/datum/component/mob_chain/proc/on_moved(mob/living/mover, turf/old_loc) + SIGNAL_HANDLER + if(isnull(back) || back.loc == old_loc) + return + back.Move(old_loc) + +/// Update our visuals based on if we have someone in front and behind +/datum/component/mob_chain/proc/on_update_icon_state(mob/living/our_mob) + SIGNAL_HANDLER + var/current_icon_state = our_mob.base_icon_state + if(isnull(front)) + current_icon_state = "[current_icon_state]_start" + else if(isnull(back)) + current_icon_state = "[current_icon_state]_end" + else + current_icon_state = "[current_icon_state]_mid" + + our_mob.icon_state = current_icon_state + if (isanimal_or_basicmob(our_mob)) + var/mob/living/basic/basic_parent = our_mob + basic_parent.icon_living = current_icon_state + +/// Do not allow someone to be pulled out of the chain +/datum/component/mob_chain/proc/on_pulled(mob/living/our_mob) + SIGNAL_HANDLER + if (!isnull(front)) + return COMSIG_ATOM_CANT_PULL + +/// Tell our tail to attack too +/datum/component/mob_chain/proc/on_attack(mob/living/our_mob, atom/target) + SIGNAL_HANDLER + if (target == back || target == front) + return COMPONENT_CANCEL_ATTACK_CHAIN + if (isnull(back) || QDELETED(target)) + return + INVOKE_ASYNC(back, TYPE_PROC_REF(/mob, ClickOn), target) + +/// Maintain glide size backwards +/datum/component/mob_chain/proc/on_glide_size_changed(mob/living/our_mob, new_size) + SIGNAL_HANDLER + back?.set_glide_size(new_size) + +/// On gain or lose stamina, adjust our tail too +/datum/component/mob_chain/proc/on_adjust_stamina(mob/living/our_mob, type, amount, forced) + SIGNAL_HANDLER + if (forced) + return + back?.adjustStaminaLoss(amount, forced = forced) + +/// On damage or heal, affect our furthest segment +/datum/component/mob_chain/proc/on_adjust_damage(mob/living/our_mob, type, amount, forced) + SIGNAL_HANDLER + if (isnull(back) || forced) + return + switch (type) + if(BRUTE) + back.adjustBruteLoss(amount, forced = forced) + if(BURN) + back.adjustFireLoss(amount, forced = forced) + if(TOX) + back.adjustToxLoss(amount, forced = forced) + if(OXY) // If all segments are suffocating we pile damage backwards until our ass starts dying forwards + back.adjustOxyLoss(amount, forced = forced) + if(CLONE) + back.adjustCloneLoss(amount, forced = forced) + return COMPONENT_IGNORE_CHANGE + +/// Special handling for if damage is delegated to a mob's limbs instead of its overall damage +/datum/component/mob_chain/proc/on_limb_damage(mob/living/our_mob, limb, brute, burn) + SIGNAL_HANDLER + if (isnull(back)) + return + if (brute != 0) + back.adjustBruteLoss(brute, updating_health = FALSE) + if (burn != 0) + back.adjustFireLoss(burn, updating_health = FALSE) + if (brute != 0 || burn != 0) + back.updatehealth() + return COMPONENT_PREVENT_LIMB_DAMAGE + +/** + * Shrink the chain of mobs into one tile. + */ +/datum/action/cooldown/worm_contract + name = "Force Contract" + desc = "Forces your body to contract onto a single tile." + background_icon_state = "bg_heretic" + overlay_icon_state = "bg_heretic_border" + button_icon = 'icons/mob/actions/actions_ecult.dmi' + button_icon_state = "worm_contract" + cooldown_time = 30 SECONDS + melee_cooldown_time = 0 SECONDS + +/datum/action/cooldown/worm_contract/Activate(atom/target) + SEND_SIGNAL(owner, COMSIG_MOB_CHAIN_CONTRACT) + StartCooldown() diff --git a/code/datums/components/rot.dm b/code/datums/components/rot.dm index 11c4f2cb617..64ddde2b2db 100644 --- a/code/datums/components/rot.dm +++ b/code/datums/components/rot.dm @@ -114,7 +114,7 @@ /datum/component/rot/proc/rot_react_touch(datum/source, mob/living/react_to) SIGNAL_HANDLER - rot_react(source, react_to, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + rot_react(source, react_to, pick(GLOB.arm_zones)) /// Triggered when something enters the component's parent. /datum/component/rot/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs) diff --git a/code/datums/components/supermatter_crystal.dm b/code/datums/components/supermatter_crystal.dm index 66087134388..38968d1e3d1 100644 --- a/code/datums/components/supermatter_crystal.dm +++ b/code/datums/components/supermatter_crystal.dm @@ -4,6 +4,11 @@ var/datum/callback/tool_act_callback ///Callback used by the SM to get the damage and matter power increase/decrease var/datum/callback/consume_callback + // A whitelist of items that can interact with the SM without dusting the user + var/static/list/sm_item_whitelist = typecacheof(list( + /obj/item/melee/roastingstick, + /obj/item/toy/crayon/spraycan + )) /datum/component/supermatter_crystal/Initialize(datum/callback/tool_act_callback, datum/callback/consume_callback) @@ -15,6 +20,7 @@ RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(hand_hit)) RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(attackby_hit)) RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_WRENCH), PROC_REF(tool_hit)) + RegisterSignal(parent, COMSIG_ATOM_SECONDARY_TOOL_ACT(TOOL_WRENCH), PROC_REF(tool_hit)) RegisterSignal(parent, COMSIG_ATOM_BUMPED, PROC_REF(bumped_hit)) RegisterSignal(parent, COMSIG_ATOM_INTERCEPT_Z_FALL, PROC_REF(intercept_z_fall)) RegisterSignal(parent, COMSIG_ATOM_ON_Z_IMPACT, PROC_REF(on_z_impact)) @@ -37,6 +43,7 @@ COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_TOOL_ACT(TOOL_WRENCH), + COMSIG_ATOM_SECONDARY_TOOL_ACT(TOOL_WRENCH), COMSIG_ATOM_BUMPED, COMSIG_ATOM_INTERCEPT_Z_FALL, COMSIG_ATOM_ON_Z_IMPACT, @@ -152,9 +159,7 @@ var/atom/atom_source = source if(!istype(item) || (item.item_flags & ABSTRACT) || !istype(user)) return - if(istype(item, /obj/item/melee/roastingstick)) - return FALSE - if(istype(item, /obj/item/toy/crayon/spraycan)) + if(is_type_in_typecache(item, sm_item_whitelist)) return FALSE if(istype(item, /obj/item/clothing/mask/cigarette)) var/obj/item/clothing/mask/cigarette/cig = item diff --git a/code/datums/components/tippable.dm b/code/datums/components/tippable.dm index eafb2345818..ee1f2c40547 100644 --- a/code/datums/components/tippable.dm +++ b/code/datums/components/tippable.dm @@ -133,6 +133,8 @@ /datum/component/tippable/proc/do_tip(mob/living/tipped_mob, mob/tipper) if(QDELETED(tipped_mob)) CRASH("Tippable component: do_tip() called with QDELETED tipped_mob!") + if (is_tipped) // sanity check in case multiple people try to tip at the same time + return to_chat(tipper, span_warning("You tip over [tipped_mob].")) if (!isnull(tipped_mob.client)) @@ -185,6 +187,8 @@ /datum/component/tippable/proc/do_untip(mob/living/tipped_mob, mob/untipper) if(QDELETED(tipped_mob)) return + if (!is_tipped) // sanity check in case multiple people try to untip at the same time + return to_chat(untipper, span_notice("You right [tipped_mob].")) tipped_mob.visible_message( diff --git a/code/datums/components/tree_climber.dm b/code/datums/components/tree_climber.dm index b3c70153c71..9f506ae516f 100644 --- a/code/datums/components/tree_climber.dm +++ b/code/datums/components/tree_climber.dm @@ -12,6 +12,8 @@ return COMPONENT_INCOMPATIBLE src.climbing_distance = climbing_distance + ADD_TRAIT(parent, TRAIT_SUBTREE_REQUIRED_OPERATIONAL_DATUM, type) + /datum/component/tree_climber/RegisterWithParent() RegisterSignals(parent, list(COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_LIVING_CLIMB_TREE), PROC_REF(climb_tree)) RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) diff --git a/code/datums/elements/ai_flee_while_injured.dm b/code/datums/elements/ai_flee_while_injured.dm index fc1a2e33281..0bbc08eb88b 100644 --- a/code/datums/elements/ai_flee_while_injured.dm +++ b/code/datums/elements/ai_flee_while_injured.dm @@ -32,14 +32,14 @@ return var/current_health_percentage = source.health / source.maxHealth - if (source.ai_controller.blackboard[BB_BASIC_MOB_FLEEING]) - if (current_health_percentage < stop_fleeing_at) + if (source.ai_controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) + if (current_health_percentage > start_fleeing_below) return - source.ai_controller.CancelActions() // Stop fleeing go back to whatever you were doing - source.ai_controller.set_blackboard_key(BB_BASIC_MOB_FLEEING, FALSE) + source.ai_controller.CancelActions() + source.ai_controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, FALSE) return - if (current_health_percentage > start_fleeing_below) + if (current_health_percentage < stop_fleeing_at) return - source.ai_controller.CancelActions() - source.ai_controller.set_blackboard_key(BB_BASIC_MOB_FLEEING, TRUE) + source.ai_controller.CancelActions() // Stop fleeing go back to whatever you were doing + source.ai_controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, TRUE) diff --git a/code/datums/elements/amputating_limbs.dm b/code/datums/elements/amputating_limbs.dm index c2fe7c454a9..f7e3d08fcc4 100644 --- a/code/datums/elements/amputating_limbs.dm +++ b/code/datums/elements/amputating_limbs.dm @@ -6,6 +6,10 @@ var/surgery_time /// What is the means by which we describe the act of amputation? var/surgery_verb + /// How awake must our target be? + var/minimum_stat + /// How likely are we to perform this action? + var/snip_chance /// The types of limb we can remove var/list/target_zones @@ -13,6 +17,8 @@ datum/target, surgery_time = 5 SECONDS, surgery_verb = "prying", + minimum_stat = SOFT_CRIT, + snip_chance = 100, list/target_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_ARM, BODY_ZONE_R_LEG), ) . = ..() @@ -23,6 +29,8 @@ src.surgery_time = surgery_time src.surgery_verb = surgery_verb + src.minimum_stat = minimum_stat + src.snip_chance = snip_chance src.target_zones = target_zones RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(try_amputate)) @@ -33,11 +41,11 @@ /// Called when you click on literally anything with your hands, see if it is an injured carbon and then try to cut it up /datum/element/amputating_limbs/proc/try_amputate(mob/living/surgeon, atom/victim) SIGNAL_HANDLER - if (!iscarbon(victim) || HAS_TRAIT(victim, TRAIT_NODISMEMBER)) + if (!iscarbon(victim) || HAS_TRAIT(victim, TRAIT_NODISMEMBER) || !prob(snip_chance)) return var/mob/living/carbon/limbed_victim = victim - if (limbed_victim.stat == CONSCIOUS) + if (limbed_victim.stat < minimum_stat) return if (DOING_INTERACTION_WITH_TARGET(surgeon, victim)) @@ -61,6 +69,6 @@ /// Chop one off /datum/element/amputating_limbs/proc/amputate(mob/living/surgeon, mob/living/carbon/victim, obj/item/bodypart/to_remove) surgeon.visible_message(span_warning("[surgeon] begins [surgery_verb] [to_remove] off of [victim]!")) - if (!do_after(surgeon, delay = surgery_time, target = victim)) + if (surgery_time > 0 && !do_after(surgeon, delay = surgery_time, target = victim)) return to_remove.dismember() diff --git a/code/datums/elements/food/microwavable.dm b/code/datums/elements/food/microwavable.dm index 3ad3e272d34..8e7305545c0 100644 --- a/code/datums/elements/food/microwavable.dm +++ b/code/datums/elements/food/microwavable.dm @@ -6,14 +6,18 @@ var/atom/default_typepath = /obj/item/food/badrecipe /// Resulting atom typepath on a completed microwave. var/atom/result_typepath + /// Reagents that should be added to the result + var/list/added_reagents -/datum/element/microwavable/Attach(datum/target, microwave_type) +/datum/element/microwavable/Attach(datum/target, microwave_type, list/reagents) . = ..() if(!isitem(target)) return ELEMENT_INCOMPATIBLE result_typepath = microwave_type || default_typepath + added_reagents = reagents + RegisterSignal(target, COMSIG_ITEM_MICROWAVE_ACT, PROC_REF(on_microwaved)) if(!ispath(result_typepath, default_typepath)) @@ -41,13 +45,15 @@ var/efficiency = istype(used_microwave) ? used_microwave.efficiency : 1 SEND_SIGNAL(result, COMSIG_ITEM_MICROWAVE_COOKED, source, efficiency) - if(IS_EDIBLE(result)) - if(microwaver && microwaver.mind) - ADD_TRAIT(result, TRAIT_FOOD_CHEF_MADE, REF(microwaver.mind)) + if(IS_EDIBLE(result) && (result_typepath != default_typepath)) + BLACKBOX_LOG_FOOD_MADE(result.type) result.reagents.clear_reagents() source.reagents?.trans_to(result, source.reagents.total_volume) + if(added_reagents) // Add any new reagents that should be added + result.reagents.add_reagent_list(added_reagents) - BLACKBOX_LOG_FOOD_MADE(result.type) + if(microwaver && microwaver.mind) + ADD_TRAIT(result, TRAIT_FOOD_CHEF_MADE, REF(microwaver.mind)) qdel(source) diff --git a/code/datums/elements/footstep.dm b/code/datums/elements/footstep.dm index 6c55b595563..3a0a9961843 100644 --- a/code/datums/elements/footstep.dm +++ b/code/datums/elements/footstep.dm @@ -40,6 +40,8 @@ footstep_sounds = GLOB.heavyfootstep if(FOOTSTEP_MOB_SHOE) footstep_sounds = GLOB.footstep + if(FOOTSTEP_MOB_RUST) + footstep_sounds = 'sound/effects/footstep/rustystep1.ogg' if(FOOTSTEP_MOB_SLIME) footstep_sounds = 'sound/effects/footstep/slime1.ogg' if(FOOTSTEP_OBJ_MACHINE) @@ -64,11 +66,12 @@ if(!istype(turf)) return - if(!turf.footstep || source.buckled || source.throwing || source.movement_type & (VENTCRAWLING | FLYING) || HAS_TRAIT(source, TRAIT_IMMOBILIZED) || CHECK_MOVE_LOOP_FLAGS(source, MOVEMENT_LOOP_OUTSIDE_CONTROL)) + if(source.buckled || source.throwing || source.movement_type & (VENTCRAWLING | FLYING) || HAS_TRAIT(source, TRAIT_IMMOBILIZED) || CHECK_MOVE_LOOP_FLAGS(source, MOVEMENT_LOOP_OUTSIDE_CONTROL)) return if(source.body_position == LYING_DOWN) //play crawling sound if we're lying - playsound(turf, 'sound/effects/footstep/crawl1.ogg', 15 * volume, falloff_distance = 1, vary = sound_vary) + if(turf.footstep) + playsound(turf, 'sound/effects/footstep/crawl1.ogg', 15 * volume, falloff_distance = 1, vary = sound_vary) return if(iscarbon(source)) @@ -92,6 +95,9 @@ . = list(FOOTSTEP_MOB_SHOE = turf.footstep, FOOTSTEP_MOB_BAREFOOT = turf.barefootstep, FOOTSTEP_MOB_HEAVY = turf.heavyfootstep, FOOTSTEP_MOB_CLAW = turf.clawfootstep, STEP_SOUND_PRIORITY = STEP_SOUND_NO_PRIORITY) SEND_SIGNAL(turf, COMSIG_TURF_PREPARE_STEP_SOUND, .) + //The turf has no footstep sound (e.g. open space) and none of the objects on that turf (e.g. catwalks) overrides it + if(isnull(turf.footstep)) + return null return . /datum/element/footstep/proc/play_simplestep(mob/living/source, atom/oldloc, direction, forced, list/old_locs, momentum_change) diff --git a/code/datums/mapgen/Cavegens/IcemoonCaves.dm b/code/datums/mapgen/Cavegens/IcemoonCaves.dm index 7d7437ccda6..b0fcd471db2 100644 --- a/code/datums/mapgen/Cavegens/IcemoonCaves.dm +++ b/code/datums/mapgen/Cavegens/IcemoonCaves.dm @@ -62,12 +62,12 @@ weighted_closed_turf_types = list(/turf/closed/mineral/random/snow/underground = 1) weighted_mob_spawn_list = list( SPAWN_MEGAFAUNA = 1, + /mob/living/basic/mining/ice_demon = 100, /mob/living/basic/mining/ice_whelp = 60, /mob/living/basic/mining/legion/snow = 100, - /mob/living/simple_animal/hostile/asteroid/ice_demon = 100, /obj/structure/spawner/ice_moon/demonic_portal = 6, - /obj/structure/spawner/ice_moon/demonic_portal/snowlegion = 6, /obj/structure/spawner/ice_moon/demonic_portal/ice_whelp = 6, + /obj/structure/spawner/ice_moon/demonic_portal/snowlegion = 6, ) weighted_megafauna_spawn_list = list(/mob/living/simple_animal/hostile/megafauna/colossus = 1) weighted_flora_spawn_list = list( diff --git a/code/datums/memory/_memory.dm b/code/datums/memory/_memory.dm index 66871aac2ec..e3f161d5f0e 100644 --- a/code/datums/memory/_memory.dm +++ b/code/datums/memory/_memory.dm @@ -256,6 +256,7 @@ /mob/living/basic/cow, /mob/living/basic/cow/wisdom, /mob/living/basic/crab, + /mob/living/basic/goat, /mob/living/basic/headslug, /mob/living/basic/killer_tomato, /mob/living/basic/lizard, @@ -275,7 +276,6 @@ /mob/living/basic/stickman/dog, /mob/living/simple_animal/hostile/gorilla, /mob/living/simple_animal/hostile/megafauna/dragon/lesser, - /mob/living/simple_animal/hostile/retaliate/goat, /mob/living/simple_animal/parrot, /mob/living/simple_animal/pet/cat, /mob/living/simple_animal/pet/cat/cak, diff --git a/code/datums/station_traits/neutral_traits.dm b/code/datums/station_traits/neutral_traits.dm index f57f6c2e9dd..26bbc689afa 100644 --- a/code/datums/station_traits/neutral_traits.dm +++ b/code/datums/station_traits/neutral_traits.dm @@ -158,8 +158,8 @@ /datum/station_trait/cargorilla/proc/replace_cargo(datum/source) SIGNAL_HANDLER - var/mob/living/simple_animal/sloth/cargo_sloth = GLOB.cargo_sloth - if(!cargo_sloth) + var/mob/living/basic/sloth/cargo_sloth = GLOB.cargo_sloth + if(isnull(cargo_sloth)) return cargorilla = new(cargo_sloth.loc) diff --git a/code/datums/status_effects/debuffs/fire_stacks.dm b/code/datums/status_effects/debuffs/fire_stacks.dm index 112e8bd8614..6f31faaefaa 100644 --- a/code/datums/status_effects/debuffs/fire_stacks.dm +++ b/code/datums/status_effects/debuffs/fire_stacks.dm @@ -147,7 +147,10 @@ if(!on_fire) return TRUE - adjust_stacks(owner.fire_stack_decay_rate * seconds_between_ticks) + if(HAS_TRAIT(owner, TRAIT_HUSK)) + adjust_stacks(-2 * seconds_between_ticks) + else + adjust_stacks(owner.fire_stack_decay_rate * seconds_between_ticks) if(stacks <= 0) qdel(src) diff --git a/code/datums/status_effects/drug_effects.dm b/code/datums/status_effects/drug_effects.dm index d01a92743b5..1d37c8f0e43 100644 --- a/code/datums/status_effects/drug_effects.dm +++ b/code/datums/status_effects/drug_effects.dm @@ -70,7 +70,7 @@ /datum/status_effect/stoned/on_apply() if(!ishuman(owner)) - CRASH("[type] status effect added to non-human owner: [owner ? owner.type : "null owner"]") + return FALSE var/mob/living/carbon/human/human_owner = owner original_eye_color_left = human_owner.eye_color_left original_eye_color_right = human_owner.eye_color_right @@ -85,7 +85,7 @@ /datum/status_effect/stoned/on_remove() if(!ishuman(owner)) - stack_trace("[type] status effect being removed from non-human owner: [owner ? owner.type : "null owner"]") + return var/mob/living/carbon/human/human_owner = owner human_owner.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/cannabis) human_owner.eye_color_left = original_eye_color_left diff --git a/code/datums/world_topic.dm b/code/datums/world_topic.dm index 265b9d49815..d930c496de6 100644 --- a/code/datums/world_topic.dm +++ b/code/datums/world_topic.dm @@ -195,7 +195,7 @@ /datum/world_topic/status/Run(list/input) . = list() .["version"] = GLOB.game_version - .["respawn"] = config ? !CONFIG_GET(flag/norespawn) : FALSE + .["respawn"] = config ? !!CONFIG_GET(flag/allow_respawn) : FALSE // show respawn as true regardless of "respawn as char" or "free respawn" .["enter"] = !LAZYACCESS(SSlag_switch.measures, DISABLE_NON_OBSJOBS) .["ai"] = CONFIG_GET(flag/allow_ai) .["host"] = world.host ? world.host : null @@ -240,4 +240,3 @@ // Shuttle status, see /__DEFINES/stat.dm .["shuttle_timer"] = SSshuttle.emergency.timeLeft() // Shuttle timer, in seconds - diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm index 89b7ba5762b..fb543aa009e 100644 --- a/code/datums/wounds/_wounds.dm +++ b/code/datums/wounds/_wounds.dm @@ -435,7 +435,7 @@ else limp_slowdown = initial(limp_slowdown) limp_chance = initial(limp_chance) - else if(limb.body_zone in list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + else if(limb.body_zone in GLOB.arm_zones) if(limb.current_gauze?.splint_factor) set_interaction_efficiency_penalty(1 + ((get_effective_actionspeed_modifier()) * limb.current_gauze.splint_factor)) else diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 5a604cd969b..54e622fb12d 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -82,17 +82,18 @@ /obj/machinery/computer/security/ui_data() var/list/data = list() - data["network"] = network data["activeCamera"] = null if(active_camera) data["activeCamera"] = list( name = active_camera.c_tag, + ref = REF(active_camera), status = active_camera.status, ) return data /obj/machinery/computer/security/ui_static_data() var/list/data = list() + data["network"] = network data["mapRef"] = cam_screen.assigned_map var/list/cameras = get_camera_list(network) data["cameras"] = list() @@ -100,6 +101,7 @@ var/obj/machinery/camera/C = cameras[i] data["cameras"] += list(list( name = C.c_tag, + ref = REF(C), )) return data @@ -110,13 +112,11 @@ return if(action == "switch_camera") - var/c_tag = params["name"] - var/list/cameras = get_camera_list(network) - var/obj/machinery/camera/selected_camera = cameras[c_tag] + var/obj/machinery/camera/selected_camera = locate(params["camera"]) in GLOB.cameranet.cameras active_camera = selected_camera playsound(src, get_sfx(SFX_TERMINAL_TYPE), 25, FALSE) - if(!selected_camera) + if(isnull(active_camera)) return TRUE update_active_camera_screen() diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index c433565dbf8..2d33779f6ab 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -135,6 +135,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) JOB_SHAFT_MINER = 51, JOB_CARGO_TECHNICIAN = 52, JOB_CUSTOMS_AGENT = 53, // SKYRAT EDIT ADDITION + JOB_BITRUNNER = 54, // 60+: Civilian/other JOB_HEAD_OF_PERSONNEL = 60, JOB_BARTENDER = 61, diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index 4b49e7ee963..7eb1163871e 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -49,7 +49,7 @@ return if (deconstruction != BLASTDOOR_FINISHED) return - var/change_id = tgui_input_number(user, "Set the door controllers ID", "Door Controller ID", id, 100) + var/change_id = tgui_input_text(user, "Set the door controllers ID", "Door Controller ID", id, 100) if(!change_id || QDELETED(usr) || QDELETED(src) || !usr.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return id = change_id diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm index 63a48dcd976..1a16c00e42d 100644 --- a/code/game/machinery/harvester.dm +++ b/code/game/machinery/harvester.dm @@ -75,21 +75,18 @@ /obj/machinery/harvester/proc/can_harvest() if(!powered() || state_open || !occupant || !iscarbon(occupant)) return - var/mob/living/carbon/C = occupant + var/mob/living/carbon/carbon_occupant = occupant if(!allow_clothing) - for(var/A in C.held_items + C.get_equipped_items()) - if(!isitem(A)) - continue - var/obj/item/I = A - if(!(HAS_TRAIT(I, TRAIT_NODROP))) + for(var/obj/item/abiotic_item in carbon_occupant.held_items + carbon_occupant.get_equipped_items()) + if(!(HAS_TRAIT(abiotic_item, TRAIT_NODROP))) say("Subject may not have abiotic items on.") playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE) return - if(!(C.mob_biotypes & MOB_ORGANIC)) + if(!(carbon_occupant.mob_biotypes & MOB_ORGANIC)) say("Subject is not organic.") playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE) return - if(!allow_living && !(C.stat == DEAD || HAS_TRAIT(C, TRAIT_FAKEDEATH))) //I mean, the machines scanners arent advanced enough to tell you're alive + if(!allow_living && !(carbon_occupant.stat == DEAD || HAS_TRAIT(carbon_occupant, TRAIT_FAKEDEATH))) //I mean, the machines scanners arent advanced enough to tell you're alive say("Subject is still alive.") playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE) return @@ -124,21 +121,21 @@ end_harvesting(success = FALSE) return playsound(src, 'sound/machines/juicer.ogg', 20, TRUE) - var/mob/living/carbon/C = occupant + var/mob/living/carbon/carbon_occupant = occupant if(!LAZYLEN(operation_order)) //The list is empty, so we're done here end_harvesting(success = TRUE) return var/turf/target = get_step(src, output_dir) - for(var/obj/item/bodypart/BP in operation_order) //first we do non-essential limbs - BP.drop_limb() - C.emote("scream") - if(BP.body_zone != "chest") - BP.forceMove(target) //Move the limbs right next to it, except chest, that's a weird one - BP.drop_organs() + for(var/obj/item/bodypart/limb_to_remove as anything in operation_order) //first we do non-essential limbs + limb_to_remove.drop_limb() + carbon_occupant.emote("scream") + if(limb_to_remove.body_zone != "chest") + limb_to_remove.forceMove(target) //Move the limbs right next to it, except chest, that's a weird one + limb_to_remove.drop_organs() else - for(var/obj/item/organ/O in BP.dismember()) - O.forceMove(target) //Some organs, like chest ones, are different so we need to manually move them - operation_order.Remove(BP) + for(var/obj/item/organ/organ_to_remove in limb_to_remove.dismember()) + organ_to_remove.forceMove(target) //Some organs, like chest ones, are different so we need to manually move them + operation_order.Remove(limb_to_remove) break use_power(active_power_usage) addtimer(CALLBACK(src, PROC_REF(harvest)), interval) @@ -154,7 +151,7 @@ say("Subject has been successfully harvested.") playsound(src, 'sound/machines/microwave/microwave-end.ogg', 100, FALSE) -/obj/machinery/harvester/screwdriver_act(mob/living/user, obj/item/I) +/obj/machinery/harvester/screwdriver_act(mob/living/user, obj/item/tool) . = TRUE if(..()) return @@ -164,20 +161,20 @@ if(state_open) to_chat(user, span_warning("[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!")) return - if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I)) + if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), tool)) return return FALSE -/obj/machinery/harvester/crowbar_act(mob/living/user, obj/item/I) - if(default_pry_open(I)) +/obj/machinery/harvester/crowbar_act(mob/living/user, obj/item/tool) + if(default_pry_open(tool)) return TRUE - if(default_deconstruction_crowbar(I)) + if(default_deconstruction_crowbar(tool)) return TRUE -/obj/machinery/harvester/default_pry_open(obj/item/I) //wew - . = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR //We removed is_operational here +/obj/machinery/harvester/default_pry_open(obj/item/tool) //wew + . = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && tool.tool_behaviour == TOOL_CROWBAR //We removed is_operational here if(.) - I.play_tool_sound(src, 50) + tool.play_tool_sound(src, 50) visible_message(span_notice("[usr] pries open \the [src]."), span_notice("You pry open [src].")) open_machine() diff --git a/code/game/objects/effects/spiderwebs.dm b/code/game/objects/effects/spiderwebs.dm index 3bdac03396f..c27ff9b302a 100644 --- a/code/game/objects/effects/spiderwebs.dm +++ b/code/game/objects/effects/spiderwebs.dm @@ -174,11 +174,11 @@ /obj/structure/spider/sticky/CanAllowThrough(atom/movable/mover, border_dir) . = ..() - if(isspider(mover)) + if(HAS_TRAIT(mover, TRAIT_WEB_SURFER)) return TRUE if(!isliving(mover)) return - if(isspider(mover.pulledby)) + if(HAS_TRAIT(mover.pulledby, TRAIT_WEB_SURFER)) return TRUE loc.balloon_alert(mover, "stuck in web!") return FALSE diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index eabf8681104..9dd7e125055 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -32,6 +32,7 @@ lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' w_class = WEIGHT_CLASS_TINY + /// Cached icon that has been built for this card. Intended to be displayed in chat. Cardboards IDs and actual IDs use it. var/icon/cached_flat_icon @@ -757,10 +758,10 @@ break /obj/item/card/id/examine_more(mob/user) + . = ..() if(!user.can_read(src)) return - . = ..() . += span_notice("You examine [src] closer, and note the following...") if(registered_age) diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index 0338da6b4fa..79efe62a225 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -605,8 +605,3 @@ name = "Medical Order" greyscale_colors = CIRCUIT_COLOR_SUPPLY build_path = /obj/machinery/computer/department_orders/medical - -/obj/item/circuitboard/computer/quantum_console - name = "Quantum Server Console" - greyscale_colors = CIRCUIT_COLOR_SUPPLY - build_path = /obj/machinery/computer/quantum_console diff --git a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm index 9ece80f0940..917589d8dfb 100644 --- a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm @@ -1535,21 +1535,3 @@ /obj/item/stack/sheet/plasteel = 2, ) -/obj/item/circuitboard/machine/quantum_server - name = "Quantum Server" - greyscale_colors = CIRCUIT_COLOR_SUPPLY - build_path = /obj/machinery/quantum_server - req_components = list( - /datum/stock_part/servo = 2, - /datum/stock_part/scanning_module = 1, - /datum/stock_part/capacitor = 1, - ) - -/obj/item/circuitboard/machine/netpod - name = "Netpod" - greyscale_colors = CIRCUIT_COLOR_SUPPLY - build_path = /obj/machinery/netpod - req_components = list( - /datum/stock_part/servo = 1, - /datum/stock_part/matter_bin = 2, - ) diff --git a/code/game/objects/items/devices/polycircuit.dm b/code/game/objects/items/devices/polycircuit.dm index 9dbdbff993d..5b7fd42d6f6 100644 --- a/code/game/objects/items/devices/polycircuit.dm +++ b/code/game/objects/items/devices/polycircuit.dm @@ -51,7 +51,7 @@ else to_chat(user, span_notice("You navigate the sharp edges of circuitry and remove a single board from [src]")) else - H.apply_damage(15, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + H.apply_damage(15, BRUTE, pick(GLOB.arm_zones)) to_chat(user, span_warning("You give yourself a wicked cut on [src]'s many sharp corners and edges!")) /obj/item/stack/circuit_stack/full diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index dcb7ddc1936..5fe777f20dc 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -20,7 +20,7 @@ unscrewed = TRUE /obj/item/radio/intercom/prison - name = "prison intercom" + name = "receive-only intercom" desc = "A station intercom. It looks like it has been modified to not broadcast." /obj/item/radio/intercom/prison/Initialize(mapload, ndir, building) diff --git a/code/game/objects/items/food/donkpocket.dm b/code/game/objects/items/food/donkpocket.dm index f2495e0ee52..d4b4636f15c 100644 --- a/code/game/objects/items/food/donkpocket.dm +++ b/code/game/objects/items/food/donkpocket.dm @@ -20,12 +20,16 @@ var/baking_time_short = 25 SECONDS /// The upper end for how long it takes to bake var/baking_time_long = 30 SECONDS + /// The reagents added when microwaved. Needed since microwaving ignores food_reagents + var/static/list/added_reagents = list(/datum/reagent/medicine/omnizine = 6) + /// The reagents that most child types add when microwaved. Needed because you can't override static lists. + var/static/list/child_added_reagents = list(/datum/reagent/medicine/omnizine = 2) /obj/item/food/donkpocket/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE) + AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, added_reagents) /obj/item/food/donkpocket/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type) + AddElement(/datum/element/microwavable, warm_type, added_reagents) /obj/item/food/donkpocket/warm name = "warm Donk-pocket" @@ -69,6 +73,12 @@ foodtypes = GRAIN warm_type = /obj/item/food/donkpocket/warm/spicy +/obj/item/food/donkpocket/spicy/make_bakeable() + AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, child_added_reagents) + +/obj/item/food/donkpocket/spicy/make_microwaveable() + AddElement(/datum/element/microwavable, warm_type, child_added_reagents) + /obj/item/food/donkpocket/warm/spicy name = "warm Spicy-pocket" desc = "The classic snack food, now maybe a bit too spicy." @@ -95,6 +105,12 @@ foodtypes = GRAIN warm_type = /obj/item/food/donkpocket/warm/teriyaki +/obj/item/food/donkpocket/teriyaki/make_bakeable() + AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, child_added_reagents) + +/obj/item/food/donkpocket/teriyaki/make_microwaveable() + AddElement(/datum/element/microwavable, warm_type, child_added_reagents) + /obj/item/food/donkpocket/warm/teriyaki name = "warm Teriyaki-pocket" desc = "An east-asian take on the classic stationside snack, now steamy and warm." @@ -121,6 +137,12 @@ foodtypes = GRAIN warm_type = /obj/item/food/donkpocket/warm/pizza +/obj/item/food/donkpocket/pizza/make_bakeable() + AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, child_added_reagents) + +/obj/item/food/donkpocket/pizza/make_microwaveable() + AddElement(/datum/element/microwavable, warm_type, child_added_reagents) + /obj/item/food/donkpocket/warm/pizza name = "warm Pizza-pocket" desc = "Delicious, cheesy, and even better when hot." @@ -146,6 +168,16 @@ foodtypes = GRAIN warm_type = /obj/item/food/donkpocket/warm/honk crafting_complexity = FOOD_COMPLEXITY_3 + var/static/list/honk_added_reagents = list( + /datum/reagent/medicine/omnizine = 2, + /datum/reagent/consumable/laughter = 6, + ) + +/obj/item/food/donkpocket/honk/make_bakeable() + AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, honk_added_reagents) + +/obj/item/food/donkpocket/honk/make_microwaveable() + AddElement(/datum/element/microwavable, warm_type, honk_added_reagents) /obj/item/food/donkpocket/warm/honk name = "warm Honk-pocket" @@ -173,6 +205,12 @@ foodtypes = GRAIN warm_type = /obj/item/food/donkpocket/warm/berry +/obj/item/food/donkpocket/berry/make_bakeable() + AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, child_added_reagents) + +/obj/item/food/donkpocket/berry/make_microwaveable() + AddElement(/datum/element/microwavable, warm_type, child_added_reagents) + /obj/item/food/donkpocket/warm/berry name = "warm Berry-pocket" desc = "A relentlessly sweet donk-pocket, now warm and delicious." @@ -198,6 +236,16 @@ foodtypes = GRAIN warm_type = /obj/item/food/donkpocket/warm/gondola + var/static/list/gondola_added_reagents = list( + /datum/reagent/medicine/omnizine = 2, + /datum/reagent/gondola_mutation_toxin = 5, + ) + +/obj/item/food/donkpocket/gondola/make_bakeable() + AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, gondola_added_reagents) + +/obj/item/food/donkpocket/gondola/make_microwaveable() + AddElement(/datum/element/microwavable, warm_type, gondola_added_reagents) /obj/item/food/donkpocket/warm/gondola name = "warm Gondola-pocket" diff --git a/code/game/objects/items/food/moth.dm b/code/game/objects/items/food/moth.dm index 3bb3c8738d4..41c2d8ec3a1 100644 --- a/code/game/objects/items/food/moth.dm +++ b/code/game/objects/items/food/moth.dm @@ -522,7 +522,7 @@ desc = "A salad with added cotton and a basic dressing. Presumably either moths are around, or the South's risen again." icon = 'icons/obj/food/moth.dmi' icon_state = "cotton_salad" - food_reagents = list(, + food_reagents = list( /datum/reagent/consumable/nutriment = 8, /datum/reagent/consumable/nutriment/vitamin = 14, ) diff --git a/code/game/objects/items/food/packaged.dm b/code/game/objects/items/food/packaged.dm index edcc0bd09ed..9c23ac3f307 100644 --- a/code/game/objects/items/food/packaged.dm +++ b/code/game/objects/items/food/packaged.dm @@ -209,11 +209,14 @@ /// What type of ready-donk are we warmed into? var/warm_type = /obj/item/food/ready_donk/warm + /// What reagents should be added when this item is warmed? + var/static/list/added_reagents = list(/datum/reagent/medicine/omnizine = 3) + /obj/item/food/ready_donk/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(15 SECONDS, 20 SECONDS), TRUE, TRUE) + AddComponent(/datum/component/bakeable, warm_type, rand(15 SECONDS, 20 SECONDS), TRUE, TRUE, added_reagents) /obj/item/food/ready_donk/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type) + AddElement(/datum/element/microwavable, warm_type, added_reagents) /obj/item/food/ready_donk/examine_more(mob/user) . = ..() diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm index fc80355a7cc..9bf33e36f2f 100644 --- a/code/game/objects/items/puzzle_pieces.dm +++ b/code/game/objects/items/puzzle_pieces.dm @@ -61,6 +61,19 @@ fire = 100 acid = 100 +/obj/machinery/door/puzzle/Initialize(mapload) + . = ..() + RegisterSignal(SSdcs, COMSIG_GLOB_PUZZLE_COMPLETED, PROC_REF(try_signal)) + +/obj/machinery/door/puzzle/Destroy(force) + . = ..() + UnregisterSignal(SSdcs, COMSIG_GLOB_PUZZLE_COMPLETED) + +/obj/machinery/door/puzzle/proc/try_signal(datum/source, try_id) + SIGNAL_HANDLER + + INVOKE_ASYNC(src, PROC_REF(try_puzzle_open), try_id) + /obj/machinery/door/puzzle/Bumped(atom/movable/AM) return !density && ..() @@ -111,15 +124,6 @@ /obj/machinery/door/puzzle/light desc = "This door only opens when a linked mechanism is powered. It looks virtually indestructible." -/obj/machinery/door/puzzle/light/Initialize(mapload) - . = ..() - RegisterSignal(SSdcs, COMSIG_GLOB_LIGHT_MECHANISM_COMPLETED, PROC_REF(check_mechanism)) - -/obj/machinery/door/puzzle/light/proc/check_mechanism(datum/source, try_id) - SIGNAL_HANDLER - - INVOKE_ASYNC(src, PROC_REF(try_puzzle_open), try_id) - //************************* //***Box Pushing Puzzles*** //************************* @@ -268,5 +272,5 @@ return visible_message(span_boldnotice("[src] becomes fully charged!")) powered = TRUE - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIGHT_MECHANISM_COMPLETED, puzzle_id) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_PUZZLE_COMPLETED, puzzle_id) playsound(src, 'sound/machines/synth_yes.ogg', 100, TRUE) diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index dc5f052c13b..abd9f8efb2f 100644 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -694,6 +694,7 @@ atom_storage.max_slots = 6 atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL // Set to this so the light replacer can fit. atom_storage.set_holdable(list( + /obj/item/access_key, /obj/item/assembly/mousetrap, /obj/item/clothing/gloves, /obj/item/flashlight, diff --git a/code/game/objects/items/tail_pin.dm b/code/game/objects/items/tail_pin.dm index 3052075c94d..de3148dd06d 100644 --- a/code/game/objects/items/tail_pin.dm +++ b/code/game/objects/items/tail_pin.dm @@ -2,7 +2,7 @@ icon = 'icons/obj/poster.dmi' icon_state = "tailpin" name = "tail pin" - desc = "Offically branded 'pin the tail on the corgi' style party implement. Not intended to be used on people." + desc = "Officially branded 'pin the tail on the corgi' style party implement. Not intended to be used on people." force = 0 w_class = WEIGHT_CLASS_SMALL throwforce = 0 diff --git a/code/game/objects/structures/fireaxe.dm b/code/game/objects/structures/fireaxe.dm index 59a00618b0e..31ba1cd47aa 100644 --- a/code/game/objects/structures/fireaxe.dm +++ b/code/game/objects/structures/fireaxe.dm @@ -211,6 +211,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/fireaxecabinet, 32) /obj/structure/fireaxecabinet/empty populate_contents = FALSE +MAPPING_DIRECTIONAL_HELPERS(/obj/structure/fireaxecabinet/empty, 32) + /obj/item/wallframe/fireaxecabinet name = "fire axe cabinet" desc = "Home to a window's greatest nightmare. Apply to wall to use." @@ -238,6 +240,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/fireaxecabinet/mechremoval, 32) /obj/structure/fireaxecabinet/mechremoval/empty populate_contents = FALSE +MAPPING_DIRECTIONAL_HELPERS(/obj/structure/fireaxecabinet/mechremoval/empty, 32) + /obj/item/wallframe/fireaxecabinet/mechremoval name = "mech removal tool cabinet" desc = "Home to a very special crowbar. Apply to wall to use." diff --git a/code/game/objects/structures/icemoon/cave_entrance.dm b/code/game/objects/structures/icemoon/cave_entrance.dm index 7393c20758e..add1f278569 100644 --- a/code/game/objects/structures/icemoon/cave_entrance.dm +++ b/code/game/objects/structures/icemoon/cave_entrance.dm @@ -20,6 +20,9 @@ GLOBAL_LIST_INIT(ore_probability, list( mob_types = list(/mob/living/simple_animal/hostile/asteroid/wolf) move_resist = INFINITY anchored = TRUE + scanner_taggable = TRUE + mob_gps_id = "WF" // wolf + spawner_gps_id = "Animal Den" /obj/structure/spawner/ice_moon/Initialize(mapload) . = ..() @@ -65,6 +68,7 @@ GLOBAL_LIST_INIT(ore_probability, list( max_mobs = 1 spawn_time = 60 SECONDS mob_types = list(/mob/living/simple_animal/hostile/asteroid/polarbear) + mob_gps_id = "BR" // bear /obj/structure/spawner/ice_moon/polarbear/clear_rock() for(var/turf/potential in RANGE_TURFS(1, src)) @@ -76,9 +80,11 @@ GLOBAL_LIST_INIT(ore_probability, list( name = "demonic portal" desc = "A portal that goes to another world, normal creatures couldn't survive there." icon_state = "nether" - mob_types = list(/mob/living/simple_animal/hostile/asteroid/ice_demon) + mob_types = list(/mob/living/basic/mining/ice_demon) light_range = 1 light_color = COLOR_SOFT_RED + mob_gps_id = "WT|B" // watcher | bluespace + spawner_gps_id = "Netheric Distortion" /obj/structure/spawner/ice_moon/demonic_portal/Initialize(mapload) . = ..() @@ -100,9 +106,11 @@ GLOBAL_LIST_INIT(ore_probability, list( /obj/structure/spawner/ice_moon/demonic_portal/ice_whelp mob_types = list(/mob/living/basic/mining/ice_whelp) + mob_gps_id = "ID|W" // ice drake | whelp /obj/structure/spawner/ice_moon/demonic_portal/snowlegion mob_types = list(/mob/living/basic/mining/legion/snow/spawner_made) + mob_gps_id = "LG|S" // legion | snow /obj/effect/collapsing_demonic_portal name = "collapsing demonic portal" diff --git a/code/game/objects/structures/lavaland/necropolis_tendril.dm b/code/game/objects/structures/lavaland/necropolis_tendril.dm index 22f7f0422cd..6d6b2e6af37 100644 --- a/code/game/objects/structures/lavaland/necropolis_tendril.dm +++ b/code/game/objects/structures/lavaland/necropolis_tendril.dm @@ -14,19 +14,22 @@ move_resist=INFINITY // just killing it tears a massive hole in the ground, let's not move it anchored = TRUE resistance_flags = FIRE_PROOF | LAVA_PROOF - - var/gps = null var/obj/effect/light_emitter/tendril/emitted_light - + scanner_taggable = TRUE + mob_gps_id = "WT" + spawner_gps_id = "Necropolis Tendril" /obj/structure/spawner/lavaland/goliath mob_types = list(/mob/living/basic/mining/goliath) + mob_gps_id = "GL" /obj/structure/spawner/lavaland/legion mob_types = list(/mob/living/basic/mining/legion/spawner_made) + mob_gps_id = "LG" /obj/structure/spawner/lavaland/icewatcher mob_types = list(/mob/living/basic/mining/watcher/icewing) + mob_gps_id = "WT|I" // icewing GLOBAL_LIST_INIT(tendrils, list()) /obj/structure/spawner/lavaland/Initialize(mapload) @@ -63,7 +66,6 @@ GLOBAL_LIST_INIT(tendrils, list()) L.client.give_award(/datum/award/score/tendril_score, L) //Progresses score by one GLOB.tendrils -= src QDEL_NULL(emitted_light) - QDEL_NULL(gps) return ..() /obj/effect/light_emitter/tendril diff --git a/code/game/objects/structures/spawner.dm b/code/game/objects/structures/spawner.dm index 340bcf212de..2ad70bdbc84 100644 --- a/code/game/objects/structures/spawner.dm +++ b/code/game/objects/structures/spawner.dm @@ -14,6 +14,52 @@ var/spawn_text = "emerges from" var/faction = list(FACTION_HOSTILE) var/spawner_type = /datum/component/spawner + /// Is this spawner taggable with something? + var/scanner_taggable = FALSE + /// If this spawner's taggable, what can we tag it with? + var/static/list/scanner_types = list(/obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner) + /// If this spawner's taggable, what's the text we use to describe what we can tag it with? + var/scanner_descriptor = "mining analyzer" + /// Has this spawner been tagged/analyzed by a mining scanner? + var/gps_tagged = FALSE + /// A short identifier for the mob it spawns. Keep around 3 characters or less? + var/mob_gps_id = "???" + /// A short identifier for what kind of spawner it is, for use in putting together its GPS tag. + var/spawner_gps_id = "Creature Nest" + /// A complete identifier. Generated on tag (if tagged), used for its examine. + var/assigned_tag + +/obj/structure/spawner/examine(mob/user) + . = ..() + if(!scanner_taggable) + return + if(gps_tagged) + . += span_notice("A holotag's been attached, projecting \"[assigned_tag]\".") + else + . += span_notice("It looks like you could probably scan and tag it with a [scanner_descriptor].") + +/obj/structure/spawner/attackby(obj/item/item, mob/user, params) + . = ..() + if(.) + return TRUE + if(scanner_taggable && is_type_in_list(item, scanner_types)) + gps_tag(user) + return TRUE + +/// Tag the spawner, prefixing its GPS entry with an identifier - or giving it one, if nonexistent. +/obj/structure/spawner/proc/gps_tag(mob/user) + if(gps_tagged) + to_chat(user, span_warning("[src] already has a holotag attached!")) + return + to_chat(user, span_notice("You affix a holotag to [src].")) + playsound(src, 'sound/machines/twobeep.ogg', 100) + gps_tagged = TRUE + assigned_tag = "\[[mob_gps_id]-[rand(100,999)]\] " + spawner_gps_id + var/datum/component/gps/our_gps = GetComponent(/datum/component/gps) + if(our_gps) + our_gps.gpstag = assigned_tag + return + AddComponent(/datum/component/gps, assigned_tag) /obj/structure/spawner/Initialize(mapload) . = ..() @@ -32,6 +78,8 @@ spawn_text = "warps in from" mob_types = list(/mob/living/basic/syndicate/ranged) faction = list(ROLE_SYNDICATE) + mob_gps_id = "SYN" // syndicate + spawner_gps_id = "Hostile Warp Beacon" /obj/structure/spawner/skeleton name = "bone pit" @@ -44,6 +92,8 @@ mob_types = list(/mob/living/simple_animal/hostile/skeleton) spawn_text = "climbs out of" faction = list(FACTION_SKELETON) + mob_gps_id = "SKL" // skeletons + spawner_gps_id = "Bone Pit" /obj/structure/spawner/clown name = "Laughing Larry" @@ -67,6 +117,8 @@ ) spawn_text = "climbs out of" faction = list(FACTION_CLOWN) + mob_gps_id = "???" // clowns + spawner_gps_id = "Clown Planet Distortion" /obj/structure/spawner/mining name = "monster den" @@ -80,7 +132,7 @@ /mob/living/basic/mining/basilisk, /mob/living/basic/mining/goldgrub, /mob/living/basic/mining/goliath/ancient, - /mob/living/basic/mining/legion, + /mob/living/basic/mining/hivelord, /mob/living/basic/wumborian_fugu, ) faction = list(FACTION_MINING) @@ -89,26 +141,31 @@ name = "goldgrub den" desc = "A den housing a nest of goldgrubs, annoying but arguably much better than anything else you'll find in a nest." mob_types = list(/mob/living/basic/mining/goldgrub) + mob_gps_id = "GG" /obj/structure/spawner/mining/goliath name = "goliath den" desc = "A den housing a nest of goliaths, oh god why?" mob_types = list(/mob/living/basic/mining/goliath/ancient) + mob_gps_id = "GL|A" /obj/structure/spawner/mining/hivelord name = "hivelord den" desc = "A den housing a nest of hivelords." mob_types = list(/mob/living/basic/mining/hivelord) + mob_gps_id = "HL" /obj/structure/spawner/mining/basilisk name = "basilisk den" desc = "A den housing a nest of basilisks, bring a coat." mob_types = list(/mob/living/basic/mining/basilisk) + mob_gps_id = "BK" /obj/structure/spawner/mining/wumborian name = "wumborian fugu den" desc = "A den housing a nest of wumborian fugus, how do they all even fit in there?" mob_types = list(/mob/living/basic/wumborian_fugu) + mob_gps_id = "WF" /obj/structure/spawner/nether name = "netherworld link" @@ -125,6 +182,9 @@ /mob/living/basic/migo, ) faction = list(FACTION_NETHER) + scanner_taggable = TRUE + mob_gps_id = "?!?" + spawner_gps_id = "Netheric Distortion" /obj/structure/spawner/nether/Initialize(mapload) . = ..() diff --git a/code/game/turfs/open/chasm.dm b/code/game/turfs/open/chasm.dm index 4c8ac12202d..49f6663d097 100644 --- a/code/game/turfs/open/chasm.dm +++ b/code/game/turfs/open/chasm.dm @@ -105,7 +105,6 @@ icon = 'icons/turf/floors/junglechasm.dmi' icon_state = "junglechasm-255" base_icon_state = "junglechasm" - initial_gas_mix = OPENTURF_LOW_PRESSURE planetary_atmos = TRUE baseturfs = /turf/open/chasm/jungle diff --git a/code/game/turfs/open/planet.dm b/code/game/turfs/open/planet.dm index e5ab02c0924..65c76cef957 100644 --- a/code/game/turfs/open/planet.dm +++ b/code/game/turfs/open/planet.dm @@ -18,14 +18,27 @@ name = "dirt flooring" //FOR THE LOVE OF GOD USE THIS INSTEAD OF DIRT FOR STATION MAPS desc = "You heard this place was dirty, but this is just absurd." baseturfs = /turf/open/floor/plating - initial_gas_mix = OPENTURF_LOW_PRESSURE + initial_gas_mix = OPENTURF_DEFAULT_ATMOS planetary_atmos = FALSE +/turf/open/misc/dirt/jungle + slowdown = 0.5 + initial_gas_mix = OPENTURF_DEFAULT_ATMOS + /turf/open/misc/dirt/dark icon_state = "greenerdirt" base_icon_state = "greenerdirt" -/turf/open/misc/dirt/jungle +/turf/open/misc/dirt/dark/station + baseturfs = /turf/open/floor/plating + initial_gas_mix = OPENTURF_DEFAULT_ATMOS + planetary_atmos = FALSE + +/turf/open/misc/dirt/dark/station/airless + initial_gas_mix = AIRLESS_ATMOS + temperature = TCMB + +/turf/open/misc/dirt/dark/jungle slowdown = 0.5 initial_gas_mix = OPENTURF_DEFAULT_ATMOS @@ -68,7 +81,7 @@ return list("jungle_damaged") /turf/closed/mineral/random/jungle - baseturfs = /turf/open/misc/dirt/dark + baseturfs = /turf/open/misc/dirt/dark/jungle /turf/closed/mineral/random/jungle/mineral_chances() return list( @@ -81,3 +94,6 @@ /obj/item/stack/ore/titanium = 11, /obj/item/stack/ore/uranium = 5, ) + +/turf/closed/mineral/random/jungle/space_safe + baseturfs = /turf/open/misc/dirt/dark/station/airless diff --git a/code/game/world.dm b/code/game/world.dm index e851bb992d4..de638624319 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -361,8 +361,8 @@ GLOBAL_VAR(restart_counter) var/server_name = CONFIG_GET(string/servername) if (server_name) new_status += "[server_name] " - if(!CONFIG_GET(flag/norespawn)) - features += "respawn" + if(CONFIG_GET(flag/allow_respawn)) + features += "respawn" // show "respawn" regardless of "respawn as char" or "free respawn" if(!CONFIG_GET(flag/allow_ai)) features += "AI disabled" hostedby = CONFIG_GET(string/hostedby) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 7f135cdbefb..243ff3d07d1 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -58,6 +58,9 @@ GLOBAL_PROTECT(admin_verbs_admin) /client/proc/admin_enable_shuttle, /*undoes the above*/ /client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/ /client/proc/admin_hostile_environment, /*Allows admins to prevent the emergency shuttle from leaving, also lets admins clear hostile environments if theres one stuck*/ + /client/proc/centcom_podlauncher,/*Open a window to launch a Supplypod and configure it or it's contents*/ + /client/proc/check_ai_laws, /*shows AI and borg laws*/ + /client/proc/check_antagonists, /*shows all antags*/ /client/proc/cmd_admin_check_contents, /*displays the contents of an instance*/ /client/proc/cmd_admin_check_player_exp, /* shows players by playtime */ /client/proc/cmd_admin_create_centcom_report, @@ -68,9 +71,7 @@ GLOBAL_PROTECT(admin_verbs_admin) /client/proc/cmd_admin_subtle_message, /*send a message to somebody as a 'voice in their head'*/ /client/proc/cmd_admin_world_narrate, /*sends text to all players with no padding*/ /client/proc/cmd_change_command_name, - /client/proc/centcom_podlauncher,/*Open a window to launch a Supplypod and configure it or it's contents*/ - /client/proc/check_ai_laws, /*shows AI and borg laws*/ - /client/proc/check_antagonists, /*shows all antags*/ + /client/proc/create_mob_worm, /client/proc/fax_panel, /*send a paper to fax*/ /client/proc/force_load_lazy_template, /client/proc/game_panel, /*game panel, allows to change game-mode etc*/ @@ -255,6 +256,7 @@ GLOBAL_PROTECT(admin_verbs_debug) /client/proc/unload_ctf, /client/proc/validate_cards, /client/proc/validate_puzzgrids, + /client/proc/GeneratePipeSpritesheet, /client/proc/view_runtimes, /client/proc/reload_interactions, /*SKYRAT EDIT ADDITION*/ @@ -1174,3 +1176,48 @@ GLOBAL_PROTECT(admin_verbs_poll) holder.library_manager = new() holder.library_manager.ui_interact(usr) SSblackbox.record_feedback("tally", "admin_verb", 1, "Library Management") // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! + +/client/proc/create_mob_worm() + set category = "Admin.Fun" + set name = "Create Mob Worm" + set desc = "Attached a linked list of mobs to a marked mob" + if (!check_rights(R_FUN)) + return + if(isnull(holder)) + return + if(!isliving(holder.marked_datum)) + to_chat(usr, span_warning("Error: Please mark a mob to attach mobs to.")) + return + var/mob/living/head = holder.marked_datum + + var/attempted_target_path = tgui_input_text( + usr, + "Enter typepath of a mob you'd like to make your chain from.", + "Typepath", + "[/mob/living/basic/pet/dog/corgi/ian]", + ) + + if (isnull(attempted_target_path)) + return //The user pressed "Cancel" + + var/desired_mob = text2path(attempted_target_path) + if(!ispath(desired_mob)) + var/static/list/mob_paths = make_types_fancy(subtypesof(/mob/living)) + desired_mob = pick_closest_path(attempted_target_path, mob_paths) + if(isnull(desired_mob) || !ispath(desired_mob) || QDELETED(head)) + return //The user pressed "Cancel" + + var/amount = tgui_input_number(usr, "How long should our tail be?", "Worm Configurator", default = 3, min_value = 1) + if (isnull(amount) || amount < 1 || QDELETED(head)) + return + head.AddComponent(/datum/component/mob_chain) + var/mob/living/previous = head + for (var/i in 1 to amount) + var/mob/living/segment = new desired_mob(head.drop_location()) + if (QDELETED(segment)) // ffs mobs which replace themselves with other mobs + i-- + continue + ADD_TRAIT(segment, TRAIT_PERMANENTLY_MORTAL, INNATE_TRAIT) + QDEL_NULL(segment.ai_controller) + segment.AddComponent(/datum/component/mob_chain, front = previous) + previous = segment diff --git a/code/modules/admin/verbs/admin_newscaster.dm b/code/modules/admin/verbs/admin_newscaster.dm index e6616e2539b..0a25ebaca65 100644 --- a/code/modules/admin/verbs/admin_newscaster.dm +++ b/code/modules/admin/verbs/admin_newscaster.dm @@ -304,7 +304,7 @@ return TRUE var/choice = tgui_alert(usr, "Please confirm feed channel creation","Network Channel Handler", list("Confirm","Cancel")) if(choice == "Confirm") - GLOB.news_network.create_feed_channel(channel_name, "Centcom Offical", channel_desc, locked = channel_locked) + GLOB.news_network.create_feed_channel(channel_name, "Centcom Official", channel_desc, locked = channel_locked) SSblackbox.record_feedback("text", "newscaster_channels", 1, "[channel_name]") creating_channel = FALSE @@ -316,7 +316,7 @@ creating_comment = FALSE return TRUE var/datum/feed_comment/new_feed_comment = new /datum/feed_comment - new_feed_comment.author = "Centcom Offical" + new_feed_comment.author = "Centcom Official" new_feed_comment.body = comment_text new_feed_comment.time_stamp = station_time_timestamp() current_message.comments += new_feed_comment diff --git a/code/modules/admin/verbs/server.dm b/code/modules/admin/verbs/server.dm index 811b2a3506d..47fe392c973 100644 --- a/code/modules/admin/verbs/server.dm +++ b/code/modules/admin/verbs/server.dm @@ -185,16 +185,42 @@ set category = "Server" set desc = "Respawn basically" set name = "Toggle Respawn" - var/new_nores = !CONFIG_GET(flag/norespawn) - CONFIG_SET(flag/norespawn, new_nores) - if (!new_nores) - to_chat(world, "You may now respawn.", confidential = TRUE) - else - to_chat(world, "You may no longer respawn :(", confidential = TRUE) - message_admins(span_adminnotice("[key_name_admin(usr)] toggled respawn to [!new_nores ? "On" : "Off"].")) - log_admin("[key_name(usr)] toggled respawn to [!new_nores ? "On" : "Off"].") + + var/respawn_state = CONFIG_GET(flag/allow_respawn) + var/new_state = -1 + var/new_state_text = "" + switch(respawn_state) + if(RESPAWN_FLAG_DISABLED) // respawn currently disabled + new_state = RESPAWN_FLAG_FREE + new_state_text = "Enabled" + to_chat(world, span_bold("You may now respawn."), confidential = TRUE) + + if(RESPAWN_FLAG_FREE) // respawn currently enabled + new_state = RESPAWN_FLAG_NEW_CHARACTER + new_state_text = "Enabled, Different Slot" + to_chat(world, span_bold("You may now respawn as a different character."), confidential = TRUE) + + if(RESPAWN_FLAG_NEW_CHARACTER) // respawn currently enabled for different slot characters only + new_state = RESPAWN_FLAG_DISABLED + new_state_text = "Disabled" + to_chat(world, span_bold("You may no longer respawn :("), confidential = TRUE) + + else + WARNING("Invalid respawn state in config: [respawn_state]") + + if(new_state == -1) + to_chat(usr, span_warning("The config for respawn is set incorrectly, please complain to your nearest server host (or fix it yourself). \ + In the meanwhile respawn has been set to \"Off\".")) + new_state = RESPAWN_FLAG_DISABLED + new_state_text = "Disabled" + + CONFIG_SET(flag/allow_respawn, new_state) + + message_admins(span_adminnotice("[key_name_admin(usr)] toggled respawn to \"[new_state_text]\".")) + log_admin("[key_name(usr)] toggled respawn to \"[new_state_text]\".") + world.update_status() - SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Respawn", "[!new_nores ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! + SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Respawn", "[new_state_text]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! /datum/admins/proc/delay() set category = "Server" diff --git a/code/modules/antagonists/cult/cult_bastard_sword.dm b/code/modules/antagonists/cult/cult_bastard_sword.dm index a30ffb1f5ee..784eaedf636 100644 --- a/code/modules/antagonists/cult/cult_bastard_sword.dm +++ b/code/modules/antagonists/cult/cult_bastard_sword.dm @@ -80,7 +80,7 @@ to_chat(user, span_cultlarge("\"You cling to the Forgotten Gods, as if you're more than their pawn.\"")) to_chat(user, span_userdanger("A horrible force yanks at your arm!")) user.emote("scream") - user.apply_damage(30, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + user.apply_damage(30, BRUTE, pick(GLOB.arm_zones)) user.dropItemToGround(src, TRUE) user.Paralyze(50) return diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index c3175d0ed4a..e5adcf0cfc5 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -100,7 +100,7 @@ Striking a noncultist, however, will tear their flesh."} span_cultlarge("\"You shouldn't play with sharp things. You'll poke someone's eye out.\"")) if(ishuman(user)) var/mob/living/carbon/human/miscreant = user - miscreant.apply_damage(rand(force/2, force), BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + miscreant.apply_damage(rand(force/2, force), BRUTE, pick(GLOB.arm_zones)) else user.adjustBruteLoss(rand(force/2,force)) return diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index 062412f70e9..de8a26187ae 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -697,7 +697,7 @@ structure_check() searches for nearby cultist structures required for the invoca barrier.Toggle() if(iscarbon(user)) var/mob/living/carbon/C = user - C.apply_damage(2, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + C.apply_damage(2, BRUTE, pick(GLOB.arm_zones)) //Rite of Joined Souls: Summons a single cultist. /obj/effect/rune/summon diff --git a/code/modules/antagonists/heretic/heretic_living_heart.dm b/code/modules/antagonists/heretic/heretic_living_heart.dm index 4af93c0da68..1766cb4cd76 100644 --- a/code/modules/antagonists/heretic/heretic_living_heart.dm +++ b/code/modules/antagonists/heretic/heretic_living_heart.dm @@ -99,7 +99,7 @@ return TRUE -/datum/action/cooldown/track_target/Trigger(trigger_flags) +/datum/action/cooldown/track_target/Trigger(trigger_flags, atom/target) right_clicked = !!(trigger_flags & TRIGGER_SECONDARY_ACTION) return ..() diff --git a/code/modules/antagonists/heretic/items/heretic_armor.dm b/code/modules/antagonists/heretic/items/heretic_armor.dm index 93ab613190b..502c52c17fb 100644 --- a/code/modules/antagonists/heretic/items/heretic_armor.dm +++ b/code/modules/antagonists/heretic/items/heretic_armor.dm @@ -105,12 +105,12 @@ . = ..() UnregisterSignal(user, list(COMSIG_MOB_UNEQUIPPED_ITEM, COMSIG_MOB_EQUIPPED_ITEM)) -/obj/item/clothing/suit/hooded/cultrobes/void/proc/hide_item(obj/item/item, slot) +/obj/item/clothing/suit/hooded/cultrobes/void/proc/hide_item(datum/source, obj/item/item, slot) SIGNAL_HANDLER if(slot & ITEM_SLOT_SUITSTORE) ADD_TRAIT(item, TRAIT_NO_STRIP, REF(src)) // i'd use examine hide but its a flag and yeah -/obj/item/clothing/suit/hooded/cultrobes/void/proc/show_item(obj/item/item, slot) +/obj/item/clothing/suit/hooded/cultrobes/void/proc/show_item(datum/source, obj/item/item, slot) SIGNAL_HANDLER REMOVE_TRAIT(item, TRAIT_NO_STRIP, REF(src)) diff --git a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm index 5fa7c3a0b7c..f3f6d971353 100644 --- a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm @@ -294,7 +294,7 @@ /obj/item/pen = 1, /obj/item/paper = 1, ) - mob_to_summon = /mob/living/simple_animal/hostile/heretic_summon/stalker + mob_to_summon = /mob/living/basic/heretic_summon/stalker cost = 1 route = PATH_FLESH poll_ignore_define = POLL_IGNORE_STALKER diff --git a/code/modules/antagonists/heretic/knowledge/side_ash_flesh.dm b/code/modules/antagonists/heretic/knowledge/side_ash_flesh.dm index f7f3c175b2f..bf840d6ed27 100644 --- a/code/modules/antagonists/heretic/knowledge/side_ash_flesh.dm +++ b/code/modules/antagonists/heretic/knowledge/side_ash_flesh.dm @@ -71,7 +71,7 @@ /obj/item/bodypart/head = 1, /obj/item/book = 1, ) - mob_to_summon = /mob/living/simple_animal/hostile/heretic_summon/ash_spirit + mob_to_summon = /mob/living/basic/heretic_summon/ash_spirit cost = 1 route = PATH_SIDE poll_ignore_define = POLL_IGNORE_ASH_SPIRIT diff --git a/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm b/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm index 8aecfe06e1f..2dbb44ea4eb 100644 --- a/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm +++ b/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm @@ -88,7 +88,7 @@ /obj/item/book = 1, /obj/item/bodypart/head = 1, ) - mob_to_summon = /mob/living/simple_animal/hostile/heretic_summon/rust_spirit + mob_to_summon = /mob/living/basic/heretic_summon/rust_walker cost = 1 route = PATH_SIDE poll_ignore_define = POLL_IGNORE_RUST_SPIRIT diff --git a/code/modules/antagonists/heretic/knowledge/side_void_blade.dm b/code/modules/antagonists/heretic/knowledge/side_void_blade.dm index 92e6e381222..643fd434af7 100644 --- a/code/modules/antagonists/heretic/knowledge/side_void_blade.dm +++ b/code/modules/antagonists/heretic/knowledge/side_void_blade.dm @@ -159,5 +159,5 @@ ) cost = 1 route = PATH_SIDE - mob_to_summon = /mob/living/simple_animal/hostile/heretic_summon/maid_in_the_mirror + mob_to_summon = /mob/living/basic/heretic_summon/maid_in_the_mirror poll_ignore_define = POLL_IGNORE_MAID_IN_MIRROR diff --git a/code/modules/antagonists/heretic/magic/ascended_shapeshift.dm b/code/modules/antagonists/heretic/magic/ascended_shapeshift.dm index 4848635b443..f1d6de56e39 100644 --- a/code/modules/antagonists/heretic/magic/ascended_shapeshift.dm +++ b/code/modules/antagonists/heretic/magic/ascended_shapeshift.dm @@ -6,10 +6,10 @@ cooldown_time = 20 SECONDS die_with_shapeshifted_form = FALSE possible_shapes = list( + /mob/living/basic/heretic_summon/ash_spirit, /mob/living/basic/heretic_summon/raw_prophet/ascended, - /mob/living/simple_animal/hostile/heretic_summon/rust_spirit, - /mob/living/simple_animal/hostile/heretic_summon/ash_spirit, - /mob/living/simple_animal/hostile/heretic_summon/stalker, + /mob/living/basic/heretic_summon/rust_walker, + /mob/living/basic/heretic_summon/stalker, ) /datum/action/cooldown/spell/shapeshift/eldritch/ascension/do_shapeshift(mob/living/caster) diff --git a/code/modules/antagonists/heretic/magic/flesh_ascension.dm b/code/modules/antagonists/heretic/magic/flesh_ascension.dm index cb9ab63e031..d086c1127fc 100644 --- a/code/modules/antagonists/heretic/magic/flesh_ascension.dm +++ b/code/modules/antagonists/heretic/magic/flesh_ascension.dm @@ -13,7 +13,7 @@ invocation_type = INVOCATION_SHOUT spell_requirements = NONE - possible_shapes = list(/mob/living/simple_animal/hostile/heretic_summon/armsy/prime) + possible_shapes = list(/mob/living/basic/heretic_summon/armsy) /// The length of our new wormy when we shed. var/segment_length = 10 @@ -35,32 +35,11 @@ return ..() -/datum/action/cooldown/spell/shapeshift/shed_human_form/do_unshapeshift(mob/living/simple_animal/hostile/heretic_summon/armsy/caster) +/datum/action/cooldown/spell/shapeshift/shed_human_form/do_unshapeshift(mob/living/basic/heretic_summon/armsy/caster) if(istype(caster)) - segment_length = caster.get_length() + segment_length = caster.get_length() - 1 // Don't count the head return ..() /datum/action/cooldown/spell/shapeshift/shed_human_form/create_shapeshift_mob(atom/loc) return new shapeshift_type(loc, TRUE, segment_length) - -/datum/action/cooldown/spell/worm_contract - name = "Force Contract" - desc = "Forces your body to contract onto a single tile." - background_icon_state = "bg_heretic" - overlay_icon_state = "bg_heretic_border" - button_icon = 'icons/mob/actions/actions_ecult.dmi' - button_icon_state = "worm_contract" - - school = SCHOOL_FORBIDDEN - cooldown_time = 30 SECONDS - - invocation_type = INVOCATION_NONE - spell_requirements = NONE - -/datum/action/cooldown/spell/worm_contract/is_valid_target(atom/cast_on) - return istype(cast_on, /mob/living/simple_animal/hostile/heretic_summon/armsy) - -/datum/action/cooldown/spell/worm_contract/cast(mob/living/simple_animal/hostile/heretic_summon/armsy/cast_on) - . = ..() - cast_on.contract_next_chain_into_single_tile() diff --git a/code/modules/antagonists/heretic/structures/knock_final.dm b/code/modules/antagonists/heretic/structures/knock_final.dm index c8a2058eb9f..f7d0d1a9ea7 100644 --- a/code/modules/antagonists/heretic/structures/knock_final.dm +++ b/code/modules/antagonists/heretic/structures/knock_final.dm @@ -20,16 +20,15 @@ var/static/list/monster_types /// A static list of heretic summons which we should not create var/static/list/monster_types_blacklist = list( + /mob/living/basic/heretic_summon/armsy, /mob/living/basic/heretic_summon/star_gazer, - /mob/living/simple_animal/hostile/heretic_summon/armsy, - /mob/living/simple_animal/hostile/heretic_summon/armsy/prime, ) /obj/structure/knock_tear/Initialize(mapload, datum/mind/ascendant_mind) . = ..() transform *= 3 if(isnull(monster_types)) - monster_types = subtypesof(/mob/living/simple_animal/hostile/heretic_summon) + subtypesof(/mob/living/basic/heretic_summon) - monster_types_blacklist + monster_types = subtypesof(/mob/living/basic/heretic_summon) - monster_types_blacklist if(!isnull(ascendant_mind)) ascendee = ascendant_mind RegisterSignals(ascendant_mind.current, list(COMSIG_LIVING_DEATH, COMSIG_QDELETING), PROC_REF(end_madness)) diff --git a/code/modules/antagonists/malf_ai/malf_ai_modules.dm b/code/modules/antagonists/malf_ai/malf_ai_modules.dm index 49d464fde16..9f527e0184a 100644 --- a/code/modules/antagonists/malf_ai/malf_ai_modules.dm +++ b/code/modules/antagonists/malf_ai/malf_ai_modules.dm @@ -455,15 +455,15 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) return FALSE caller.playsound_local(caller, 'sound/misc/interference.ogg', 50, FALSE, use_reverb = FALSE) - adjust_uses(-1) - - if(uses) - desc = "[initial(desc)] It has [uses] use\s remaining." - build_all_button_icons() clicked_machine.audible_message(span_userdanger("You hear a loud electrical buzzing sound coming from [clicked_machine]!")) addtimer(CALLBACK(src, PROC_REF(animate_machine), caller, clicked_machine), 5 SECONDS) //kabeep! unset_ranged_ability(caller, span_danger("Sending override signal...")) + adjust_uses(-1) //adjust after we unset the active ability since we may run out of charges, thus deleting the ability + + if(uses) + desc = "[initial(desc)] It has [uses] use\s remaining." + build_all_button_icons() return TRUE /datum/action/innate/ai/ranged/override_machine/proc/animate_machine(mob/living/caller, obj/machinery/to_animate) diff --git a/code/modules/antagonists/traitor/objectives/kill_pet.dm b/code/modules/antagonists/traitor/objectives/kill_pet.dm index 51a54d99e30..f90599e6c35 100644 --- a/code/modules/antagonists/traitor/objectives/kill_pet.dm +++ b/code/modules/antagonists/traitor/objectives/kill_pet.dm @@ -26,8 +26,8 @@ JOB_CHIEF_MEDICAL_OFFICER = /mob/living/simple_animal/pet/cat/runtime, JOB_CHIEF_ENGINEER = /mob/living/simple_animal/parrot/poly, JOB_QUARTERMASTER = list( - /mob/living/simple_animal/sloth/citrus, - /mob/living/simple_animal/sloth/paperwork, + /mob/living/basic/sloth/citrus, + /mob/living/basic/sloth/paperwork, /mob/living/simple_animal/hostile/gorilla/cargo_domestic, ) ) diff --git a/code/modules/art/paintings.dm b/code/modules/art/paintings.dm index e2448c1aacc..9a18a2b0269 100644 --- a/code/modules/art/paintings.dm +++ b/code/modules/art/paintings.dm @@ -249,7 +249,7 @@ painting_metadata.patron_name = user.real_name painting_metadata.credit_value = offer_amount last_patron = WEAKREF(user.mind) - to_chat(user, span_notice("Nanotrasen Trust Foundation thanks you for your contribution. You're now offical patron of this painting.")) + to_chat(user, span_notice("Nanotrasen Trust Foundation thanks you for your contribution. You're now an official patron of this painting.")) var/list/possible_frames = SSpersistent_paintings.get_available_frames(offer_amount) if(possible_frames.len <= 1) // Not much room for choices here. return diff --git a/code/modules/atmospherics/gasmixtures/gas_types.dm b/code/modules/atmospherics/gasmixtures/gas_types.dm index ae3367ace59..060b5a12ae9 100644 --- a/code/modules/atmospherics/gasmixtures/gas_types.dm +++ b/code/modules/atmospherics/gasmixtures/gas_types.dm @@ -64,6 +64,8 @@ ///How does a single mole of this gas sell for? Formula to calculate maximum value is in code\modules\cargo\exports\large_objects.dm. Doesn't matter for roundstart gasses. var/base_value = 0 var/desc + ///RGB code for use when a generic color representing the gas is needed. Colors taken from contants.ts + var/primary_color /datum/gas/oxygen @@ -74,6 +76,7 @@ purchaseable = TRUE base_value = 0.2 desc = "The gas most life forms need to be able to survive. Also an oxidizer." + primary_color = "#0000ff" /datum/gas/nitrogen id = GAS_N2 @@ -83,6 +86,7 @@ purchaseable = TRUE base_value = 0.1 desc = "A very common gas that used to pad artifical atmospheres to habitable pressure." + primary_color = "#ffff00" /datum/gas/carbon_dioxide //what the fuck is this? id = GAS_CO2 @@ -93,6 +97,7 @@ purchaseable = TRUE base_value = 0.2 desc = "What the fuck is carbon dioxide?" + primary_color = "#808080" /datum/gas/plasma id = GAS_PLASMA @@ -104,6 +109,7 @@ rarity = 800 base_value = 1.5 desc = "A flammable gas with many other curious properties. It's research is one of NT's primary objective." + primary_color = "#ffc0cb" /datum/gas/water_vapor id = GAS_WATER_VAPOR @@ -116,6 +122,7 @@ purchaseable = TRUE base_value = 0.5 desc = "Water, in gas form. Makes things slippery." + primary_color = "#b0c4de" /datum/gas/hypernoblium id = GAS_HYPER_NOBLIUM @@ -127,6 +134,7 @@ rarity = 50 base_value = 2.5 desc = "The most noble gas of them all. High quantities of hyper-noblium actively prevents reactions from occuring." + primary_color = "#008080" /datum/gas/nitrous_oxide id = GAS_N2O @@ -140,6 +148,7 @@ purchaseable = TRUE base_value = 1.5 desc = "Causes drowsiness, euphoria, and eventually unconsciousness." + primary_color = "#ffe4c4" /datum/gas/nitrium id = GAS_NITRIUM @@ -152,6 +161,7 @@ rarity = 1 base_value = 6 desc = "An experimental performance enhancing gas. Nitrium can have amplified effects as more of it gets into your bloodstream." + primary_color = "#a52a2a" /datum/gas/tritium id = GAS_TRITIUM @@ -164,6 +174,7 @@ rarity = 300 base_value = 2.5 desc = "A highly flammable and radioctive gas." + primary_color = "#32cd32" /datum/gas/bz id = GAS_BZ @@ -175,6 +186,7 @@ purchaseable = TRUE base_value = 1.5 desc = "A powerful hallucinogenic nerve agent able to induce cognitive damage." + primary_color = "#9370db" /datum/gas/pluoxium id = GAS_PLUOXIUM @@ -184,6 +196,7 @@ rarity = 200 base_value = 2.5 desc = "A gas that could supply even more oxygen to the bloodstream when inhaled, without being an oxidizer." + primary_color = "#7b68ee" /datum/gas/miasma id = GAS_MIASMA @@ -195,6 +208,7 @@ rarity = 250 base_value = 1 desc = "Not necessarily a gas, miasma refers to biological pollutants found in the atmosphere." + primary_color = "#808000" /datum/gas/freon id = GAS_FREON @@ -207,6 +221,7 @@ rarity = 10 base_value = 5 desc = "A coolant gas. Mainly used for it's endothermic reaction with oxygen." + primary_color = "#afeeee" /datum/gas/hydrogen id = GAS_HYDROGEN @@ -217,6 +232,7 @@ rarity = 600 base_value = 1 desc = "A highly flammable gas." + primary_color = "#ffffff" /datum/gas/healium id = GAS_HEALIUM @@ -228,6 +244,7 @@ rarity = 300 base_value = 5.5 desc = "Causes deep, regenerative sleep." + primary_color = "#fa8072" /datum/gas/proto_nitrate id = GAS_PROTO_NITRATE @@ -239,6 +256,7 @@ rarity = 200 base_value = 2.5 desc = "A very volatile gas that reacts differently with various gases." + primary_color = "#adff2f" /datum/gas/zauker id = GAS_ZAUKER @@ -250,6 +268,7 @@ rarity = 1 base_value = 7 desc = "A highly toxic gas, it's production is highly regulated on top of being difficult. It also breaks down when in contact with nitrogen." + primary_color = "#006400" /datum/gas/halon id = GAS_HALON @@ -261,6 +280,7 @@ rarity = 300 base_value = 4 desc = "A potent fire supressant. Removes oxygen from high temperature fires and cools down the area" + primary_color = "#800080" /datum/gas/helium id = GAS_HELIUM @@ -270,6 +290,7 @@ rarity = 50 base_value = 3.5 desc = "A very inert gas produced by the fusion of hydrogen and it's derivatives." + primary_color = "#f0f8ff" /datum/gas/antinoblium id = GAS_ANTINOBLIUM @@ -282,6 +303,7 @@ rarity = 1 base_value = 10 desc = "We still don't know what it does, but it sells for a lot." + primary_color = "#800000" /obj/effect/overlay/gas icon = 'icons/effects/atmospherics.dmi' diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index 417e5055de7..62c2b562d51 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -352,9 +352,9 @@ return /** - * Similar to set_pipenet() but instead of setting a network to a pipeline, it replaces the old pipeline with a new one, called by Merge() in datum_pipeline.dm + * Replaces the connection to the old_pipenet with the new_pipenet */ -/obj/machinery/atmospherics/proc/replace_pipenet() +/obj/machinery/atmospherics/proc/replace_pipenet(datum/pipeline/old_pipenet, datum/pipeline/new_pipenet) return /** diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index 2c56aba6831..2abb282711b 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -1,5 +1,7 @@ /datum/pipeline + /// The gases contained within this pipeline var/datum/gas_mixture/air + /// The gas_mixtures of objects directly connected to this pipeline var/list/datum/gas_mixture/other_airs var/list/obj/machinery/atmospherics/pipe/members @@ -8,6 +10,10 @@ /// We're essentially caching this to avoid needing to filter over it when processing our machines var/list/obj/machinery/atmospherics/components/require_custom_reconcilation + /// The weighted color blend of the gas mixture in this pipeline + var/gasmix_color + /// A named list of icon_file:overlay_object that gets automatically colored when the gasmix_color updates + var/list/gas_visuals ///Should we equalize air amoung all our members? var/update = TRUE @@ -19,6 +25,7 @@ members = list() other_atmos_machines = list() require_custom_reconcilation = list() + gas_visuals = list() SSair.networks += src /datum/pipeline/Destroy() @@ -28,7 +35,7 @@ if(air?.volume) temporarily_store_air() for(var/obj/machinery/atmospherics/pipe/considered_pipe in members) - considered_pipe.parent = null + considered_pipe.replace_pipenet(considered_pipe.parent, null) if(QDELETED(considered_pipe)) continue SSair.add_to_rebuild_queue(considered_pipe) @@ -42,6 +49,13 @@ reconcile_air() //Only react if the mix has changed, and don't keep updating if it hasn't update = air.react(src) + CalculateGasmixColor(air) + +/datum/pipeline/proc/set_air(datum/gas_mixture/new_air) + if(new_air == air) + return + air = new_air + CalculateGasmixColor(air) ///Preps a pipeline for rebuilding, insterts it into the rebuild queue /datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/base) @@ -52,13 +66,13 @@ volume = considered_pipe.volume members += considered_pipe if(considered_pipe.air_temporary) - air = considered_pipe.air_temporary + set_air(considered_pipe.air_temporary) considered_pipe.air_temporary = null else add_machinery_member(base) if(!air) - air = new + set_air(new /datum/gas_mixture) air.volume = volume SSair.add_to_expansion(src, base) @@ -71,13 +85,13 @@ volume = considered_pipe.volume members += considered_pipe if(considered_pipe.air_temporary) - air = considered_pipe.air_temporary + set_air(considered_pipe.air_temporary) considered_pipe.air_temporary = null else add_machinery_member(base) if(!air) - air = new + set_air(new /datum/gas_mixture) var/list/possible_expansions = list(base) while(possible_expansions.len) for(var/obj/machinery/atmospherics/borderline in possible_expansions) @@ -105,7 +119,7 @@ possible_expansions += item volume += item.volume - item.parent = src + item.replace_pipenet(item.parent, src) if(item.air_temporary) air.merge(item.air_temporary) @@ -142,7 +156,7 @@ var/obj/machinery/atmospherics/pipe/reference_pipe = reference_device if(reference_pipe.parent) merge(reference_pipe.parent) - reference_pipe.parent = src + reference_pipe.replace_pipenet(reference_pipe.parent, src) var/list/adjacent = reference_pipe.pipeline_expansion() for(var/obj/machinery/atmospherics/pipe/adjacent_pipe in adjacent) if(adjacent_pipe.parent == src) @@ -159,7 +173,7 @@ air.volume += parent_pipeline.air.volume members.Add(parent_pipeline.members) for(var/obj/machinery/atmospherics/pipe/reference_pipe in parent_pipeline.members) - reference_pipe.parent = src + reference_pipe.replace_pipenet(reference_pipe.parent, src) air.merge(parent_pipeline.air) for(var/obj/machinery/atmospherics/components/reference_component in parent_pipeline.other_atmos_machines) reference_component.replace_pipenet(parent_pipeline, src) @@ -295,3 +309,64 @@ //Update individual gas_mixtures by volume ratio for(var/datum/gas_mixture/gas_mixture as anything in gas_mixture_list) gas_mixture.copy_from_ratio(total_gas_mixture, gas_mixture.volume / volume_sum) + +//-------------------- +// GAS VISUALS STUFF +// +// If I could have gotten layer filters to obey the RESET_COLOR appearance flag I would have used that here +// so that only a single overlay object needs to exist for all pipelines per icon file. It shouldn't be too +// hard to switch over to that if it becomes possible in the future or some other equivalent feature is added. + +/** + * Used to create and/or get the gas visual overlay created using the given icon file. + * The color is automatically kept up to date and expected to be used as a vis_contents object. + */ +/datum/pipeline/proc/GetGasVisual(icon/icon_file) + if(gas_visuals[icon_file]) + return gas_visuals[icon_file] + + var/obj/effect/abstract/new_overlay = new + new_overlay.icon = icon_file + new_overlay.appearance_flags = RESET_COLOR | KEEP_APART + new_overlay.vis_flags = VIS_INHERIT_ICON_STATE | VIS_INHERIT_LAYER | VIS_INHERIT_PLANE | VIS_INHERIT_ID + new_overlay.color = gasmix_color + + gas_visuals[icon_file] = new_overlay + return new_overlay + +/// Called when the gasmix color has changed and the gas visuals need to be updated. +/datum/pipeline/proc/UpdateGasVisuals() + for(var/icon/source as anything in gas_visuals) + var/obj/effect/abstract/overlay = gas_visuals[source] + animate(overlay, time=5, color=gasmix_color) + +/// After updating, this proc handles looking at the new gas mixture and blends the colors together according to percentage of the gas mix. +/datum/pipeline/proc/CalculateGasmixColor(datum/gas_mixture/source) + SIGNAL_HANDLER + + var/current_weight = 0 + var/current_color + for(var/datum/gas/gas_path as anything in air.gases) + var/gas_weight = air.gases[gas_path][MOLES] + if(!gas_weight) + continue + var/gas_color = RGBtoHSV(initial(gas_path.primary_color)) + current_weight += gas_weight + if(!current_color) + current_color = gas_color + else + current_color = BlendHSV(current_color, gas_color, gas_weight / current_weight) + + if(!current_color) + current_color = "#000000" + else + // Empty weight is prety much arbitrary, just tuned to make the color change from black reasonably quickly without hitting max color immediately + var/empty_weight = (air.volume * 1.5 - current_weight) / 10 + if(empty_weight > 0) + current_color = BlendHSV("#000000", current_color, current_weight / (empty_weight + current_weight)) + + current_color = HSVtoRGB(current_color) + + if(gasmix_color != current_color) + gasmix_color = current_color + UpdateGasVisuals() diff --git a/code/modules/atmospherics/machinery/pipes/bridge_pipe.dm b/code/modules/atmospherics/machinery/pipes/bridge_pipe.dm index 9cda298ccd4..472cb3ed203 100644 --- a/code/modules/atmospherics/machinery/pipes/bridge_pipe.dm +++ b/code/modules/atmospherics/machinery/pipes/bridge_pipe.dm @@ -13,6 +13,8 @@ construction_type = /obj/item/pipe/binary pipe_state = "bridge_center" + has_gas_visuals = FALSE + /obj/machinery/atmospherics/pipe/bridge_pipe/set_init_directions() switch(dir) if(NORTH, SOUTH) diff --git a/code/modules/atmospherics/machinery/pipes/color_adapter.dm b/code/modules/atmospherics/machinery/pipes/color_adapter.dm index 02c550fd558..06812aaa649 100644 --- a/code/modules/atmospherics/machinery/pipes/color_adapter.dm +++ b/code/modules/atmospherics/machinery/pipes/color_adapter.dm @@ -16,6 +16,8 @@ paintable = FALSE hide = FALSE + has_gas_visuals = FALSE + ///cache for the icons var/static/list/mutable_appearance/center_cache = list() @@ -34,7 +36,7 @@ . = ..() var/mutable_appearance/center = center_cache["[piping_layer]"] if(!center) - center = mutable_appearance(icon, "adapter_center") + center = mutable_appearance(initial(icon), "adapter_center") PIPING_LAYER_DOUBLE_SHIFT(center, piping_layer) center_cache["[piping_layer]"] = center . += center diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm index 05350445370..39b65fda7af 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm @@ -8,6 +8,8 @@ hide = FALSE + has_gas_visuals = FALSE + /obj/machinery/atmospherics/pipe/heat_exchanging/Initialize(mapload) . = ..() diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/junction.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/junction.dm index 00ef058333a..a6bfcc533d2 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/junction.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/junction.dm @@ -15,6 +15,8 @@ construction_type = /obj/item/pipe/directional pipe_state = "junction" + has_gas_visuals = FALSE + /obj/machinery/atmospherics/pipe/heat_exchanging/junction/set_init_directions() switch(dir) if(NORTH, SOUTH) diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm index e340d7f54cc..5841486ba9b 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm @@ -16,6 +16,8 @@ construction_type = /obj/item/pipe/trinary pipe_state = "he_manifold" + has_gas_visuals = FALSE + /obj/machinery/atmospherics/pipe/heat_exchanging/manifold/set_init_directions() initialize_directions = ALL_CARDINALS initialize_directions &= ~dir diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm index 03ef32b4354..83870ee210b 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm @@ -15,6 +15,8 @@ construction_type = /obj/item/pipe/quaternary pipe_state = "he_manifold4w" + has_gas_visuals = FALSE + /obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w/set_init_directions() initialize_directions = initial(initialize_directions) diff --git a/code/modules/atmospherics/machinery/pipes/layermanifold.dm b/code/modules/atmospherics/machinery/pipes/layermanifold.dm index bdfbda9ba6c..09c8a3a9367 100644 --- a/code/modules/atmospherics/machinery/pipes/layermanifold.dm +++ b/code/modules/atmospherics/machinery/pipes/layermanifold.dm @@ -12,6 +12,7 @@ construction_type = /obj/item/pipe/binary pipe_state = "manifoldlayer" paintable = TRUE + has_gas_visuals = FALSE ///Reference to all the nodes in the front var/list/front_nodes diff --git a/code/modules/atmospherics/machinery/pipes/multiz.dm b/code/modules/atmospherics/machinery/pipes/multiz.dm index cfc24ab8291..7e14b8a9806 100644 --- a/code/modules/atmospherics/machinery/pipes/multiz.dm +++ b/code/modules/atmospherics/machinery/pipes/multiz.dm @@ -15,6 +15,8 @@ construction_type = /obj/item/pipe/directional pipe_state = "multiz" + has_gas_visuals = FALSE + ///Our central icon var/mutable_appearance/center = null ///The pipe icon diff --git a/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm b/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm new file mode 100644 index 00000000000..9642442a973 --- /dev/null +++ b/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm @@ -0,0 +1,148 @@ +/client/proc/GeneratePipeSpritesheet() + set name = "Generate Pipe Spritesheet" + set category = "Debug" + + var/datum/pipe_icon_generator/generator = new + generator.Start() + fcopy(generator.generated_icons, "icons/obj/pipes_n_cables/!pipes_bitmask.dmi") + + generator.Start("-gas") + fcopy(generator.generated_icons, "icons/obj/pipes_n_cables/!pipe_gas_overlays.dmi") + +/datum/pipe_icon_generator + var/static/icon/template_pieces = icon('icons/obj/pipes_n_cables/pipe_template_pieces.dmi') + var/static/list/icon/damage_masks = list( + "[NORTH]"=icon('icons/obj/pipes_n_cables/pipe_template_pieces.dmi', "damage_mask", NORTH), + "[EAST]"=icon('icons/obj/pipes_n_cables/pipe_template_pieces.dmi', "damage_mask", EAST), + "[SOUTH]"=icon('icons/obj/pipes_n_cables/pipe_template_pieces.dmi', "damage_mask", SOUTH), + "[WEST]"=icon('icons/obj/pipes_n_cables/pipe_template_pieces.dmi', "damage_mask", WEST), + ) + + var/icon/generated_icons + +/datum/pipe_icon_generator/proc/Start(icon_state_suffix="") + var/list/outputs = list() + for(var/layer in 1 to 5) + // Since dirs are bitflags, if we want to iterate over every possible direction + // combination we just need to iterate over every number that can be contained in 4 bits. + // + // I wrote this all the hard way originally >.> + for(var/combined_dirs in 1 to 15) + switch(combined_dirs) + if(NORTH, EAST, SOUTH, WEST) + continue + + outputs += GeneratePipeDir(icon_state_suffix, layer, combined_dirs) + + generated_icons = icon('icons/testing/greyscale_error.dmi') + for(var/icon/generated_icon as anything in outputs) + var/pending_icon_state = outputs[generated_icon] + generated_icons.Insert(generated_icon, pending_icon_state) + +/datum/pipe_icon_generator/proc/GeneratePipeDir(icon_state_suffix, layer, combined_dirs) + var/list/output + + switch(combined_dirs) + if(NORTH | SOUTH, EAST | WEST) + output = GeneratePipeStraight(icon_state_suffix, layer, combined_dirs) + if(NORTH | EAST, SOUTH | EAST, SOUTH | WEST, NORTH | WEST) + output = GeneratePipeElbow(icon_state_suffix, layer, combined_dirs) + if(NORTH | EAST | SOUTH, EAST | SOUTH | WEST, SOUTH | WEST | NORTH, WEST | NORTH | EAST) + output = GeneratePipeTJunction(icon_state_suffix, layer, combined_dirs) + if(NORTH | EAST | SOUTH | WEST) + output = GeneratePipeCross(icon_state_suffix, layer, combined_dirs) + + var/shift_amount = (layer - 1) * 5 + for(var/icon/sprite as anything in output) + if(shift_amount > 0) + sprite.Shift(EAST, shift_amount) + sprite.Shift(NORTH, shift_amount) + sprite.Crop(33, 33, 64, 64) + + return output + +/// Generates all variants of damaged pipe from a given icon and the dirs that can be broken +/datum/pipe_icon_generator/proc/GenerateDamaged(icon/working, layer, dirs, x_offset=1, y_offset=1) + var/outputs = list() + var/completed = list() + for(var/combined_dirs in 1 to 15) + combined_dirs &= dirs + + var/completion_key = "[combined_dirs]" + if(completed[completion_key] || (combined_dirs == NONE)) + continue + completed[completion_key] = TRUE + + var/icon/damaged = icon(working) + for(var/i in 0 to 3) + var/dir = 1 << i + if(!(combined_dirs & dir)) + continue + var/icon/damage_mask = damage_masks["[dir]"] + damaged.Blend(damage_mask, ICON_MULTIPLY, x_offset, y_offset) + + var/icon_state_dirs = (dirs & ~combined_dirs) | CARDINAL_TO_SHORTPIPES(combined_dirs) + outputs[damaged] = "[icon_state_dirs]_[layer]" + return outputs + + +/datum/pipe_icon_generator/proc/GeneratePipeStraight(icon_state_suffix, layer, combined_dirs) + var/list/output = list() + var/north_or_east = combined_dirs & (NORTH | EAST) + var/icon/working = icon(template_pieces, "straight[icon_state_suffix]", north_or_east) + + output[working] = "[combined_dirs]_[layer]" + + var/offset = 1 + (5-layer) * 2 + switch(combined_dirs) + if(NORTH | SOUTH) + output += GenerateDamaged(working, layer, combined_dirs, y_offset=offset) + if(EAST | WEST) + output += GenerateDamaged(working, layer, combined_dirs, x_offset=offset) + + return output + +/datum/pipe_icon_generator/proc/GeneratePipeElbow(icon_state_suffix, layer, combined_dirs) + var/list/output = list() + var/icon/working + switch(combined_dirs) + if(NORTH | EAST) + working = icon(template_pieces, "elbow[icon_state_suffix]", NORTH) + if(NORTH | WEST) + working = icon(template_pieces, "elbow[icon_state_suffix]", WEST) + if(SOUTH | EAST) + working = icon(template_pieces, "elbow[icon_state_suffix]", EAST) + if(SOUTH | WEST) + working = icon(template_pieces, "elbow[icon_state_suffix]", SOUTH) + + output[working] = "[combined_dirs]_[layer]" + output += GenerateDamaged(working, layer, combined_dirs) + + return output + +/datum/pipe_icon_generator/proc/GeneratePipeTJunction(icon_state_suffix, layer, combined_dirs) + var/list/output = list() + var/icon/working + switch(combined_dirs) + if(WEST | NORTH | EAST) + working = icon(template_pieces, "tee[icon_state_suffix]", NORTH) + if(NORTH | EAST | SOUTH) + working = icon(template_pieces, "tee[icon_state_suffix]", EAST) + if(EAST | SOUTH | WEST) + working = icon(template_pieces, "tee[icon_state_suffix]", SOUTH) + if(SOUTH | WEST | NORTH) + working = icon(template_pieces, "tee[icon_state_suffix]", WEST) + + output[working] = "[combined_dirs]_[layer]" + output += GenerateDamaged(working, layer, combined_dirs) + + return output + +/datum/pipe_icon_generator/proc/GeneratePipeCross(icon_state_suffix, layer, combined_dirs) + var/list/output = list() + var/icon/working = icon(template_pieces, "cross[icon_state_suffix]") + + output[working] = "[combined_dirs]_[layer]" + output += GenerateDamaged(working, layer, combined_dirs) + + return output diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm index c1c128c2e80..c94caf31174 100644 --- a/code/modules/atmospherics/machinery/pipes/pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/pipes.dm @@ -1,15 +1,22 @@ /obj/machinery/atmospherics/pipe - icon = 'icons/obj/pipes_n_cables/pipes_bitmask.dmi' + icon = 'icons/obj/pipes_n_cables/!pipes_bitmask.dmi' damage_deflection = 12 - var/datum/gas_mixture/air_temporary //used when reconstructing a pipeline that broke + /// Temporary holder for gases in the absence of a pipeline + var/datum/gas_mixture/air_temporary + + /// The gas capacity this pipe contributes to a pipeline var/volume = 0 use_power = NO_POWER_USE can_unwrench = 1 + /// The pipeline this pipe is a member of var/datum/pipeline/parent = null paintable = TRUE + /// Determines if this pipe will be given gas visuals + var/has_gas_visuals = TRUE + //Buckling can_buckle = TRUE buckle_requires_restraints = TRUE @@ -27,6 +34,23 @@ if(hide) AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) //if changing this, change the subtypes RemoveElements too, because thats how bespoke works +/obj/machinery/atmospherics/pipe/Destroy() + QDEL_NULL(parent) + + releaseAirToTurf() + + var/turf/local_turf = loc + for(var/obj/machinery/meter/meter in local_turf) + if(meter.target != src) + continue + var/obj/item/pipe_meter/meter_object = new (local_turf) + meter.transfer_fingerprints_to(meter_object) + qdel(meter) + return ..() + +//----------------- +// PIPENET STUFF + /obj/machinery/atmospherics/pipe/nullify_node(i) var/obj/machinery/atmospherics/old_node = nodes[i] . = ..() @@ -39,7 +63,7 @@ /obj/machinery/atmospherics/pipe/get_rebuild_targets() if(!QDELETED(parent)) return - parent = new + replace_pipenet(parent, new /datum/pipeline) return list(parent) /obj/machinery/atmospherics/pipe/proc/releaseAirToTurf() @@ -73,25 +97,33 @@ /obj/machinery/atmospherics/pipe/return_pipenet() return parent -/obj/machinery/atmospherics/pipe/set_pipenet(datum/pipeline/pipenet_to_set) - parent = pipenet_to_set +/obj/machinery/atmospherics/pipe/replace_pipenet(datum/pipeline/old_pipenet, datum/pipeline/new_pipenet) + if(parent && has_gas_visuals) + vis_contents -= parent.GetGasVisual('icons/obj/pipes_n_cables/!pipe_gas_overlays.dmi') -/obj/machinery/atmospherics/pipe/Destroy() - QDEL_NULL(parent) + parent = new_pipenet - releaseAirToTurf() + if(parent && has_gas_visuals) // null is a valid argument here + vis_contents += parent.GetGasVisual('icons/obj/pipes_n_cables/!pipe_gas_overlays.dmi') - var/turf/local_turf = loc - for(var/obj/machinery/meter/meter in local_turf) - if(meter.target != src) - continue - var/obj/item/pipe_meter/meter_object = new (local_turf) - meter.transfer_fingerprints_to(meter_object) - qdel(meter) +/obj/machinery/atmospherics/pipe/return_pipenets() + . = list(parent) + +//-------------------- +// APPEARANCE STUFF + +/obj/machinery/atmospherics/pipe/update_icon() + update_pipe_icon() + update_layer() return ..() /obj/machinery/atmospherics/pipe/proc/update_pipe_icon() - icon = 'icons/obj/pipes_n_cables/pipes_bitmask.dmi' + switch(initialize_directions) + if(NORTH, EAST, SOUTH, WEST) // Pipes with only a single connection aren't handled by this system + icon = null + return + else + icon = 'icons/obj/pipes_n_cables/!pipes_bitmask.dmi' var/connections = NONE var/bitfield = NONE for(var/i in 1 to device_type) @@ -104,11 +136,6 @@ bitfield |= CARDINAL_TO_SHORTPIPES(initialize_directions & ~connections) icon_state = "[bitfield]_[piping_layer]" -/obj/machinery/atmospherics/pipe/update_icon() - update_pipe_icon() - update_layer() - return ..() - /obj/machinery/atmospherics/proc/update_node_icon() for(var/i in 1 to device_type) if(!nodes[i]) @@ -116,9 +143,6 @@ var/obj/machinery/atmospherics/current_node = nodes[i] current_node.update_icon() -/obj/machinery/atmospherics/pipe/return_pipenets() - . = list(parent) - /obj/machinery/atmospherics/pipe/paint(paint_color) if(paintable) add_atom_colour(paint_color, FIXED_COLOUR_PRIORITY) diff --git a/code/modules/atmospherics/machinery/pipes/smart.dm b/code/modules/atmospherics/machinery/pipes/smart.dm index 9b1a1d486d1..365d48e4121 100644 --- a/code/modules/atmospherics/machinery/pipes/smart.dm +++ b/code/modules/atmospherics/machinery/pipes/smart.dm @@ -30,7 +30,7 @@ GLOBAL_LIST_INIT(atmos_components, typecacheof(list(/obj/machinery/atmospherics) return bit_flag /obj/machinery/atmospherics/pipe/smart/update_pipe_icon() - icon = 'icons/obj/pipes_n_cables/pipes_bitmask.dmi' + icon = 'icons/obj/pipes_n_cables/!pipes_bitmask.dmi' //find all directions this pipe is connected with other nodes connections = NONE diff --git a/code/modules/bitrunning/components/avatar_connection.dm b/code/modules/bitrunning/components/avatar_connection.dm index 3f881c89795..20c063145e1 100644 --- a/code/modules/bitrunning/components/avatar_connection.dm +++ b/code/modules/bitrunning/components/avatar_connection.dm @@ -68,7 +68,7 @@ /datum/component/avatar_connection/RegisterWithParent() ADD_TRAIT(parent, TRAIT_TEMPORARY_BODY, REF(src)) RegisterSignal(parent, COMSIG_BITRUNNER_SAFE_DISCONNECT, PROC_REF(on_safe_disconnect)) - RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(on_sever_connection), override = TRUE) + RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(on_sever_connection)) RegisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(on_linked_damage)) /datum/component/avatar_connection/UnregisterFromParent() @@ -79,7 +79,9 @@ /// Disconnects the avatar and returns the mind to the old_body. /datum/component/avatar_connection/proc/full_avatar_disconnect(forced = FALSE, datum/source) +#ifndef UNIT_TESTS return_to_old_body() +#endif var/obj/machinery/netpod/hosting_netpod = netpod_ref?.resolve() if(isnull(hosting_netpod) && istype(source, /obj/machinery/netpod)) diff --git a/code/modules/bitrunning/designs.dm b/code/modules/bitrunning/designs.dm new file mode 100644 index 00000000000..4e7bca1c1a8 --- /dev/null +++ b/code/modules/bitrunning/designs.dm @@ -0,0 +1,87 @@ +// Quantum server + +/obj/item/circuitboard/machine/quantum_server + name = "Quantum Server" + greyscale_colors = CIRCUIT_COLOR_SUPPLY + build_path = /obj/machinery/quantum_server + req_components = list( + /datum/stock_part/servo = 2, + /datum/stock_part/scanning_module = 1, + /datum/stock_part/capacitor = 1, + ) + +/** + * quantum server design + * are you absolutely sure?? + */ + +// Netpod + +/obj/item/circuitboard/machine/netpod + name = "Netpod" + greyscale_colors = CIRCUIT_COLOR_SUPPLY + build_path = /obj/machinery/netpod + req_components = list( + /datum/stock_part/servo = 1, + /datum/stock_part/matter_bin = 2, + ) + +/datum/design/board/netpod + name = "Netpod Board" + desc = "The circuit board for a netpod." + id = "netpod" + build_path = /obj/item/circuitboard/machine/netpod + category = list( + RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_CARGO + ) + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING + +// Quantum console + +/obj/item/circuitboard/computer/quantum_console + name = "Quantum Console" + greyscale_colors = CIRCUIT_COLOR_SUPPLY + build_path = /obj/machinery/computer/quantum_console + +/datum/design/board/quantum_console + name = "Quantum Console Board" + desc = "Allows for the construction of circuit boards used to build a Quantum Console." + id = "quantum_console" + build_path = /obj/item/circuitboard/computer/quantum_console + category = list( + RND_CATEGORY_COMPUTER + RND_SUBCATEGORY_COMPUTER_CARGO + ) + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING + +// Byteforge + +/obj/item/circuitboard/machine/byteforge + name = "Byteforge" + greyscale_colors = CIRCUIT_COLOR_SUPPLY + build_path = /obj/machinery/byteforge + req_components = list( + /datum/stock_part/micro_laser = 1, + ) + +/datum/design/board/byteforge + name = "Byteforge Board" + desc = "Allows for the construction of circuit boards used to build a Byteforge." + id = "byteforge" + build_path = /obj/item/circuitboard/machine/byteforge + category = list( + RND_CATEGORY_COMPUTER + RND_SUBCATEGORY_COMPUTER_CARGO + ) + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING + + +/datum/techweb_node/bitrunning + id = "bitrunning" + display_name = "Bitrunning Technology" + description = "Bluespace technology has led to the development of quantum-scale computing, which unlocks the means to materialize atomic structures while executing advanced programs." + prereq_ids = list("practical_bluespace") + design_ids = list( + "byteforge", + "quantum_console", + "netpod", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) diff --git a/code/modules/bitrunning/objects/byteforge.dm b/code/modules/bitrunning/objects/byteforge.dm new file mode 100644 index 00000000000..e4543601ce9 --- /dev/null +++ b/code/modules/bitrunning/objects/byteforge.dm @@ -0,0 +1,55 @@ +/obj/machinery/byteforge + name = "byteforge" + + circuit = /obj/item/circuitboard/machine/byteforge + desc = "A machine used by the quantum server. Quantum code converges here, materializing decrypted assets from the virtual abyss." + icon = 'icons/obj/machines/bitrunning.dmi' + icon_state = "byteforge" + obj_flags = BLOCKS_CONSTRUCTION + /// Idle particles + var/mutable_appearance/byteforge_particles + +/obj/machinery/byteforge/Initialize(mapload) + . = ..() + + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/byteforge/LateInitialize() + . = ..() + + byteforge_particles = mutable_appearance(initial(icon), "on_particles", ABOVE_MOB_LAYER) + setup_particles() + +/obj/machinery/byteforge/update_appearance(updates) + . = ..() + + setup_particles() + +/// Adds the particle overlays to the byteforge +/obj/machinery/byteforge/proc/setup_particles() + cut_overlays() + + if(is_operational) + add_overlay(byteforge_particles) + +/// Begins spawning the crate - lights, overlays, etc +/obj/machinery/byteforge/proc/start_to_spawn(obj/structure/closet/crate/secure/bitrunning/encrypted/cache) + addtimer(CALLBACK(src, PROC_REF(spawn_crate), cache), 1 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE) + + var/mutable_appearance/lighting = mutable_appearance(initial(icon), "on_overlay") + flick_overlay_view(lighting, 1 SECONDS) + + set_light(l_range = 2, l_power = 1.5, l_color = LIGHT_COLOR_BABY_BLUE, l_on = TRUE) + +/// Sparks, moves the crate to the location +/obj/machinery/byteforge/proc/spawn_crate(obj/structure/closet/crate/secure/bitrunning/encrypted/cache) + if(QDELETED(cache)) + return + + playsound(src, 'sound/magic/blink.ogg', 50, TRUE) + var/datum/effect_system/spark_spread/quantum/sparks = new() + sparks.set_up(5, 1, loc) + sparks.start() + + cache.forceMove(loc) + set_light(l_on = FALSE) diff --git a/code/modules/bitrunning/objects/host_monitor.dm b/code/modules/bitrunning/objects/host_monitor.dm index f59ca61cbd0..c35edea6319 100644 --- a/code/modules/bitrunning/objects/host_monitor.dm +++ b/code/modules/bitrunning/objects/host_monitor.dm @@ -2,10 +2,10 @@ name = "host monitor" custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 2) - desc = "A complex medical device that, when attached to an avatar's data stream, can detect the user of their host's health." + desc = "A complex electronic that will analyze the connection health between host and avatar." flags_1 = CONDUCT_1 icon = 'icons/obj/device.dmi' - icon_state = "gps-b" + icon_state = "host_monitor" inhand_icon_state = "electronic" item_flags = NOBLUDGEON lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi' diff --git a/code/modules/bitrunning/objects/landmarks.dm b/code/modules/bitrunning/objects/landmarks.dm index d78283c6a8b..a4539c7c3da 100644 --- a/code/modules/bitrunning/objects/landmarks.dm +++ b/code/modules/bitrunning/objects/landmarks.dm @@ -44,11 +44,6 @@ qdel(src) -/// Where the crates get ported to station -/obj/effect/landmark/bitrunning/station_reward_spawn - name = "Bitrunning rewards spawn" - icon_state = "station" - /// Where the exit hololadder spawns /obj/effect/landmark/bitrunning/hololadder_spawn name = "Bitrunning hololadder spawn" diff --git a/code/modules/bitrunning/objects/netpod.dm b/code/modules/bitrunning/objects/netpod.dm index 33d468a3825..d92da961b86 100644 --- a/code/modules/bitrunning/objects/netpod.dm +++ b/code/modules/bitrunning/objects/netpod.dm @@ -189,7 +189,7 @@ return TRUE /obj/machinery/netpod/ui_interact(mob/user, datum/tgui/ui) - if(!is_operational) + if(!is_operational || occupant) return ui = SStgui.try_update_ui(user, src, ui) @@ -242,20 +242,12 @@ to_chat(player, span_notice("The machine disconnects itself and begins to drain.")) open_machine() -/** - * ### Disconnect occupant - * If this goes smoothly, should reconnect a receiving mind to the occupant's body - * - * This is the second stage of the process - if you want to disconn avatars start at the mind first - */ +/// Handles occupant post-disconnection effects like damage, sounds, etc /obj/machinery/netpod/proc/disconnect_occupant(forced = FALSE) - var/mob/living/mob_occupant = occupant - if(isnull(occupant) || !isliving(occupant)) - return - connected = FALSE - if(mob_occupant.stat == DEAD) + var/mob/living/mob_occupant = occupant + if(isnull(occupant) || !isliving(occupant) || mob_occupant.stat == DEAD) open_machine() return @@ -347,8 +339,9 @@ return server_ref = WEAKREF(server) - RegisterSignal(server, COMSIG_BITRUNNER_SERVER_UPGRADED, PROC_REF(on_server_upgraded), override = TRUE) - RegisterSignal(server, COMSIG_BITRUNNER_DOMAIN_COMPLETE, PROC_REF(on_domain_complete), override = TRUE) + RegisterSignal(server, COMSIG_BITRUNNER_SERVER_UPGRADED, PROC_REF(on_server_upgraded)) + RegisterSignal(server, COMSIG_BITRUNNER_DOMAIN_COMPLETE, PROC_REF(on_domain_complete)) + RegisterSignal(server, COMSIG_BITRUNNER_DOMAIN_SCRUBBED, PROC_REF(on_domain_scrubbed)) return server @@ -395,6 +388,7 @@ account.bitrunning_points += reward_points * 100 +/// User inspects the machine /obj/machinery/netpod/proc/on_examine(datum/source, mob/examiner, list/examine_text) SIGNAL_HANDLER @@ -409,6 +403,15 @@ examine_text += span_notice("It is currently occupied by [occupant].") examine_text += span_notice("It can be pried open with a crowbar, but its safety mechanisms will alert the occupant.") +/// The domain has been fully purged, so we should double check our avatar is deleted +/obj/machinery/netpod/proc/on_domain_scrubbed(datum/source) + SIGNAL_HANDLER + + var/mob/living/current_avatar = avatar_ref?.resolve() + if(isnull(current_avatar)) + return + + QDEL_NULL(current_avatar) /// When the server is upgraded, drops brain damage a little /obj/machinery/netpod/proc/on_server_upgraded(datum/source, servo_rating) diff --git a/code/modules/bitrunning/objects/bit_vendor.dm b/code/modules/bitrunning/objects/vendor.dm similarity index 100% rename from code/modules/bitrunning/objects/bit_vendor.dm rename to code/modules/bitrunning/objects/vendor.dm diff --git a/code/modules/bitrunning/server/loot.dm b/code/modules/bitrunning/server/loot.dm index 29b730aae78..8b3af95607c 100644 --- a/code/modules/bitrunning/server/loot.dm +++ b/code/modules/bitrunning/server/loot.dm @@ -16,14 +16,16 @@ /// Generates a reward based on the given domain /obj/machinery/quantum_server/proc/generate_loot() - if(!length(receive_turfs) && !locate_receive_turfs()) + var/list/obj/machinery/byteforge/nearby_forges = get_nearby_forges() + if(isnull(nearby_forges)) + say(src, "No nearby byteforges detected.") return FALSE points += generated_domain.reward_points playsound(src, 'sound/machines/terminal_success.ogg', 30, 2) - var/turf/dest_turf = pick(receive_turfs) - if(isnull(dest_turf)) + var/obj/machinery/byteforge/chosen_forge = pick(nearby_forges) + if(isnull(chosen_forge)) stack_trace("Failed to find a turf to spawn loot crate on.") return FALSE @@ -34,11 +36,11 @@ certificate.name = "certificate of domain completion" certificate.update_appearance() - var/obj/structure/closet/crate/secure/bitrunning/decrypted/reward_crate = new(dest_turf, generated_domain, bonus) + var/obj/structure/closet/crate/secure/bitrunning/decrypted/reward_crate = new(src, generated_domain, bonus) reward_crate.manifest = certificate reward_crate.update_appearance() - spark_at_location(reward_crate) + chosen_forge.start_to_spawn(reward_crate) return TRUE /// Returns the markdown text containing domain completion information diff --git a/code/modules/bitrunning/server/map_handling.dm b/code/modules/bitrunning/server/map_handling.dm index 02126c290f7..741fad476f0 100644 --- a/code/modules/bitrunning/server/map_handling.dm +++ b/code/modules/bitrunning/server/map_handling.dm @@ -1,3 +1,4 @@ +#define ONLY_TURF 1 /// Gives all current occupants a notification that the server is going down /obj/machinery/quantum_server/proc/begin_shutdown(mob/user) @@ -119,7 +120,6 @@ new /obj/structure/closet/crate/secure/bitrunning/encrypted(pick(crate_turfs)) return TRUE -#define ONLY_TURF 1 // There should only ever be one turf at the bottom left of the map. /// Loads the safehouse /obj/machinery/quantum_server/proc/initialize_safehouse() @@ -160,7 +160,8 @@ /// Deletes all the tile contents /obj/machinery/quantum_server/proc/scrub_vdom() - SEND_SIGNAL(src, COMSIG_BITRUNNER_SEVER_AVATAR) // just in case + SEND_SIGNAL(src, COMSIG_BITRUNNER_SEVER_AVATAR) /// just in case someone's connected + SEND_SIGNAL(src, COMSIG_BITRUNNER_DOMAIN_SCRUBBED) // avatar cleanup just in case if(length(generated_domain.reservations)) var/datum/turf_reservation/res = generated_domain.reservations[1] diff --git a/code/modules/bitrunning/server/quantum_server.dm b/code/modules/bitrunning/server/quantum_server.dm index 404a31cca6a..b869fb7f02e 100644 --- a/code/modules/bitrunning/server/quantum_server.dm +++ b/code/modules/bitrunning/server/quantum_server.dm @@ -48,8 +48,6 @@ var/servo_bonus = 0 /// The turfs we can place a hololadder on. var/turf/exit_turfs = list() - /// The turfs on station where we generate loot. - var/turf/receive_turfs = list() /obj/machinery/quantum_server/Initialize(mapload) . = ..() @@ -84,18 +82,17 @@ avatar_connection_refs.Cut() spawned_threat_refs.Cut() QDEL_NULL(exit_turfs) - QDEL_NULL(receive_turfs) QDEL_NULL(generated_domain) QDEL_NULL(generated_safehouse) QDEL_NULL(radio) /obj/machinery/quantum_server/update_appearance(updates) if(isnull(generated_domain) || !is_operational) - set_light(0) + set_light(l_on = FALSE) return ..() set_light_color(is_ready ? LIGHT_COLOR_BABY_BLUE : LIGHT_COLOR_FIRE) - set_light(2, 1.5) + set_light(l_range = 2, l_power = 1.5, l_on = TRUE) return ..() diff --git a/code/modules/bitrunning/server/util.dm b/code/modules/bitrunning/server/util.dm index c4f1319cd12..f4dbada9ef6 100644 --- a/code/modules/bitrunning/server/util.dm +++ b/code/modules/bitrunning/server/util.dm @@ -107,14 +107,14 @@ return shuffle(mutation_candidate_refs) -/// Locates any turfs with crate out landmarks -/obj/machinery/quantum_server/proc/locate_receive_turfs() - for(var/obj/effect/landmark/bitrunning/station_reward_spawn/spawner in GLOB.landmarks_list) - if(IN_GIVEN_RANGE(src, spawner, MAX_DISTANCE)) - receive_turfs += get_turf(spawner) - qdel(spawner) +/// Locates any turfs with forges on them +/obj/machinery/quantum_server/proc/get_nearby_forges() + var/list/obj/machinery/byteforge/nearby_forges = list() - return length(receive_turfs) > 0 + for(var/obj/machinery/byteforge/forge in oview(MAX_DISTANCE, src)) + nearby_forges += forge + + return nearby_forges /// Finds any mobs with minds in the zones and gives them the bad news /obj/machinery/quantum_server/proc/notify_spawned_threats() @@ -132,10 +132,10 @@ to_chat(baddie, span_userdanger("You have been flagged for deletion! Thank you for your service.")) /// Do some magic teleport sparks -/obj/machinery/quantum_server/proc/spark_at_location(obj/crate) - playsound(crate, 'sound/magic/blink.ogg', 50, TRUE) +/obj/machinery/quantum_server/proc/spark_at_location(obj/cache) + playsound(cache, 'sound/magic/blink.ogg', 50, TRUE) var/datum/effect_system/spark_spread/quantum/sparks = new() - sparks.set_up(5, 1, get_turf(crate)) + sparks.set_up(5, 1, get_turf(cache)) sparks.start() #undef REDACTED diff --git a/code/modules/bitrunning/virtual_domain/domains/beach_bar.dm b/code/modules/bitrunning/virtual_domain/domains/beach_bar.dm index 871c2cb1338..a6fb3e921e0 100644 --- a/code/modules/bitrunning/virtual_domain/domains/beach_bar.dm +++ b/code/modules/bitrunning/virtual_domain/domains/beach_bar.dm @@ -8,12 +8,12 @@ map_name = "beach_bar" safehouse_path = /datum/map_template/safehouse/mine -/obj/item/reagent_containers/cup/glass/drinkingglass/virtual_domain +/obj/item/reagent_containers/cup/glass/drinkingglass/filled/virtual_domain name = "pina colada" desc = "Whose drink is this? Not yours, that's for sure. Well, it's not like they're going to miss it." list_reagents = list(/datum/reagent/consumable/ethanol/pina_colada = 30) -/obj/item/reagent_containers/cup/glass/drinkingglass/virtual_domain/Initialize(mapload, vol) +/obj/item/reagent_containers/cup/glass/drinkingglass/filled/virtual_domain/Initialize(mapload, vol) . = ..() AddComponent(/datum/component/bitrunning_points, \ diff --git a/code/modules/cargo/goodies.dm b/code/modules/cargo/goodies.dm index a9e11a370e1..27a770005c1 100644 --- a/code/modules/cargo/goodies.dm +++ b/code/modules/cargo/goodies.dm @@ -313,3 +313,9 @@ desc = "A less cheap imported climbing hook. Absolutely no use outside of planetary stations." cost = PAYCHECK_CREW * 5 contains = list(/obj/item/climbing_hook) + +/datum/supply_pack/goody/fish_analyzer + name = "Fish Analyzer" + desc = "A single analyzer to monitor fish's status and traits with, in case you don't have the technology to print one." + cost = CARGO_CRATE_VALUE * 2.5 + contains = list(/obj/item/fish_analyzer) diff --git a/code/modules/cargo/packs/general.dm b/code/modules/cargo/packs/general.dm index 5bfcf01eb00..99f8972ccb8 100644 --- a/code/modules/cargo/packs/general.dm +++ b/code/modules/cargo/packs/general.dm @@ -68,13 +68,6 @@ contains = list(/obj/item/storage/fish_case/tiziran = 2) crate_name = "tiziran fish crate" -/datum/supply_pack/misc/fish_analyzers - name = "Fish Analyzers" - desc = "A pack containing three analyzers to monitor fish's status and traits with." - cost = CARGO_CRATE_VALUE * 2.5 - contains = list(/obj/item/fish_analyzer = 3) - crate_name = "fish analyzers crate" - /datum/supply_pack/misc/bicycle name = "Bicycle" desc = "Nanotrasen reminds all employees to never toy with powers outside their control." @@ -221,7 +214,7 @@ /obj/item/clothing/under/misc/burial = 2, ) crate_name = "religious supplies crate" - + /datum/supply_pack/misc/candles_bulk name = "Candle Box Crate" desc = "Keep your local chapel lit with three candle boxes!" diff --git a/code/modules/cargo/packs/livestock.dm b/code/modules/cargo/packs/livestock.dm index d2bdd904e3b..69dd7e61807 100644 --- a/code/modules/cargo/packs/livestock.dm +++ b/code/modules/cargo/packs/livestock.dm @@ -140,7 +140,7 @@ name = "Goat Crate" desc = "The goat goes baa! Contains one goat. Warranty void if used as a replacement for Pete." cost = CARGO_CRATE_VALUE * 5 - contains = list(/mob/living/simple_animal/hostile/retaliate/goat) + contains = list(/mob/living/basic/goat) crate_name = "goat crate" /datum/supply_pack/critter/rabbit diff --git a/code/modules/cargo/packs/security.dm b/code/modules/cargo/packs/security.dm index 7abe5f7601e..784b870fea0 100644 --- a/code/modules/cargo/packs/security.dm +++ b/code/modules/cargo/packs/security.dm @@ -225,6 +225,14 @@ crate_name = "energy gun crate" crate_type = /obj/structure/closet/crate/secure/plasma +/datum/supply_pack/security/armory/laser_carbine + name = "Laser Carbine Crate" + desc = "Contains three laser carbines, capable of rapidly firing weak lasers." + cost = CARGO_CRATE_VALUE * 9 + contains = list(/obj/item/gun/energy/laser/carbine = 3) + crate_name = "laser carbine crate" + crate_type = /obj/structure/closet/crate/secure/plasma + /datum/supply_pack/security/armory/exileimp name = "Exile Implants Crate" desc = "Contains five Exile implants." diff --git a/code/modules/client/player_details.dm b/code/modules/client/player_details.dm index 24c6754b95c..8931dffcdb4 100644 --- a/code/modules/client/player_details.dm +++ b/code/modules/client/player_details.dm @@ -2,14 +2,26 @@ ///assoc list of ckey -> /datum/player_details GLOBAL_LIST_EMPTY(player_details) +/// Tracks information about a client between log in and log outs /datum/player_details - var/list/player_actions = list() + /// Action datums assigned to this player + var/list/datum/action/player_actions = list() + /// Tracks client action logging var/list/logging = list() + /// Callbacks invoked when this client logs in again var/list/post_login_callbacks = list() + /// Callbacks invoked when this client logs out var/list/post_logout_callbacks = list() - var/list/played_names = list() //List of names this key played under this round + /// List of names this key played under this round + var/list/played_names = list() + /// Lazylist of preference slots this client has joined the round under + /// Numbers are stored as strings + var/list/joined_as_slots + /// Version of byond this client is using var/byond_version = "Unknown" + /// Tracks achievements they have earned var/datum/achievement_data/achievements + /// World.time this player last died var/time_of_death = 0 /datum/player_details/New(key) diff --git a/code/modules/clothing/masks/moustache.dm b/code/modules/clothing/masks/moustache.dm index ecfd5d5e007..aaf59be51e4 100644 --- a/code/modules/clothing/masks/moustache.dm +++ b/code/modules/clothing/masks/moustache.dm @@ -2,6 +2,7 @@ name = "fake moustache" desc = "Warning: moustache is fake." icon_state = "fake-moustache" + alternate_worn_layer = ABOVE_BODY_FRONT_HEAD_LAYER w_class = WEIGHT_CLASS_TINY flags_inv = HIDEFACE species_exception = list(/datum/species/golem) diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index aa88961e3c4..118c28c0e51 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -208,7 +208,7 @@ to_chat(our_guy, span_userdanger("You stamp on [user]'s hand! What the- [user.p_they()] [user.p_were()] [tied ? "knotting" : "untying"] your shoelaces!")) user.emote("scream") if(istype(L)) - var/obj/item/bodypart/ouchie = L.get_bodypart(pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + var/obj/item/bodypart/ouchie = L.get_bodypart(pick(GLOB.arm_zones)) if(ouchie) ouchie.receive_damage(brute = 10) L.adjustStaminaLoss(40) diff --git a/code/modules/clothing/suits/wintercoats.dm b/code/modules/clothing/suits/wintercoats.dm index 60cbcae1473..283878339fe 100644 --- a/code/modules/clothing/suits/wintercoats.dm +++ b/code/modules/clothing/suits/wintercoats.dm @@ -247,8 +247,10 @@ icon_state = "coatjanitor" inhand_icon_state = null allowed = list( + /obj/item/access_key, /obj/item/grenade/chem_grenade, /obj/item/holosign_creator, + /obj/item/key/janitor, /obj/item/reagent_containers/cup/beaker, /obj/item/reagent_containers/cup/bottle, /obj/item/reagent_containers/cup/tube, diff --git a/code/modules/events/ghost_role/sentience.dm b/code/modules/events/ghost_role/sentience.dm index da380278608..abc57d33a07 100644 --- a/code/modules/events/ghost_role/sentience.dm +++ b/code/modules/events/ghost_role/sentience.dm @@ -4,20 +4,20 @@ GLOBAL_LIST_INIT(high_priority_sentience, typecacheof(list( /mob/living/basic/carp/pet/cayenne, /mob/living/basic/chicken, /mob/living/basic/cow, + /mob/living/basic/goat, /mob/living/basic/lizard, /mob/living/basic/mouse/brown/tom, /mob/living/basic/pet, /mob/living/basic/pig, /mob/living/basic/rabbit, /mob/living/basic/sheep, + /mob/living/basic/sloth, /mob/living/basic/snake, /mob/living/basic/spider/giant/sgt_araneus, /mob/living/simple_animal/bot/secbot/beepsky, - /mob/living/simple_animal/hostile/retaliate/goat, /mob/living/simple_animal/hostile/retaliate/goose/vomit, /mob/living/simple_animal/parrot, /mob/living/simple_animal/pet, - /mob/living/simple_animal/sloth, ))) /datum/round_event_control/sentience diff --git a/code/modules/events/wizard/petsplosion.dm b/code/modules/events/wizard/petsplosion.dm index 33f7718f740..a9664d8dd47 100644 --- a/code/modules/events/wizard/petsplosion.dm +++ b/code/modules/events/wizard/petsplosion.dm @@ -5,6 +5,7 @@ GLOBAL_LIST_INIT(petsplosion_candidates, typecacheof(list( /mob/living/basic/carp/pet/cayenne, /mob/living/basic/chicken, /mob/living/basic/cow, + /mob/living/basic/goat, /mob/living/basic/lizard, /mob/living/basic/mothroach, /mob/living/basic/mouse/brown/tom, @@ -12,13 +13,12 @@ GLOBAL_LIST_INIT(petsplosion_candidates, typecacheof(list( /mob/living/basic/pig, /mob/living/basic/rabbit, /mob/living/basic/sheep, + /mob/living/basic/sloth, /mob/living/basic/snake, /mob/living/basic/spider/giant/sgt_araneus, - /mob/living/simple_animal/hostile/retaliate/goat, /mob/living/simple_animal/hostile/retaliate/goose/vomit, /mob/living/simple_animal/parrot, /mob/living/simple_animal/pet, - /mob/living/simple_animal/sloth, ))) /datum/round_event_control/wizard/petsplosion //the horror diff --git a/code/modules/fishing/aquarium/fish_analyzer.dm b/code/modules/fishing/aquarium/fish_analyzer.dm index 8afe053a4d5..a83aa4296b6 100644 --- a/code/modules/fishing/aquarium/fish_analyzer.dm +++ b/code/modules/fishing/aquarium/fish_analyzer.dm @@ -33,6 +33,17 @@ case_color = rgb(rand(16, 255), rand(16, 255), rand(16, 255)) set_greyscale(colors = list(case_color)) . = ..() + + var/static/list/fishe_signals = list( + COMSIG_FISH_ANALYZER_ANALYZE_STATUS = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_handheld_experiment), + ) + AddComponent(/datum/component/experiment_handler, \ + config_mode = EXPERIMENT_CONFIG_ALTCLICK, \ + allowed_experiments = list(/datum/experiment/scanning/fish), \ + config_flags = EXPERIMENT_CONFIG_SILENT_FAIL|EXPERIMENT_CONFIG_IMMEDIATE_ACTION, \ + experiment_signals = fishe_signals, \ + ) + register_item_context() update_appearance() @@ -42,6 +53,10 @@ radial_choices = null return ..() +/obj/item/fish_analyzer/examine(mob/user) + . = ..() + . += span_notice("Alt-Click to access the Experiment Configuration UI") + /obj/item/fish_analyzer/update_icon_state() . = ..() icon_state = base_icon_state @@ -206,6 +221,8 @@ to_chat(user, examine_block(jointext(render_list, "")), type = MESSAGE_TYPE_INFO) + SEND_SIGNAL(src, COMSIG_FISH_ANALYZER_ANALYZE_STATUS, fish, user) + /** * Called when a fish or a menu choice is left-clicked. * This returns the fish's progenitors, traits and their inheritability. diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index caee1bbac8d..4ceddb09854 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -437,3 +437,36 @@ chaser.monster_damage_boost = FALSE // Weaker cuz no cooldown chaser.damage = 20 log_combat(user, target, "fired a chaser at", src) + +/obj/item/crusher_trophy/ice_demon_cube + name = "demonic cube" + desc = "A stone cold cube dropped from an ice demon." + icon_state = "ice_demon_cube" + denied_type = /obj/item/crusher_trophy/ice_demon_cube + ///how many will we summon? + var/summon_amount = 2 + ///cooldown to summon demons upon the target + COOLDOWN_DECLARE(summon_cooldown) + +/obj/item/crusher_trophy/ice_demon_cube/effect_desc() + return "mark detonation to unleash demonic ice clones upon the target" + +/obj/item/crusher_trophy/ice_demon_cube/on_mark_detonation(mob/living/target, mob/living/user) + if(isnull(target) || !COOLDOWN_FINISHED(src, summon_cooldown)) + return + for(var/i in 1 to summon_amount) + var/turf/drop_off = find_dropoff_turf(target, user) + var/mob/living/basic/mining/demon_afterimage/crusher/friend = new(drop_off) + friend.faction = list(FACTION_NEUTRAL) + friend.befriend(user) + friend.ai_controller?.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, target) + COOLDOWN_START(src, summon_cooldown, 30 SECONDS) + +///try to make them spawn all around the target to surround him +/obj/item/crusher_trophy/ice_demon_cube/proc/find_dropoff_turf(mob/living/target, mob/living/user) + var/list/turfs_list = get_adjacent_open_turfs(target) + for(var/turf/possible_turf in turfs_list) + if(possible_turf.is_blocked_turf()) + continue + return possible_turf + return get_turf(user) diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index a38fe171174..5c07c8c8fd4 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -176,6 +176,12 @@ /mob/dead/new_player/proc/AttemptLateSpawn(rank) + // Check that they're picking someone new for new character respawning + if(CONFIG_GET(flag/allow_respawn) == RESPAWN_FLAG_NEW_CHARACTER) + if("[client.prefs.default_slot]" in client.player_details.joined_as_slots) + tgui_alert(usr, "You already have played this character in this round!") + return FALSE + var/error = IsJobUnavailable(rank) if(error != JOB_AVAILABLE) tgui_alert(usr, get_job_unavailable_error_message(error, rank)) @@ -305,6 +311,8 @@ preserved_mind.original_character_slot_index = client.prefs.default_slot preserved_mind.transfer_to(spawning_mob) //won't transfer key since the mind is not active preserved_mind.set_original_character(spawning_mob) + + LAZYADD(client.player_details.joined_as_slots, "[client.prefs.default_slot]") client.init_verbs() . = spawning_mob new_character = . diff --git a/code/modules/mob/living/basic/farm_animals/deer.dm b/code/modules/mob/living/basic/farm_animals/deer.dm index 445ad831e59..a948ec4d7a6 100644 --- a/code/modules/mob/living/basic/farm_animals/deer.dm +++ b/code/modules/mob/living/basic/farm_animals/deer.dm @@ -34,7 +34,6 @@ /datum/ai_controller/basic_controller/deer blackboard = list( - BB_BASIC_MOB_FLEEING = TRUE, BB_STATIONARY_MOVE_TO_TARGET = TRUE, BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction, ) diff --git a/code/modules/mob/living/basic/farm_animals/goat/_goat.dm b/code/modules/mob/living/basic/farm_animals/goat/_goat.dm new file mode 100644 index 00000000000..f698e5015e8 --- /dev/null +++ b/code/modules/mob/living/basic/farm_animals/goat/_goat.dm @@ -0,0 +1,135 @@ +/// The Greatest (animal) Of All Time. Cud chewing, shin-kicking, kitchen-dwelling nuisance. +/mob/living/basic/goat + name = "goat" + desc = "Not known for their pleasant disposition." + icon_state = "goat" + icon_living = "goat" + icon_dead = "goat_dead" + + speak_emote = list("brays") + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" + attack_verb_continuous = "kicks" + attack_verb_simple = "kick" + attack_sound = 'sound/weapons/punch1.ogg' + attack_vis_effect = ATTACK_EFFECT_KICK + + butcher_results = list(/obj/item/food/meat/slab/grassfed = 4) + + faction = list(FACTION_NEUTRAL) + mob_biotypes = MOB_ORGANIC | MOB_BEAST + + health = 40 + maxHealth = 40 + melee_damage_lower = 1 + melee_damage_upper = 2 + environment_smash = ENVIRONMENT_SMASH_NONE + + minimum_survivable_temperature = COLD_ROOM_TEMP - 75 // enough so that they can survive the cold room spawn with plenty of room for comfort + + blood_volume = BLOOD_VOLUME_NORMAL + + ai_controller = /datum/ai_controller/basic_controller/goat + + /// List of stuff (flora) that we want to eat + var/static/list/edibles = list( + /obj/structure/alien/resin/flower_bud, + /obj/structure/glowshroom, + /obj/structure/spacevine, + ) + +/mob/living/basic/goat/Initialize(mapload) + . = ..() + add_udder() + AddElement(/datum/element/cliff_walking) //we walk the cliff + AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_SHOE) + AddElement(/datum/element/ai_retaliate) + + RegisterSignal(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(on_pre_attack)) + RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_attacked)) + RegisterSignal(src, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(on_move)) + + ai_controller.set_blackboard_key(BB_BASIC_FOODS, edibles) + +/// Called when we attack something in order to piece together the intent of the AI/user and provide desired behavior. The element might be okay here but I'd rather the fluff. +/// Goats are really good at beating up plants by taking bites out of them, but we use the default attack for everything else +/mob/living/basic/goat/proc/on_pre_attack(datum/source, atom/target) + if(is_type_in_list(target, edibles)) + eat_plant(list(target)) + return COMPONENT_HOSTILE_NO_ATTACK + + if(!isliving(target)) + return + + var/mob/living/living_target = target + if(!(living_target.mob_biotypes & MOB_PLANT)) + return + + living_target.adjustBruteLoss(20) + playsound(src, 'sound/items/eatfood.ogg', rand(30, 50), TRUE) + var/obj/item/bodypart/edible_bodypart + + if(ishuman(living_target)) + var/mob/living/carbon/human/plant_man = target + edible_bodypart = pick(plant_man.bodyparts) + edible_bodypart.dismember() + + living_target.visible_message( + span_warning("[src] takes a big chomp out of [living_target]!"), + span_userdanger("[src] takes a big chomp out of your [edible_bodypart || "body"]!"), + ) + + return COMPONENT_HOSTILE_NO_ATTACK + +/// If we are being attacked by someone who we are already retaliating against, give a nice fluff message. +/mob/living/basic/goat/proc/on_attacked(datum/source, atom/attacker, attack_flags) + var/is_attacker_shitlisted = locate(attacker) in ai_controller.blackboard[BB_BASIC_MOB_RETALIATE_LIST] + if(!is_attacker_shitlisted) + return + + visible_message( + span_danger("[src] gets an evil-looking gleam in [p_their()] eye."), + ) + +/// Handles automagically eating a plant when we move into a turf that has one. +/mob/living/basic/goat/proc/on_move(datum/source, atom/entering_loc) + SIGNAL_HANDLER + if(!isturf(entering_loc)) + return + + var/list/edible_plants = list() + for(var/obj/target in entering_loc) + if(is_type_in_list(target, edibles)) + edible_plants += target + + INVOKE_ASYNC(src, PROC_REF(eat_plant), edible_plants) + +/// When invoked, adds an udder. Overridden on subtypes +/mob/living/basic/goat/proc/add_udder() + AddComponent(/datum/component/udder) + +/// Proc that handles dealing with the various types of plants we might eat. Assumes that a valid list of type(s) will be passed in. +/mob/living/basic/goat/proc/eat_plant(list/plants) + var/eaten = FALSE + + for(var/atom/target as anything in plants) + if(istype(target, /obj/structure/spacevine)) + var/obj/structure/spacevine/vine = target + vine.eat(src) + eaten = TRUE + + if(istype(target, /obj/structure/alien/resin/flower_bud)) + target.take_damage(rand(30, 50), BRUTE, 0) + eaten = TRUE + + if(istype(target, /obj/structure/glowshroom)) + qdel(target) + eaten = TRUE + + if(eaten && prob(10)) + say("Nom") // bon appetit + playsound(src, 'sound/items/eatfood.ogg', rand(30, 50), TRUE) diff --git a/code/modules/mob/living/basic/farm_animals/goat/goat_ai.dm b/code/modules/mob/living/basic/farm_animals/goat/goat_ai.dm new file mode 100644 index 00000000000..41fc448a3b6 --- /dev/null +++ b/code/modules/mob/living/basic/farm_animals/goat/goat_ai.dm @@ -0,0 +1,22 @@ +/// Goats are normally content to sorta hang around and crunch any plant in sight, but they will go ape on someone who attacks them. +/datum/ai_controller/basic_controller/goat + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + ) + + ai_traits = STOP_MOVING_WHEN_PULLED + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + + planning_subtrees = list( + /datum/ai_planning_subtree/target_retaliate, + /datum/ai_planning_subtree/find_food, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + /datum/ai_planning_subtree/random_speech/goat, + ) + +/datum/ai_planning_subtree/random_speech/goat + speech_chance = 3 + emote_hear = list("brays.") + emote_see = list("shakes their head.", "stamps a foot.", "glares around.") + speak = list("EHEHEHEHEH", "eh?") diff --git a/code/modules/mob/living/basic/farm_animals/goat/goat_subtypes.dm b/code/modules/mob/living/basic/farm_animals/goat/goat_subtypes.dm new file mode 100644 index 00000000000..19d50fb3809 --- /dev/null +++ b/code/modules/mob/living/basic/farm_animals/goat/goat_subtypes.dm @@ -0,0 +1,12 @@ +/mob/living/basic/goat/pete // Pete! + name = "Pete" + gender = MALE + +/mob/living/basic/goat/pete/examine() + . = ..() + var/area/goat_area = get_area(src) + if((bodytemperature < T20C) || istype(goat_area, /area/station/service/kitchen/coldroom)) + . += span_notice("[p_They()] [p_do()]n't seem to be too bothered about the cold.") // special for pete + +/mob/living/basic/goat/pete/add_udder() + return //no thank you diff --git a/code/modules/mob/living/basic/farm_animals/rabbit.dm b/code/modules/mob/living/basic/farm_animals/rabbit.dm index 92d40e0228e..e837fc3bf83 100644 --- a/code/modules/mob/living/basic/farm_animals/rabbit.dm +++ b/code/modules/mob/living/basic/farm_animals/rabbit.dm @@ -49,7 +49,6 @@ /datum/ai_controller/basic_controller/rabbit blackboard = list( - BB_BASIC_MOB_FLEEING = TRUE, BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/farm_animals/sheep.dm b/code/modules/mob/living/basic/farm_animals/sheep.dm index 691f1db14e3..4452c5ae77c 100644 --- a/code/modules/mob/living/basic/farm_animals/sheep.dm +++ b/code/modules/mob/living/basic/farm_animals/sheep.dm @@ -81,7 +81,6 @@ /datum/ai_controller/basic_controller/sheep blackboard = list( - BB_BASIC_MOB_FLEEING = TRUE, BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), ) ai_traits = STOP_MOVING_WHEN_PULLED diff --git a/code/modules/mob/living/basic/health_adjustment.dm b/code/modules/mob/living/basic/health_adjustment.dm index e453bf7306e..9644a1a6299 100644 --- a/code/modules/mob/living/basic/health_adjustment.dm +++ b/code/modules/mob/living/basic/health_adjustment.dm @@ -1,5 +1,5 @@ /** - * Adjusts the health of a simple mob by a set amount and wakes AI if its idle to react + * Adjusts the health of a simple mob by a set amount * * Arguments: * * amount The amount that will be used to adjust the mob's health @@ -9,44 +9,57 @@ */ /mob/living/basic/proc/adjust_health(amount, updating_health = TRUE, forced = FALSE) . = FALSE - if(forced || !(status_flags & GODMODE)) - . = bruteloss // bruteloss value before applying damage - bruteloss = round(clamp(bruteloss + amount, 0, maxHealth * 2), DAMAGE_PRECISION) - if(updating_health) - updatehealth() - . -= bruteloss + if(!forced && (status_flags & GODMODE)) + return 0 + . = bruteloss // bruteloss value before applying damage + bruteloss = round(clamp(bruteloss + amount, 0, maxHealth * 2), DAMAGE_PRECISION) + if(updating_health) + updatehealth() + return . - bruteloss /mob/living/basic/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype) + if(!can_adjust_brute_loss(amount, forced, required_bodytype)) + return 0 if(forced) . = adjust_health(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced) else if(damage_coeff[BRUTE]) . = adjust_health(amount * damage_coeff[BRUTE] * CONFIG_GET(number/damage_multiplier), updating_health, forced) /mob/living/basic/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype) + if(!can_adjust_fire_loss(amount, forced, required_bodytype)) + return 0 if(forced) . = adjust_health(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced) else if(damage_coeff[BURN]) . = adjust_health(amount * damage_coeff[BURN] * CONFIG_GET(number/damage_multiplier), updating_health, forced) /mob/living/basic/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype, required_respiration_type) + if(!can_adjust_oxy_loss(amount, forced, required_biotype, required_respiration_type)) + return 0 if(forced) . = adjust_health(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced) else if(damage_coeff[OXY]) . = adjust_health(amount * damage_coeff[OXY] * CONFIG_GET(number/damage_multiplier), updating_health, forced) /mob/living/basic/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype) + if(!can_adjust_tox_loss(amount, forced, required_biotype)) + return 0 if(forced) . = adjust_health(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced) else if(damage_coeff[TOX]) . = adjust_health(amount * damage_coeff[TOX] * CONFIG_GET(number/damage_multiplier), updating_health, forced) /mob/living/basic/adjustCloneLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype) + if(!can_adjust_clone_loss(amount, forced, required_biotype)) + return 0 if(forced) . = adjust_health(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced) else if(damage_coeff[CLONE]) . = adjust_health(amount * damage_coeff[CLONE] * CONFIG_GET(number/damage_multiplier), updating_health, forced) /mob/living/basic/adjustStaminaLoss(amount, updating_stamina = TRUE, forced = FALSE, required_biotype) + if(!can_adjust_stamina_loss(amount, forced, required_biotype)) + return 0 . = staminaloss if(forced) staminaloss = max(0, min(BASIC_MOB_MAX_STAMINALOSS, staminaloss + amount)) diff --git a/code/modules/mob/living/basic/heretic/ash_spirit.dm b/code/modules/mob/living/basic/heretic/ash_spirit.dm new file mode 100644 index 00000000000..b2d4d8b4d29 --- /dev/null +++ b/code/modules/mob/living/basic/heretic/ash_spirit.dm @@ -0,0 +1,25 @@ +/** + * Player-only mob which is fast, can jaunt a short distance, and is dangerous at close range + */ +/mob/living/basic/heretic_summon/ash_spirit + name = "Ash Spirit" + real_name = "Ashy" + desc = "A manifestation of ash, trailing a perpetual cloud of short-lived cinders." + icon_state = "ash_walker" + icon_living = "ash_walker" + maxHealth = 75 + health = 75 + melee_damage_lower = 15 + melee_damage_upper = 20 + sight = SEE_TURFS + +/mob/living/basic/heretic_summon/ash_spirit/Initialize(mapload) + . = ..() + var/static/list/actions_to_add = list( + /datum/action/cooldown/spell/fire_sworn, + /datum/action/cooldown/spell/jaunt/ethereal_jaunt/ash, + /datum/action/cooldown/spell/pointed/cleave, + ) + for (var/action in actions_to_add) + var/datum/action/cooldown/new_action = new action(src) + new_action.Grant(src) diff --git a/code/modules/mob/living/basic/heretic/flesh_stalker.dm b/code/modules/mob/living/basic/heretic/flesh_stalker.dm new file mode 100644 index 00000000000..6f31b3ce7c5 --- /dev/null +++ b/code/modules/mob/living/basic/heretic/flesh_stalker.dm @@ -0,0 +1,46 @@ +/// Durable ambush mob with an EMP ability +/mob/living/basic/heretic_summon/stalker + name = "Flesh Stalker" + real_name = "Flesh Stalker" + desc = "An abomination cobbled together from varied remains. Its appearance changes slightly every time you blink." + icon_state = "stalker" + icon_living = "stalker" + maxHealth = 150 + health = 150 + melee_damage_lower = 15 + melee_damage_upper = 20 + sight = SEE_MOBS + ai_controller = /datum/ai_controller/basic_controller/stalker + /// Associative list of action types we would like to have, and what blackboard key (if any) to put it in + var/static/list/actions_to_add = list( + /datum/action/cooldown/spell/emp/eldritch = BB_GENERIC_ACTION, + /datum/action/cooldown/spell/jaunt/ethereal_jaunt/ash = null, + /datum/action/cooldown/spell/shapeshift/eldritch = BB_SHAPESHIFT_ACTION, + ) + +/mob/living/basic/heretic_summon/stalker/Initialize(mapload) + . = ..() + AddComponent(/datum/component/ai_target_timer) + for (var/action_type in actions_to_add) + var/datum/action/new_action = new action_type(src) + new_action.Grant(src) + var/blackboard_key = actions_to_add[action_type] + if (!isnull(blackboard_key)) + ai_controller?.set_blackboard_key(blackboard_key, new_action) + +/// Changes shape and lies in wait when it has no target, uses EMP and attacks once it does +/datum/ai_controller/basic_controller/stalker + ai_traits = CAN_ACT_IN_STASIS + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/shapechange_ambush, + /datum/ai_planning_subtree/use_mob_ability, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) diff --git a/code/modules/mob/living/basic/heretic/flesh_worm.dm b/code/modules/mob/living/basic/heretic/flesh_worm.dm new file mode 100644 index 00000000000..05ef707faf4 --- /dev/null +++ b/code/modules/mob/living/basic/heretic/flesh_worm.dm @@ -0,0 +1,137 @@ +/// Armsy starts to look a bit funky if he's shorter than this +#define MINIMUM_ARMSY_LENGTH 2 + +// What if we took a linked list... But made it a mob? +/// The "Terror of the Night" / Armsy, a large worm made of multiple bodyparts that occupies multiple tiles +/mob/living/basic/heretic_summon/armsy + name = "Lord of the Night" + real_name = "Master of Decay" + desc = "An abomination made from dozens and dozens of severed and malformed limbs grasping onto each other." + icon_state = "armsy_start" + icon_living = "armsy_start" + base_icon_state = "armsy" + maxHealth = 400 + health = 400 + melee_damage_lower = 30 + melee_damage_upper = 50 + obj_damage = 200 + move_force = MOVE_FORCE_OVERPOWERING + move_resist = MOVE_FORCE_OVERPOWERING + pull_force = MOVE_FORCE_OVERPOWERING + mob_size = MOB_SIZE_HUGE + sentience_type = SENTIENCE_BOSS + mob_biotypes = MOB_ORGANIC|MOB_SPECIAL + ///Previous segment in the chain, we hold onto this purely to keep track of how long we currently are and to attach new growth to the back + var/mob/living/basic/heretic_summon/armsy/back + ///How many arms do we have to eat to expand? + var/stacks_to_grow = 5 + ///Currently eaten arms + var/current_stacks = 0 +/* + * Arguments + * * spawn_bodyparts - whether we spawn additional armsy bodies until we reach length. + * * worm_length - the length of the worm we're creating. Below 2 doesn't work very well. + */ +/mob/living/basic/heretic_summon/armsy/Initialize(mapload, spawn_bodyparts = TRUE, worm_length = 6) + . = ..() + AddElement(/datum/element/wall_smasher, ENVIRONMENT_SMASH_RWALLS) + AddElement(\ + /datum/element/amputating_limbs,\ + surgery_time = 0 SECONDS,\ + surgery_verb = "tearing",\ + minimum_stat = CONSCIOUS,\ + snip_chance = 10,\ + target_zones = GLOB.arm_zones,\ + ) + AddComponent(\ + /datum/component/blood_walk, \ + blood_type = /obj/effect/decal/cleanable/blood/tracks, \ + target_dir_change = TRUE,\ + ) + + if(spawn_bodyparts) + build_tail(worm_length) + +// We are a vessel of otherworldly destruction, we bring our gravity with us +/mob/living/basic/heretic_summon/armsy/has_gravity(turf/gravity_turf) + return TRUE + +/mob/living/basic/heretic_summon/armsy/can_be_pulled() + return FALSE // The component does this but not on the head. We don't want the head to be pulled either. + +/mob/living/basic/heretic_summon/armsy/proc/build_tail(worm_length) + worm_length = max(worm_length, MINIMUM_ARMSY_LENGTH) + // Sets the hp of the head to be exactly the (length * hp), so the head is de facto the hardest to destroy. + maxHealth = worm_length * maxHealth + health = maxHealth + + AddComponent(/datum/component/mob_chain, vary_icon_state = TRUE) // We're the front + + var/mob/living/basic/heretic_summon/armsy/prev = src + for(var/i in 1 to worm_length) + prev = new_segment(behind = prev) + update_appearance(UPDATE_ICON_STATE) + +/// Grows a new segment behind the passed mob +/mob/living/basic/heretic_summon/armsy/proc/new_segment(mob/living/basic/heretic_summon/armsy/behind) + var/mob/living/segment = new type(drop_location(), FALSE) + ADD_TRAIT(segment, TRAIT_PERMANENTLY_MORTAL, INNATE_TRAIT) + segment.AddComponent(/datum/component/mob_chain, front = behind, vary_icon_state = TRUE) + behind.register_behind(segment) + return segment + +/// Record that we got another guy on our ass +/mob/living/basic/heretic_summon/armsy/proc/register_behind(mob/living/tail) + if(!isnull(back)) // Shouldn't happen but just in case + UnregisterSignal(back, COMSIG_QDELETING) + back = tail + update_appearance(UPDATE_ICON_STATE) + if(!isnull(back)) + RegisterSignal(back, COMSIG_QDELETING, PROC_REF(tail_deleted)) + +/// When our tail is gone stop holding a reference to it +/mob/living/basic/heretic_summon/armsy/proc/tail_deleted() + SIGNAL_HANDLER + register_behind(null) + +/mob/living/basic/heretic_summon/armsy/melee_attack(atom/target, list/modifiers, ignore_cooldown) + if(!istype(target, /obj/item/bodypart/arm)) + return ..() + visible_message(span_warning("[src] devours [target]!")) + playsound(src, 'sound/magic/demon_consume.ogg', 50, TRUE) + qdel(target) + on_arm_eaten() + +/* + * Handle healing our chain. + * Eating arms off the ground heals us, and if we eat enough arms while above a certain health threshold we get longer! + */ +/mob/living/basic/heretic_summon/armsy/proc/on_arm_eaten() + if(!isnull(back)) + back.on_arm_eaten() + return + + adjustBruteLoss(-maxHealth * 0.5, FALSE) + adjustFireLoss(-maxHealth * 0.5, FALSE) + + if(health < maxHealth * 0.8) + return + + current_stacks++ + if(current_stacks < stacks_to_grow) + return + + visible_message(span_boldwarning("[src] flexes and expands!")) + current_stacks = 0 + new_segment(behind = src) + +/* + * Recursively get the length of our chain. + */ +/mob/living/basic/heretic_summon/armsy/proc/get_length() + . = 1 + if(isnull(back)) + return + . += back.get_length() + +#undef MINIMUM_ARMSY_LENGTH diff --git a/code/modules/antagonists/heretic/mobs/maid_in_mirror.dm b/code/modules/mob/living/basic/heretic/maid_in_the_mirror.dm similarity index 60% rename from code/modules/antagonists/heretic/mobs/maid_in_mirror.dm rename to code/modules/mob/living/basic/heretic/maid_in_the_mirror.dm index b53bbe147d3..edc5148b3cc 100644 --- a/code/modules/antagonists/heretic/mobs/maid_in_mirror.dm +++ b/code/modules/mob/living/basic/heretic/maid_in_the_mirror.dm @@ -1,11 +1,11 @@ -// A summon which floats around the station incorporeally, and can appear in any mirror -/mob/living/simple_animal/hostile/heretic_summon/maid_in_the_mirror +/// Scout and assassin who can appear and disappear from glass surfaces. Damaged by being examined. +/mob/living/basic/heretic_summon/maid_in_the_mirror name = "Maid in the Mirror" real_name = "Maid in the Mirror" desc = "A floating and flowing wisp of chilled air. Glancing at it causes it to shimmer slightly." icon = 'icons/mob/simple/mob.dmi' icon_state = "stand" - icon_living = "stand" // Placeholder sprite + icon_living = "stand" // Placeholder sprite... still speak_emote = list("whispers") movement_type = FLOATING status_flags = CANSTUN | CANPUSH @@ -16,36 +16,34 @@ melee_damage_upper = 16 sight = SEE_MOBS | SEE_OBJS | SEE_TURFS death_message = "shatters and vanishes, releasing a gust of cold air." - loot = list( - /obj/item/shard, + /// Whether we take damage when someone looks at us + var/harmed_by_examine = TRUE + /// How often being examined by a specific mob can hurt us + var/recent_examine_damage_cooldown = 10 SECONDS + /// A list of REFs to people who recently examined us + var/list/recent_examiner_refs = list() + +/mob/living/basic/heretic_summon/Initialize(mapload) + . = ..() + var/static/list/loot = list( /obj/effect/decal/cleanable/ash, /obj/item/clothing/suit/armor/vest, /obj/item/organ/internal/lungs, + /obj/item/shard, ) - actions_to_add = list(/datum/action/cooldown/spell/jaunt/mirror_walk) + AddElement(/datum/element/death_drops, loot) + var/datum/action/cooldown/spell/jaunt/mirror_walk/jaunt = new (src) + jaunt.Grant(src) - /// Whether we take damage when we're examined - var/weak_on_examine = TRUE - /// The cooldown after being examined that the same mob cannot trigger it again - var/recent_examine_damage_cooldown = 10 SECONDS - /// A list of REFs to people who recently examined us - var/list/recent_examiner_refs = list() - -/mob/living/simple_animal/hostile/heretic_summon/maid_in_the_mirror/death(gibbed) +/mob/living/basic/heretic_summon/maid_in_the_mirror/death(gibbed) var/turf/death_turf = get_turf(src) - death_turf.TakeTemperature(-40) + death_turf.TakeTemperature(-40) // Spooky return ..() // Examining them will harm them, on a cooldown. -/mob/living/simple_animal/hostile/heretic_summon/maid_in_the_mirror/examine(mob/user) +/mob/living/basic/heretic_summon/maid_in_the_mirror/examine(mob/user) . = ..() - if(!weak_on_examine) - return - - if(!isliving(user) || user.stat == DEAD) - return - - if(IS_HERETIC_OR_MONSTER(user) || user == src) + if(!harmed_by_examine || user == src || user.stat == DEAD || !isliving(user) || IS_HERETIC_OR_MONSTER(user)) return var/user_ref = REF(user) @@ -62,7 +60,9 @@ recent_examiner_refs += user_ref apply_damage(maxHealth * 0.1) // We take 10% of our health as damage upon being examined playsound(src, 'sound/effects/ghost2.ogg', 40, TRUE) - addtimer(CALLBACK(src, PROC_REF(clear_recent_examiner), user_ref), recent_examine_damage_cooldown) + addtimer(CALLBACK(src, PROC_REF(clear_recent_examiner), user_ref), recent_examine_damage_cooldown, TIMER_DELETE_ME) + animate(src, alpha = 120, time = 0.5 SECONDS, easing = ELASTIC_EASING, loop = 2, flags = ANIMATION_PARALLEL) + animate(alpha = 255, time = 0.5 SECONDS, easing = ELASTIC_EASING) // If we're examined on low enough health we die straight up else @@ -73,7 +73,7 @@ death() -/mob/living/simple_animal/hostile/heretic_summon/maid_in_the_mirror/proc/clear_recent_examiner(mob_ref) +/mob/living/basic/heretic_summon/maid_in_the_mirror/proc/clear_recent_examiner(mob_ref) if(!(mob_ref in recent_examiner_refs)) return diff --git a/code/modules/mob/living/basic/heretic/rust_walker.dm b/code/modules/mob/living/basic/heretic/rust_walker.dm new file mode 100644 index 00000000000..070326c0281 --- /dev/null +++ b/code/modules/mob/living/basic/heretic/rust_walker.dm @@ -0,0 +1,87 @@ +/// Pretty simple mob which creates areas of rust and has a rust-creating projectile spell +/mob/living/basic/heretic_summon/rust_walker + name = "Rust Walker" + real_name = "Rusty" + desc = "A grinding, clanking construct which leaches life from its surroundings with every armoured step." + icon_state = "rust_walker_s" + base_icon_state = "rust_walker" + icon_living = "rust_walker_s" + maxHealth = 75 + health = 75 + melee_damage_lower = 15 + melee_damage_upper = 20 + sight = SEE_TURFS + speed = 1 + ai_controller = /datum/ai_controller/basic_controller/rust_walker + +/mob/living/basic/heretic_summon/rust_walker/Initialize(mapload) + . = ..() + AddElement(/datum/element/footstep, FOOTSTEP_MOB_RUST) + var/datum/action/cooldown/spell/aoe/rust_conversion/small/conversion = new(src) + conversion.Grant(src) + ai_controller?.set_blackboard_key(BB_GENERIC_ACTION, conversion) + + var/datum/action/cooldown/spell/basic_projectile/rust_wave/short/wave = new(src) + wave.Grant(src) + ai_controller?.set_blackboard_key(BB_TARGETTED_ACTION, wave) + +/mob/living/basic/heretic_summon/rust_walker/setDir(newdir) + . = ..() + update_appearance(UPDATE_ICON_STATE) + +/mob/living/basic/heretic_summon/rust_walker/update_icon_state() + . = ..() + if(stat == DEAD) // We usually delete on death but just in case + return + if(dir & NORTH) + icon_state = "[base_icon_state]_n" + else if(dir & SOUTH) + icon_state = "[base_icon_state]_s" + icon_living = icon_state + +/mob/living/basic/heretic_summon/rust_walker/Life(seconds_per_tick = SSMOBS_DT, times_fired) + if(stat == DEAD) + return ..() + var/turf/our_turf = get_turf(src) + if(HAS_TRAIT(our_turf, TRAIT_RUSTY)) + adjustBruteLoss(-3 * seconds_per_tick) + + return ..() + +/// Converts unconverted terrain, sprays pocket sand around +/datum/ai_controller/basic_controller/rust_walker + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk/rust + planning_subtrees = list( + /datum/ai_planning_subtree/use_mob_ability/rust_walker, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/targeted_mob_ability, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) + +/// Moves a lot if healthy and on rust (to find more tiles to rust) or unhealthy and not on rust (to find healing rust) +/// Still moving in random directions though we're not really seeking it out +/datum/idle_behavior/idle_random_walk/rust + +/datum/idle_behavior/idle_random_walk/rust/perform_idle_behavior(seconds_per_tick, datum/ai_controller/controller) + var/mob/living/our_mob = controller.pawn + var/turf/our_turf = get_turf(our_mob) + if (HAS_TRAIT(our_turf, TRAIT_RUSTY)) + walk_chance = (our_mob.health < our_mob.maxHealth) ? 10 : 50 + else + walk_chance = (our_mob.health < our_mob.maxHealth) ? 50 : 10 + return ..() + +/// Use if we're not stood on rust right now +/datum/ai_planning_subtree/use_mob_ability/rust_walker + +/datum/ai_planning_subtree/use_mob_ability/rust_walker/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/turf/our_turf = get_turf(controller.pawn) + if (HAS_TRAIT(our_turf, TRAIT_RUSTY)) + return + return ..() diff --git a/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon.dm b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon.dm new file mode 100644 index 00000000000..960f875365b --- /dev/null +++ b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon.dm @@ -0,0 +1,89 @@ +/mob/living/basic/mining/ice_demon + name = "demonic watcher" + desc = "A creature formed entirely out of ice, bluespace energy emanates from inside of it." + icon = 'icons/mob/simple/icemoon/icemoon_monsters.dmi' + icon_state = "ice_demon" + icon_living = "ice_demon" + icon_gib = "syndicate_gib" + mob_biotypes = MOB_ORGANIC|MOB_BEAST + mouse_opacity = MOUSE_OPACITY_ICON + basic_mob_flags = DEL_ON_DEATH + speed = 2 + maxHealth = 150 + health = 150 + obj_damage = 40 + melee_damage_lower = 15 + melee_damage_upper = 15 + attack_verb_continuous = "slices" + attack_verb_simple = "slice" + attack_sound = 'sound/weapons/bladeslice.ogg' + attack_vis_effect = ATTACK_EFFECT_SLASH + move_force = MOVE_FORCE_VERY_STRONG + move_resist = MOVE_FORCE_VERY_STRONG + pull_force = MOVE_FORCE_VERY_STRONG + crusher_loot = /obj/item/crusher_trophy/ice_demon_cube + ai_controller = /datum/ai_controller/basic_controller/ice_demon + death_message = "fades as the energies that tied it to this world dissipate." + death_sound = 'sound/magic/demon_dies.ogg' + +/mob/living/basic/mining/ice_demon/Initialize(mapload) + . = ..() + var/datum/action/cooldown/mob_cooldown/slippery_ice_floors/ice_floor = new(src) + ice_floor.Grant(src) + ai_controller.set_blackboard_key(BB_DEMON_SLIP_ABILITY, ice_floor) + var/datum/action/cooldown/mob_cooldown/ice_demon_teleport/demon_teleport = new(src) + demon_teleport.Grant(src) + ai_controller.set_blackboard_key(BB_DEMON_TELEPORT_ABILITY, demon_teleport) + var/datum/action/cooldown/spell/conjure/create_afterimages/afterimage = new(src) + afterimage.Grant(src) + ai_controller.set_blackboard_key(BB_DEMON_CLONE_ABILITY, afterimage) + AddComponent(\ + /datum/component/ranged_attacks,\ + projectile_type = /obj/projectile/temp/ice_demon,\ + projectile_sound = 'sound/weapons/pierce.ogg',\ + ) + var/static/list/death_loot = list(/obj/item/stack/ore/bluespace_crystal = 3) + AddElement(/datum/element/death_drops, death_loot) + AddElement(/datum/element/simple_flying) + +/mob/living/basic/mining/ice_demon/death(gibbed) + if(prob(5)) + new /obj/item/raw_anomaly_core/bluespace(loc) + return ..() + +/mob/living/basic/mining/demon_afterimage + name = "afterimage demonic watcher" + desc = "Is this some sort of illusion?" + icon = 'icons/mob/simple/icemoon/icemoon_monsters.dmi' + icon_state = "ice_demon" + icon_living = "ice_demon" + icon_gib = "syndicate_gib" + mob_biotypes = MOB_ORGANIC|MOB_BEAST + mouse_opacity = MOUSE_OPACITY_ICON + basic_mob_flags = DEL_ON_DEATH + speed = 5 + maxHealth = 20 + health = 20 + melee_damage_lower = 5 + melee_damage_upper = 5 + attack_verb_continuous = "slices" + attack_verb_simple = "slice" + attack_sound = 'sound/weapons/bladeslice.ogg' + alpha = 80 + ai_controller = /datum/ai_controller/basic_controller/ice_demon/afterimage + ///how long do we exist for + var/existence_period = 15 SECONDS + +/mob/living/basic/mining/demon_afterimage/Initialize(mapload) + . = ..() + AddElement(/datum/element/simple_flying) + AddElement(/datum/element/temporary_atom, life_time = existence_period) + +///afterimage subtypes summoned by the crusher +/mob/living/basic/mining/demon_afterimage/crusher + speed = 2 + health = 60 + maxHealth = 60 + melee_damage_lower = 10 + melee_damage_upper = 10 + existence_period = 7 SECONDS diff --git a/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_abilities.dm b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_abilities.dm new file mode 100644 index 00000000000..79c9ee9bd58 --- /dev/null +++ b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_abilities.dm @@ -0,0 +1,117 @@ +/obj/projectile/temp/ice_demon + name = "ice blast" + icon_state = "ice_2" + damage = 5 + damage_type = BURN + armor_flag = ENERGY + speed = 1 + pixel_speed_multiplier = 0.25 + temperature = -75 + +/datum/action/cooldown/mob_cooldown/ice_demon_teleport + name = "Bluespace Teleport" + desc = "Teleport towards a destination target!" + button_icon = 'icons/obj/ore.dmi' + button_icon_state = "bluespace_crystal" + cooldown_time = 3 SECONDS + melee_cooldown_time = 0 SECONDS + ///time delay before teleport + var/time_delay = 0.5 SECONDS + +/datum/action/cooldown/mob_cooldown/ice_demon_teleport/Activate(atom/target_atom) + if(isclosedturf(get_turf(target_atom))) + owner.balloon_alert(owner, "blocked!") + return FALSE + animate(owner, transform = matrix().Scale(0.8), time = time_delay, easing = SINE_EASING) + addtimer(CALLBACK(src, PROC_REF(teleport_to_turf), target_atom), time_delay) + StartCooldown() + return TRUE + +/datum/action/cooldown/mob_cooldown/ice_demon_teleport/proc/teleport_to_turf(atom/target) + animate(owner, transform = matrix(), time = 0.5 SECONDS, easing = SINE_EASING) + do_teleport(teleatom = owner, destination = target, channel = TELEPORT_CHANNEL_BLUESPACE, forced = TRUE) + +/datum/action/cooldown/mob_cooldown/slippery_ice_floors + name = "Iced Floors" + desc = "Summon slippery ice floors all around!" + button_icon = 'icons/turf/floors/ice_turf.dmi' + button_icon_state = "ice_turf-6" + cooldown_time = 2 SECONDS + click_to_activate = FALSE + melee_cooldown_time = 0 SECONDS + ///perimeter we will spawn the iced floors on + var/radius = 1 + ///intervals we will spawn the ice floors in + var/spread_duration = 0.2 SECONDS + +/datum/action/cooldown/mob_cooldown/slippery_ice_floors/Activate(atom/target_atom) + for(var/i in 0 to radius) + var/list/list_of_turfs = border_diamond_range_turfs(owner, i) + addtimer(CALLBACK(src, PROC_REF(spawn_icy_floors), list_of_turfs), i * spread_duration) + StartCooldown() + return TRUE + +/datum/action/cooldown/mob_cooldown/slippery_ice_floors/proc/spawn_icy_floors(list/list_of_turfs) + if(!length(list_of_turfs)) + return + for(var/turf/location in list_of_turfs) + if(isnull(location)) + continue + if(isclosedturf(location) || isspaceturf(location)) + continue + new /obj/effect/temp_visual/slippery_ice(location) + +/obj/effect/temp_visual/slippery_ice + name = "slippery acid" + icon = 'icons/turf/floors/ice_turf.dmi' + icon_state = "ice_turf-6" + layer = BELOW_MOB_LAYER + plane = GAME_PLANE + anchored = TRUE + duration = 3 SECONDS + alpha = 100 + /// how long does it take for the effect to phase in + var/phase_in_period = 2 SECONDS + +/obj/effect/temp_visual/slippery_ice/Initialize(mapload) + . = ..() + animate(src, alpha = 160, time = phase_in_period) + animate(alpha = 0, time = duration - phase_in_period) /// slowly fade out of existence + addtimer(CALLBACK(src, PROC_REF(add_slippery_component), phase_in_period)) //only become slippery after we phased in + +/obj/effect/temp_visual/slippery_ice/proc/add_slippery_component() + AddComponent(/datum/component/slippery, 2 SECONDS) + +/datum/action/cooldown/spell/conjure/create_afterimages + name = "Create After Images" + button_icon = 'icons/mob/simple/icemoon/icemoon_monsters.dmi' + button_icon_state = "ice_demon" + spell_requirements = NONE + cooldown_time = 1 MINUTES + summon_type = list(/mob/living/basic/mining/demon_afterimage) + summon_radius = 1 + summon_amount = 2 + ///max number of after images + var/max_afterimages = 2 + ///How many clones do we have summoned + var/number_of_afterimages = 0 + +/datum/action/cooldown/spell/conjure/create_afterimages/can_cast_spell(feedback = TRUE) + . = ..() + if(!.) + return FALSE + if(number_of_afterimages >= max_afterimages) + return FALSE + return TRUE + +/datum/action/cooldown/spell/conjure/create_afterimages/post_summon(atom/summoned_object, atom/cast_on) + var/mob/living/basic/created_copy = summoned_object + created_copy.AddComponent(/datum/component/joint_damage, overlord_mob = owner) + RegisterSignals(created_copy, list(COMSIG_QDELETING, COMSIG_LIVING_DEATH), PROC_REF(delete_copy)) + number_of_afterimages++ + +/datum/action/cooldown/spell/conjure/create_afterimages/proc/delete_copy(mob/source) + SIGNAL_HANDLER + + UnregisterSignal(source, list(COMSIG_QDELETING, COMSIG_LIVING_DEATH)) + number_of_afterimages-- diff --git a/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm new file mode 100644 index 00000000000..b17d5c1a30d --- /dev/null +++ b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon_ai.dm @@ -0,0 +1,118 @@ +/datum/ai_controller/basic_controller/ice_demon + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_LIST_SCARY_ITEMS = list( + /obj/item/weldingtool, + /obj/item/flashlight/flare, + ), + BB_BASIC_MOB_FLEEING = TRUE, + BB_MINIMUM_DISTANCE_RANGE = 3, + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/flee_target/ice_demon, + /datum/ai_planning_subtree/ranged_skirmish/ice_demon, + /datum/ai_planning_subtree/maintain_distance/cover_minimum_distance/ice_demon, + /datum/ai_planning_subtree/teleport_away_from_target, + /datum/ai_planning_subtree/find_and_hunt_target/teleport_destination, + /datum/ai_planning_subtree/targeted_mob_ability/summon_afterimages, + ) + + +/datum/ai_planning_subtree/maintain_distance/cover_minimum_distance/ice_demon + maximum_distance = 7 + +/datum/ai_planning_subtree/teleport_away_from_target + ability_key = BB_DEMON_TELEPORT_ABILITY + +/datum/ai_planning_subtree/find_and_hunt_target/teleport_destination + target_key = BB_TELEPORT_DESTINATION + hunting_behavior = /datum/ai_behavior/hunt_target/use_ability_on_target/demon_teleport + finding_behavior = /datum/ai_behavior/find_valid_teleport_location + hunt_targets = list(/turf/open) + hunt_range = 3 + finish_planning = FALSE + +/datum/ai_planning_subtree/find_and_hunt_target/teleport_destination/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + if(!controller.blackboard_key_exists(BB_BASIC_MOB_CURRENT_TARGET)) + return + if(controller.blackboard_key_exists(BB_ESCAPE_DESTINATION)) + controller.clear_blackboard_key(BB_TELEPORT_DESTINATION) + return + var/datum/action/cooldown/ability = controller.blackboard[BB_DEMON_TELEPORT_ABILITY] + if(!ability?.IsAvailable()) + return + return ..() + +/datum/ai_behavior/find_valid_teleport_location + +/datum/ai_behavior/find_valid_teleport_location/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, types_to_hunt, hunt_range) + . = ..() + var/mob/living/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + var/list/possible_turfs = list() + + if(QDELETED(target)) + finish_action(controller, FALSE) + return + + for(var/turf/open/potential_turf in oview(hunt_range, target)) //we check for turfs around the target + if(potential_turf.is_blocked_turf()) + continue + if(!can_see(target, potential_turf, hunt_range)) + continue + possible_turfs += potential_turf + + if(!length(possible_turfs)) + finish_action(controller, FALSE) + return + + controller.set_blackboard_key(hunting_target_key, pick(possible_turfs)) + finish_action(controller, TRUE) + +/datum/ai_behavior/hunt_target/use_ability_on_target/demon_teleport + hunt_cooldown = 2 SECONDS + ability_key = BB_DEMON_TELEPORT_ABILITY + behavior_flags = NONE + +/datum/ai_planning_subtree/targeted_mob_ability/summon_afterimages + ability_key = BB_DEMON_CLONE_ABILITY + +/datum/ai_planning_subtree/targeted_mob_ability/summon_afterimages/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/mob/living/living_pawn = controller.pawn + if(living_pawn.health / living_pawn.maxHealth > 0.5) //only use this ability when under half health + return + return ..() + +/datum/ai_planning_subtree/flee_target/ice_demon + +/datum/ai_planning_subtree/flee_target/ice_demon/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/atom/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + if(QDELETED(target)) + return + if(!iscarbon(target)) + return + var/mob/living/carbon/human_target = target + + for(var/obj/held_item in human_target.held_items) + if(!is_type_in_list(held_item, controller.blackboard[BB_LIST_SCARY_ITEMS])) + continue + if(!held_item.light_on) + continue + var/datum/action/cooldown/slip_ability = controller.blackboard[BB_DEMON_SLIP_ABILITY] + if(slip_ability?.IsAvailable()) + controller.queue_behavior(/datum/ai_behavior/use_mob_ability, BB_DEMON_SLIP_ABILITY) + return ..() + +/datum/ai_planning_subtree/ranged_skirmish/ice_demon + min_range = 0 + +/datum/ai_controller/basic_controller/ice_demon/afterimage + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/flee_target/ice_demon, //even the afterimages are afraid of flames! + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) + diff --git a/code/modules/mob/living/basic/jungle/mega_arachnid/mega_arachnid_ai.dm b/code/modules/mob/living/basic/jungle/mega_arachnid/mega_arachnid_ai.dm index c88178135dc..8964ebf837e 100644 --- a/code/modules/mob/living/basic/jungle/mega_arachnid/mega_arachnid_ai.dm +++ b/code/modules/mob/living/basic/jungle/mega_arachnid/mega_arachnid_ai.dm @@ -1,7 +1,6 @@ /datum/ai_controller/basic_controller/mega_arachnid blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_BASIC_MOB_FLEEING = TRUE, BB_BASIC_MOB_FLEE_DISTANCE = 5, ) @@ -37,7 +36,7 @@ flee_behaviour = /datum/ai_behavior/run_away_from_target/mega_arachnid /datum/ai_planning_subtree/flee_target/mega_arachnid/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - if(!controller.blackboard[BB_BASIC_MOB_FLEEING]) + if(controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) return var/datum/action/cooldown/slip_acid = controller.blackboard[BB_ARACHNID_SLIP] diff --git a/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub_ai.dm b/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub_ai.dm index 58efaf1f81b..3c652f888c2 100644 --- a/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub_ai.dm +++ b/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub_ai.dm @@ -3,7 +3,6 @@ BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/not_friends, BB_ORE_IGNORE_TYPES = list(/obj/item/stack/ore/iron, /obj/item/stack/ore/glass), - BB_BASIC_MOB_FLEEING = TRUE, BB_STORM_APPROACHING = FALSE, ) @@ -25,7 +24,6 @@ BB_ORE_IGNORE_TYPES = list(/obj/item/stack/ore/glass), BB_FIND_MOM_TYPES = list(/mob/living/basic/mining/goldgrub), BB_IGNORE_MOM_TYPES = list(/mob/living/basic/mining/goldgrub/baby), - BB_BASIC_MOB_FLEEING = TRUE, BB_STORM_APPROACHING = FALSE, ) diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm index 6b3525cb32a..cbadd709047 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm @@ -2,7 +2,6 @@ /datum/ai_controller/basic_controller/legion blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead/legion, - BB_BASIC_MOB_FLEEING = TRUE, BB_AGGRO_RANGE = 5, // Unobservant BB_BASIC_MOB_FLEE_DISTANCE = 6, ) diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm index 18cd7321936..f7feaa88265 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm @@ -28,8 +28,6 @@ ai_controller = /datum/ai_controller/basic_controller/lobstrosity /// Charging ability var/datum/action/cooldown/mob_cooldown/charge/basic_charge/lobster/charge - /// Limbs we will cut off an unconscious man - var/static/list/target_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) /// Things we will eat if we see them (arms, chiefly) var/static/list/target_foods = list(/obj/item/bodypart/arm) @@ -42,7 +40,7 @@ AddElement(\ /datum/element/amputating_limbs,\ surgery_verb = "snipping",\ - target_zones = target_limbs,\ + target_zones = GLOB.arm_zones,\ ) charge = new(src) charge.Grant(src) @@ -76,7 +74,7 @@ var/mob/living/basic/basic_source = source var/mob/living/living_target = target basic_source.melee_attack(living_target, ignore_cooldown = TRUE) - basic_source.ai_controller?.set_blackboard_key(BB_BASIC_MOB_FLEEING, FALSE) + basic_source.ai_controller?.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, TRUE) basic_source.start_pulling(living_target) /datum/action/cooldown/mob_cooldown/charge/basic_charge/lobster/do_charge(atom/movable/charger, atom/target_atom, delay, past) diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm index 8e4dfe9e294..7b6926fca04 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm @@ -2,7 +2,6 @@ blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/lobster, BB_LOBSTROSITY_EXPLOIT_TRAITS = list(TRAIT_INCAPACITATED, TRAIT_FLOORED, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT), - BB_BASIC_MOB_FLEEING = TRUE, BB_LOBSTROSITY_FINGER_LUST = 0 ) @@ -26,7 +25,7 @@ melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/lobster /datum/ai_planning_subtree/basic_melee_attack_subtree/lobster/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - if (controller.blackboard[BB_BASIC_MOB_FLEEING]) + if (!controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) return if (!isnull(controller.blackboard[BB_LOBSTROSITY_TARGET_LIMB])) return @@ -48,8 +47,8 @@ is_vulnerable = TRUE break if (!is_vulnerable) - controller.set_blackboard_key(BB_BASIC_MOB_FLEEING, TRUE) - if (controller.blackboard[BB_BASIC_MOB_FLEEING]) + controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, FALSE) + if (!controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) finish_action(controller = controller, succeeded = TRUE, target_key = target_key) // We don't want to clear our target return return ..() @@ -57,6 +56,12 @@ /datum/ai_planning_subtree/flee_target/lobster flee_behaviour = /datum/ai_behavior/run_away_from_target/lobster +/datum/ai_planning_subtree/flee_target/lobster/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/datum/action/cooldown/using_action = controller.blackboard[BB_TARGETTED_ACTION] + if (using_action?.IsAvailable()) + return + return ..() + /datum/ai_behavior/run_away_from_target/lobster clear_failed_targets = FALSE @@ -64,10 +69,11 @@ var/atom/target = controller.blackboard[target_key] if(isnull(target)) return ..() + for (var/trait in controller.blackboard[BB_LOBSTROSITY_EXPLOIT_TRAITS]) if (!HAS_TRAIT(target, trait)) continue - controller.set_blackboard_key(BB_BASIC_MOB_FLEEING, FALSE) + controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, TRUE) finish_action(controller, succeeded = FALSE) return diff --git a/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm b/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm index a25234817f3..348bbcfcaa7 100644 --- a/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm +++ b/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm @@ -27,13 +27,10 @@ return ..() /datum/ai_planning_subtree/ranged_skirmish/watcher - attack_behavior = /datum/ai_behavior/ranged_skirmish/watcher + min_range = 0 /datum/ai_planning_subtree/ranged_skirmish/watcher/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) var/mob/living/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] if (QDELETED(target) || HAS_TRAIT(target, TRAIT_OVERWATCHED)) return // Don't bully people who are playing red light green light return ..() - -/datum/ai_behavior/ranged_skirmish/watcher - min_range = 0 diff --git a/code/modules/mob/living/basic/pets/fox.dm b/code/modules/mob/living/basic/pets/fox.dm index 578a64ba08d..f7a86be1e5c 100644 --- a/code/modules/mob/living/basic/pets/fox.dm +++ b/code/modules/mob/living/basic/pets/fox.dm @@ -38,7 +38,6 @@ /datum/ai_controller/basic_controller/fox blackboard = list( - BB_BASIC_MOB_FLEEING = TRUE, BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/ours_or_smaller/ignore_faction, BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction ) diff --git a/code/modules/mob/living/basic/pets/sloth.dm b/code/modules/mob/living/basic/pets/sloth.dm new file mode 100644 index 00000000000..5058e7d5334 --- /dev/null +++ b/code/modules/mob/living/basic/pets/sloth.dm @@ -0,0 +1,97 @@ +GLOBAL_DATUM(cargo_sloth, /mob/living/basic/sloth) + +/mob/living/basic/sloth + name = "sloth" + desc = "An adorable, sleepy creature." + icon = 'icons/mob/simple/pets.dmi' + icon_state = "sloth" + icon_living = "sloth" + icon_dead = "sloth_dead" + + speak_emote = list("yawns") + + can_be_held = TRUE + held_state = "sloth" + + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" + + attack_verb_continuous = "bites" + attack_verb_simple = "bite" + attack_sound = 'sound/weapons/bite.ogg' + attack_vis_effect = ATTACK_EFFECT_BITE + + mob_biotypes = MOB_ORGANIC|MOB_BEAST + gold_core_spawnable = FRIENDLY_SPAWN + + melee_damage_lower = 18 + melee_damage_upper = 18 + health = 50 + maxHealth = 50 + speed = 10 // speed is fucking weird man. they aren't fast though don't worry + butcher_results = list(/obj/item/food/meat/slab = 3) + + ai_controller = /datum/ai_controller/basic_controller/sloth + +/mob/living/basic/sloth/Initialize(mapload) + . = ..() + AddElement(/datum/element/pet_bonus, "slowly smiles!") + AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_CLAW) + AddElement(/datum/element/ai_retaliate) + AddComponent(/datum/component/tree_climber) + + if(!mapload || isnull(GLOB.cargo_sloth) || !is_station_level(z)) + return + + // If someone adds non-cargo sloths to maps we'll have a problem but we're fine for now + GLOB.cargo_sloth = src + +/mob/living/basic/sloth/Destroy() + if(GLOB.cargo_sloth == src) + GLOB.cargo_sloth = null + + return ..() + +/mob/living/basic/sloth/paperwork + name = "Paperwork" + desc = "Cargo's pet sloth. About as useful as the rest of the techs." + gender = MALE + gold_core_spawnable = NO_SPAWN + +/mob/living/basic/sloth/citrus + name = "Citrus" + desc = "Cargo's pet sloth. She's dressed in a horrible sweater." + icon_state = "cool_sloth" + icon_living = "cool_sloth" + icon_dead = "cool_sloth_dead" + gender = FEMALE + butcher_results = list(/obj/item/toy/spinningtoy = 1) + gold_core_spawnable = NO_SPAWN + +/// They're really passive in game, so they just wanna get away if you start smacking them. No trees in space from them to use for clawing your eyes out, but they will try if desperate. +/datum/ai_controller/basic_controller/sloth + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction, + BB_BASIC_MOB_FLEEING = TRUE, + BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction, + ) + + ai_traits = STOP_MOVING_WHEN_PULLED + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + + planning_subtrees = list( + /datum/ai_planning_subtree/target_retaliate/to_flee, + /datum/ai_planning_subtree/flee_target/from_flee_key, + /datum/ai_planning_subtree/climb_trees, + /datum/ai_planning_subtree/random_speech/sloth, + ) + +/datum/ai_planning_subtree/random_speech/sloth + speech_chance = 1 + emote_hear = list("snores.", "yawns.") + emote_see = list("dozes off.", "looks around sleepily.") diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm index d220325ca15..fc6997896b0 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm @@ -31,7 +31,7 @@ finish_planning = TRUE /datum/ai_planning_subtree/make_carp_rift/panic_teleport/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - if (!controller.blackboard[BB_BASIC_MOB_FLEEING]) + if (controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) return return ..() diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm index b3097014535..503264c3dc2 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm @@ -9,6 +9,7 @@ */ /datum/ai_controller/basic_controller/carp blackboard = list( + BB_BASIC_MOB_STOP_FLEEING = TRUE, BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items(), BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/not_friends() ) @@ -35,6 +36,7 @@ */ /datum/ai_controller/basic_controller/carp/pet blackboard = list( + BB_BASIC_MOB_STOP_FLEEING = TRUE, BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/not_friends() ) @@ -78,6 +80,7 @@ */ /datum/ai_controller/basic_controller/carp/passive blackboard = list( + BB_BASIC_MOB_STOP_FLEEING = TRUE, BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/not_friends() ) diff --git a/code/modules/mob/living/basic/space_fauna/demon/demon.dm b/code/modules/mob/living/basic/space_fauna/demon/demon.dm index c2d8c751cde..741ac27712f 100644 --- a/code/modules/mob/living/basic/space_fauna/demon/demon.dm +++ b/code/modules/mob/living/basic/space_fauna/demon/demon.dm @@ -32,6 +32,7 @@ obj_damage = 40 melee_damage_lower = 10 melee_damage_upper = 15 + melee_attack_cooldown = CLICK_CD_MELEE death_message = "screams in agony as it sublimates into a sulfurous smoke." death_sound = 'sound/magic/demon_dies.ogg' diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_ai.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_ai.dm index ef92c7b3b76..97dbdbd0a7d 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_ai.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_ai.dm @@ -1,7 +1,6 @@ /datum/ai_controller/basic_controller/regal_rat blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, - BB_BASIC_MOB_FLEEING = TRUE, BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction, ) diff --git a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_ai.dm b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_ai.dm index f998b7b53cd..9894d15fdfb 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_ai.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_ai.dm @@ -45,7 +45,6 @@ blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/ours_or_smaller(), // Hunt mobs our size BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/larger(), // Run away from mobs bigger than we are - BB_BASIC_MOB_FLEEING = TRUE, ) idle_behavior = /datum/idle_behavior/idle_random_walk diff --git a/code/modules/mob/living/basic/space_fauna/spider/spiderlings/spiderling.dm b/code/modules/mob/living/basic/space_fauna/spider/spiderlings/spiderling.dm index 7108983c310..c949b438683 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/spiderlings/spiderling.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/spiderlings/spiderling.dm @@ -61,7 +61,6 @@ /datum/ai_controller/basic_controller/spiderling blackboard = list( BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/larger, // Run away from mobs bigger than we are - BB_BASIC_MOB_FLEEING = TRUE, BB_VENTCRAWL_COOLDOWN = 20 SECONDS, // enough time to get splatted while we're out in the open. BB_TIME_TO_GIVE_UP_ON_VENT_PATHING = 30 SECONDS, ) diff --git a/code/modules/mob/living/basic/space_fauna/statue/statue.dm b/code/modules/mob/living/basic/space_fauna/statue/statue.dm index bce35146ecf..d2ea5e8a831 100644 --- a/code/modules/mob/living/basic/space_fauna/statue/statue.dm +++ b/code/modules/mob/living/basic/space_fauna/statue/statue.dm @@ -162,7 +162,7 @@ maxHealth = 5000 melee_damage_lower = 65 melee_damage_upper = 65 - faction = list("statue","mining") + faction = list(FACTION_STATUE,FACTION_MINING) /mob/living/basic/statue/frosty/Initialize(mapload) . = ..() diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/inflation.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/inflation.dm index d459648892b..a9e2b538bdd 100644 --- a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/inflation.dm +++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/inflation.dm @@ -65,7 +65,7 @@ fugu.melee_damage_upper = 20 fugu.status_flags |= GODMODE fugu.obj_damage = 60 - fugu.ai_controller.set_blackboard_key(BB_BASIC_MOB_FLEEING, FALSE) + fugu.ai_controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, TRUE) fugu.ai_controller.CancelActions() /datum/status_effect/inflated/on_remove() @@ -84,7 +84,7 @@ if (fugu.stat != DEAD) fugu.icon_state = "Fugu0" fugu.obj_damage = 0 - fugu.ai_controller.set_blackboard_key(BB_BASIC_MOB_FLEEING, TRUE) + fugu.ai_controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, FALSE) fugu.ai_controller.CancelActions() /// Remove status effect if we die diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_ai.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_ai.dm index 9d3a09c5348..e405ee3755a 100644 --- a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_ai.dm +++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_ai.dm @@ -2,7 +2,6 @@ /datum/ai_controller/basic_controller/wumborian_fugu blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), - BB_BASIC_MOB_FLEEING = TRUE, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/vermin/crab.dm b/code/modules/mob/living/basic/vermin/crab.dm index abe5c25117b..4843c6e6f7b 100644 --- a/code/modules/mob/living/basic/vermin/crab.dm +++ b/code/modules/mob/living/basic/vermin/crab.dm @@ -77,7 +77,7 @@ ///The basic ai controller for crabs /datum/ai_controller/basic_controller/crab blackboard = list( - BB_BASIC_MOB_FLEEING = FALSE, + BB_BASIC_MOB_STOP_FLEEING = TRUE, BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/of_size/ours_or_smaller, BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction, ) diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index 46e175c5323..87d549ac523 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -376,8 +376,7 @@ /// The mouse AI controller /datum/ai_controller/basic_controller/mouse - blackboard = list( - BB_BASIC_MOB_FLEEING = TRUE, // Always cowardly + blackboard = list( // Always cowardly BB_CURRENT_HUNTING_TARGET = null, // cheese BB_LOW_PRIORITY_HUNTING_TARGET = null, // cable BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), // Use this to find people to run away from diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 9354f02e2b2..bc0d2e3d8e8 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -41,11 +41,14 @@ //Effects of bloodloss var/word = pick("dizzy","woozy","faint") switch(blood_volume) - if(BLOOD_VOLUME_EXCESS to BLOOD_VOLUME_MAX_LETHAL) + if(BLOOD_VOLUME_MAX_LETHAL to INFINITY) if(SPT_PROB(7.5, seconds_per_tick)) to_chat(src, span_userdanger("Blood starts to tear your skin apart. You're going to burst!")) investigate_log("has been gibbed by having too much blood.", INVESTIGATE_DEATHS) inflate_gib() + if(BLOOD_VOLUME_EXCESS to BLOOD_VOLUME_MAX_LETHAL) + if(SPT_PROB(5, seconds_per_tick)) + to_chat(src, span_warning("You feel your skin swelling.")) if(BLOOD_VOLUME_MAXIMUM to BLOOD_VOLUME_EXCESS) if(SPT_PROB(5, seconds_per_tick)) to_chat(src, span_warning("You feel terribly bloated.")) @@ -94,7 +97,7 @@ //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)) + add_splatter_floor(loc, (amt <= 10)) /mob/living/carbon/human/bleed(amt) amt *= physiology.bleed_mod diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 8cb32613da8..a51e9c3430e 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -479,8 +479,7 @@ var/immediately_stun = should_stun && !(flags & SHOCK_DELAY_STUN) if (immediately_stun) if (paralyze) - //Paralyze(40) - SKYRAT EDIT REMOVAL - StaminaKnockdown(10, TRUE) // SKYRAT EDIT ADDITION + StaminaKnockdown(stun_duration / 4) // SKYRAT EDIT CHANGE - ORIGINAL: Paralyze(40) else Knockdown(stun_duration) //Jitter and other fluff. @@ -494,8 +493,7 @@ ///Called slightly after electrocute act to apply a secondary stun. /mob/living/carbon/proc/secondary_shock(paralyze, stun_duration) if (paralyze) - //Paralyze(60) - SKYRAT EDIT REMOVAL - StaminaKnockdown(10, TRUE) //SKYRAT EDIT ADDITION + StaminaKnockdown(stun_duration / 6) // SKYRAT EDIT CHANGE - ORIGINAL: Paralyze(60) else Knockdown(stun_duration) diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index 963f064286b..040bf76a3db 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -56,8 +56,8 @@ return amount /mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype) - if(!forced && (status_flags & GODMODE)) - return FALSE + if(!can_adjust_brute_loss(amount, forced, required_bodytype)) + return 0 if(amount > 0) . = take_overall_damage(brute = amount, updating_health = updating_health, forced = forced, required_bodytype = required_bodytype) else @@ -73,8 +73,8 @@ return adjustBruteLoss(diff, updating_health, forced, required_bodytype) /mob/living/carbon/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype) - if(!forced && (status_flags & GODMODE)) - return FALSE + if(!can_adjust_fire_loss(amount, forced, required_bodytype)) + return 0 if(amount > 0) . = take_overall_damage(burn = amount, updating_health = updating_health, forced = forced, required_bodytype = required_bodytype) else @@ -90,10 +90,8 @@ return adjustFireLoss(diff, updating_health, forced, required_bodytype) /mob/living/carbon/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) - if(!forced && (status_flags & GODMODE)) - return FALSE - if(!forced && !(mob_biotypes & required_biotype)) - return FALSE + if(!can_adjust_tox_loss(amount, forced, required_biotype)) + return 0 if(!forced && HAS_TRAIT(src, TRAIT_TOXINLOVER)) //damage becomes healing and healing becomes damage amount = -amount if(HAS_TRAIT(src, TRAIT_TOXIMMUNE)) //Prevents toxin damage, but not healing diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 4fbd3062351..059ca18f4fa 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -492,7 +492,7 @@ GLOBAL_LIST_EMPTY(features_by_species) else if(old_species.exotic_bloodtype && !exotic_bloodtype) human_who_gained_species.dna.blood_type = random_blood_type() - //Resets blood if it is excessively high for some reason + //Resets blood if it is excessively high so they don't gib normalize_blood(human_who_gained_species) if(ishuman(human_who_gained_species)) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 680e5c14f7e..0905a4ac40f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -733,7 +733,7 @@ if(heal_flags & HEAL_NEGATIVE_MUTATIONS) for(var/datum/mutation/human/existing_mutation in dna.mutations) if(existing_mutation.quality != POSITIVE) - dna.remove_mutation(existing_mutation.name) + dna.remove_mutation(existing_mutation) if(heal_flags & HEAL_TEMP) set_coretemperature(get_body_temp_normal(apply_change = FALSE)) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 9daab06a5a6..45a35bb6e15 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -159,18 +159,24 @@ return TRUE - /mob/living/proc/getBruteLoss() return bruteloss -/mob/living/proc/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype = ALL) +/mob/living/proc/can_adjust_brute_loss(amount, forced, required_bodytype) if(!forced && (status_flags & GODMODE)) return FALSE + if(SEND_SIGNAL(src, COMSIG_LIVING_ADJUST_BRUTE_DAMAGE, BRUTE, amount, forced) & COMPONENT_IGNORE_CHANGE) + return FALSE + return TRUE + +/mob/living/proc/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype = ALL) + if (!can_adjust_brute_loss(amount, forced, required_bodytype)) + return 0 . = bruteloss bruteloss = clamp((bruteloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2) . -= bruteloss if(!.) // no change, no need to update - return FALSE + return 0 if(updating_health) updatehealth() @@ -190,18 +196,25 @@ /mob/living/proc/getOxyLoss() return oxyloss -/mob/living/proc/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL, required_respiration_type = ALL) +/mob/living/proc/can_adjust_oxy_loss(amount, forced, required_biotype, required_respiration_type) if(!forced) if(status_flags & GODMODE) return FALSE + if (required_respiration_type) + var/obj/item/organ/internal/lungs/affected_lungs = get_organ_slot(ORGAN_SLOT_LUNGS) + if(isnull(affected_lungs)) + if(!(mob_respiration_type & required_respiration_type)) // if the mob has no lungs, use mob_respiration_type + return FALSE + else + if(!(affected_lungs.respiration_type & required_respiration_type)) // otherwise use the lungs' respiration_type + return FALSE + if(SEND_SIGNAL(src, COMSIG_LIVING_ADJUST_OXY_DAMAGE, OXY, amount, forced) & COMPONENT_IGNORE_CHANGE) + return FALSE + return TRUE - var/obj/item/organ/internal/lungs/affected_lungs = get_organ_slot(ORGAN_SLOT_LUNGS) - if(isnull(affected_lungs)) - if(!(mob_respiration_type & required_respiration_type)) // if the mob has no lungs, use mob_respiration_type - return FALSE - else - if(!(affected_lungs.respiration_type & required_respiration_type)) // otherwise use the lungs' respiration_type - return FALSE +/mob/living/proc/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL, required_respiration_type = ALL) + if(!can_adjust_oxy_loss(amount, forced, required_biotype, required_respiration_type)) + return 0 . = oxyloss oxyloss = clamp((oxyloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2) . -= oxyloss @@ -233,11 +246,16 @@ /mob/living/proc/getToxLoss() return toxloss -/mob/living/proc/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) - if(!forced && (status_flags & GODMODE)) +/mob/living/proc/can_adjust_tox_loss(amount, forced, required_biotype) + if(!forced && ((status_flags & GODMODE) || !(mob_biotypes & required_biotype))) return FALSE - if(!forced && !(mob_biotypes & required_biotype)) + if(SEND_SIGNAL(src, COMSIG_LIVING_ADJUST_TOX_DAMAGE, TOX, amount, forced) & COMPONENT_IGNORE_CHANGE) return FALSE + return TRUE + +/mob/living/proc/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) + if(!can_adjust_tox_loss(amount, forced, required_biotype)) + return 0 . = toxloss toxloss = clamp((toxloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2) . -= toxloss @@ -262,41 +280,53 @@ /mob/living/proc/getFireLoss() return fireloss -/mob/living/proc/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype = ALL) +/mob/living/proc/can_adjust_fire_loss(amount, forced, required_bodytype) if(!forced && (status_flags & GODMODE)) return FALSE + if(SEND_SIGNAL(src, COMSIG_LIVING_ADJUST_BURN_DAMAGE, BURN, amount, forced) & COMPONENT_IGNORE_CHANGE) + return FALSE + return TRUE + +/mob/living/proc/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype = ALL) + if(!can_adjust_fire_loss(amount, forced, required_bodytype)) + return 0 . = fireloss fireloss = clamp((fireloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2) . -= fireloss - if(!.) // no change, no need to update - return FALSE + if(. == 0) // no change, no need to update + return if(updating_health) updatehealth() /mob/living/proc/setFireLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype = ALL) if(!forced && (status_flags & GODMODE)) - return FALSE + return 0 . = fireloss fireloss = amount . -= fireloss - if(!.) // no change, no need to update - return FALSE + if(. == 0) // no change, no need to update + return 0 if(updating_health) updatehealth() /mob/living/proc/getCloneLoss() return cloneloss -/mob/living/proc/adjustCloneLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) - if(!forced && ( (status_flags & GODMODE) || HAS_TRAIT(src, TRAIT_NOCLONELOSS)) ) +/mob/living/proc/can_adjust_clone_loss(amount, forced, required_biotype) + if(!forced && (!(mob_biotypes & required_biotype) || status_flags & GODMODE || HAS_TRAIT(src, TRAIT_NOCLONELOSS))) return FALSE - if(!forced && !(mob_biotypes & required_biotype)) + if(SEND_SIGNAL(src, COMSIG_LIVING_ADJUST_CLONE_DAMAGE, CLONE, amount, forced) & COMPONENT_IGNORE_CHANGE) return FALSE + return TRUE + +/mob/living/proc/adjustCloneLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) + if(!can_adjust_clone_loss(amount, forced, required_biotype)) + return 0 . = cloneloss cloneloss = clamp((cloneloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2) . -= cloneloss - if(!.) // no change, no need to update - return FALSE + if(. == 0) // no change, no need to update + return 0 if(updating_health) updatehealth() @@ -325,16 +355,21 @@ /mob/living/proc/getStaminaLoss() return staminaloss -/mob/living/proc/adjustStaminaLoss(amount, updating_stamina = TRUE, forced = FALSE, required_biotype = ALL) - if(!forced && (status_flags & GODMODE)) +/mob/living/proc/can_adjust_stamina_loss(amount, forced, required_biotype) + if(!forced && (!(mob_biotypes & required_biotype) || status_flags & GODMODE)) return FALSE - if(!forced && !(mob_biotypes & required_biotype)) + if(SEND_SIGNAL(src, COMSIG_LIVING_ADJUST_STAMINA_DAMAGE, STAMINA, amount, forced) & COMPONENT_IGNORE_CHANGE) return FALSE + return TRUE + +/mob/living/proc/adjustStaminaLoss(amount, updating_stamina = TRUE, forced = FALSE, required_biotype = ALL) + if(!can_adjust_stamina_loss(amount, forced, required_biotype)) + return 0 . = staminaloss staminaloss = clamp((staminaloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, max_stamina) . -= staminaloss - if(!.) // no change, no need to update - return FALSE + if(. == 0) // no change, no need to update + return 0 if(updating_stamina) updatehealth() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 8e51a6a8149..3e93bc6314b 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1488,6 +1488,7 @@ /mob/living/basic/chicken, /mob/living/basic/cow, /mob/living/basic/crab, + /mob/living/basic/goat, /mob/living/basic/headslug, /mob/living/basic/killer_tomato, /mob/living/basic/lizard, @@ -1507,7 +1508,6 @@ /mob/living/basic/stickman/dog, /mob/living/simple_animal/hostile/gorilla, /mob/living/simple_animal/hostile/megafauna/dragon/lesser, - /mob/living/simple_animal/hostile/retaliate/goat, /mob/living/simple_animal/parrot, /mob/living/simple_animal/pet/cat, /mob/living/simple_animal/pet/cat/cak, diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index 3a09256ee69..18d35782d73 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -404,7 +404,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( filter += tts_filter.Join(",") if(ishuman(src)) var/mob/living/carbon/human/human_speaker = src - if(human_speaker.wear_mask) + if(istype(human_speaker.wear_mask, /obj/item/clothing/mask)) var/obj/item/clothing/mask/worn_mask = human_speaker.wear_mask if(worn_mask.voice_override) voice_to_use = worn_mask.voice_override diff --git a/code/modules/mob/living/simple_animal/damage_procs.dm b/code/modules/mob/living/simple_animal/damage_procs.dm index 1f7638325ce..9640dbb9de4 100644 --- a/code/modules/mob/living/simple_animal/damage_procs.dm +++ b/code/modules/mob/living/simple_animal/damage_procs.dm @@ -19,36 +19,48 @@ toggle_ai(AI_ON) /mob/living/simple_animal/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype) + if(!can_adjust_brute_loss(amount, forced, required_bodytype)) + return 0 if(forced) . = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced) else if(damage_coeff[BRUTE]) . = adjustHealth(amount * damage_coeff[BRUTE] * CONFIG_GET(number/damage_multiplier), updating_health, forced) /mob/living/simple_animal/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype) + if(!can_adjust_fire_loss(amount, forced, required_bodytype)) + return 0 if(forced) . = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced) else if(damage_coeff[BURN]) . = adjustHealth(amount * damage_coeff[BURN] * CONFIG_GET(number/damage_multiplier), updating_health, forced) /mob/living/simple_animal/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype, required_respiration_type) + if(!can_adjust_oxy_loss(amount, forced, required_biotype, required_respiration_type)) + return 0 if(forced) . = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced) else if(damage_coeff[OXY]) . = adjustHealth(amount * damage_coeff[OXY] * CONFIG_GET(number/damage_multiplier), updating_health, forced) /mob/living/simple_animal/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype) + if(!can_adjust_tox_loss(amount, forced, required_biotype)) + return 0 if(forced) . = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced) else if(damage_coeff[TOX]) . = adjustHealth(amount * damage_coeff[TOX] * CONFIG_GET(number/damage_multiplier), updating_health, forced) /mob/living/simple_animal/adjustCloneLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype) + if(!can_adjust_clone_loss(amount, forced, required_biotype)) + return 0 if(forced) . = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced) else if(damage_coeff[CLONE]) . = adjustHealth(amount * damage_coeff[CLONE] * CONFIG_GET(number/damage_multiplier), updating_health, forced) /mob/living/simple_animal/adjustStaminaLoss(amount, updating_stamina = TRUE, forced = FALSE, required_biotype) + if(!can_adjust_stamina_loss(amount, forced, required_biotype)) + return 0 if(forced) staminaloss = max(0, min(max_staminaloss, staminaloss + amount)) else diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm deleted file mode 100644 index af1b4eb1370..00000000000 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ /dev/null @@ -1,121 +0,0 @@ -//goat -/mob/living/simple_animal/hostile/retaliate/goat - name = "goat" - desc = "Not known for their pleasant disposition." - icon_state = "goat" - icon_living = "goat" - icon_dead = "goat_dead" - speak = list("EHEHEHEHEH","eh?") - speak_emote = list("brays") - emote_hear = list("brays.") - emote_see = list("shakes their head.", "stamps a foot.", "glares around.") - speak_chance = 1 - turns_per_move = 5 - butcher_results = list(/obj/item/food/meat/slab/grassfed = 4) - response_help_continuous = "pets" - response_help_simple = "pet" - response_disarm_continuous = "gently pushes aside" - response_disarm_simple = "gently push aside" - response_harm_continuous = "kicks" - response_harm_simple = "kick" - faction = list(FACTION_NEUTRAL) - mob_biotypes = MOB_ORGANIC|MOB_BEAST - attack_same = 1 - attack_verb_continuous = "kicks" - attack_verb_simple = "kick" - attack_sound = 'sound/weapons/punch1.ogg' - attack_vis_effect = ATTACK_EFFECT_KICK - health = 40 - maxHealth = 40 - minbodytemp = 180 - melee_damage_lower = 1 - melee_damage_upper = 2 - environment_smash = ENVIRONMENT_SMASH_NONE - stop_automated_movement_when_pulled = 1 - blood_volume = BLOOD_VOLUME_NORMAL - - footstep_type = FOOTSTEP_MOB_SHOE - -/mob/living/simple_animal/hostile/retaliate/goat/Initialize(mapload) - AddComponent(/datum/component/udder) - AddElement(/datum/element/cliff_walking) //we walk the cliff - . = ..() - -/mob/living/simple_animal/hostile/retaliate/goat/Life(seconds_per_tick = SSMOBS_DT, times_fired) - . = ..() - if(.) - //chance to go crazy and start wacking stuff - if(!enemies.len && SPT_PROB(0.5, seconds_per_tick)) - Retaliate() - - if(enemies.len && SPT_PROB(5, seconds_per_tick)) - enemies.Cut() - LoseTarget() - src.visible_message(span_notice("[src] calms down.")) - if(stat != CONSCIOUS) - return - - eat_plants() - if(pulledby) - return - - for(var/direction in shuffle(list(1,2,4,8,5,6,9,10))) - var/turf/step = get_step(src, direction) - - if(!istype(step)) - return - - var/vine = locate(/obj/structure/spacevine) in step - var/mushroom = locate(/obj/structure/glowshroom) in step - var/flower = locate(/obj/structure/alien/resin/flower_bud) in step - - if(vine || mushroom || flower) - Move(step, get_dir(src, step)) - -/mob/living/simple_animal/hostile/retaliate/goat/Retaliate() - ..() - src.visible_message(span_danger("[src] gets an evil-looking gleam in [p_their()] eye.")) - -/mob/living/simple_animal/hostile/retaliate/goat/Move() - . = ..() - if(!stat) - eat_plants() - -/mob/living/simple_animal/hostile/retaliate/goat/proc/eat_plants() - var/obj/structure/spacevine/vine = locate(/obj/structure/spacevine) in loc - if(vine) - vine.eat(src) - - var/obj/structure/alien/resin/flower_bud/flower = locate(/obj/structure/alien/resin/flower_bud) in loc - if(flower) - flower.take_damage(rand(30, 50), BRUTE, 0) - - var/obj/structure/glowshroom/mushroom = locate(/obj/structure/glowshroom) in loc - if(mushroom) - qdel(mushroom) - - if((vine || flower || mushroom) && prob(10)) - say("Nom") // bon appetit - playsound(src, 'sound/items/eatfood.ogg', rand(30, 50), TRUE) - -/mob/living/simple_animal/hostile/retaliate/goat/AttackingTarget() - . = ..() - - if(!. || !isliving(target)) - return - - var/mob/living/plant_target = target - if(!(plant_target.mob_biotypes & MOB_PLANT)) - return - - plant_target.adjustBruteLoss(20) - playsound(src, 'sound/items/eatfood.ogg', rand(30, 50), TRUE) - var/obj/item/bodypart/edible_bodypart - - if(ishuman(plant_target)) - var/mob/living/carbon/human/plant_man = target - edible_bodypart = pick(plant_man.bodyparts) - edible_bodypart.dismember() - - plant_target.visible_message(span_warning("[src] takes a big chomp out of [plant_target]!"), \ - span_userdanger("[src] takes a big chomp out of your [edible_bodypart || "body"]!")) diff --git a/code/modules/mob/living/simple_animal/friendly/sloth.dm b/code/modules/mob/living/simple_animal/friendly/sloth.dm deleted file mode 100644 index 8e308c58d12..00000000000 --- a/code/modules/mob/living/simple_animal/friendly/sloth.dm +++ /dev/null @@ -1,68 +0,0 @@ -GLOBAL_DATUM(cargo_sloth, /mob/living/simple_animal/sloth) - -/mob/living/simple_animal/sloth - name = "sloth" - desc = "An adorable, sleepy creature." - icon = 'icons/mob/simple/pets.dmi' - icon_state = "sloth" - icon_living = "sloth" - icon_dead = "sloth_dead" - speak_emote = list("yawns") - emote_hear = list("snores.","yawns.") - emote_see = list("dozes off.", "looks around sleepily.") - speak_chance = 1 - turns_per_move = 5 - can_be_held = TRUE - butcher_results = list(/obj/item/food/meat/slab = 3) - response_help_continuous = "pets" - response_help_simple = "pet" - response_disarm_continuous = "gently pushes aside" - response_disarm_simple = "gently push aside" - response_harm_continuous = "kicks" - response_harm_simple = "kick" - mob_biotypes = MOB_ORGANIC|MOB_BEAST - gold_core_spawnable = FRIENDLY_SPAWN - melee_damage_lower = 18 - melee_damage_upper = 18 - health = 50 - maxHealth = 50 - speed = 10 - held_state = "sloth" - ///In the case 'melee_damage_upper' is somehow raised above 0 - attack_verb_continuous = "bites" - attack_verb_simple = "bite" - attack_sound = 'sound/weapons/bite.ogg' - attack_vis_effect = ATTACK_EFFECT_BITE - - footstep_type = FOOTSTEP_MOB_CLAW - -/mob/living/simple_animal/sloth/Initialize(mapload) - . = ..() - AddElement(/datum/element/pet_bonus, "slowly smiles!") - // If someone adds non-cargo sloths to maps we'll have a problem but we're fine for now - if(!GLOB.cargo_sloth && mapload && is_station_level(z)) - GLOB.cargo_sloth = src - -/mob/living/simple_animal/sloth/Destroy() - if(GLOB.cargo_sloth == src) - GLOB.cargo_sloth = null - - return ..() - -//Cargo Sloth -/mob/living/simple_animal/sloth/paperwork - name = "Paperwork" - desc = "Cargo's pet sloth. About as useful as the rest of the techs." - gold_core_spawnable = NO_SPAWN - -//Cargo Sloth 2 - -/mob/living/simple_animal/sloth/citrus - name = "Citrus" - desc = "Cargo's pet sloth. She's dressed in a horrible sweater." - icon_state = "cool_sloth" - icon_living = "cool_sloth" - icon_dead = "cool_sloth_dead" - gender = FEMALE - butcher_results = list(/obj/item/toy/spinningtoy = 1) - gold_core_spawnable = NO_SPAWN diff --git a/code/modules/mob/living/simple_animal/hostile/heretic_monsters.dm b/code/modules/mob/living/simple_animal/hostile/heretic_monsters.dm deleted file mode 100644 index 741e698a568..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/heretic_monsters.dm +++ /dev/null @@ -1,346 +0,0 @@ -/mob/living/simple_animal/hostile/heretic_summon - name = "Eldritch Demon" - real_name = "Eldritch Demon" - desc = "A horror from beyond this realm." - icon = 'icons/mob/nonhuman-player/eldritch_mobs.dmi' - gender = NEUTER - mob_biotypes = NONE - attack_sound = 'sound/weapons/punch1.ogg' - response_help_continuous = "thinks better of touching" - response_help_simple = "think better of touching" - response_disarm_continuous = "flails at" - response_disarm_simple = "flail at" - response_harm_continuous = "reaps" - response_harm_simple = "tears" - speak_emote = list("screams") - speak_chance = 1 - speed = 0 - combat_mode = TRUE - stop_automated_movement = TRUE - AIStatus = AI_OFF - // Sort of greenish brown, to match the vibeTM - lighting_cutoff_red = 20 - lighting_cutoff_green = 25 - lighting_cutoff_blue = 5 - damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - maxbodytemp = INFINITY - movement_type = GROUND - pressure_resistance = 100 - del_on_death = TRUE - death_message = "implodes into itself." - loot = list(/obj/effect/gibspawner/human) - faction = list(FACTION_HERETIC) - simple_mob_flags = SILENCE_RANGED_MESSAGE - - /// Innate spells that are added when a beast is created. - var/list/actions_to_add - -/mob/living/simple_animal/hostile/heretic_summon/Initialize(mapload) - . = ..() - for(var/spell in actions_to_add) - var/datum/action/cooldown/spell/new_spell = new spell(src) - new_spell.Grant(src) - -// What if we took a linked list... But made it a mob? -/// The "Terror of the Night" / Armsy, a large worm made of multiple bodyparts that occupies multiple tiles -/mob/living/simple_animal/hostile/heretic_summon/armsy - name = "Terror of the night" - real_name = "Armsy" - desc = "An abomination made from dozens and dozens of severed and malformed limbs piled onto each other." - icon_state = "armsy_start" - icon_living = "armsy_start" - maxHealth = 200 - health = 200 - melee_damage_lower = 10 - melee_damage_upper = 15 - move_force = MOVE_FORCE_OVERPOWERING - move_resist = MOVE_FORCE_OVERPOWERING - pull_force = MOVE_FORCE_OVERPOWERING - movement_type = GROUND - mob_size = MOB_SIZE_HUGE - sentience_type = SENTIENCE_BOSS - environment_smash = ENVIRONMENT_SMASH_RWALLS - mob_biotypes = MOB_ORGANIC|MOB_SPECIAL - obj_damage = 200 - ranged_cooldown_time = 5 - ranged = TRUE - rapid = 1 - actions_to_add = list(/datum/action/cooldown/spell/worm_contract) - ///Previous segment in the chain - var/mob/living/simple_animal/hostile/heretic_summon/armsy/back - ///Next segment in the chain - var/mob/living/simple_animal/hostile/heretic_summon/armsy/front - ///Your old location - var/oldloc - ///Allow / disallow pulling - var/allow_pulling = FALSE - ///How many arms do we have to eat to expand? - var/stacks_to_grow = 5 - ///Currently eaten arms - var/current_stacks = 0 - ///Does this follow other pieces? - var/follow = TRUE - -/* - * Arguments - * * spawn_bodyparts - whether we spawn additional armsy bodies until we reach length. - * * worm_length - the length of the worm we're creating. Below 3 doesn't work very well. - */ -/mob/living/simple_animal/hostile/heretic_summon/armsy/Initialize(mapload, spawn_bodyparts = TRUE, worm_length = 6) - . = ..() - if(worm_length < 3) - stack_trace("[type] created with invalid len ([worm_length]). Reverting to 3.") - worm_length = 3 //code breaks below 3, let's just not allow it. - - oldloc = loc - RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(update_chain_links)) - if(!spawn_bodyparts) - return - - AddComponent(/datum/component/blood_walk, \ - blood_type = /obj/effect/decal/cleanable/blood/tracks, \ - target_dir_change = TRUE) - - allow_pulling = TRUE - // Sets the hp of the head to be exactly the (length * hp), so the head is de facto the hardest to destroy. - maxHealth = worm_length * maxHealth - health = maxHealth - - // The previous link in the chain - var/mob/living/simple_animal/hostile/heretic_summon/armsy/prev = src - // The current link in the chain - var/mob/living/simple_animal/hostile/heretic_summon/armsy/current - - for(var/i in 1 to worm_length) - current = new type(drop_location(), FALSE) - ADD_TRAIT(current, TRAIT_PERMANENTLY_MORTAL, INNATE_TRAIT) - current.icon_state = "armsy_mid" - current.icon_living = "armsy_mid" - current.AIStatus = AI_OFF - current.front = prev - prev.back = current - prev = current - - prev.icon_state = "armsy_end" - prev.icon_living = "armsy_end" - -/mob/living/simple_animal/hostile/heretic_summon/armsy/adjustBruteLoss(amount, updating_health, forced, required_bodytype) - if(back) - return back.adjustBruteLoss(amount, updating_health, forced) - - return ..() - -/mob/living/simple_animal/hostile/heretic_summon/armsy/adjustFireLoss(amount, updating_health, forced, required_bodytype) - if(back) - return back.adjustFireLoss(amount, updating_health, forced) - - return ..() - -// We are literally a vessel of otherworldly destruction, we bring our own gravity unto this plane -/mob/living/simple_animal/hostile/heretic_summon/armsy/has_gravity(turf/gravity_turf) - return TRUE - -/mob/living/simple_animal/hostile/heretic_summon/armsy/can_be_pulled() - return FALSE - -/// Updates every body in the chain to force move onto a single tile. -/mob/living/simple_animal/hostile/heretic_summon/armsy/proc/contract_next_chain_into_single_tile() - if(!back) - return - - back.forceMove(loc) - back.contract_next_chain_into_single_tile() - -/* - * Recursively get the length of our chain. - */ -/mob/living/simple_animal/hostile/heretic_summon/armsy/proc/get_length() - . = 1 - if(back) - . += back.get_length() - -/// Updates the next mob in the chain to move to our last location. Fixes the chain if somehow broken. -/mob/living/simple_animal/hostile/heretic_summon/armsy/proc/update_chain_links() - SIGNAL_HANDLER - - if(!follow) - return - - if(back && back.loc != oldloc) - back.Move(oldloc) - - // self fixing properties if somehow broken - if(front && loc != front.oldloc) - forceMove(front.oldloc) - - oldloc = loc - -/mob/living/simple_animal/hostile/heretic_summon/armsy/Destroy() - if(front) - front.icon_state = "armsy_end" - front.icon_living = "armsy_end" - front.back = null - front = null - if(back) - QDEL_NULL(back) // chain destruction baby - return ..() - -/* - * Handle healing our chain. - * - * Eating arms off the ground heals us, - * and if we eat enough arms while above - * a certain health threshold, we even gain back parts! - */ -/mob/living/simple_animal/hostile/heretic_summon/armsy/proc/heal() - if(back) - back.heal() - return - - adjustBruteLoss(-maxHealth * 0.5, FALSE) - adjustFireLoss(-maxHealth * 0.5, FALSE) - - if(health < maxHealth * 0.8) - return - - current_stacks++ - if(current_stacks < stacks_to_grow) - return - - var/mob/living/simple_animal/hostile/heretic_summon/armsy/prev = new type(drop_location(), FALSE) - icon_state = "armsy_mid" - icon_living = "armsy_mid" - back = prev - prev.icon_state = "armsy_end" - prev.icon_living = "armsy_end" - prev.front = src - prev.AIStatus = AI_OFF - current_stacks = 0 - -/mob/living/simple_animal/hostile/heretic_summon/armsy/Shoot(atom/targeted_atom) - GiveTarget(targeted_atom) - AttackingTarget() - -/mob/living/simple_animal/hostile/heretic_summon/armsy/AttackingTarget() - if(istype(target, /obj/item/bodypart/arm)) - playsound(src, 'sound/magic/demon_consume.ogg', 50, TRUE) - qdel(target) - heal() - return - if(target == back || target == front) - return - if(back) - back.GiveTarget(target) - back.AttackingTarget() - if(!Adjacent(target)) - return - do_attack_animation(target) - - if(iscarbon(target)) - var/mob/living/carbon/carbon_target = target - if(HAS_TRAIT(carbon_target, TRAIT_NODISMEMBER)) - return ..() - - var/list/parts_to_remove = list() - for(var/obj/item/bodypart/bodypart in carbon_target.bodyparts) - if(bodypart.body_part != HEAD && bodypart.body_part != CHEST && bodypart.body_part != LEG_LEFT && bodypart.body_part != LEG_RIGHT) - if(!(bodypart.bodypart_flags & BODYPART_UNREMOVABLE)) - parts_to_remove += bodypart - - if(parts_to_remove.len && prob(10)) - var/obj/item/bodypart/lost_arm = pick(parts_to_remove) - lost_arm.dismember() - - return ..() - -/mob/living/simple_animal/hostile/heretic_summon/armsy/prime - name = "Lord of the Night" - real_name = "Master of Decay" - maxHealth = 400 - health = 400 - melee_damage_lower = 30 - melee_damage_upper = 50 - -/mob/living/simple_animal/hostile/heretic_summon/armsy/prime/Initialize(mapload, spawn_bodyparts = TRUE, worm_length = 9) - . = ..() - var/matrix/matrix_transformation = matrix() - matrix_transformation.Scale(1.4, 1.4) - transform = matrix_transformation - -/mob/living/simple_animal/hostile/heretic_summon/rust_spirit - name = "Rust Walker" - real_name = "Rusty" - desc = "An incomprehensible abomination. Everywhere it steps, it appears to be actively seeping life out of its surroundings." - icon_state = "rust_walker_s" - icon_living = "rust_walker_s" - status_flags = CANPUSH - maxHealth = 75 - health = 75 - melee_damage_lower = 15 - melee_damage_upper = 20 - sight = SEE_TURFS - actions_to_add = list( - /datum/action/cooldown/spell/aoe/rust_conversion/small, - /datum/action/cooldown/spell/basic_projectile/rust_wave/short, - ) - -/mob/living/simple_animal/hostile/heretic_summon/rust_spirit/setDir(newdir) - . = ..() - if(newdir == NORTH) - icon_state = "rust_walker_n" - else if(newdir == SOUTH) - icon_state = "rust_walker_s" - update_appearance(UPDATE_ICON_STATE) - -/mob/living/simple_animal/hostile/heretic_summon/rust_spirit/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) - . = ..() - playsound(src, 'sound/effects/footstep/rustystep1.ogg', 100, TRUE) - -/mob/living/simple_animal/hostile/heretic_summon/rust_spirit/Life(seconds_per_tick = SSMOBS_DT, times_fired) - if(stat == DEAD) - return ..() - - var/turf/our_turf = get_turf(src) - if(HAS_TRAIT(our_turf, TRAIT_RUSTY)) - adjustBruteLoss(-1.5 * seconds_per_tick, FALSE) - adjustFireLoss(-1.5 * seconds_per_tick, FALSE) - - return ..() - -/mob/living/simple_animal/hostile/heretic_summon/ash_spirit - name = "Ash Man" - real_name = "Ashy" - desc = "An incomprehensible abomination. As it moves, a thin trail of ash follows, appearing from seemingly nowhere." - icon_state = "ash_walker" - icon_living = "ash_walker" - status_flags = CANPUSH - maxHealth = 75 - health = 75 - melee_damage_lower = 15 - melee_damage_upper = 20 - sight = SEE_TURFS - actions_to_add = list( - /datum/action/cooldown/spell/jaunt/ethereal_jaunt/ash, - /datum/action/cooldown/spell/pointed/cleave, - /datum/action/cooldown/spell/fire_sworn, - ) - -/mob/living/simple_animal/hostile/heretic_summon/stalker - name = "Flesh Stalker" - real_name = "Flesh Stalker" - desc = "An abomination made from several limbs and organs. Every moment you stare at it, it appears to shift and change unnaturally." - icon_state = "stalker" - icon_living = "stalker" - status_flags = CANPUSH - maxHealth = 150 - health = 150 - melee_damage_lower = 15 - melee_damage_upper = 20 - sight = SEE_MOBS - actions_to_add = list( - /datum/action/cooldown/spell/shapeshift/eldritch, - /datum/action/cooldown/spell/jaunt/ethereal_jaunt/ash, - /datum/action/cooldown/spell/emp/eldritch, - ) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_demon.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_demon.dm deleted file mode 100644 index 25d1ea9da74..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_demon.dm +++ /dev/null @@ -1,85 +0,0 @@ -/mob/living/simple_animal/hostile/asteroid/ice_demon - name = "demonic watcher" - desc = "A creature formed entirely out of ice, bluespace energy emanates from inside of it." - icon = 'icons/mob/simple/icemoon/icemoon_monsters.dmi' - icon_state = "ice_demon" - icon_living = "ice_demon" - icon_dead = "ice_demon_dead" - icon_gib = "syndicate_gib" - mob_biotypes = MOB_ORGANIC|MOB_BEAST - mouse_opacity = MOUSE_OPACITY_ICON - speak_emote = list("telepathically cries") - speed = 2 - move_to_delay = 2 - projectiletype = /obj/projectile/temp/ice_demon - projectilesound = 'sound/weapons/pierce.ogg' - ranged = TRUE - ranged_message = "manifests ice" - ranged_cooldown_time = 1.5 SECONDS - minimum_distance = 3 - retreat_distance = 3 - maxHealth = 150 - health = 150 - obj_damage = 40 - melee_damage_lower = 15 - melee_damage_upper = 15 - attack_verb_continuous = "slices" - attack_verb_simple = "slice" - attack_sound = 'sound/weapons/bladeslice.ogg' - attack_vis_effect = ATTACK_EFFECT_SLASH - vision_range = 9 - aggro_vision_range = 9 - move_force = MOVE_FORCE_VERY_STRONG - move_resist = MOVE_FORCE_VERY_STRONG - pull_force = MOVE_FORCE_VERY_STRONG - del_on_death = TRUE - loot = list() - crusher_loot = /obj/item/crusher_trophy/demon_core /// SKYRAT EDIT CHANGE - ORIGINAL : crusher_loot = /obj/item/crusher_trophy/watcher_wing/ice_wing - death_message = "fades as the energies that tied it to this world dissipate." - death_sound = 'sound/magic/demon_dies.ogg' - stat_attack = HARD_CRIT - robust_searching = TRUE - footstep_type = FOOTSTEP_MOB_CLAW - /// Distance the demon will teleport from the target - var/teleport_distance = 3 - -/mob/living/simple_animal/hostile/asteroid/ice_demon/Initialize(mapload) - . = ..() - AddElement(/datum/element/simple_flying) - -/obj/projectile/temp/ice_demon - name = "ice blast" - icon_state = "ice_2" - damage = 5 - damage_type = BURN - armor_flag = ENERGY - speed = 1 - pixel_speed_multiplier = 0.25 - range = 200 - temperature = -75 - -/mob/living/simple_animal/hostile/asteroid/ice_demon/OpenFire() - ranged_cooldown = world.time + ranged_cooldown_time - // Sentient ice demons teleporting has been linked to server crashes - if(client) - return ..() - if(teleport_distance <= 0) - return ..() - var/list/possible_ends = view(teleport_distance, target.loc) - view(teleport_distance - 1, target.loc) - for(var/turf/closed/turf_to_remove in possible_ends) - possible_ends -= turf_to_remove - if(!possible_ends.len) - return ..() - var/turf/end = pick(possible_ends) - do_teleport(src, end, 0, channel=TELEPORT_CHANNEL_BLUESPACE, forced = TRUE) - SLEEP_CHECK_DEATH(8, src) - return ..() - -/mob/living/simple_animal/hostile/asteroid/ice_demon/death(gibbed) - move_force = MOVE_FORCE_DEFAULT - move_resist = MOVE_RESIST_DEFAULT - pull_force = PULL_FORCE_DEFAULT - new /obj/item/stack/ore/bluespace_crystal(loc, 3) - if(prob(5)) - new /obj/item/raw_anomaly_core/bluespace(loc) - return ..() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index cebb747f6ba..00bd1d0ebc9 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -808,18 +808,26 @@ * * This sends you back to the lobby creating a new dead mob * - * Only works if flag/norespawn is allowed in config + * Only works if flag/allow_respawn is allowed in config */ /mob/verb/abandon_mob() set name = "Respawn" set category = "OOC" - if (CONFIG_GET(flag/norespawn)) - if (!check_rights_for(usr.client, R_ADMIN)) - to_chat(usr, span_boldnotice("Respawning is not enabled!")) - return - else if (tgui_alert(usr, "Respawning is currently disabled, do you want to use your permissions to circumvent it?", "Respawn", list("Yes", "No")) != "Yes") - return + switch(CONFIG_GET(flag/allow_respawn)) + if(RESPAWN_FLAG_NEW_CHARACTER) + if(tgui_alert(usr, "Note, respawning is only allowed as another character. If you don't have another free slot you may not be able to respawn.", "Respawn", list("Ok", "Nevermind")) != "Ok") + return + + if(RESPAWN_FLAG_FREE) + pass() // Normal respawn + + if(RESPAWN_FLAG_DISABLED) + if (!check_rights_for(usr.client, R_ADMIN)) + to_chat(usr, span_boldnotice("Respawning is not enabled!")) + return + if (tgui_alert(usr, "Respawning is currently disabled, do you want to use your permissions to circumvent it?", "Respawn", list("Yes", "No")) != "Yes") + return if (stat != DEAD) to_chat(usr, span_boldnotice("You must be dead to use this!")) @@ -856,15 +864,14 @@ M.key = key +/// Checks if the mob can respawn yet according to the respawn delay /mob/proc/check_respawn_delay(override_delay = 0) if(!override_delay && !CONFIG_GET(number/respawn_delay)) return TRUE var/death_time = world.time - client.player_details.time_of_death - var/required_delay = override_delay - if(!required_delay) - required_delay = CONFIG_GET(number/respawn_delay) + var/required_delay = override_delay || CONFIG_GET(number/respawn_delay) if(death_time < required_delay) if(!check_rights_for(usr.client, R_ADMIN)) diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index 6fe91c9575b..0de25b903ab 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -42,7 +42,7 @@ ///The program currently active on the tablet. var/datum/computer_file/program/active_program ///Idle programs on background. They still receive process calls but can't be interacted with. - var/list/idle_threads = list() + var/list/datum/computer_file/program/idle_threads = list() /// Amount of programs that can be ran at once var/max_idle_programs = 2 @@ -72,12 +72,10 @@ /// The built-in light's color, editable by players. var/comp_light_color = "#FFFFFF" - ///The last recorded amount of power used. - var/last_power_usage = 0 ///Power usage when the computer is open (screen is active) and can be interacted with. - var/base_active_power_usage = 75 - ///Power usage when the computer is idle and screen is off (currently only applies to laptops) - var/base_idle_power_usage = 5 + var/base_active_power_usage = 15 // SKYRAT EDIT CHANGE - Original: 125 + ///Power usage when the computer is idle and screen is off. + var/base_idle_power_usage = 2 // SKYRAT EDIT CHANGE - Original: 5 // Modular computers can run on various devices. Each DEVICE (Laptop, Console & Tablet) // must have it's own DMI file. Icon states must be called exactly the same in all files, but may look differently @@ -369,6 +367,9 @@ /obj/item/modular_computer/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) . = ..() + if(held_item?.tool_behaviour == TOOL_SCREWDRIVER && internal_cell) + context[SCREENTIP_CONTEXT_RMB] = "Remove Cell" + . = CONTEXTUAL_SCREENTIP_SET if(held_item?.tool_behaviour == TOOL_WRENCH) context[SCREENTIP_CONTEXT_RMB] = "Deconstruct" . = CONTEXTUAL_SCREENTIP_SET @@ -440,7 +441,7 @@ to_chat(user, span_warning("You press the power button, but the computer fails to boot up, displaying variety of errors before shutting down again.")) return FALSE - if(use_power()) // use_power() checks if the PC is powered + if(use_power()) // checks if the PC is powered if(issynth) to_chat(user, span_notice("You send an activation signal to \the [src], turning it on.")) else @@ -462,7 +463,6 @@ // Process currently calls handle_power(), may be expanded in future if more things are added. /obj/item/modular_computer/process(seconds_per_tick) if(!enabled) // The computer is turned off - last_power_usage = 0 return if(atom_integrity <= integrity_failure * max_integrity) @@ -736,7 +736,7 @@ return if(istype(attacking_item, /obj/item/stock_parts/cell)) - if(ismachinery(loc)) + if(ismachinery(physical)) return if(internal_cell) to_chat(user, span_warning("You try to connect \the [attacking_item] to \the [src], but its connectors are occupied.")) @@ -800,6 +800,16 @@ return ..() +/obj/item/modular_computer/screwdriver_act_secondary(mob/living/user, obj/item/tool) + . = ..() + if(internal_cell) + user.balloon_alert(user, "cell removed") + internal_cell.forceMove(drop_location()) + internal_cell = null + return TOOL_ACT_TOOLTYPE_SUCCESS + else + user.balloon_alert(user, "no cell!") + /obj/item/modular_computer/wrench_act_secondary(mob/living/user, obj/item/tool) . = ..() tool.play_tool_sound(src, user, 20, volume=20) diff --git a/code/modules/modular_computers/computers/item/computer_power.dm b/code/modules/modular_computers/computers/item/computer_power.dm index 6b6230ed0d4..24950621de6 100644 --- a/code/modules/modular_computers/computers/item/computer_power.dm +++ b/code/modules/modular_computers/computers/item/computer_power.dm @@ -1,9 +1,13 @@ +///The multiplier given to the base overtime charge drain value if its flashlight is on. +#define FLASHLIGHT_DRAIN_MULTIPLIER 1.1 + // Tries to draw power from charger or, if no operational charger is present, from power cell. /obj/item/modular_computer/proc/use_power(amount = 0) if(check_power_override()) return TRUE - if(ismachinery(loc)) - var/obj/machinery/machine_holder = loc + + if(ismachinery(physical)) + var/obj/machinery/machine_holder = physical if(machine_holder.powered()) machine_holder.use_power(amount) return TRUE @@ -27,20 +31,31 @@ return if(active_program) active_program.event_powerfailure() + if(light_on) + set_light_on(FALSE) for(var/datum/computer_file/program/programs as anything in idle_threads) programs.event_powerfailure() shutdown_computer(loud = FALSE) -// Handles power-related things, such as battery interaction, recharging, shutdown when it's discharged +///Takes the charge necessary from the Computer, shutting it off if it's unable to provide it. +///Charge depends on whether the PC is on, and what programs are running/idle on it. /obj/item/modular_computer/proc/handle_power(seconds_per_tick) var/power_usage = screen_on ? base_active_power_usage : base_idle_power_usage - if(use_power(power_usage)) - last_power_usage = power_usage + if(light_on) + power_usage *= FLASHLIGHT_DRAIN_MULTIPLIER + if(active_program) + power_usage += active_program.power_cell_use + for(var/datum/computer_file/program/open_programs as anything in idle_threads) + if(!open_programs.power_cell_use) + continue + if(open_programs in idle_threads) + power_usage += (open_programs.power_cell_use / 2) + + if(use_power(power_usage * seconds_per_tick)) return TRUE - else - power_failure() - return FALSE + power_failure() + return FALSE ///Used by subtypes for special cases for power usage, returns TRUE if it should stop the use_power chain. /obj/item/modular_computer/proc/check_power_override() @@ -49,3 +64,5 @@ //Integrated (Silicon) tablets don't drain power, because the tablet is required to state laws, so it being disabled WILL cause problems. /obj/item/modular_computer/pda/silicon/check_power_override() return TRUE + +#undef FLASHLIGHT_DRAIN_MULTIPLIER diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm index d5dcf98c623..1b87a014f18 100644 --- a/code/modules/modular_computers/computers/item/computer_ui.dm +++ b/code/modules/modular_computers/computers/item/computer_ui.dm @@ -44,7 +44,7 @@ // Operates TGUI /obj/item/modular_computer/ui_interact(mob/user, datum/tgui/ui) - if(!enabled || !user.can_read(src, READING_CHECK_LITERACY) || !use_power()) + if(!enabled || !user.can_read(src, READING_CHECK_LITERACY)) if(ui) ui.close() return diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm index 293cdd9c5f7..c54d3295fe3 100644 --- a/code/modules/modular_computers/computers/machinery/modular_computer.dm +++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm @@ -13,8 +13,6 @@ var/internal_cell = null ///A flag that describes this device type var/hardware_flag = PROGRAM_CONSOLE - ///Power usage during last tick - var/last_power_usage = 0 /// Amount of programs that can be ran at once var/max_idle_programs = 4 @@ -72,7 +70,7 @@ set_light(cpu?.enabled ? light_strength : 0) /obj/machinery/modular_computer/update_icon_state() - if(!cpu || !cpu.enabled || !cpu.use_power() || (machine_stat & NOPOWER)) + if(!cpu || !cpu.enabled || (machine_stat & NOPOWER)) icon_state = icon_state_unpowered else icon_state = icon_state_powered @@ -83,7 +81,7 @@ if(!cpu) return . - if(cpu.enabled && cpu.use_power()) + if(cpu.enabled) . += cpu.active_program?.program_icon_state || screen_icon_state_menu else if(!(machine_stat & NOPOWER)) . += screen_icon_screensaver diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index 1f36713380d..6f693b5bf99 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -1,8 +1,14 @@ +///The default amount a program should take in cell use. +#define PROGRAM_BASIC_CELL_USE 15 + // /program/ files are executable programs that do things. /datum/computer_file/program filetype = "PRG" /// File name. FILE NAME MUST BE UNIQUE IF YOU WANT THE PROGRAM TO BE DOWNLOADABLE FROM NTNET! filename = "UnknownProgram" + + ///How much power running this program costs. + var/power_cell_use = PROGRAM_BASIC_CELL_USE /// List of required accesses to *run* the program. Any match will do. var/list/required_access = list() /// List of required access to download or file host the program. Any match will do. @@ -211,3 +217,5 @@ computer.update_tablet_open_uis(usr) computer.update_appearance(UPDATE_ICON) return TRUE + +#undef PROGRAM_BASIC_CELL_USE diff --git a/code/modules/modular_computers/file_system/programs/frontier.dm b/code/modules/modular_computers/file_system/programs/frontier.dm index cf6cc4b2bc2..b724892da7e 100644 --- a/code/modules/modular_computers/file_system/programs/frontier.dm +++ b/code/modules/modular_computers/file_system/programs/frontier.dm @@ -25,7 +25,7 @@ /datum/computer_file/program/scipaper_program/on_start(mob/living/user) . = ..() if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb) - CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, src) + CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, computer) /datum/computer_file/program/scipaper_program/application_attackby(obj/item/attacking_item, mob/living/user) if(!istype(attacking_item, /obj/item/multitool)) diff --git a/code/modules/modular_computers/file_system/programs/secureye.dm b/code/modules/modular_computers/file_system/programs/secureye.dm index bba55b4474e..6e3e69cdccf 100644 --- a/code/modules/modular_computers/file_system/programs/secureye.dm +++ b/code/modules/modular_computers/file_system/programs/secureye.dm @@ -100,18 +100,19 @@ /datum/computer_file/program/secureye/ui_data() var/list/data = list() - data["network"] = network data["activeCamera"] = null var/obj/machinery/camera/active_camera = camera_ref?.resolve() if(active_camera) data["activeCamera"] = list( name = active_camera.c_tag, + ref = REF(active_camera), status = active_camera.status, ) return data /datum/computer_file/program/secureye/ui_static_data(mob/user) var/list/data = list() + data["network"] = network data["mapRef"] = cam_screen.assigned_map data["can_spy"] = !!spying var/list/cameras = get_camera_list(network) @@ -120,6 +121,7 @@ var/obj/machinery/camera/C = cameras[i] data["cameras"] += list(list( name = C.c_tag, + ref = REF(C), )) return data @@ -130,13 +132,14 @@ return switch(action) if("switch_camera") - var/c_tag = format_text(params["name"]) - var/list/cameras = get_camera_list(network) - var/obj/machinery/camera/selected_camera = cameras[c_tag] - camera_ref = WEAKREF(selected_camera) + var/obj/machinery/camera/selected_camera = locate(params["camera"]) in GLOB.cameranet.cameras + if(selected_camera) + camera_ref = WEAKREF(selected_camera) + else + camera_ref = null if(!spying) playsound(computer, get_sfx(SFX_TERMINAL_TYPE), 25, FALSE) - if(!selected_camera) + if(isnull(camera_ref)) return TRUE if(internal_tracker && internal_tracker.tracking) internal_tracker.set_tracking(FALSE) diff --git a/code/modules/modular_computers/file_system/programs/techweb.dm b/code/modules/modular_computers/file_system/programs/techweb.dm index 9c097b2fb9b..dc9538cf358 100644 --- a/code/modules/modular_computers/file_system/programs/techweb.dm +++ b/code/modules/modular_computers/file_system/programs/techweb.dm @@ -24,7 +24,7 @@ /datum/computer_file/program/science/on_start(mob/living/user) . = ..() if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research) - CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src) + CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, computer) /datum/computer_file/program/science/application_attackby(obj/item/attacking_item, mob/living/user) if(!istype(attacking_item, /obj/item/multitool)) diff --git a/code/modules/pai/camera.dm b/code/modules/pai/camera.dm index a091b208638..319f20e3699 100644 --- a/code/modules/pai/camera.dm +++ b/code/modules/pai/camera.dm @@ -1,10 +1,3 @@ -/mob/living/silicon/pai/ClickOn(atom/target, params) - . = ..() - if(aicamera && aicamera.in_camera_mode) - aicamera.toggle_camera_mode(sound = FALSE) - aicamera.captureimage(target, usr) - return TRUE - /obj/item/camera/siliconcam/pai_camera name = "pAI photo camera" light_color = COLOR_PAI_GREEN @@ -13,7 +6,7 @@ var/number = length(stored) picture.picture_name = "Image [number] (taken by [loc.name])" stored[picture] = TRUE - playsound(loc, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 75, TRUE, -3) + playsound(src, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 75, TRUE, -3) balloon_alert(user, "image recorded") /** diff --git a/code/modules/pai/defense.dm b/code/modules/pai/defense.dm index 3a888fa9c83..75c437c2546 100644 --- a/code/modules/pai/defense.dm +++ b/code/modules/pai/defense.dm @@ -73,17 +73,17 @@ to_chat(src, span_userdanger("The impact degrades your holochassis!")) return amount -/mob/living/silicon/pai/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype) - return take_holo_damage(amount) +/// Called when we take burn or brute damage, pass it to the shell instead +/mob/living/silicon/pai/proc/on_shell_damaged(datum/hurt, type, amount, forced) + SIGNAL_HANDLER + take_holo_damage(amount) + return COMPONENT_IGNORE_CHANGE -/mob/living/silicon/pai/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype) - return take_holo_damage(amount) - -/mob/living/silicon/pai/adjustStaminaLoss(amount, updating_stamina, forced = FALSE, required_biotype) - if(forced) - take_holo_damage(amount) - else - take_holo_damage(amount * 0.25) +/// Called when we take stamina damage, pass it to the shell instead +/mob/living/silicon/pai/proc/on_shell_weakened(datum/hurt, type, amount, forced) + SIGNAL_HANDLER + take_holo_damage(amount * ((forced) ? 1 : 0.25)) + return COMPONENT_IGNORE_CHANGE /mob/living/silicon/pai/getBruteLoss() return HOLOCHASSIS_MAX_HEALTH - holochassis_health diff --git a/code/modules/pai/hud.dm b/code/modules/pai/hud.dm index 530780758d2..523d57d17b3 100644 --- a/code/modules/pai/hud.dm +++ b/code/modules/pai/hud.dm @@ -147,7 +147,8 @@ required_software = "Photography Module" /atom/movable/screen/pai/image_take/Click() - if(!..()) + . = ..() + if(!.) return var/mob/living/silicon/pai/pAI = usr pAI.aicamera.toggle_camera_mode(usr) diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm index e1a4dfb0ae0..3c0a1bfb82c 100644 --- a/code/modules/pai/pai.dm +++ b/code/modules/pai/pai.dm @@ -227,6 +227,8 @@ update_appearance(UPDATE_DESC) RegisterSignal(src, COMSIG_LIVING_CULT_SACRIFICED, PROC_REF(on_cult_sacrificed)) + RegisterSignals(src, list(COMSIG_LIVING_ADJUST_BRUTE_DAMAGE, COMSIG_LIVING_ADJUST_BURN_DAMAGE), PROC_REF(on_shell_damaged)) + RegisterSignal(src, COMSIG_LIVING_ADJUST_STAMINA_DAMAGE, PROC_REF(on_shell_weakened)) /mob/living/silicon/pai/make_laws() laws = new /datum/ai_laws/pai() diff --git a/code/modules/photography/camera/silicon_camera.dm b/code/modules/photography/camera/silicon_camera.dm index 836ecc2690a..9cdbee1bc2b 100644 --- a/code/modules/photography/camera/silicon_camera.dm +++ b/code/modules/photography/camera/silicon_camera.dm @@ -1,23 +1,47 @@ /obj/item/camera/siliconcam name = "silicon photo camera" - var/in_camera_mode = FALSE + resistance_flags = INDESTRUCTIBLE + /// List of all pictures taken by this camera. var/list/datum/picture/stored = list() -/obj/item/camera/siliconcam/ai_camera - name = "AI photo camera" - flash_enabled = FALSE +/// Checks if we can take a picture at this moment. Returns TRUE if we can, FALSE if we can't. +/obj/item/camera/siliconcam/proc/can_take_picture(mob/living/silicon/clicker) + if(clicker.stat != CONSCIOUS || clicker.incapacitated()) + return FALSE + return TRUE + +/obj/item/camera/siliconcam/proc/InterceptClickOn(mob/living/silicon/clicker, params, atom/clicked_on) + if(!can_take_picture(clicker)) + return + clicker.face_atom(clicked_on) + captureimage(clicked_on, clicker) + toggle_camera_mode(clicker, sound = FALSE) +/// Toggles the camera mode on or off. +/// If sound is TRUE, plays a sound effect and displays a message on successful toggle /obj/item/camera/siliconcam/proc/toggle_camera_mode(mob/user, sound = TRUE) - in_camera_mode = !in_camera_mode + if(user.click_intercept == src) + user.click_intercept = null + + else if(isnull(user.click_intercept)) + user.click_intercept = src + + else + // Trying to turn on camera mode while you have another click intercept active, such as malf abilities + if(sound) + balloon_alert(user, "can't enable camera mode!") + playsound(user, 'sound/machines/buzz-sigh.ogg', 25, TRUE) + return + if(sound) - playsound(src, 'sound/items/wirecutter.ogg', 50, TRUE) - to_chat(user, span_notice("Camera mode: [in_camera_mode ? "Activated" : "Deactivated"].")) + playsound(user, 'sound/items/wirecutter.ogg', 50, TRUE) + balloon_alert(user, "camera mode [user.click_intercept == src ? "activated" : "deactivated"]") /obj/item/camera/siliconcam/proc/selectpicture(mob/user) RETURN_TYPE(/datum/picture) if(!length(stored)) - to_chat(user, span_notice("ERROR: No stored photos located.")) + user.balloon_alert(user, "no stored photos!") return var/list/nametemp = list() var/list/temp = list() @@ -25,9 +49,7 @@ nametemp += stored_photo.picture_name temp[stored_photo.picture_name] = stored_photo var/find = tgui_input_list(user, "Select image", "Storage", nametemp) - if(isnull(find)) - return - if(isnull(temp[find])) + if(isnull(find) || isnull(temp[find])) return return temp[find] @@ -36,48 +58,70 @@ if(istype(selection)) show_picture(user, selection) +/obj/item/camera/siliconcam/ai_camera + name = "AI photo camera" + flash_enabled = FALSE + +/obj/item/camera/siliconcam/ai_camera/can_take_picture(mob/living/silicon/ai/clicker) + if(clicker.control_disabled) + return FALSE + return ..() + +/obj/item/camera/siliconcam/ai_camera/balloon_alert(mob/viewer, text) + if(isAI(loc)) + // redirects balloon alerts on us to balloon alerts on our ai eye + var/mob/living/silicon/ai/ai = loc + return ai.eyeobj.balloon_alert(viewer, text) + + return ..() + /obj/item/camera/siliconcam/ai_camera/after_picture(mob/user, datum/picture/picture) var/number = length(stored) picture.picture_name = "Image [number] (taken by [loc.name])" stored[picture] = TRUE - to_chat(user, span_notice("Image recorded.")) + balloon_alert(user, "image recorded") + user.playsound_local(get_turf(user), pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 50, TRUE, -3) /obj/item/camera/siliconcam/robot_camera name = "Cyborg photo camera" var/printcost = 2 -/obj/item/camera/siliconcam/robot_camera/after_picture(mob/user, datum/picture/picture) - var/mob/living/silicon/robot/C = loc - if(istype(C) && istype(C.connected_ai)) - var/number = C.connected_ai.aicamera.stored.len +/obj/item/camera/siliconcam/robot_camera/can_take_picture(mob/living/silicon/robot/clicker) + if(clicker.lockcharge) + return FALSE + return ..() + +/obj/item/camera/siliconcam/robot_camera/after_picture(mob/living/silicon/robot/user, datum/picture/picture) + if(istype(user) && istype(user.connected_ai)) + var/number = user.connected_ai.aicamera.stored.len picture.picture_name = "Image [number] (taken by [loc.name])" - C.connected_ai.aicamera.stored[picture] = TRUE - to_chat(usr, span_notice("Image recorded and saved to remote database.")) + user.connected_ai.aicamera.stored[picture] = TRUE + balloon_alert(user, "image recorded and uploaded") else var/number = stored.len picture.picture_name = "Image [number] (taken by [loc.name])" stored[picture] = TRUE - to_chat(usr, span_notice("Image recorded and saved to local storage. Upload will happen automatically if unit is lawsynced.")) + balloon_alert(user, "image recorded and saved locally") + playsound(src, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 75, TRUE, -3) -/obj/item/camera/siliconcam/robot_camera/selectpicture(mob/user) - var/mob/living/silicon/robot/R = loc - if(istype(R) && R.connected_ai) - R.picturesync() - return R.connected_ai.aicamera.selectpicture(user) - else - return ..() +/obj/item/camera/siliconcam/robot_camera/selectpicture(mob/living/silicon/robot/user) + if(istype(user) && user.connected_ai) + user.picturesync() + return user.connected_ai.aicamera.selectpicture(user) + return ..() -/obj/item/camera/siliconcam/robot_camera/proc/borgprint(mob/user) - var/mob/living/silicon/robot/C = loc - if(!istype(C) || C.toner < 20) - to_chat(user, span_warning("Insufficent toner to print image.")) +/obj/item/camera/siliconcam/robot_camera/proc/borgprint(mob/living/silicon/robot/user) + if(!istype(user) || user.toner < printcost) + balloon_alert(user, "not enough toner!") return var/datum/picture/selection = selectpicture(user) if(!istype(selection)) - to_chat(user, span_warning("Invalid Image.")) + balloon_alert(user, "invalid image!") return - var/obj/item/photo/p = new /obj/item/photo(C.loc, selection) - p.pixel_x = p.base_pixel_x + rand(-10, 10) - p.pixel_y = p.base_pixel_y + rand(-10, 10) - C.toner -= printcost //All fun allowed. - user.visible_message(span_notice("[C.name] spits out a photograph from a narrow slot on its chassis."), span_notice("You print a photograph.")) + var/obj/item/photo/printed = new(user.drop_location(), selection) + printed.pixel_x = printed.base_pixel_x + rand(-10, 10) + printed.pixel_y = printed.base_pixel_y + rand(-10, 10) + user.toner -= printcost //All fun allowed. + user.visible_message(span_notice("[user.name] spits out a photograph from a narrow slot on its chassis."), span_notice("You print a photograph.")) + balloon_alert(user, "photograph printed") + playsound(src, 'sound/items/taperecorder/taperecorder_print.ogg', 50, TRUE, -3) diff --git a/code/modules/projectiles/ammunition/ballistic/pistol.dm b/code/modules/projectiles/ammunition/ballistic/pistol.dm index c61888b9525..a2f55f797bd 100644 --- a/code/modules/projectiles/ammunition/ballistic/pistol.dm +++ b/code/modules/projectiles/ammunition/ballistic/pistol.dm @@ -21,6 +21,11 @@ desc = "A 10mm incendiary bullet casing." projectile_type = /obj/projectile/bullet/incendiary/c10mm +/obj/item/ammo_casing/c10mm/reaper + name = "10mm reaper bullet casing" + desc = "A 10mm reaper bullet casing." + projectile_type = /obj/projectile/bullet/c10mm/reaper + // 9mm (Makarov, Stechkin APS, PP-95) /obj/item/ammo_casing/c9mm diff --git a/code/modules/projectiles/ammunition/ballistic/shotgun.dm b/code/modules/projectiles/ammunition/ballistic/shotgun.dm index 53ff1f8a350..81e2fe97931 100644 --- a/code/modules/projectiles/ammunition/ballistic/shotgun.dm +++ b/code/modules/projectiles/ammunition/ballistic/shotgun.dm @@ -136,6 +136,16 @@ icon_state = "cshell" projectile_type = null +/obj/item/ammo_casing/shotgun/techshell/Initialize(mapload) + . = ..() + + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/meteorslug, /datum/crafting_recipe/pulseslug, /datum/crafting_recipe/dragonsbreath, /datum/crafting_recipe/ionslug, /datum/crafting_recipe/laserslug) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/ammo_casing/shotgun/dart name = "shotgun dart" desc = "A dart for use in shotguns. Can be injected with up to 15 units of any chemical." diff --git a/code/modules/projectiles/ammunition/energy/laser.dm b/code/modules/projectiles/ammunition/energy/laser.dm index fbf9b289aa0..4f62af047d4 100644 --- a/code/modules/projectiles/ammunition/energy/laser.dm +++ b/code/modules/projectiles/ammunition/energy/laser.dm @@ -16,6 +16,11 @@ e_cost = 62.5 select_name = "kill" +/obj/item/ammo_casing/energy/lasergun/carbine + projectile_type = /obj/projectile/beam/laser/carbine + e_cost = 25 // 40 shots + select_name = "kill" + /obj/item/ammo_casing/energy/lasergun/old projectile_type = /obj/projectile/beam/laser e_cost = 200 diff --git a/code/modules/projectiles/boxes_magazines/external/pistol.dm b/code/modules/projectiles/boxes_magazines/external/pistol.dm index 49ea0029f8f..8b0bc1da7e5 100644 --- a/code/modules/projectiles/boxes_magazines/external/pistol.dm +++ b/code/modules/projectiles/boxes_magazines/external/pistol.dm @@ -107,15 +107,11 @@ multiple_sprites = AMMO_BOX_PER_BULLET /obj/item/ammo_box/magazine/r10mm - name = "regal condor magazine (10mm)" + name = "regal condor magazine (10mm Reaper)" icon_state = "r10mm-8" base_icon_state = "r10mm" - ammo_type = /obj/item/ammo_casing/c10mm + ammo_type = /obj/item/ammo_casing/c10mm/reaper caliber = CALIBER_10MM max_ammo = 8 multiple_sprites = AMMO_BOX_PER_BULLET multiple_sprite_use_base = TRUE - -/obj/item/ammo_box/magazine/r10mm/empty - icon_state = "r10mm-0" - start_empty = TRUE diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm index 220df569ecb..f69494e0a18 100644 --- a/code/modules/projectiles/guns/ballistic/pistol.dm +++ b/code/modules/projectiles/guns/ballistic/pistol.dm @@ -99,9 +99,6 @@ actions_types = list(/datum/action/item_action/toggle_firemode) obj_flags = UNIQUE_RENAME // if you did the sidequest, you get the customization -/obj/item/gun/ballistic/automatic/pistol/deagle/regal/no_mag - spawnwithmagazine = FALSE - /obj/item/gun/ballistic/automatic/pistol/aps name = "\improper Stechkin APS machine pistol" desc = "A modernized reproduction of an old Soviet machine pistol. It fires quickly, but kicks like a mule. Uses 9mm ammo. Has a threaded barrel for suppressors." //SKYRAT EDIT diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index 0409f2fe037..9ad095f67e0 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -37,6 +37,16 @@ cell_type = /obj/item/stock_parts/cell //SKYRAT EDIT ADDITION - GUNSGALORE ammo_x_offset = 3 +/obj/item/gun/energy/laser/carbine + name = "laser carbine" + desc = "A modified laser gun which can shoot far faster, but each shot is far less damaging." + icon_state = "laser_carbine" + ammo_type = list(/obj/item/ammo_casing/energy/lasergun/carbine) + +/obj/item/gun/energy/laser/carbine/Initialize(mapload) + . = ..() + AddComponent(/datum/component/automatic_fire, 0.15 SECONDS, allow_akimbo = FALSE) + /obj/item/gun/energy/laser/retro/old name ="laser gun" icon_state = "retro" diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index e5c4d520d0e..d6c47531c91 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -28,6 +28,11 @@ damage = 25 bare_wound_bonus = 40 +/obj/projectile/beam/laser/carbine + icon_state = "carbine_laser" + impact_effect_type = /obj/effect/temp_visual/impact_effect/yellow_laser + damage = 10 + //overclocked laser, does a bit more damage but has much higher wound power (-0 vs -20) /obj/projectile/beam/laser/hellfire name = "hellfire laser" diff --git a/code/modules/projectiles/projectile/bullets/pistol.dm b/code/modules/projectiles/projectile/bullets/pistol.dm index ece260f92fb..8fccc510ff8 100644 --- a/code/modules/projectiles/projectile/bullets/pistol.dm +++ b/code/modules/projectiles/projectile/bullets/pistol.dm @@ -42,3 +42,22 @@ name = "10mm incendiary bullet" damage = 20 fire_stacks = 3 + +/obj/projectile/bullet/c10mm/reaper + name = "10mm reaper pellet" + damage = 50 + armour_penetration = 40 + tracer_type = /obj/effect/projectile/tracer/sniper + impact_type = /obj/effect/projectile/impact/sniper + muzzle_type = /obj/effect/projectile/muzzle/sniper + hitscan = TRUE + impact_effect_type = null + hitscan_light_intensity = 3 + hitscan_light_range = 0.75 + hitscan_light_color_override = LIGHT_COLOR_DIM_YELLOW + muzzle_flash_intensity = 5 + muzzle_flash_range = 1 + muzzle_flash_color_override = LIGHT_COLOR_DIM_YELLOW + impact_light_intensity = 5 + impact_light_range = 1 + impact_light_color_override = LIGHT_COLOR_DIM_YELLOW diff --git a/code/modules/reagents/chemistry/equilibrium.dm b/code/modules/reagents/chemistry/equilibrium.dm index 7d7aff20fae..f46c636c50f 100644 --- a/code/modules/reagents/chemistry/equilibrium.dm +++ b/code/modules/reagents/chemistry/equilibrium.dm @@ -324,8 +324,8 @@ //keep limited if(delta_chem_factor > step_target_vol) delta_chem_factor = step_target_vol - else if (delta_chem_factor < CHEMICAL_VOLUME_MINIMUM) - delta_chem_factor = CHEMICAL_VOLUME_MINIMUM + else if (delta_chem_factor < CHEMICAL_QUANTISATION_LEVEL) + delta_chem_factor = CHEMICAL_QUANTISATION_LEVEL //Normalise to multiproducts delta_chem_factor /= product_ratio //delta_chem_factor = round(delta_chem_factor, CHEMICAL_QUANTISATION_LEVEL) // Might not be needed - left here incase testmerge shows that it does. Remove before full commit. diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index b03a736e3f8..69eb3524cdf 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -1,136 +1,6 @@ -#define REAGENTS_UI_MODE_LOOKUP 0 -#define REAGENTS_UI_MODE_REAGENT 1 -#define REAGENTS_UI_MODE_RECIPE 2 - #define REAGENT_TRANSFER_AMOUNT "amount" #define REAGENT_PURITY "purity" -/// Initialises all /datum/reagent into a list indexed by reagent id -/proc/init_chemical_reagent_list() - var/list/reagent_list = list() - - var/paths = subtypesof(/datum/reagent) - - for(var/path in paths) - if(path in GLOB.fake_reagent_blacklist) - continue - var/datum/reagent/D = new path() - D.mass = rand(10, 800) //This is terrible and should be removed ASAP! - reagent_list[path] = D - - return reagent_list - -/// Creates an list which is indexed by reagent name . used by plumbing reaction chamber and chemical filter UI -/proc/init_chemical_name_list() - var/list/name_list = list() - for(var/X in GLOB.chemical_reagents_list) - var/datum/reagent/Reagent = GLOB.chemical_reagents_list[X] - name_list += Reagent.name - return sort_list(name_list) - - -/proc/build_chemical_reactions_lists() - //Chemical Reactions - Initialises all /datum/chemical_reaction into a list - // It is filtered into multiple lists within a list. - // For example: - // chemical_reactions_list_reactant_index[/datum/reagent/toxin/plasma] is a list of all reactions relating to plasma - //For chemical reaction list product index - indexes reactions based off the product reagent type - see get_recipe_from_reagent_product() in helpers - //For chemical reactions list lookup list - creates a bit list of info passed to the UI. This is saved to reduce lag from new windows opening, since it's a lot of data. - - //Prevent these reactions from appearing in lookup tables (UI code) - var/list/blacklist = typecacheof(/datum/chemical_reaction/randomized) - - if(GLOB.chemical_reactions_list_reactant_index) - return - - //Randomized need to go last since they need to check against conflicts with normal recipes - var/paths = subtypesof(/datum/chemical_reaction) - typesof(/datum/chemical_reaction/randomized) + subtypesof(/datum/chemical_reaction/randomized) - GLOB.chemical_reactions_list = list() //typepath to reaction list - GLOB.chemical_reactions_list_reactant_index = list() //reagents to reaction list - GLOB.chemical_reactions_results_lookup_list = list() //UI glob - GLOB.chemical_reactions_list_product_index = list() //product to reaction list - - var/list/datum/chemical_reaction/reactions = list() - for(var/path in paths) - var/datum/chemical_reaction/reaction = new path() - reactions += reaction - - // Ok so we're gonna do a thingTM here - // I want to distribute all our reactions such that each reagent id links to as few as possible - // I get the feeling there's a canonical way of doing this, but I don't know it - // So instead, we're gonna wing it - var/list/reagent_to_react_count = list() - for(var/datum/chemical_reaction/reaction as anything in reactions) - for(var/reagent_id as anything in reaction.required_reagents) - reagent_to_react_count[reagent_id] += 1 - - var/list/reaction_lookup = GLOB.chemical_reactions_list_reactant_index - // Create filters based on a random reagent id in the required reagents list - this is used to speed up handle_reactions() - // Basically, we only really need to care about ONE reagent, at least when initially filtering, since any others are ignorable - // Doing this separately because it relies on the loop above, and this is easier to parse - for(var/datum/chemical_reaction/reaction as anything in reactions) - var/preferred_id = null - for(var/reagent_id as anything in reaction.required_reagents) - if(!preferred_id) - preferred_id = reagent_id - continue - // If we would have less then they would, take it - if(length(reaction_lookup[reagent_id]) < length(reaction_lookup[preferred_id])) - preferred_id = reagent_id - continue - // If they potentially have more then us, we take it - if(reagent_to_react_count[reagent_id] < reagent_to_react_count[preferred_id]) - preferred_id = reagent_id - continue - if (preferred_id != null) - if(!reaction_lookup[preferred_id]) - reaction_lookup[preferred_id] = list() - reaction_lookup[preferred_id] += reaction - - for(var/datum/chemical_reaction/reaction as anything in reactions) - var/list/product_ids = list() - var/list/reagents = list() - var/list/product_names = list() - var/bitflags = reaction.reaction_tags - - if(!reaction.required_reagents || !reaction.required_reagents.len) //Skip impossible reactions - continue - - GLOB.chemical_reactions_list[reaction.type] = reaction - - for(var/reagent_path in reaction.required_reagents) - var/datum/reagent/reagent = find_reagent_object_from_type(reagent_path) - if(!istype(reagent)) - stack_trace("Invalid reagent found in [reaction] required_reagents: [reagent_path]") - continue - reagents += list(list("name" = reagent.name, "id" = reagent.type)) - - for(var/product in reaction.results) - var/datum/reagent/reagent = find_reagent_object_from_type(product) - if(!istype(reagent)) - stack_trace("Invalid reagent found in [reaction] results: [product]") - continue - product_names += reagent.name - product_ids += product - - var/product_name - if(!length(product_names)) - var/list/names = splittext("[reaction.type]", "/") - product_name = names[names.len] - else - product_name = product_names[1] - - if(!is_type_in_typecache(reaction.type, blacklist)) - //Master list of ALL reactions that is used in the UI lookup table. This is expensive to make, and we don't want to lag the server by creating it on UI request, so it's cached to send to UIs instantly. - GLOB.chemical_reactions_results_lookup_list += list(list("name" = product_name, "id" = reaction.type, "bitflags" = bitflags, "reactants" = reagents)) - - // Create filters based on each reagent id in the required reagents list - this is specifically for finding reactions from product(reagent) ids/typepaths. - for(var/id in product_ids) - if(!GLOB.chemical_reactions_list_product_index[id]) - GLOB.chemical_reactions_list_product_index[id] = list() - GLOB.chemical_reactions_list_product_index[id] += reaction - - ///////////////////////////////Main reagents code///////////////////////////////////////////// /// Holder for a bunch of [/datum/reagent] @@ -147,8 +17,6 @@ var/chem_temp = 150 ///pH of the whole system var/ph = CHEMICAL_NORMAL_PH - /// unused - var/last_tick = 1 /// various flags, see code\__DEFINES\reagents.dm var/flags ///list of reactions currently on going, this is a lazylist for optimisation @@ -171,7 +39,7 @@ ///If we're syncing with the beaker - so return reactions that are actively happening var/ui_beaker_sync = FALSE -/datum/reagents/New(maximum=100, new_flags=0) +/datum/reagents/New(maximum = 100, new_flags = 0) maximum_volume = maximum flags = new_flags @@ -203,21 +71,36 @@ * * override_base_ph - ingore the present pH of the reagent, and instead use the default (i.e. if buffers/reactions alter it) * * ignore splitting - Don't call the process that handles reagent spliting in a mob (impure/inverse) - generally leave this false unless you care about REAGENTS_DONOTSPLIT flags (see reagent defines) */ -/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = DEFAULT_REAGENT_TEMPERATURE, added_purity = null, added_ph, no_react = FALSE, override_base_ph = FALSE, ignore_splitting = FALSE) - // Prevents small amount problems, as well as zero and below zero amounts. - if(amount <= CHEMICAL_QUANTISATION_LEVEL) +/datum/reagents/proc/add_reagent( + datum/reagent/reagent_type, + amount, + list/data = null, + reagtemp = DEFAULT_REAGENT_TEMPERATURE, + added_purity = null, + added_ph, + no_react = FALSE, + override_base_ph = FALSE, + ignore_splitting = FALSE +) + if(!ispath(reagent_type)) + stack_trace("invalid reagent passed to add reagent [reagent_type]") return FALSE if(!IS_FINITE(amount)) - stack_trace("non finite amount passed to add reagent [amount] [reagent]") + stack_trace("non finite amount passed to add reagent [amount] [reagent_type]") + return FALSE + + if(SEND_SIGNAL(src, COMSIG_REAGENTS_PRE_ADD_REAGENT, reagent_type, amount, reagtemp, data, no_react) & COMPONENT_CANCEL_REAGENT_ADD) return FALSE - if(SEND_SIGNAL(src, COMSIG_REAGENTS_PRE_ADD_REAGENT, reagent, amount, reagtemp, data, no_react) & COMPONENT_CANCEL_REAGENT_ADD) + // Prevents small amount problems, as well as zero and below zero amounts. + amount = FLOOR(amount, CHEMICAL_QUANTISATION_LEVEL) + if(amount <= 0) return FALSE - var/datum/reagent/glob_reagent = GLOB.chemical_reagents_list[reagent] + var/datum/reagent/glob_reagent = GLOB.chemical_reagents_list[reagent_type] if(!glob_reagent) - stack_trace("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])") + stack_trace("[my_atom] attempted to add a reagent called '[reagent_type]' which doesn't exist. ([usr])") return FALSE if(isnull(added_purity)) //Because purity additions can be 0 added_purity = glob_reagent.creation_purity //Usually 1 @@ -227,8 +110,8 @@ //Split up the reagent if it's in a mob var/has_split = FALSE if(!ignore_splitting && (flags & REAGENT_HOLDER_ALIVE)) //Stomachs are a pain - they will constantly call on_mob_add unless we split on addition to stomachs, but we also want to make sure we don't double split - var/adjusted_vol = process_mob_reagent_purity(glob_reagent, amount, added_purity) - if(!adjusted_vol) //If we're inverse or FALSE cancel addition + var/adjusted_vol = FLOOR(process_mob_reagent_purity(glob_reagent, amount, added_purity), CHEMICAL_QUANTISATION_LEVEL) + if(adjusted_vol <= 0) //If we're inverse or FALSE cancel addition return TRUE /* We return true here because of #63301 The only cases where this will be false or 0 if its an inverse chem, an impure chem of 0 purity (highly unlikely if even possible), or if glob_reagent is null (which shouldn't happen at all as there's a check for that a few lines up), @@ -240,7 +123,7 @@ update_total() var/cached_total = total_volume if(cached_total + amount > maximum_volume) - amount = (maximum_volume - cached_total) //Doesnt fit in. Make it disappear. shouldn't happen. Will happen. + amount = FLOOR(maximum_volume - cached_total, CHEMICAL_QUANTISATION_LEVEL) //Doesnt fit in. Make it disappear. shouldn't happen. Will happen. if(amount <= 0) return FALSE @@ -255,13 +138,13 @@ //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.type == reagent_type) 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 iter_reagent.creation_purity = iter_reagent.purity iter_reagent.ph = ((iter_reagent.ph*(iter_reagent.volume))+(added_ph*amount))/(iter_reagent.volume+amount) - iter_reagent.volume += round(amount, CHEMICAL_QUANTISATION_LEVEL) + iter_reagent.volume += FLOOR(amount, CHEMICAL_QUANTISATION_LEVEL) update_total() iter_reagent.on_merge(data, amount) @@ -278,7 +161,7 @@ return TRUE //otherwise make a new one - var/datum/reagent/new_reagent = new reagent(data) + var/datum/reagent/new_reagent = new reagent_type(data) cached_reagents += new_reagent new_reagent.holder = src new_reagent.volume = amount @@ -306,40 +189,71 @@ handle_reactions() return TRUE -/// Like add_reagent but you can enter a list. Format it like this: list(/datum/reagent/toxin = 10, "beer" = 15) -/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null) +/** + * Like add_reagent but you can enter a list. + * Arguments + * + * * [list_reagents][list] - list to add. Format it like this: list(/datum/reagent/toxin = 10, "beer" = 15) + * * [data][list] - additional data to add + */ +/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data = null) for(var/r_id in list_reagents) var/amt = list_reagents[r_id] add_reagent(r_id, amt, data) -/// Remove a specific reagent -/datum/reagents/proc/remove_reagent(reagent, amount, safety = TRUE)//Added a safety check for the trans_id_to - if(isnull(amount)) - stack_trace("null amount passed to reagent code") +/** + * Removes a specific reagent. can supress reactions if needed + * Arguments + * + * * [reagent_type][datum/reagent] - the type of reagent + * * amount - the volume to remove + * * safety - if FALSE will initiate reactions upon removing. used for trans_id_to + */ +/datum/reagents/proc/remove_reagent(datum/reagent/reagent_type, amount, safety = TRUE) + if(!ispath(reagent_type)) + stack_trace("invalid reagent passed to remove reagent [reagent_type]") return FALSE - if(amount < 0 || !IS_FINITE(amount)) - stack_trace("invalid number passed to remove_reagent [amount]") + if(!IS_FINITE(amount)) + stack_trace("non finite amount passed to remove reagent [amount] [reagent_type]") + return FALSE + + // Prevents small amount problems, as well as zero and below zero amounts. + amount = FLOOR(amount, CHEMICAL_QUANTISATION_LEVEL) + if(amount <= 0) return FALSE var/list/cached_reagents = reagent_list for(var/datum/reagent/cached_reagent as anything in cached_reagents) - if(cached_reagent.type == reagent) + if(cached_reagent.type == reagent_type) //clamp the removal amount to be between current reagent amount //and zero, to prevent removing more than the holder has stored - amount = clamp(amount, 0, cached_reagent.volume) + amount = FLOOR(clamp(amount, 0, cached_reagent.volume), CHEMICAL_QUANTISATION_LEVEL) cached_reagent.volume -= amount update_total() if(!safety)//So it does not handle reactions when it need not to handle_reactions() - SEND_SIGNAL(src, COMSIG_REAGENTS_REM_REAGENT, QDELING(cached_reagent) ? reagent : cached_reagent, amount) + SEND_SIGNAL(src, COMSIG_REAGENTS_REM_REAGENT, QDELING(cached_reagent) ? reagent_type : cached_reagent, amount) return TRUE return FALSE -/// Remove an amount of reagents without caring about what they are +/** + * Removes a reagent at random by the specified amount + * Arguments + * + * * amount- the volume to remove + */ /datum/reagents/proc/remove_any(amount = 1) + if(!IS_FINITE(amount)) + stack_trace("non finite amount passed to remove any reagent [amount]") + return FALSE + + amount = FLOOR(amount, CHEMICAL_QUANTISATION_LEVEL) + if(amount <= 0) + return FALSE + var/list/cached_reagents = reagent_list var/total_removed = 0 var/current_list_element = 1 @@ -356,10 +270,10 @@ if(current_list_element > cached_reagents.len) current_list_element = 1 - var/datum/reagent/R = cached_reagents[current_list_element] - var/remove_amt = min(amount-total_removed,round(amount/rand(2,initial_list_length),round(amount/10,0.01))) //double round to keep it at a somewhat even spread relative to amount without getting funky numbers. + var/datum/reagent/target_holder = cached_reagents[current_list_element] + var/remove_amt = min(amount - total_removed, round(amount / rand(2, initial_list_length), round(amount / 10, 0.01))) //double round to keep it at a somewhat even spread relative to amount without getting funky numbers. //min ensures we don't go over amount. - remove_reagent(R.type, remove_amt) + remove_reagent(target_holder.type, remove_amt) current_list_element++ total_removed += remove_amt @@ -368,22 +282,72 @@ handle_reactions() return total_removed //this should be amount unless the loop is prematurely broken, in which case it'll be lower. It shouldn't ever go OVER amount. -/// Removes all reagents from this holder +/** + * Removes all reagents by an amount equal to + * [amount specified] / total volume present in this holder + * Arguments + * + * * amount - the volume of each reagent + */ + /datum/reagents/proc/remove_all(amount = 1) + if(!total_volume) + return FALSE + + if(!IS_FINITE(amount)) + stack_trace("non finite amount passed to remove all reagents [amount]") + return FALSE + + // Prevents small amount problems, as well as zero and below zero amounts. + amount = FLOOR(amount, CHEMICAL_QUANTISATION_LEVEL) + if(amount <= 0) + return FALSE + var/list/cached_reagents = reagent_list - if(total_volume > 0) - var/part = amount / total_volume + var/removed_amount = 0 + var/equal_contribution = amount * (1 / length(cached_reagents)) + var/final_contribution = 0 + // when i = 1(1st iteration) each reagent contributes equally to the requested amount + // when i = 2(2nd iteration) each reagent contributes maximum to how much is left over + for(var/i in 1 to 2) for(var/datum/reagent/reagent as anything in cached_reagents) - remove_reagent(reagent.type, reagent.volume * part) + var/remove_amount = FLOOR(min(reagent.volume, i == 1 ? equal_contribution : final_contribution), CHEMICAL_QUANTISATION_LEVEL) + remove_reagent(reagent.type, remove_amount) + removed_amount += remove_amount + if(removed_amount >= amount) + break + if(i == 2) + final_contribution = amount - removed_amount - //finish_reacting() //A just in case - update total is in here - should be unneeded, make sure to test this - handle_reactions() - return amount + final_contribution = amount - removed_amount + if(!total_volume || final_contribution < CHEMICAL_QUANTISATION_LEVEL) + break + + handle_reactions() + return removed_amount + +/** + * Removes all reagent of X type + * Arguments + * + * * [reagent_type][datum/reagent] - the reagent typepath we are trying to remove + * * amount - the volume of reagent to remove + * * strict - If TRUE will also remove childs of this reagent type + */ +/datum/reagents/proc/remove_all_type(datum/reagent/reagent_type, amount, strict = 0, safety = 1) + if(!ispath(reagent_type)) + stack_trace("invalid reagent path passed to remove all type [reagent_type]") + return FALSE + + if(!IS_FINITE(amount)) + stack_trace("non finite amount passed to remove all type reagent [amount] [reagent_type]") + return FALSE + + // Prevents small amount problems, as well as zero and below zero amounts. + amount = FLOOR(amount, CHEMICAL_QUANTISATION_LEVEL) + if(amount <= 0) + return FALSE -/// Removes all reagent of X type. @strict set to 1 determines whether the childs of the type are included. -/datum/reagents/proc/remove_all_type(reagent_type, amount, strict = 0, safety = 1) - if(!isnum(amount)) - return 1 var/list/cached_reagents = reagent_list var/has_removed_reagent = 0 @@ -403,8 +367,17 @@ return has_removed_reagent -/// Fuck this one reagent -/datum/reagents/proc/del_reagent(target_reagent_typepath) +/** + * Removes an specific reagent from this holder + * Arguments + * + * * [target_reagent_typepath][datum/reagent] - type typepath of the reagent to remove + */ +/datum/reagents/proc/del_reagent(datum/reagent/target_reagent_typepath) + if(!ispath(target_reagent_typepath)) + stack_trace("invalid reagent path passed to del reagent [target_reagent_typepath]") + return FALSE + var/list/cached_reagents = reagent_list for(var/datum/reagent/reagent as anything in cached_reagents) if(reagent.type == target_reagent_typepath) @@ -421,19 +394,37 @@ SEND_SIGNAL(src, COMSIG_REAGENTS_DEL_REAGENT, reagent) return TRUE -/// Turn one reagent into another, preserving volume, temp, purity, ph -/datum/reagents/proc/convert_reagent(source_reagent_typepath, target_reagent_typepath, multiplier = 1, include_source_subtypes = FALSE) +/** + * Turn one reagent into another, preserving volume, temp, purity, ph + * Arguments + * + * * [source_reagent_typepath][/datum/reagent] - the typepath of the reagent you are trying to convert + * * [target_reagent_typepath][/datum/reagent] - the final typepath the source_reagent_typepath will be converted into + * * multiplier - the multiplier applied on the source_reagent_typepath volume before converting + * * include_source_subtypes- if TRUE will convert all subtypes of source_reagent_typepath into target_reagent_typepath as well + */ +/datum/reagents/proc/convert_reagent( + datum/reagent/source_reagent_typepath, + datum/reagent/target_reagent_typepath, + multiplier = 1, + include_source_subtypes = FALSE +) + if(!ispath(source_reagent_typepath)) + stack_trace("invalid reagent path passed to convert reagent [source_reagent_typepath]") + return FALSE + var/reagent_amount var/reagent_purity var/reagent_ph if(include_source_subtypes) reagent_ph = ph var/weighted_purity + var/list/reagent_type_list = typecacheof(source_reagent_typepath) for(var/datum/reagent/reagent as anything in reagent_list) - if(reagent.type in typecacheof(source_reagent_typepath)) + if(reagent.type in reagent_type_list) weighted_purity += reagent.volume * reagent.purity reagent_amount += reagent.volume - remove_reagent(reagent.type, reagent.volume) + remove_reagent(reagent.type, reagent.volume * multiplier) reagent_purity = weighted_purity / reagent_amount else var/datum/reagent/source_reagent = get_reagent(source_reagent_typepath) @@ -443,21 +434,6 @@ remove_reagent(source_reagent_typepath, reagent_amount) add_reagent(target_reagent_typepath, reagent_amount * multiplier, reagtemp = chem_temp, added_purity = reagent_purity, added_ph = reagent_ph) -//Converts the creation_purity to purity -/datum/reagents/proc/uncache_creation_purity(id) - var/datum/reagent/R = has_reagent(id) - if(!R) - return - R.purity = R.creation_purity - -/// Remove every reagent except this one -/datum/reagents/proc/isolate_reagent(reagent) - var/list/cached_reagents = reagent_list - for(var/datum/reagent/cached_reagent as anything in cached_reagents) - if(cached_reagent.type != reagent) - del_reagent(cached_reagent.type) - update_total() - /// Removes all reagents /datum/reagents/proc/clear_reagents() var/list/cached_reagents = reagent_list @@ -467,16 +443,28 @@ /** - * Check if this holder contains this reagent. - * Reagent takes a PATH to a reagent. - * Amount checks for having a specific amount of that chemical. + * Check if this holder contains this reagent. Reagent takes a PATH to a reagent * Needs matabolizing takes into consideration if the chemical is metabolizing when it's checked. - * Check subtypes controls whether it should it should also include subtypes: ispath(type, reagent) versus type == reagent. + * Arguments + * + * * [target_reagent][datum/reagent] - the reagent typepath to check for + * * amount - checks for having a specific amount of that chemical + * * needs_metabolizing - takes into consideration if the chemical is matabolizing when it's checked. + * * check_subtypes - controls whether it should it should also include subtypes: ispath(type, reagent) versus type == reagent. */ -/datum/reagents/proc/has_reagent(reagent, amount = -1, needs_metabolizing = FALSE, check_subtypes = FALSE) +/datum/reagents/proc/has_reagent( + datum/reagent/target_reagent, + amount = -1, + needs_metabolizing = FALSE, + check_subtypes = FALSE +) + if(!ispath(target_reagent)) + stack_trace("invalid reagent path passed to has reagent [target_reagent]") + return FALSE + var/list/cached_reagents = reagent_list for(var/datum/reagent/holder_reagent as anything in cached_reagents) - if (check_subtypes ? ispath(holder_reagent.type, reagent) : holder_reagent.type == reagent) + if (check_subtypes ? ispath(holder_reagent.type, target_reagent) : holder_reagent.type == target_reagent) if(!amount) if(needs_metabolizing && !holder_reagent.metabolizing) if(check_subtypes) @@ -484,7 +472,7 @@ return FALSE return holder_reagent else - if(round(holder_reagent.volume, CHEMICAL_QUANTISATION_LEVEL) >= amount) + if(FLOOR(holder_reagent.volume, CHEMICAL_QUANTISATION_LEVEL) >= amount) if(needs_metabolizing && !holder_reagent.metabolizing) if(check_subtypes) continue @@ -497,7 +485,10 @@ /** * Check if this holder contains a reagent with a chemical_flags containing this flag * Reagent takes the bitflag to search for - * Amount checks for having a specific amount of reagents matching that chemical + * + * Arguments + * * chemical_flag - the flag to check for + * * amount - checks for having a specific amount of reagents matching that chemical */ /datum/reagents/proc/has_chemical_flag(chemical_flag, amount = 0) var/found_amount = 0 @@ -526,72 +517,118 @@ * * round_robin - if round_robin=TRUE, so transfer 5 from 15 water, 15 sugar and 15 plasma becomes 10, 15, 15 instead of 13.3333, 13.3333 13.3333. Good if you hate floating point errors * * ignore_stomach - when using methods INGEST will not use the stomach as the target */ -/datum/reagents/proc/trans_to(obj/target, amount = 1, multiplier = 1, preserve_data = TRUE, no_react = FALSE, mob/transferred_by, remove_blacklisted = FALSE, methods = NONE, show_message = TRUE, round_robin = FALSE, ignore_stomach = FALSE) - var/list/cached_reagents = reagent_list - if(!target || !total_volume) - return - if(amount < 0) +/datum/reagents/proc/trans_to( + obj/target, + amount = 1, + multiplier = 1, + preserve_data = TRUE, + no_react = FALSE, + mob/transferred_by, + remove_blacklisted = FALSE, + methods = NONE, + show_message = TRUE, + round_robin = FALSE, + ignore_stomach = FALSE +) + if(QDELETED(target) || !total_volume) return - var/cached_amount = amount + if(!IS_FINITE(amount)) + stack_trace("non finite amount passed to trans_to [amount] amount of reagents") + return FALSE + + var/list/cached_reagents = reagent_list + var/atom/target_atom - var/datum/reagents/R + var/datum/reagents/target_holder if(istype(target, /datum/reagents)) - R = target - target_atom = R.my_atom + target_holder = target + target_atom = target_holder.my_atom else if(!ignore_stomach && (methods & INGEST) && iscarbon(target)) var/mob/living/carbon/eater = target var/obj/item/organ/internal/stomach/belly = eater.get_organ_slot(ORGAN_SLOT_STOMACH) if(!belly) - eater.expel_ingested(my_atom, amount) + var/expel_amount = FLOOR(amount, CHEMICAL_QUANTISATION_LEVEL) + if(expel_amount > 0 ) + eater.expel_ingested(my_atom, expel_amount) return - R = belly.reagents + target_holder = belly.reagents target_atom = belly else if(!target.reagents) return else - R = target.reagents + target_holder = target.reagents target_atom = target + var/cached_amount = amount + + // Prevents small amount problems, as well as zero and below zero amounts. + amount = FLOOR(min(amount * multiplier, total_volume, target_holder.maximum_volume - target_holder.total_volume), CHEMICAL_QUANTISATION_LEVEL) + if(amount <= 0) + return FALSE + //Set up new reagents to inherit the old ongoing reactions if(!no_react) - transfer_reactions(R) + transfer_reactions(target_holder) - amount = min(min(amount, src.total_volume), R.maximum_volume-R.total_volume) + var/transfered_amount = 0 var/trans_data = null - var/transfer_log = list() - var/r_to_send = list() // Validated list of reagents to be exposed - var/reagents_to_remove = list() + var/list/transfer_log = list() + var/list/r_to_send = list() // Validated list of reagents to be exposed + var/list/reagents_to_remove = list() if(!round_robin) - var/part = amount / src.total_volume - for(var/datum/reagent/reagent as anything in cached_reagents) - if(remove_blacklisted && !(reagent.chemical_flags & REAGENT_CAN_BE_SYNTHESIZED)) - continue - var/transfer_amount = reagent.volume * part - if(preserve_data) - trans_data = copy_data(reagent) - if(reagent.intercept_reagents_transfer(R, cached_amount))//Use input amount instead. - continue - if(!R.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT)) //we only handle reaction after every reagent has been transferred. - continue - if(methods) - r_to_send += reagent - - reagents_to_remove += reagent - - if(isorgan(target_atom)) - R.expose_multiple(r_to_send, target, methods, part, show_message) - else - R.expose_multiple(r_to_send, target_atom, methods, part, show_message) + var/part = 1 / length(cached_reagents) + + var/equal_contribution = amount * part + var/final_contribution = 0 + // when i = 1(1st iteration) each reagent contributes equally to the requested amount + // when i = 2(2nd iteration) each reagent contributes maximum to how much is left over + for(var/i in 1 to 2) + //clear lists when/if we go to the 2nd iteration + r_to_send.Cut() + reagents_to_remove.Cut() + + //first add reagents to target + for(var/datum/reagent/reagent as anything in cached_reagents) + if(remove_blacklisted && !(reagent.chemical_flags & REAGENT_CAN_BE_SYNTHESIZED)) + continue + if(preserve_data) + trans_data = copy_data(reagent) + if(reagent.intercept_reagents_transfer(target_holder, cached_amount)) + continue + var/transfer_amount = FLOOR(min(reagent.volume, i == 1 ? equal_contribution : final_contribution), CHEMICAL_QUANTISATION_LEVEL) + if(!target_holder.add_reagent(reagent.type, transfer_amount, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT)) //we only handle reaction after every reagent has been transferred. + continue + if(methods) + r_to_send += reagent + reagents_to_remove += list(list("R" = reagent, "T" = transfer_amount)) + transfered_amount += transfer_amount + if(transfered_amount >= amount) + break + if(i == 2) + final_contribution = (amount - transfered_amount) + + //expose target to reagent changes + target_holder.expose_multiple(r_to_send, isorgan(target_atom) ? target : target_atom, methods, part, show_message) + + //remove chemicals that were added above + for(var/list/data as anything in reagents_to_remove) + var/datum/reagent/reagent = data["R"] + var/transfer_amount = data["T"] + if(methods) + reagent.on_transfer(target_atom, methods, transfer_amount) + remove_reagent(reagent.type, transfer_amount) + if(!transfer_log[reagent.type]) + transfer_log[reagent.type] = list(REAGENT_TRANSFER_AMOUNT = transfer_amount, REAGENT_PURITY = reagent.purity) + else + var/list/logs = transfer_log[reagent.type] + logs["[REAGENT_TRANSFER_AMOUNT]"] += transfer_amount - for(var/datum/reagent/reagent as anything in reagents_to_remove) - var/transfer_amount = reagent.volume * part - if(methods) - reagent.on_transfer(target_atom, methods, transfer_amount * multiplier) - remove_reagent(reagent.type, transfer_amount) - var/list/reagent_qualities = list(REAGENT_TRANSFER_AMOUNT = transfer_amount, REAGENT_PURITY = reagent.purity) - transfer_log[reagent.type] = reagent_qualities + //see if we can contribute more to the requested amount and go again in the 2nd iteration + final_contribution = (amount - transfered_amount) + if(!total_volume || final_contribution < CHEMICAL_QUANTISATION_LEVEL) + break else var/to_transfer = amount @@ -602,59 +639,74 @@ continue if(preserve_data) trans_data = copy_data(reagent) - var/transfer_amount = amount - if(amount > reagent.volume) - transfer_amount = reagent.volume - if(reagent.intercept_reagents_transfer(R, cached_amount))//Use input amount instead. + if(reagent.intercept_reagents_transfer(target_holder, cached_amount)) continue - if(!R.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT)) //we only handle reaction after every reagent has been transferred. + var/transfer_amount = FLOOR(min(amount, reagent.volume), CHEMICAL_QUANTISATION_LEVEL) + if(!target_holder.add_reagent(reagent.type, transfer_amount, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT)) //we only handle reaction after every reagent has been transferred. continue to_transfer = max(to_transfer - transfer_amount , 0) if(methods) - if(isorgan(target_atom)) - R.expose_single(reagent, target, methods, transfer_amount, show_message) - else - R.expose_single(reagent, target_atom, methods, transfer_amount, show_message) - reagent.on_transfer(target_atom, methods, transfer_amount * multiplier) + target_holder.expose_multiple(r_to_send, isorgan(target_atom) ? target : target_atom, methods, transfer_amount, show_message) + reagent.on_transfer(target_atom, methods, transfer_amount) remove_reagent(reagent.type, transfer_amount) - var/list/reagent_qualities = list(REAGENT_TRANSFER_AMOUNT = transfer_amount, REAGENT_PURITY = reagent.purity) - transfer_log[reagent.type] = reagent_qualities + transfered_amount += transfer_amount + transfer_log[reagent.type] = list(REAGENT_TRANSFER_AMOUNT = transfer_amount, REAGENT_PURITY = reagent.purity) if(transferred_by && target_atom) target_atom.add_hiddenprint(transferred_by) //log prints so admins can figure out who touched it last. log_combat(transferred_by, target_atom, "transferred reagents ([get_external_reagent_log_string(transfer_log)]) from [my_atom] to") update_total() - R.update_total() + target_holder.update_total() if(!no_react) - R.handle_reactions() + target_holder.handle_reactions() src.handle_reactions() - return amount + return transfered_amount -/// Transfer a specific reagent id to the target object -/datum/reagents/proc/trans_id_to(obj/target, reagent, amount=1, preserve_data=1)//Not sure why this proc didn't exist before. It does now! /N - var/list/cached_reagents = reagent_list - if (!target) +/** + * Transfer a specific reagent id to the target object + * Arguments + * + * * [target][obj] - the target to transfer reagents to + * * [reagent_type][datum/reagent] - the type of reagent to transfer to the target + * * amount - volume to transfer + * * preserve_data- if TRUE reagent user data will remain preserved + */ +/datum/reagents/proc/trans_id_to( + obj/target, + datum/reagent/reagent_type, + amount = 1, + preserve_data = 1 +) + if (QDELETED(target) || !total_volume) return + if(!IS_FINITE(amount)) + stack_trace("non finite amount passed to trans_id_to [amount] [reagent_type]") + return FALSE + + var/cached_amount = amount + + var/available_volume = get_reagent_amount(reagent_type) var/datum/reagents/holder if(istype(target, /datum/reagents)) holder = target - else if(target.reagents && total_volume > 0 && get_reagent_amount(reagent)) + else if(target.reagents && available_volume) holder = target.reagents else return - if(amount < 0) + + // Prevents small amount problems, as well as zero and below zero amounts. + amount = FLOOR(min(amount, available_volume, holder.maximum_volume - holder.total_volume), CHEMICAL_QUANTISATION_LEVEL) + if(amount <= 0) return - var/cached_amount = amount - if(get_reagent_amount(reagent) < amount) - amount = get_reagent_amount(reagent) - amount = min(round(amount, CHEMICAL_VOLUME_ROUNDING), holder.maximum_volume - holder.total_volume) + var/list/cached_reagents = reagent_list + var/trans_data = null for (var/looping_through_reagents in cached_reagents) var/datum/reagent/current_reagent = looping_through_reagents - if(current_reagent.type == reagent) + if(current_reagent.type == reagent_type) if(preserve_data) trans_data = current_reagent.data if(current_reagent.intercept_reagents_transfer(holder, cached_amount))//Use input amount instead. @@ -669,12 +721,29 @@ holder.handle_reactions() return amount -/// Copies the reagents to the target object -/datum/reagents/proc/copy_to(obj/target, amount = 1, multiplier = 1, preserve_data = TRUE, no_react = FALSE) - var/list/cached_reagents = reagent_list - if(!target || !total_volume) +/** + * Copies the reagents to the target object + * Arguments + * + * * [target][obj] - the target to transfer reagents to + * * multiplier - the multiplier applied on all reagent volumes before transfering + * * preserve_data - preserve user data of all reagents after transfering + * * no_react - if TRUE will not handle reactions + */ +/datum/reagents/proc/copy_to( + atom/target, + amount = 1, + multiplier = 1, + preserve_data = TRUE, + no_react = FALSE +) + if(QDELETED(target) || !total_volume) return + if(!IS_FINITE(amount)) + stack_trace("non finite amount passed to copy_to [amount] amount of reagents") + return FALSE + var/datum/reagents/target_holder if(istype(target, /datum/reagents)) target_holder = target @@ -683,29 +752,54 @@ return target_holder = target.reagents - if(amount < 0) + // Prevents small amount problems, as well as zero and below zero amounts. + amount = FLOOR(min(amount * multiplier, total_volume, target_holder.maximum_volume - target_holder.total_volume), CHEMICAL_QUANTISATION_LEVEL) + if(amount <= 0) return - amount = min(min(amount, total_volume), target_holder.maximum_volume - target_holder.total_volume) - var/part = amount / total_volume + var/list/cached_reagents = reagent_list + + var/part = 1 / length(cached_reagents) + var/equal_contribution = amount * part + var/final_contribution = 0 + var/transfered_amount = 0 var/trans_data = null - for(var/datum/reagent/reagent as anything in cached_reagents) - var/copy_amount = reagent.volume * part - if(preserve_data) - trans_data = reagent.data - target_holder.add_reagent(reagent.type, copy_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT) + /** + * when i = 1(1st iteration) each reagent contributes equally to the requested amount + * when i = 2(2nd iteration) each reagent contributes maximum to how much is left over + */ + for(var/i in 1 to 2) + for(var/datum/reagent/reagent as anything in cached_reagents) + var/transfer_amount = FLOOR(min(reagent.volume, i == 1 ? equal_contribution : final_contribution), CHEMICAL_QUANTISATION_LEVEL) + if(preserve_data) + trans_data = reagent.data + if(!target_holder.add_reagent(reagent.type, transfer_amount, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT)) + continue + transfered_amount += transfer_amount + if(transfered_amount >= amount) + break + if(i == 2) + final_contribution = amount - transfered_amount - if(!no_react) - // pass over previous ongoing reactions before handle_reactions is called - transfer_reactions(target_holder) + if(!no_react) + // pass over previous ongoing reactions before handle_reactions is called + transfer_reactions(target_holder) - target_holder.update_total() - target_holder.handle_reactions() + target_holder.update_total() + target_holder.handle_reactions() - return amount + final_contribution = amount - transfered_amount + if(final_contribution < CHEMICAL_QUANTISATION_LEVEL) + break + + return transfered_amount -///Multiplies the reagents inside this holder by a specific amount -/datum/reagents/proc/multiply_reagents(multiplier=1) +/** + * Multiplies the reagents inside this holder by a specific amount + * Arguments + * * multiplier - the amount to multiply each reagent by + */ +/datum/reagents/proc/multiply_reagents(multiplier = 1) var/list/cached_reagents = reagent_list if(!total_volume) return @@ -784,7 +878,7 @@ // skip metabolizing effects for small units of toxins if(istype(reagent, /datum/reagent/toxin) && liver && !dead) var/datum/reagent/toxin/toxin = reagent - var/amount = round(toxin.volume, CHEMICAL_QUANTISATION_LEVEL) + var/amount = FLOOR(toxin.volume, CHEMICAL_QUANTISATION_LEVEL) if(belly) amount += belly.reagents.get_reagent_amount(toxin.type) @@ -865,7 +959,13 @@ need_mob_update += reagent.on_mob_dead(owner, seconds_per_tick) return need_mob_update -/// Signals that metabolization has stopped, triggering the end of trait-based effects +/** + * Signals that metabolization has stopped, triggering the end of trait-based effects + * Arguments + * + * * [C][mob/living/carbon] - the mob to end metabolization on + * * keep_liverless - if true will work without a liver + */ /datum/reagents/proc/end_metabolization(mob/living/carbon/C, keep_liverless = TRUE) var/list/cached_reagents = reagent_list for(var/datum/reagent/reagent as anything in cached_reagents) @@ -907,7 +1007,14 @@ return FALSE //prevent addition return added_volume -///Processes any chems that have the REAGENT_IGNORE_STASIS bitflag ONLY +/** + * Processes any chems that have the REAGENT_IGNORE_STASIS bitflag ONLY + * Arguments + * + * * [owner][mob/living/carbon] - the mob we are doing stasis handlng on + * * seconds_per_tick - passed from process + * * times_fired - number of times to metabolize this reagent + */ /datum/reagents/proc/handle_stasis_chems(mob/living/carbon/owner, seconds_per_tick, times_fired) var/need_mob_update = FALSE for(var/datum/reagent/reagent as anything in reagent_list) @@ -918,19 +1025,6 @@ owner.updatehealth() update_total() -/** - * Calls [/datum/reagent/proc/on_move] on every reagent in this holder - * - * Arguments: - * * atom/A - passed to on_move - * * Running - passed to on_move - */ -/datum/reagents/proc/conditional_update_move(atom/A, Running = 0) - var/list/cached_reagents = reagent_list - for(var/datum/reagent/reagent as anything in cached_reagents) - reagent.on_move(A, Running) - update_total() - /** * Calls [/datum/reagent/proc/on_update] on every reagent in this holder * @@ -992,7 +1086,7 @@ var/granularity = 1 if(!(reaction.reaction_flags & REACTION_INSTANT)) - granularity = CHEMICAL_VOLUME_MINIMUM + granularity = CHEMICAL_QUANTISATION_LEVEL var/list/cached_required_reagents = reaction.required_reagents for(var/req_reagent in cached_required_reagents) @@ -1114,7 +1208,7 @@ * This ends a single instance of an ongoing reaction * * Arguments: -* * E - the equilibrium that will be ended +* * [equilibrium][datum/equilibrium] - the equilibrium that will be ended * Returns: * * mix_message - the associated mix message of a reaction */ @@ -1146,7 +1240,6 @@ /* * This stops the holder from processing at the end of a series of reactions (i.e. when all the equilibriums are completed) -* * Also resets reaction variables to be null/empty/FALSE so that it can restart correctly in the future */ /datum/reagents/proc/finish_reacting() @@ -1154,7 +1247,7 @@ is_reacting = FALSE //Cap off values for(var/datum/reagent/reagent as anything in reagent_list) - reagent.volume = round(reagent.volume, CHEMICAL_VOLUME_ROUNDING)//To prevent runaways. + reagent.volume = FLOOR(reagent.volume, CHEMICAL_QUANTISATION_LEVEL)//To prevent runaways. LAZYNULL(previous_reagent_list) //reset it to 0 - because any change will be different now. update_total() if(!QDELING(src)) @@ -1254,7 +1347,7 @@ var/datum/cached_my_atom = my_atom var/multiplier = INFINITY for(var/reagent in cached_required_reagents) - multiplier = min(multiplier, round(get_reagent_amount(reagent) / cached_required_reagents[reagent])) + multiplier = FLOOR(min(multiplier, get_reagent_amount(reagent) / cached_required_reagents[reagent]), CHEMICAL_QUANTISATION_LEVEL) if(multiplier == 0)//Incase we're missing reagents - usually from on_reaction being called in an equlibrium when the results.len == 0 handlier catches a misflagged reaction return FALSE @@ -1300,31 +1393,13 @@ selected_reaction.on_reaction(src, null, multiplier) -///Possibly remove - see if multiple instant reactions is okay (Though, this "sorts" reactions by temp decending) -///Presently unused -/datum/reagents/proc/get_priority_instant_reaction(list/possible_reactions) - if(!length(possible_reactions)) - return FALSE - var/datum/chemical_reaction/selected_reaction = possible_reactions[1] - //select the reaction with the most extreme temperature requirements - for(var/datum/chemical_reaction/competitor as anything in possible_reactions) - if(selected_reaction.is_cold_recipe) - if(competitor.required_temp <= selected_reaction.required_temp) - selected_reaction = competitor - else - if(competitor.required_temp >= selected_reaction.required_temp) - selected_reaction = competitor - return selected_reaction - /// Updates [/datum/reagents/var/total_volume] /datum/reagents/proc/update_total() var/list/cached_reagents = reagent_list . = 0 // This is a relatively hot proc. var/total_ph = 0 // I know I know, I'm sorry for(var/datum/reagent/reagent as anything in cached_reagents) - if((reagent.volume < 0.05) && !is_reacting) - del_reagent(reagent.type) - else if(reagent.volume <= CHEMICAL_VOLUME_MINIMUM)//For clarity + if(reagent.volume < CHEMICAL_QUANTISATION_LEVEL)//For clarity del_reagent(reagent.type) else . += reagent.volume @@ -1378,56 +1453,73 @@ return A.expose_reagents(reagents, src, methods, volume_modifier, show_message) -/// Same as [/datum/reagents/proc/expose] but only for one reagent -/datum/reagents/proc/expose_single(datum/reagent/R, atom/A, methods = TOUCH, volume_modifier = 1, show_message = TRUE) - if(isnull(A)) - return null - - if(ispath(R)) - R = get_reagent(R) - if(isnull(R)) - return null - - // Yes, we need the parentheses. - return A.expose_reagents(list((R) = R.volume * volume_modifier), src, methods, volume_modifier, show_message) - /// Is this holder full or not /datum/reagents/proc/holder_full() return total_volume >= maximum_volume -/// Get the amount of this reagent -/datum/reagents/proc/get_reagent_amount(reagent, include_subtypes = FALSE) +/** + * Get the amount of this reagent or the sum of all its subtypes if specified + * Arguments + * * [reagent][datum/reagent] - the typepath of the reagent to look for + * * include_subtypes - if TRUE returns the sum of volumes of all subtypes of the above param reagent + */ +/datum/reagents/proc/get_reagent_amount(datum/reagent/reagent, include_subtypes = FALSE) + if(!ispath(reagent)) + stack_trace("invalid path passed to get_reagent_amount [reagent]") + return 0 + var/list/cached_reagents = reagent_list var/total_amount = 0 for(var/datum/reagent/cached_reagent as anything in cached_reagents) if((!include_subtypes && cached_reagent.type == reagent) || (include_subtypes && ispath(cached_reagent.type, reagent))) - total_amount += round(cached_reagent.volume, CHEMICAL_QUANTISATION_LEVEL) + total_amount += FLOOR(cached_reagent.volume, CHEMICAL_QUANTISATION_LEVEL) return total_amount +/** + * Gets the sum of volumes of all reagent type paths present in the list + * Arguments + * * [reagents][list] - list of reagent typepaths + */ /datum/reagents/proc/get_multiple_reagent_amounts(list/reagents) var/list/cached_reagents = reagent_list var/total_amount = 0 for(var/datum/reagent/cached_reagent as anything in cached_reagents) if(cached_reagent.type in reagents) - total_amount += round(cached_reagent.volume, CHEMICAL_QUANTISATION_LEVEL) + total_amount += FLOOR(cached_reagent.volume, CHEMICAL_QUANTISATION_LEVEL) return total_amount -/// Get the purity of this reagent -/datum/reagents/proc/get_reagent_purity(reagent) +/** + * Get the purity of this reagent + * Arguments + * * [reagent][datum/reagent] - the typepath of the specific reagent to get purity of + */ +/datum/reagents/proc/get_reagent_purity(datum/reagent/reagent) + if(!ispath(reagent)) + stack_trace("invalid reagent typepath passed to get_reagent_purity [reagent]") + return 0 + var/list/cached_reagents = reagent_list for(var/datum/reagent/cached_reagent as anything in cached_reagents) if(cached_reagent.type == reagent) return round(cached_reagent.purity, 0.01) return 0 -/// Directly set the purity of all contained reagents to a new value +/** + * Directly set the purity of all contained reagents to a new value + * Arguments + * * new_purity - the new purity value + */ /datum/reagents/proc/set_all_reagents_purity(new_purity = 0) var/list/cached_reagents = reagent_list for(var/datum/reagent/cached_reagent as anything in cached_reagents) cached_reagent.purity = max(0, new_purity) -/// Get the average purity of all reagents (or all subtypes of provided typepath) -/datum/reagents/proc/get_average_purity(parent_type = null) +/** + * Get the average purity of all reagents (or all subtypes of provided typepath) + * Arguments + * * [parent_type][datum/reagent] - the typepath of specific reagents to look for + */ +/datum/reagents/proc/get_average_purity(datum/reagent/parent_type = null) var/total_amount var/weighted_purity var/list/cached_reagents = reagent_list @@ -1438,42 +1530,11 @@ weighted_purity += reagent.volume * reagent.purity return weighted_purity / total_amount -/// Get the average nutriment_factor of all consumable reagents -/datum/reagents/proc/get_average_nutriment_factor() - var/consumable_volume - var/weighted_nutriment_factor - var/list/cached_reagents = reagent_list - for(var/datum/reagent/reagent as anything in cached_reagents) - if(istype(reagent, /datum/reagent/consumable)) - var/datum/reagent/consumable/consumable_reagent = reagent - consumable_volume += consumable_reagent.volume - weighted_nutriment_factor += consumable_reagent.volume * consumable_reagent.nutriment_factor - return weighted_nutriment_factor / consumable_volume - -/// Get a comma separated string of every reagent name in this holder. UNUSED -/datum/reagents/proc/get_reagent_names() - var/list/names = list() - var/list/cached_reagents = reagent_list - for(var/datum/reagent/reagent as anything in cached_reagents) - names += reagent.name - - return jointext(names, ",") - -/// helper function to preserve data across reactions (needed for xenoarch) -/datum/reagents/proc/get_data(reagent_id) - var/list/cached_reagents = reagent_list - for(var/datum/reagent/reagent as anything in cached_reagents) - if(reagent.type == reagent_id) - return reagent.data - -/// helper function to preserve data across reactions (needed for xenoarch) -/datum/reagents/proc/set_data(reagent_id, new_data) - var/list/cached_reagents = reagent_list - for(var/datum/reagent/reagent as anything in cached_reagents) - if(reagent.type == reagent_id) - reagent.data = new_data - -/// Shallow copies (deep copy of viruses) data from the provided reagent into our copy of that reagent +/** + * Shallow copies (deep copy of viruses) data from the provided reagent into our copy of that reagent + * Arguments + * [current_reagent][datum/reagent] - the reagent(not typepath) to copy data from + */ /datum/reagents/proc/copy_data(datum/reagent/current_reagent) if(!current_reagent || !current_reagent.data) return null @@ -1495,8 +1556,12 @@ return trans_data -/// Get a reference to the reagent if it exists -/datum/reagents/proc/get_reagent(type) +/** + * Get a reference to the reagent if it exists + * Arguments + * * [type][datum/reagent] - the typepath of the reagent to look up + */ +/datum/reagents/proc/get_reagent(datum/reagent/type) var/list/cached_reagents = reagent_list . = locate(type) in cached_reagents @@ -1562,8 +1627,14 @@ return // no div/0 please set_temperature(clamp(chem_temp + (delta_energy / heat_capacity), min_temp, max_temp)) -/// Applies heat to this holder -/datum/reagents/proc/expose_temperature(temperature, coeff=0.02) +/** + * Applies heat to this holder + * Arguments + * + * * temperature - the temperature we to heat/cool by + * * coeff - multiplier to be applied on temp diff between param temp and current temp + */ +/datum/reagents/proc/expose_temperature(temperature, coeff = 0.02) if(istype(my_atom,/obj/item/reagent_containers)) var/obj/item/reagent_containers/RCs = my_atom if(RCs.reagent_flags & NO_REACT) //stasis holders IE cryobeaker @@ -1603,21 +1674,6 @@ for(var/datum/reagent/reagent as anything in reagent_list) reagent.ph = clamp(reagent.ph + value, lower_limit, upper_limit) -/* -* Adjusts the base pH of all of the listed types -* -* - moves it towards acidic -* + moves it towards basic -* Arguments: -* * input_reagents_list - list of reagent objects to adjust -* * value - How much to adjust the base pH by -*/ -/datum/reagents/proc/adjust_specific_reagent_list_ph(list/input_reagents_list, value, lower_limit = 0, upper_limit = 14) - for(var/datum/reagent/reagent as anything in input_reagents_list) - if(!reagent) //We can call this with missing reagents. - continue - reagent.ph = clamp(reagent.ph + value, lower_limit, upper_limit) - /* * Adjusts the base pH of a specific type * @@ -1649,16 +1705,11 @@ for(var/reagent_type in external_list) var/list/qualities = external_list[reagent_type] - data += "[reagent_type] ([round(qualities[REAGENT_TRANSFER_AMOUNT], 0.1)]u, [qualities[REAGENT_PURITY]] purity)" + data += "[reagent_type] ([FLOOR(qualities[REAGENT_TRANSFER_AMOUNT], CHEMICAL_QUANTISATION_LEVEL)]u, [qualities[REAGENT_PURITY]] purity)" return english_list(data) -/** - * Outputs a log-friendly list of reagents based on the internal reagent_list. - * - * Arguments: - * * external_list - Assoc list of (reagent_type) = list(REAGENT_TRANSFER_AMOUNT = amounts, REAGENT_PURITY = purity) - */ +/// Outputs a log-friendly list of reagents based on the internal reagent_list. /datum/reagents/proc/get_reagent_log_string() if(!length(reagent_list)) return "no reagents" @@ -1666,7 +1717,7 @@ var/list/data = list() for(var/datum/reagent/reagent as anything in reagent_list) - data += "[reagent.type] ([round(reagent.volume, 0.1)]u, [reagent.purity] purity)" + data += "[reagent.type] ([FLOOR(reagent.volume, CHEMICAL_QUANTISATION_LEVEL)]u, [reagent.purity] purity)" return english_list(data) @@ -2017,7 +2068,7 @@ ui_reaction_id = text2path(params["id"]) return TRUE if("search_reagents") - var/input_reagent = tgui_input_list(usr, "Select reagent", "Reagent", GLOB.chemical_name_list) + var/input_reagent = tgui_input_list(usr, "Select reagent", "Reagent", GLOB.name2reagent) input_reagent = get_reagent_type_from_product_string(input_reagent) //from string to type var/datum/reagent/reagent = find_reagent_object_from_type(input_reagent) if(!reagent) @@ -2135,13 +2186,5 @@ reagents = new /datum/reagents(max_vol, flags) reagents.my_atom = src -/atom/movable/chem_holder - name = "This atom exists to hold chems. If you can see this, make an issue report" - desc = "God this is stupid" - #undef REAGENT_TRANSFER_AMOUNT #undef REAGENT_PURITY - -#undef REAGENTS_UI_MODE_LOOKUP -#undef REAGENTS_UI_MODE_REAGENT -#undef REAGENTS_UI_MODE_RECIPE diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 46ac1eda360..f62cf8a86be 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -1,21 +1,3 @@ -GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) - -/proc/build_name2reagent() - . = list() - for (var/t in subtypesof(/datum/reagent)) - var/datum/reagent/R = t - if (length(initial(R.name))) - .[ckey(initial(R.name))] = t - -GLOBAL_LIST_INIT(blacklisted_metalgen_types, typecacheof(list( - /turf/closed/indestructible, //indestructible turfs should be indestructible, metalgen transmutation to plasma allows them to be destroyed - /turf/open/indestructible -))) - -//Various reagents -//Toxin & acid reagents -//Hydroponics stuff - /// A single reagent /datum/reagent /// datums don't have names by default @@ -60,8 +42,6 @@ GLOBAL_LIST_INIT(blacklisted_metalgen_types, typecacheof(list( var/reagent_weight = 1 ///is it currently metabolizing var/metabolizing = FALSE - /// is it bad for you? Currently only used for borghypo. C2s and Toxins have it TRUE by default. - var/harmful = FALSE /// Are we from a material? We might wanna know that for special stuff. Like metalgen. Is replaced with a ref of the material on New() var/datum/material/material ///A list of causes why this chem should skip being removed, if the length is 0 it will be removed from holder naturally, if this is >0 it will not be removed from the holder. @@ -119,7 +99,8 @@ GLOBAL_LIST_INIT(blacklisted_metalgen_types, typecacheof(list( if(!mass) mass = rand(10, 800) -/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references +/// This should only be called by the holder, so it's already handled clearing its references +/datum/reagent/Destroy() . = ..() holder = null @@ -187,7 +168,7 @@ GLOBAL_LIST_INIT(blacklisted_metalgen_types, typecacheof(list( Used to run functions before a reagent is transferred. Returning TRUE will block the transfer attempt. Primarily used in reagents/reaction_agents */ -/datum/reagent/proc/intercept_reagents_transfer(datum/reagents/target) +/datum/reagent/proc/intercept_reagents_transfer(datum/reagents/target, amount) return FALSE ///Called after a reagent is transferred @@ -222,10 +203,6 @@ Primarily used in reagents/reaction_agents if(holder) holder.remove_reagent(type, metabolization_rate * affected_mob.metabolism_efficiency * seconds_per_tick) -/// Called by [/datum/reagents/proc/conditional_update_move] -/datum/reagent/proc/on_move(mob/affected_mob) - return - /// Called after add_reagents creates a new reagent. /datum/reagent/proc/on_new(data) if(data) diff --git a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm index 53558cbd820..b944fdbee80 100644 --- a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm @@ -1,6 +1,5 @@ // Category 2 medicines are medicines that have an ill effect regardless of volume/OD to dissuade doping. Mostly used as emergency chemicals OR to convert damage (and heal a bit in the process). The type is used to prompt borgs that the medicine is harmful. /datum/reagent/medicine/c2 - harmful = TRUE metabolization_rate = 0.5 * REAGENTS_METABOLISM inverse_chem = null //Some of these use inverse chems - we're just defining them all to null here to avoid repetition, eventually this will be moved up to parent creation_purity = REAGENT_STANDARD_PURITY//All sources by default are 0.75 - reactions are primed to resolve to roughly the same with no intervention for these. @@ -203,14 +202,19 @@ inverse_chem = /datum/reagent/inverse/hercuri inverse_chem_val = 0.3 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + process_flags = REAGENT_ORGANIC | REAGENT_SYNTHETIC // SKYRAT EDIT ADDITION - Lets hercuri process in synths /datum/reagent/medicine/c2/hercuri/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() var/need_mob_update - if(affected_mob.getFireLoss() > 50) - need_mob_update = affected_mob.adjustFireLoss(-2 * REM * seconds_per_tick * normalise_creation_purity(), updating_health = FALSE, required_bodytype = affected_bodytype) - else - need_mob_update = affected_mob.adjustFireLoss(-1.25 * REM * seconds_per_tick * normalise_creation_purity(), updating_health = FALSE, required_bodytype = affected_bodytype) + // SKYRAT EDIT CHANGE BEGIN -- Adds check for owner_flags; indented the getFireLoss check and everything under it, so synths can get cooled down + var/owner_flags = affected_mob.dna.species.reagent_flags + if (owner_flags & PROCESS_ORGANIC) + if(affected_mob.getFireLoss() > 50) + need_mob_update = affected_mob.adjustFireLoss(-2 * REM * seconds_per_tick * normalise_creation_purity(), updating_health = FALSE, required_bodytype = affected_bodytype) + else + need_mob_update = affected_mob.adjustFireLoss(-1.25 * REM * seconds_per_tick * normalise_creation_purity(), updating_health = FALSE, required_bodytype = affected_bodytype) + // SKYRAT EDIT CHANGE END affected_mob.adjust_bodytemperature(rand(-25,-5) * TEMPERATURE_DAMAGE_COEFFICIENT * REM * seconds_per_tick, 50) if(ishuman(affected_mob)) var/mob/living/carbon/human/humi = affected_mob diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index e64716296b0..af75cc46db2 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -480,6 +480,8 @@ /datum/reagent/consumable/salt/expose_mob(mob/living/exposed_mob, methods, reac_volume) . = ..() + if(!iscarbon(exposed_mob)) + return var/mob/living/carbon/carbies = exposed_mob if(!(methods & (PATCH|TOUCH|VAPOR))) return @@ -654,6 +656,8 @@ /datum/reagent/consumable/flour/expose_mob(mob/living/exposed_mob, methods, reac_volume) . = ..() + if(!iscarbon(exposed_mob)) + return var/mob/living/carbon/carbies = exposed_mob if(!(methods & (PATCH|TOUCH|VAPOR))) return @@ -758,6 +762,8 @@ // Starch has similar absorbing properties to flour (Stronger here because it's rarer) /datum/reagent/consumable/corn_starch/expose_mob(mob/living/exposed_mob, methods, reac_volume) . = ..() + if(!iscarbon(exposed_mob)) + return var/mob/living/carbon/carbies = exposed_mob if(!(methods & (PATCH|TOUCH|VAPOR))) return diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index ff1671852c1..a28e47703df 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -928,7 +928,6 @@ color = "#A0E85E" metabolization_rate = 1.25 * REAGENTS_METABOLISM taste_description = "magnets" - harmful = TRUE ph = 0.5 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /// The amount of damage a single unit of this will heal @@ -1371,7 +1370,6 @@ metabolization_rate = 0.4 * REAGENTS_METABOLISM ph = 4.3 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - harmful = TRUE /datum/reagent/medicine/haloperidol/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 5e1d7b849e6..62a6d52c4f1 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -321,6 +321,8 @@ /datum/reagent/water/salt/expose_mob(mob/living/exposed_mob, methods, reac_volume) . = ..() + if(!iscarbon(exposed_mob)) + return var/mob/living/carbon/carbies = exposed_mob if(!(methods & (PATCH|TOUCH|VAPOR))) return @@ -2201,15 +2203,17 @@ /datum/reagent/barbers_aid/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=FALSE) . = ..() - if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_mob) || HAS_TRAIT(exposed_mob, TRAIT_BALD) || HAS_TRAIT(exposed_mob, TRAIT_SHAVED)) + if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_mob) || (HAS_TRAIT(exposed_mob, TRAIT_BALD) && HAS_TRAIT(exposed_mob, TRAIT_SHAVED))) return var/mob/living/carbon/human/exposed_human = exposed_mob - var/datum/sprite_accessory/hair/picked_hair = pick(GLOB.hairstyles_list) - var/datum/sprite_accessory/facial_hair/picked_beard = pick(GLOB.facial_hairstyles_list) - to_chat(exposed_human, span_notice("Hair starts sprouting from your scalp.")) - exposed_human.set_facial_hairstyle(picked_beard, update = FALSE) - exposed_human.set_hairstyle(picked_hair, update = TRUE) + if(!HAS_TRAIT(exposed_human, TRAIT_SHAVED)) + var/datum/sprite_accessory/facial_hair/picked_beard = pick(GLOB.facial_hairstyles_list) + exposed_human.set_facial_hairstyle(picked_beard, update = FALSE) + if(!HAS_TRAIT(exposed_human, TRAIT_BALD)) + var/datum/sprite_accessory/hair/picked_hair = pick(GLOB.hairstyles_list) + exposed_human.set_hairstyle(picked_hair, update = TRUE) + to_chat(exposed_human, span_notice("Hair starts sprouting from your [HAS_TRAIT(exposed_human, TRAIT_BALD) ? "face" : "scalp"].")) /datum/reagent/concentrated_barbers_aid name = "Concentrated Barber's Aid" @@ -2222,13 +2226,15 @@ /datum/reagent/concentrated_barbers_aid/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=FALSE) . = ..() - if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_mob) || HAS_TRAIT(exposed_mob, TRAIT_BALD) || HAS_TRAIT(exposed_mob, TRAIT_SHAVED)) + if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_mob) || (HAS_TRAIT(exposed_mob, TRAIT_BALD) && HAS_TRAIT(exposed_mob, TRAIT_SHAVED))) return var/mob/living/carbon/human/exposed_human = exposed_mob - to_chat(exposed_human, span_notice("Your hair starts growing at an incredible speed!")) - exposed_human.set_facial_hairstyle("Beard (Very Long)", update = FALSE) - exposed_human.set_hairstyle("Very Long Hair", update = TRUE) + if(!HAS_TRAIT(exposed_human, TRAIT_SHAVED)) + exposed_human.set_facial_hairstyle("Beard (Very Long)", update = FALSE) + if(!HAS_TRAIT(exposed_human, TRAIT_BALD)) + exposed_human.set_hairstyle("Very Long Hair", update = TRUE) + to_chat(exposed_human, span_notice("Your[HAS_TRAIT(exposed_human, TRAIT_BALD) ? " facial" : ""] hair starts growing at an incredible speed!")) /datum/reagent/concentrated_barbers_aid/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 7f4acabef6e..390c3d7bfd4 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -7,7 +7,6 @@ color = "#CF3600" // rgb: 207, 54, 0 taste_description = "bitterness" taste_mult = 1.2 - harmful = TRUE chemical_flags = REAGENT_CAN_BE_SYNTHESIZED ///The amount of toxin damage this will cause when metabolized (also used to calculate liver damage) var/toxpwr = 1.5 diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index f03cd4927f8..5bc39b389b3 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -140,7 +140,7 @@ // Where the cast chain starts /datum/action/cooldown/spell/PreActivate(atom/target) - if(SEND_SIGNAL(owner, COMSIG_MOB_ABILITY_STARTED, src) & COMPONENT_BLOCK_ABILITY_START) + if(SEND_SIGNAL(owner, COMSIG_MOB_ABILITY_STARTED, src, target) & COMPONENT_BLOCK_ABILITY_START) return FALSE if(target == owner) target = get_caster_from_target(target) diff --git a/code/modules/spells/spell_types/shapeshift/_shapeshift.dm b/code/modules/spells/spell_types/shapeshift/_shapeshift.dm index 8acd6ca9247..a5e590685c0 100644 --- a/code/modules/spells/spell_types/shapeshift/_shapeshift.dm +++ b/code/modules/spells/spell_types/shapeshift/_shapeshift.dm @@ -159,6 +159,12 @@ spell_requirements &= ~(SPELL_REQUIRES_HUMAN|SPELL_REQUIRES_WIZARD_GARB) ADD_TRAIT(new_shape, TRAIT_DONT_WRITE_MEMORY, SHAPESHIFT_TRAIT) // If you shapeshift into a pet subtype we don't want to update Poly's deathcount or something when you die + // Make sure that if you shapechanged into a bot, the AI can't just turn you off. + var/mob/living/simple_animal/bot/polymorph_bot = new_shape + if (istype(polymorph_bot)) + polymorph_bot.bot_cover_flags |= BOT_COVER_EMAGGED + polymorph_bot.bot_mode_flags &= ~BOT_MODE_REMOTE_ENABLED + return new_shape /// Actually does the un-shapeshift, from the caster. (Caster is a shapeshifted mob.) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 61a23a81a41..56e1493fc74 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -460,10 +460,14 @@ var/hit_percent = (100-blocked)/100 if((!brute && !burn) || hit_percent <= 0) return FALSE - if(!forced && owner && (owner.status_flags & GODMODE)) - return FALSE //godmode - if(!forced && required_bodytype && !(bodytype & required_bodytype)) - return FALSE + if (!forced) + if(!isnull(owner)) + if (owner.status_flags & GODMODE) + return FALSE + if (SEND_SIGNAL(owner, COMSIG_CARBON_LIMB_DAMAGED, src, brute, burn) & COMPONENT_PREVENT_LIMB_DAMAGE) + return FALSE + if(required_bodytype && !(bodytype & required_bodytype)) + return FALSE var/dmg_multi = CONFIG_GET(number/damage_multiplier) * hit_percent brute = round(max(brute * dmg_multi * brute_modifier, 0), DAMAGE_PRECISION) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index e05c2516045..dd3a7ec9eff 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -100,6 +100,7 @@ #include "baseturfs.dm" #include "bespoke_id.dm" #include "binary_insert.dm" +#include "bitrunning.dm" #include "blindness.dm" #include "bloody_footprints.dm" #include "breath.dm" @@ -175,6 +176,7 @@ #include "metabolizing.dm" #include "mindbound_actions.dm" #include "missing_icons.dm" +#include "mob_chains.dm" #include "mob_damage.dm" #include "mob_faction.dm" #include "mob_spawn.dm" diff --git a/code/modules/unit_tests/bitrunning.dm b/code/modules/unit_tests/bitrunning.dm new file mode 100644 index 00000000000..568eeeed8c1 --- /dev/null +++ b/code/modules/unit_tests/bitrunning.dm @@ -0,0 +1,15 @@ +/// Ensures settings on vdoms are correct +/datum/unit_test/bitrunner_vdom_settings + +/datum/unit_test/bitrunner_vdom_settings/Run() + var/obj/structure/closet/crate/secure/bitrunning/decrypted/cache = allocate(/obj/structure/closet/crate/secure/bitrunning/decrypted) + + for(var/path in subtypesof(/datum/lazy_template/virtual_domain)) + var/datum/lazy_template/virtual_domain/vdom = new path + TEST_ASSERT_NOTNULL(vdom.key, "[path] should have a key") + TEST_ASSERT_NOTNULL(vdom.map_name, "[path] should have a map name") + + if(!length(vdom.extra_loot)) + continue + + TEST_ASSERT_EQUAL(cache.spawn_loot(vdom.extra_loot), TRUE, "[path] didn't spawn loot. Extra loot should be an associative list") diff --git a/code/modules/unit_tests/mob_chains.dm b/code/modules/unit_tests/mob_chains.dm new file mode 100644 index 00000000000..2562019958e --- /dev/null +++ b/code/modules/unit_tests/mob_chains.dm @@ -0,0 +1,31 @@ +/// Checks if mobs who are linked together with the mob chain component react as expected +/datum/unit_test/mob_chains + +/datum/unit_test/mob_chains/Run() + var/mob/living/centipede_head = allocate(/mob/living/basic/pet/dog) + var/list/segments = list(centipede_head) + centipede_head.AddComponent(/datum/component/mob_chain) + var/mob/living/centipede_tail = centipede_head + for (var/i in 1 to 2) + var/mob/living/new_segment = allocate(/mob/living/basic/pet/dog) + new_segment.AddComponent(/datum/component/mob_chain, front = centipede_tail) + segments += new_segment + centipede_tail = new_segment + + var/test_damage = 15 + centipede_head.apply_damage(test_damage, BRUTE) + TEST_ASSERT_EQUAL(centipede_head.bruteloss, 0, "Centipede head took damage which should have been passed to its tail.") + TEST_ASSERT_EQUAL(centipede_tail.bruteloss, test_damage, "Centipede tail did not take damage which should have originated from its head.") + + var/expected_damage = 5 + for (var/mob/living/segment as anything in segments) + segment.combat_mode = TRUE + segment.melee_damage_lower = expected_damage + segment.melee_damage_upper = expected_damage + + var/mob/living/victim = allocate(/mob/living/basic/pet/dog) + centipede_head.ClickOn(victim) + TEST_ASSERT_EQUAL(victim.bruteloss, expected_damage * 3, "Centipede failed to do damage with all of its segments.") + + centipede_head.death() + TEST_ASSERT_EQUAL(centipede_tail.stat, DEAD, "Centipede tail failed to die with head.") diff --git a/code/modules/unit_tests/mob_damage.dm b/code/modules/unit_tests/mob_damage.dm index 3d257e0f775..50046141a88 100644 --- a/code/modules/unit_tests/mob_damage.dm +++ b/code/modules/unit_tests/mob_damage.dm @@ -37,6 +37,56 @@ // testing with godmode enabled test_godmode(dummy) +/** + * Test whether the adjust damage procs return the correct values and that the mob's health is the expected value afterwards. + * + * By default this calls apply_damage(amount) followed by verify_damage(amount_after) and returns TRUE if both succeeded. + * amount_after defaults to the mob's current stamina loss but can be overridden as needed. + * + * Arguments: + * * testing_mob - the mob to apply the damage to + * * amount - the amount of damage to apply to the mob + * * expected - what the expected return value of the damage proc is + * * amount_after - in case you want to specify what the damage amount on the mob should be afterwards + * * included_types - Bitflag of damage types to apply + * * biotypes - the biotypes of damage to apply + * * bodytypes - the bodytypes of damage to apply + * * forced - whether or not this is forced damage + */ +/datum/unit_test/mob_damage/proc/test_apply_damage(mob/living/testing_mob, amount, expected = -amount, amount_after, included_types, biotypes, bodytypes, forced) + if(isnull(amount_after)) + amount_after = testing_mob.getStaminaLoss() - expected // stamina loss applies to both carbon and basic mobs the same way, so that's why we're using it here + if(!apply_damage(testing_mob, amount, expected, included_types, biotypes, bodytypes, forced)) + return FALSE + if(!verify_damage(testing_mob, amount_after, included_types)) + return FALSE + return TRUE + +/** + * Test whether the set damage procs return the correct values and that the mob's health is the expected value afterwards. + * + * By default this calls set_damage(amount) followed by verify_damage(amount_after) and returns TRUE if both succeeded. + * amount_after defaults to the mob's current stamina loss but can be overridden as needed. + * + * Arguments: + * * testing_mob - the mob to apply the damage to + * * amount - the amount of damage to apply to the mob + * * expected - what the expected return value of the damage proc is + * * amount_after - in case you want to specify what the damage amount on the mob should be afterwards + * * included_types - Bitflag of damage types to apply + * * biotypes - the biotypes of damage to apply + * * bodytypes - the bodytypes of damage to apply + * * forced - whether or not this is forced damage + */ +/datum/unit_test/mob_damage/proc/test_set_damage(mob/living/testing_mob, amount, expected, amount_after, included_types, biotypes, bodytypes, forced) + if(isnull(amount_after)) + amount_after = testing_mob.getStaminaLoss() - expected + if(!set_damage(testing_mob, amount, expected, included_types, biotypes, bodytypes, forced)) + return FALSE + if(!verify_damage(testing_mob, amount_after, included_types)) + return FALSE + return TRUE + /** * Check that the mob has a specific amount of damage * @@ -65,6 +115,7 @@ if(included_types & STAMINALOSS) TEST_ASSERT_EQUAL(testing_mob.getStaminaLoss(), amount, \ "[testing_mob] should have [amount] stamina damage, instead they have [testing_mob.getStaminaLoss()]!") + return TRUE /** * Apply a specific amount of damage to the mob using adjustBruteLoss(), adjustToxLoss(), etc. @@ -105,6 +156,7 @@ damage_returned = testing_mob.adjustStaminaLoss(amount, updating_stamina = FALSE, forced = forced, required_biotype = biotypes) TEST_ASSERT_EQUAL(damage_returned, expected, \ "adjustStaminaLoss() should have returned [expected], but returned [damage_returned] instead!") + return TRUE /** * Set a specific amount of damage for the mob using setBruteLoss(), setToxLoss(), etc. @@ -145,40 +197,43 @@ damage_returned = testing_mob.setStaminaLoss(amount, updating_stamina = FALSE, forced = forced, required_biotype = biotypes) TEST_ASSERT_EQUAL(damage_returned, expected, \ "setStaminaLoss() should have returned [expected], but returned [damage_returned] instead!") + return TRUE /// Sanity tests damage and healing using adjustToxLoss, adjustBruteLoss, etc /datum/unit_test/mob_damage/proc/test_sanity_simple(mob/living/carbon/human/consistent/dummy) - // Apply 5 damage and then heal it - apply_damage(dummy, 5) - verify_damage(dummy, 5) + if(!test_apply_damage(dummy, amount = 5)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! damage was not applied correctly") - apply_damage(dummy, -5) - verify_damage(dummy, 0) + if(!test_apply_damage(dummy, amount = -5)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! healing was not applied correctly") // Apply 15 damage and heal 3 - apply_damage(dummy, 15) - verify_damage(dummy, 15) + if(!test_apply_damage(dummy, amount = 15)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! damage was not applied correctly") - apply_damage(dummy, -3) - verify_damage(dummy, 12) + if(!test_apply_damage(dummy, amount = -3)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! underhealing was not applied correctly") // Now overheal by 666. It should heal for 12. - apply_damage(dummy, -666, expected = 12) - verify_damage(dummy, 0) + if(!test_apply_damage(dummy, amount = -666, expected = 12)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! overhealing was not applied correctly") // Now test the damage setter procs // set all types of damage to 5 - set_damage(dummy, 5, expected = -5) - verify_damage(dummy, 5) + if(!test_set_damage(dummy, amount = 5, expected = -5)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! failed to set damage to 5") // now try healing 5 - set_damage(dummy, 0, expected = 5) - verify_damage(dummy, 0) + if(!test_set_damage(dummy, amount = 0, expected = 5)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! failed to set damage to 0") /// Sanity tests damage and healing using the more complex procs like take_overall_damage(), heal_overall_damage(), etc /datum/unit_test/mob_damage/proc/test_sanity_complex(mob/living/carbon/human/consistent/dummy) + // Heal up, so that errors from the previous tests we won't cause this one to fail + dummy.fully_heal(HEAL_DAMAGE) + var/damage_returned // take 5 brute, 2 burn damage_returned = round(dummy.take_bodypart_damage(5, 2, updating_health = FALSE), 1) @@ -195,21 +250,24 @@ TEST_ASSERT_EQUAL(damage_returned, 5, \ "heal_bodypart_damage() should have returned 5, but returned [damage_returned] instead!") - verify_damage(dummy, 1, included_types = BRUTELOSS|FIRELOSS) + if(!verify_damage(dummy, 1, included_types = BRUTELOSS|FIRELOSS)) + TEST_FAIL("heal_bodypart_damage did not apply its healing correctly on the mob!") // heal 1 brute, 1 burn damage_returned = round(dummy.heal_overall_damage(1, 1, updating_health = FALSE), 1) TEST_ASSERT_EQUAL(damage_returned, 2, \ "heal_overall_damage() should have returned 2, but returned [damage_returned] instead!") - verify_damage(dummy, 0, included_types = BRUTELOSS|FIRELOSS) + if(!verify_damage(dummy, 0, included_types = BRUTELOSS|FIRELOSS)) + TEST_FAIL("heal_overall_damage did not apply its healing correctly on the mob!") // take 50 brute, 50 burn damage_returned = round(dummy.take_overall_damage(50, 50, updating_health = FALSE), 1) TEST_ASSERT_EQUAL(damage_returned, -100, \ "take_overall_damage() should have returned -100, but returned [damage_returned] instead!") - verify_damage(dummy, 50, included_types = BRUTELOSS|FIRELOSS) + if(!verify_damage(dummy, 50, included_types = BRUTELOSS|FIRELOSS)) + TEST_FAIL("take_overall_damage did not apply its damage correctly on the mob!") // testing negative damage amount args with the overall damage procs - the sign should be ignored for these procs @@ -229,7 +287,8 @@ TEST_ASSERT_EQUAL(damage_returned, 10, \ "heal_overall_damage() should have returned 10, but returned [damage_returned] instead!") - verify_damage(dummy, 50, included_types = BRUTELOSS|FIRELOSS) + if(!verify_damage(dummy, 50, included_types = BRUTELOSS|FIRELOSS)) + TEST_FAIL("heal_overall_damage did not apply its healingcorrectly on the mob!") // testing overhealing @@ -237,134 +296,150 @@ TEST_ASSERT_EQUAL(damage_returned, 100, \ "heal_overall_damage() should have returned 100, but returned [damage_returned] instead!") - verify_damage(dummy, 0, included_types = BRUTELOSS|FIRELOSS) + if(!verify_damage(dummy, 0, included_types = BRUTELOSS|FIRELOSS)) + TEST_FAIL("heal_overall_damage did not apply its healing correctly on the mob!") /// Tests damage procs with godmode on /datum/unit_test/mob_damage/proc/test_godmode(mob/living/carbon/human/consistent/dummy) + // Heal up, so that errors from the previous tests we won't cause this one to fail + dummy.fully_heal(HEAL_DAMAGE) // flip godmode bit to 1 dummy.status_flags ^= GODMODE // Apply 9 damage and then heal it - apply_damage(dummy, 9, expected = 0) - verify_damage(dummy, 0) + if(!test_apply_damage(dummy, amount = 9, expected = 0)) + TEST_FAIL("ABOVE FAILURE: failed test_godmode! mob took damage despite having godmode enabled.") - apply_damage(dummy, -9, expected = 0) - verify_damage(dummy, 0) + if(!test_apply_damage(dummy, amount = -9, expected = 0)) + TEST_FAIL("ABOVE FAILURE: failed test_godmode! mob healed when they should've been at full health.") // Apply 11 damage and then heal it, this time with forced enabled. The damage should go through regardless of godmode. - apply_damage(dummy, 11, forced = TRUE) - verify_damage(dummy, 11) + if(!test_apply_damage(dummy, amount = 11, forced = TRUE)) + TEST_FAIL("ABOVE FAILURE: failed test_godmode! godmode did not respect forced = TRUE") - apply_damage(dummy, -11, forced = TRUE) - verify_damage(dummy, 0) + if(!test_apply_damage(dummy, amount = -11, forced = TRUE)) + TEST_FAIL("ABOVE FAILURE: failed test_godmode! godmode did not respect forced = TRUE") // flip godmode bit back to 0 dummy.status_flags ^= GODMODE /// Testing biotypes /datum/unit_test/mob_damage/proc/test_biotypes(mob/living/carbon/human/consistent/dummy) + // Heal up, so that errors from the previous tests we won't cause this one to fail + dummy.fully_heal(HEAL_DAMAGE) // Testing biotypes using a plasmaman, who is MOB_MINERAL and MOB_HUMANOID dummy.set_species(/datum/species/plasmaman) // argumentless default: should default to required_biotype = ALL. The damage should be applied in that case. - apply_damage(dummy, 1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS) - verify_damage(dummy, 1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS) + if(!test_apply_damage(dummy, 1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS)) + TEST_FAIL("ABOVE FAILURE: plasmaman did not take damage with biotypes = ALL") // If we specify MOB_ORGANIC, the damage should not get applied because plasmamen lack that biotype. - apply_damage(dummy, 1, expected = 0, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_ORGANIC) - verify_damage(dummy, 1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS) + if(!test_apply_damage(dummy, 1, expected = 0, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_ORGANIC)) + TEST_FAIL("ABOVE FAILURE: plasmaman took damage with biotypes = MOB_ORGANIC") // Now if we specify MOB_MINERAL the damage should get applied. - apply_damage(dummy, 1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_MINERAL) - verify_damage(dummy, 2, included_types = TOXLOSS|CLONELOSS|STAMINALOSS) + if(!test_apply_damage(dummy, 1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_MINERAL)) + TEST_FAIL("ABOVE FAILURE: plasmaman did not take damage with biotypes = MOB_MINERAL") // Transform back to human dummy.set_species(/datum/species/human) // We have 2 damage presently. // Try to heal it; let's specify MOB_MINERAL, which should no longer work because we have changed back to a human. - apply_damage(dummy, -2, expected = 0, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_MINERAL) - verify_damage(dummy, 2, included_types = TOXLOSS|CLONELOSS|STAMINALOSS) + if(!test_apply_damage(dummy, -2, expected = 0, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_MINERAL)) + TEST_FAIL("ABOVE FAILURE: human took damage with biotypes = MOB_MINERAL") // Force heal some of the damage. When forced = TRUE the damage/healing gets applied no matter what. - apply_damage(dummy, -1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_MINERAL, forced = TRUE) - verify_damage(dummy, 1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS) + if(!test_apply_damage(dummy, -1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_MINERAL, forced = TRUE)) + TEST_FAIL("ABOVE FAILURE: human did not get healed when biotypes = MOB_MINERAL and forced = TRUE") // Now heal the rest of it with the correct biotype. Make sure that this works. We should have 0 damage afterwards. - apply_damage(dummy, -1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_ORGANIC) - verify_damage(dummy, 0, included_types = TOXLOSS|CLONELOSS|STAMINALOSS) + if(!test_apply_damage(dummy, -1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_ORGANIC)) + TEST_FAIL("ABOVE FAILURE: human did not get healed with biotypes = MOB_ORGANIC") /// Testing oxyloss with the TRAIT_NOBREATH /datum/unit_test/mob_damage/proc/test_nobreath(mob/living/carbon/human/consistent/dummy) + // Heal up, so that errors from the previous tests we won't cause this one to fail + dummy.fully_heal(HEAL_DAMAGE) + // TRAIT_NOBREATH is supposed to prevent oxyloss damage (but not healing). Let's make sure that's the case. ADD_TRAIT(dummy, TRAIT_NOBREATH, TRAIT_SOURCE_UNIT_TESTS) // force some oxyloss here dummy.setOxyLoss(2, updating_health = FALSE, forced = TRUE) // Try to take more oxyloss damage with TRAIT_NOBREATH. It should not work. - apply_damage(dummy, 2, expected = 0, included_types = OXYLOSS) - verify_damage(dummy, 2, included_types = OXYLOSS) + if(!test_apply_damage(dummy, 2, expected = 0, amount_after = dummy.getOxyLoss(), included_types = OXYLOSS)) + TEST_FAIL("ABOVE FAILURE: failed test_nobreath! mob took oxyloss damage while having TRAIT_NOBREATH") // Make sure we are still be able to heal the oxyloss. This should work. - apply_damage(dummy, -2, included_types = OXYLOSS) - verify_damage(dummy, 0, included_types = OXYLOSS) + if(!test_apply_damage(dummy, -2, amount_after = dummy.getOxyLoss()-2, included_types = OXYLOSS)) + TEST_FAIL("ABOVE FAILURE: failed test_nobreath! mob could not heal oxyloss damage while having TRAIT_NOBREATH") REMOVE_TRAIT(dummy, TRAIT_NOBREATH, TRAIT_SOURCE_UNIT_TESTS) /// Testing toxloss with TRAIT_TOXINLOVER and TRAIT_TOXIMMUNE /datum/unit_test/mob_damage/proc/test_toxintraits(mob/living/carbon/human/consistent/dummy) + // Heal up, so that errors from the previous tests we won't cause this one to fail + dummy.fully_heal(HEAL_DAMAGE) + // TRAIT_TOXINLOVER is supposed to invert toxin damage and healing. Things that would normally cause toxloss now heal it, and vice versa. ADD_TRAIT(dummy, TRAIT_TOXINLOVER, TRAIT_SOURCE_UNIT_TESTS) // force some toxloss here dummy.setToxLoss(2, updating_health = FALSE, forced = TRUE) // Try to take more toxloss damage with TRAIT_TOXINLOVER. It should heal instead. - apply_damage(dummy, 2, expected = 2, included_types = TOXLOSS) - verify_damage(dummy, 0, included_types = TOXLOSS) + if(!test_apply_damage(dummy, 2, expected = 2, amount_after = dummy.getToxLoss()-2, included_types = TOXLOSS)) + TEST_FAIL("ABOVE FAILURE: failed test_toxintraits! mob did not heal from toxin damage with TRAIT_TOXINLOVER") // If we try to heal the toxloss we should take damage instead - apply_damage(dummy, -2, expected = -2, included_types = TOXLOSS) - verify_damage(dummy, 2, included_types = TOXLOSS) + if(!test_apply_damage(dummy, -2, expected = -2, amount_after = dummy.getToxLoss()+2, included_types = TOXLOSS)) + TEST_FAIL("ABOVE FAILURE: failed test_toxintraits! mob did not take damage from toxin healing with TRAIT_TOXINLOVER") // TOXIMMUNE trait should prevent the damage you get from being healed by toxins medicines while having TRAIT_TOXINLOVER ADD_TRAIT(dummy, TRAIT_TOXIMMUNE, TRAIT_SOURCE_UNIT_TESTS) // need to force apply some toxin damage since the TOXIMUNNE trait sets toxloss to 0 upon being added - apply_damage(dummy, 2, included_types = TOXLOSS, forced = TRUE) + dummy.setToxLoss(2, updating_health = FALSE, forced = TRUE) // try to 'heal' again - this time it should just do nothing because we should be immune to any sort of toxin damage - including from inverted healing - apply_damage(dummy, -2, expected = 0, included_types = TOXLOSS) - verify_damage(dummy, 2, included_types = TOXLOSS) + if(!test_apply_damage(dummy, -2, expected = 0, amount_after = dummy.getToxLoss(), included_types = TOXLOSS)) + TEST_FAIL("ABOVE FAILURE: failed test_toxintraits! mob should not have taken any damage or healing with TRAIT_TOXINLOVER + TRAIT_TOXIMMUNE") // ok, let's try taking 'damage'. The inverted damage should still heal mobs with the TOXIMMUNE trait. - apply_damage(dummy, 2, expected = 2, included_types = TOXLOSS) - verify_damage(dummy, 0, included_types = TOXLOSS) + if(!test_apply_damage(dummy, 2, expected = 2, amount_after = dummy.getToxLoss()-2, included_types = TOXLOSS)) + TEST_FAIL("ABOVE FAILURE: failed test_toxintraits! mob did not heal from taking toxin damage with TRAIT_TOXINLOVER + TRAIT_TOXIMMUNE") REMOVE_TRAIT(dummy, TRAIT_TOXINLOVER, TRAIT_SOURCE_UNIT_TESTS) REMOVE_TRAIT(dummy, TRAIT_TOXIMMUNE, TRAIT_SOURCE_UNIT_TESTS) /// Testing cloneloss with TRAIT_NOCLONELOSS /datum/unit_test/mob_damage/proc/test_nocloneloss(mob/living/carbon/human/consistent/dummy) - // TRAIT_NOBREATH is supposed to prevent cloneloss damage and healing. Let's make sure that's the case. + // Heal up, so that errors from the previous tests we won't cause this one to fail + dummy.fully_heal(HEAL_DAMAGE) + + // TRAIT_TRAIT_NOCLONELOSS is supposed to prevent cloneloss damage and healing. Let's make sure that's the case. ADD_TRAIT(dummy, TRAIT_NOCLONELOSS, TRAIT_SOURCE_UNIT_TESTS) // force some cloneloss here dummy.setCloneLoss(2, updating_health = FALSE, forced = TRUE) // Try to take more cloneloss damage with TRAIT_NOCLONELOSS. It should not work. - apply_damage(dummy, 2, expected = 0, included_types = CLONELOSS) - verify_damage(dummy, 2, included_types = CLONELOSS) + if(!test_apply_damage(dummy, 2, expected = 0, amount_after = dummy.getCloneLoss(), included_types = CLONELOSS)) + TEST_FAIL("ABOVE FAILURE: failed test_nocloneloss! mob took cloneloss damage with TRAIT_NOCLONELOSS") // Healing the cloneloss should not work either, unless we force it - apply_damage(dummy, -2, expected = 0, included_types = CLONELOSS) - verify_damage(dummy, 2, included_types = CLONELOSS) + if(!test_apply_damage(dummy, -2, expected = 0, amount_after = dummy.getCloneLoss(), included_types = CLONELOSS)) + TEST_FAIL("ABOVE FAILURE: failed test_nocloneloss! mob healed cloneloss damage with TRAIT_NOCLONELOSS") // so let's force it - apply_damage(dummy, -2, expected = 2, included_types = CLONELOSS, forced = TRUE) - verify_damage(dummy, 0, included_types = CLONELOSS) + if(!test_apply_damage(dummy, -2, expected = 2, amount_after = dummy.getCloneLoss()-2, included_types = CLONELOSS, forced = TRUE)) + TEST_FAIL("ABOVE FAILURE: failed test_nocloneloss! mob could not heal cloneloss damage with forced = TRUE and TRAIT_NOCLONELOSS") REMOVE_TRAIT(dummy, TRAIT_NOCLONELOSS, TRAIT_SOURCE_UNIT_TESTS) /// Testing heal_ordered_damage() /datum/unit_test/mob_damage/proc/test_ordered_healing(mob/living/carbon/human/consistent/dummy) + // Heal up, so that errors from the previous tests we won't cause this one to fail + dummy.fully_heal(HEAL_DAMAGE) var/damage_returned // We apply 20 brute, 20 burn, and 20 toxin damage. 60 damage total @@ -381,12 +456,12 @@ TEST_ASSERT_EQUAL(dummy.getFireLoss(), 10, \ "[src] should have 10 burn damage, but has [dummy.getFireLoss()] instead!") TEST_ASSERT_EQUAL(dummy.getToxLoss(), 20, \ - "[src] should have 2 toxin damage, but has [dummy.getToxLoss()] instead!") + "[src] should have 20 toxin damage, but has [dummy.getToxLoss()] instead!") // Now heal the remaining 30, overhealing by 5. damage_returned = round(dummy.heal_ordered_damage(35, list(BRUTE, BURN, TOX)), 1) TEST_ASSERT_EQUAL(damage_returned, 30, \ - "heal_ordered_damage() should have returned 0, but returned [damage_returned] instead!") + "heal_ordered_damage() should have returned 30, but returned [damage_returned] instead!") // Should have no damage remaining TEST_ASSERT_EQUAL(dummy.getBruteLoss(), 0, \ @@ -439,37 +514,42 @@ if(included_types & STAMINALOSS) TEST_ASSERT_EQUAL(testing_mob.getStaminaLoss(), amount, \ "[testing_mob] should have [amount] stamina damage, instead they have [testing_mob.getStaminaLoss()]!") + return TRUE /datum/unit_test/mob_damage/basic/test_sanity_simple(mob/living/basic/mouse/gray/gusgus) // check to see if basic mob damage works // Simple damage and healing // Take 1 damage, heal for 1 - apply_damage(gusgus, 1) - verify_damage(gusgus, 1) + if(!test_apply_damage(gusgus, amount = 1)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! damage was not applied correctly") - apply_damage(gusgus, -1) - verify_damage(gusgus, 0) + if(!test_apply_damage(gusgus, amount = -1)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! healing was not applied correctly") // Give 2 damage of every time (translates to 10 brute, 2 staminaloss) - apply_damage(gusgus, 2) - verify_damage(gusgus, 2) + if(!test_apply_damage(gusgus, amount = 2)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! damage was not applied correctly") // underhealing: heal 1 damage of every type (translates to 5 brute, 1 staminaloss) - apply_damage(gusgus, -1) - verify_damage(gusgus, 1) + if(!test_apply_damage(gusgus, amount = -1)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! healing was not applied correctly") // overhealing // heal 11 points of toxloss (should take care of all 5 brute damage remaining) - apply_damage(gusgus, -11, expected = 5, included_types = TOXLOSS) + if(!apply_damage(gusgus, -11, expected = 5, included_types = TOXLOSS)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! toxloss was not applied correctly") // heal the remaining point of staminaloss - apply_damage(gusgus, -11, expected = 1, included_types = STAMINALOSS) + if(!apply_damage(gusgus, -11, expected = 1, included_types = STAMINALOSS)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! failed to heal staminaloss correctly") // heal 35 points of each type, we should already be at full health so nothing should happen - apply_damage(gusgus, -35, expected = 0) - verify_damage(gusgus, 0) + if(!test_apply_damage(gusgus, amount = -35, expected = 0)) + TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! overhealing was not applied correctly") /datum/unit_test/mob_damage/basic/test_sanity_complex(mob/living/basic/mouse/gray/gusgus) + // Heal up, so that errors from the previous tests we won't cause this one to fail + gusgus.fully_heal(HEAL_DAMAGE) var/damage_returned // overall damage procs @@ -508,7 +588,8 @@ TEST_ASSERT_EQUAL(damage_returned, -6, \ "take_overall_damage() should have returned -6, but returned [damage_returned] instead!") - verify_damage(gusgus, 1, expected = 6, included_types = BRUTELOSS) + if(!verify_damage(gusgus, 1, expected = 6, included_types = BRUTELOSS)) + TEST_FAIL("take_overall_damage did not apply its damage correctly on the mouse!") // testing negative args with the overall damage procs @@ -528,7 +609,8 @@ TEST_ASSERT_EQUAL(damage_returned, 2, \ "heal_overall_damage() should have returned 2, but returned [damage_returned] instead!") - verify_damage(gusgus, 1, expected = 6, included_types = BRUTELOSS) + if(!verify_damage(gusgus, 1, expected = 6, included_types = BRUTELOSS)) + TEST_FAIL("heal_overall_damage did not apply its healing correctly on the mouse!") // testing overhealing @@ -536,4 +618,5 @@ TEST_ASSERT_EQUAL(damage_returned, 6, \ "heal_overall_damage() should have returned 6, but returned [damage_returned] instead!") - verify_damage(gusgus, 0, included_types = BRUTELOSS) + if(!verify_damage(gusgus, 0, included_types = BRUTELOSS)) + TEST_FAIL("heal_overall_damage did not apply its healing correctly on the mouse!") diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm index 312405d7382..92416001b79 100644 --- a/code/modules/unit_tests/simple_animal_freeze.dm +++ b/code/modules/unit_tests/simple_animal_freeze.dm @@ -64,7 +64,6 @@ /mob/living/simple_animal/hostile/asteroid/gutlunch/grublunch, /mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck, /mob/living/simple_animal/hostile/asteroid/gutlunch/guthen, - /mob/living/simple_animal/hostile/asteroid/ice_demon, /mob/living/simple_animal/hostile/asteroid/polarbear, /mob/living/simple_animal/hostile/asteroid/polarbear/lesser, /mob/living/simple_animal/hostile/asteroid/wolf, @@ -103,13 +102,6 @@ /mob/living/simple_animal/hostile/guardian/ranged, /mob/living/simple_animal/hostile/guardian/standard, /mob/living/simple_animal/hostile/guardian/support, - /mob/living/simple_animal/hostile/heretic_summon, - /mob/living/simple_animal/hostile/heretic_summon/armsy, - /mob/living/simple_animal/hostile/heretic_summon/armsy/prime, - /mob/living/simple_animal/hostile/heretic_summon/ash_spirit, - /mob/living/simple_animal/hostile/heretic_summon/maid_in_the_mirror, - /mob/living/simple_animal/hostile/heretic_summon/rust_spirit, - /mob/living/simple_animal/hostile/heretic_summon/stalker, /mob/living/simple_animal/hostile/illusion, /mob/living/simple_animal/hostile/illusion/escape, /mob/living/simple_animal/hostile/illusion/mirage, @@ -164,7 +156,6 @@ /mob/living/simple_animal/hostile/pirate/ranged, /mob/living/simple_animal/hostile/pirate/ranged/space, /mob/living/simple_animal/hostile/retaliate, - /mob/living/simple_animal/hostile/retaliate/goat, /mob/living/simple_animal/hostile/retaliate/goose, /mob/living/simple_animal/hostile/retaliate/goose/vomit, /mob/living/simple_animal/hostile/retaliate/nanotrasenpeace, @@ -206,9 +197,6 @@ /mob/living/simple_animal/slime/pet, /mob/living/simple_animal/slime/random, /mob/living/simple_animal/slime/transformed_slime, - /mob/living/simple_animal/sloth, - /mob/living/simple_animal/sloth/citrus, - /mob/living/simple_animal/sloth/paperwork, /mob/living/simple_animal/soulscythe, //MODULAR SKYRAT ENTRIES diff --git a/code/modules/uplink/uplink_items/ammunition.dm b/code/modules/uplink/uplink_items/ammunition.dm index 292f87ffe13..e8872781252 100644 --- a/code/modules/uplink/uplink_items/ammunition.dm +++ b/code/modules/uplink/uplink_items/ammunition.dm @@ -18,7 +18,6 @@ /datum/uplink_item/ammo/pistol name = "9mm Handgun Magazine" desc = "An additional 8-round 9mm magazine, compatible with the Makarov pistol." - progression_minimum = 10 MINUTES item = /obj/item/ammo_box/magazine/m9mm cost = 1 purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) @@ -28,7 +27,6 @@ name = "9mm Armour Piercing Magazine" desc = "An additional 8-round 9mm magazine, compatible with the Makarov pistol. \ These rounds are less effective at injuring the target but penetrate protective gear." - progression_minimum = 30 MINUTES item = /obj/item/ammo_box/magazine/m9mm/ap cost = 2 purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) @@ -37,7 +35,6 @@ name = "9mm Hollow Point Magazine" desc = "An additional 8-round 9mm magazine, compatible with the Makarov pistol. \ These rounds are more damaging but ineffective against armour." - progression_minimum = 30 MINUTES item = /obj/item/ammo_box/magazine/m9mm/hp cost = 3 purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) @@ -46,7 +43,6 @@ name = "9mm Incendiary Magazine" desc = "An additional 8-round 9mm magazine, compatible with the Makarov pistol. \ Loaded with incendiary rounds which inflict little damage, but ignite the target." - progression_minimum = 30 MINUTES item = /obj/item/ammo_box/magazine/m9mm/fire cost = 2 purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) @@ -55,7 +51,6 @@ name = ".357 Speed Loader" desc = "A speed loader that contains seven additional .357 Magnum rounds; usable with the Syndicate revolver. \ For when you really need a lot of things dead." - progression_minimum = 30 MINUTES item = /obj/item/ammo_box/a357 cost = 4 purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) //nukies get their own version diff --git a/code/modules/uplink/uplink_items/badass.dm b/code/modules/uplink/uplink_items/badass.dm index 93087be9dd0..67676edcd7d 100644 --- a/code/modules/uplink/uplink_items/badass.dm +++ b/code/modules/uplink/uplink_items/badass.dm @@ -48,7 +48,6 @@ manufactured to pack a little bit more of a punch if your client needs some convincing." item = /obj/item/storage/secure/briefcase/syndie cost = 3 - progression_minimum = 5 MINUTES restricted = TRUE illegal_tech = FALSE diff --git a/code/modules/uplink/uplink_items/bundle.dm b/code/modules/uplink/uplink_items/bundle.dm index 912c28e2bcb..a930784fe14 100644 --- a/code/modules/uplink/uplink_items/bundle.dm +++ b/code/modules/uplink/uplink_items/bundle.dm @@ -58,7 +58,6 @@ These items are collectively worth more than 25 telecrystals, but you do not know which specialization \ you will receive. May contain discontinued and/or exotic items. \ The Syndicate will only provide one Syndi-Kit per agent." - progression_minimum = 30 MINUTES item = /obj/item/storage/box/syndicate/bundle_a cost = 20 stock_key = UPLINK_SHARED_STOCK_KITS @@ -70,7 +69,6 @@ In Syndi-kit Special, you will receive items used by famous syndicate agents of the past. \ Collectively worth more than 25 telecrystals, the syndicate loves a good throwback. \ The Syndicate will only provide one Syndi-Kit per agent." - progression_minimum = 30 MINUTES item = /obj/item/storage/box/syndicate/bundle_b cost = 20 stock_key = UPLINK_SHARED_STOCK_KITS @@ -149,7 +147,6 @@ The Syndicate will only provide one surplus item per agent." cost = 20 item = /obj/structure/closet/crate/syndicrate - progression_minimum = 30 MINUTES stock_key = UPLINK_SHARED_STOCK_SURPLUS crate_tc_value = 80 crate_type = /obj/structure/closet/crate/syndicrate @@ -173,6 +170,5 @@ The Syndicate will only provide one surplus item per agent." cost = 20 item = /obj/item/syndicrate_key - progression_minimum = 30 MINUTES purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) stock_key = UPLINK_SHARED_STOCK_SURPLUS diff --git a/code/modules/uplink/uplink_items/dangerous.dm b/code/modules/uplink/uplink_items/dangerous.dm index 0cdcf3a7bb7..f1788c6e1de 100644 --- a/code/modules/uplink/uplink_items/dangerous.dm +++ b/code/modules/uplink/uplink_items/dangerous.dm @@ -19,7 +19,6 @@ name = "Makarov Pistol" desc = "A small, easily concealable handgun that uses 9mm auto rounds in 8-round magazines and is compatible \ with suppressors." - progression_minimum = 10 MINUTES item = /obj/item/gun/ballistic/automatic/pistol cost = 7 purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) @@ -28,7 +27,6 @@ name = "Box of Throwing Weapons" desc = "A box of shurikens and reinforced bolas from ancient Earth martial arts. They are highly effective \ throwing weapons. The bolas can knock a target down and the shurikens will embed into limbs." - progression_minimum = 10 MINUTES item = /obj/item/storage/box/syndie_kit/throwing_weapons cost = 3 illegal_tech = FALSE @@ -95,7 +93,6 @@ name = "Syndicate Revolver" desc = "Waffle Co.'s modernized Syndicate revolver. Fires 7 brutal rounds of .357 Magnum." item = /obj/item/gun/ballistic/revolver/syndicate - progression_minimum = 30 MINUTES cost = 13 surplus = 50 purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) //nukies get their own version diff --git a/code/modules/uplink/uplink_items/explosive.dm b/code/modules/uplink/uplink_items/explosive.dm index 32a5ad49d57..59a44325673 100644 --- a/code/modules/uplink/uplink_items/explosive.dm +++ b/code/modules/uplink/uplink_items/explosive.dm @@ -16,7 +16,6 @@ desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls, sabotage equipment, or connect \ an assembly to it in order to alter the way it detonates. It can be attached to almost all objects and has a modifiable timer with a \ minimum setting of 10 seconds." - progression_minimum = 5 MINUTES item = /obj/item/grenade/c4 cost = 1 @@ -24,7 +23,6 @@ name = "Bag of C-4 explosives" desc = "Because sometimes quantity is quality. Contains 10 C-4 plastic explosives." item = /obj/item/storage/backpack/duffelbag/syndie/c4 - progression_minimum = 10 MINUTES cost = 8 //20% discount! cant_discount = TRUE @@ -43,7 +41,6 @@ desc = "When inserted into a tablet, this cartridge gives you four opportunities to \ detonate tablets of crewmembers who have their message feature enabled. \ The concussive effect from the explosion will knock the recipient out for a short period, and deafen them for longer." - progression_minimum = 20 MINUTES item = /obj/item/computer_disk/virus/detomatix cost = 6 restricted = TRUE @@ -64,7 +61,7 @@ name = "Pizza Bomb" desc = "A pizza box with a bomb cunningly attached to the lid. The timer needs to be set by opening the box; afterwards, \ opening the box again will trigger the detonation after the timer has elapsed. Comes with free pizza, for you or your target!" - progression_minimum = 30 MINUTES + progression_minimum = 15 MINUTES item = /obj/item/pizzabox/bomb cost = 6 surplus = 8 @@ -82,7 +79,6 @@ /datum/uplink_item/explosives/syndicate_bomb/emp name = "Syndicate EMP Bomb" desc = "A variation of the syndicate bomb designed to produce a large EMP effect." - progression_minimum = 30 MINUTES item = /obj/item/sbeacondrop/emp cost = 7 diff --git a/code/modules/uplink/uplink_items/job.dm b/code/modules/uplink/uplink_items/job.dm index e585b07bb5f..dca19777471 100644 --- a/code/modules/uplink/uplink_items/job.dm +++ b/code/modules/uplink/uplink_items/job.dm @@ -150,7 +150,6 @@ name = "Magillitis Serum Autoinjector" desc = "A single-use autoinjector which contains an experimental serum that causes rapid muscular growth in Hominidae. \ Side-affects may include hypertrichosis, violent outbursts, and an unending affinity for bananas." - progression_minimum = 10 MINUTES item = /obj/item/reagent_containers/hypospray/medipen/magillitis cost = 15 restricted_roles = list(JOB_GENETICIST, JOB_RESEARCH_DIRECTOR) @@ -159,7 +158,6 @@ name = "Box of Gorilla Cubes" desc = "A box with three Waffle Co. brand gorilla cubes. Eat big to get big. \ Caution: Product may rehydrate when exposed to water." - progression_minimum = 15 MINUTES item = /obj/item/storage/box/gorillacubes cost = 6 restricted_roles = list(JOB_GENETICIST, JOB_RESEARCH_DIRECTOR) @@ -209,7 +207,8 @@ name = "Kinetic Accelerator Pressure Mod" desc = "A modification kit which allows Kinetic Accelerators to do greatly increased damage while indoors. \ Occupies 35% mod capacity." - progression_minimum = 30 MINUTES + // While less deadly than a revolver it does have infinite ammo + progression_minimum = 15 MINUTES item = /obj/item/borg/upgrade/modkit/indoors cost = 5 //you need two for full damage, so total of 10 for maximum damage limited_stock = 2 //you can't use more than two! @@ -220,7 +219,6 @@ name = "Guide to Advanced Mimery Series" desc = "The classical two part series on how to further hone your mime skills. Upon studying the series, the user should be able to make 3x1 invisible walls, and shoot bullets out of their fingers. \ Obviously only works for Mimes." - progression_minimum = 20 MINUTES cost = 12 item = /obj/item/storage/box/syndie_kit/mimery restricted_roles = list(JOB_MIME) @@ -238,7 +236,7 @@ /datum/uplink_item/role_restricted/chemical_gun name = "Reagent Dartgun" desc = "A heavily modified syringe gun which is capable of synthesizing its own chemical darts using input reagents. Can hold 90u of reagents." - progression_minimum = 20 MINUTES + progression_minimum = 15 MINUTES item = /obj/item/gun/chem cost = 12 restricted_roles = list(JOB_CHEMIST, JOB_CHIEF_MEDICAL_OFFICER, JOB_BOTANIST) @@ -246,7 +244,6 @@ /datum/uplink_item/role_restricted/pie_cannon name = "Banana Cream Pie Cannon" desc = "A special pie cannon for a special clown, this gadget can hold up to 20 pies and automatically fabricates one every two seconds!" - progression_minimum = 10 MINUTES cost = 10 item = /obj/item/pneumatic_cannon/pie/selfcharge restricted_roles = list(JOB_CLOWN) @@ -276,9 +273,6 @@ someone saves them or they manage to crawl out. Be sure not to ram into any walls or vending machines, as the springloaded seats \ are very sensitive. Now with our included lube defense mechanism which will protect you against any angry shitcurity! \ Premium features can be unlocked with a cryptographic sequencer!" - // It has a low progression cost because it's the sort of item that only works well early in the round - // Plus, it costs all your TC, and it's not an instant kill tool. - progression_minimum = 5 MINUTES item = /obj/vehicle/sealed/car/clowncar cost = 20 restricted_roles = list(JOB_CLOWN) @@ -290,9 +284,6 @@ His Grace grants gradual regeneration and complete stun immunity to His wielder, but be wary: if He gets too hungry, He will become impossible to drop and eventually kill you if not fed. \ However, if left alone for long enough, He will fall back to slumber. \ To activate His Grace, simply unlatch Him." - // It has a low progression cost because it's the sort of item that only works well early in the round - // Plus, it costs all your TC and will lock your uplink. - progression_minimum = 5 MINUTES lock_other_purchases = TRUE cant_discount = TRUE item = /obj/item/his_grace diff --git a/code/modules/uplink/uplink_items/stealthy.dm b/code/modules/uplink/uplink_items/stealthy.dm index 491f8e8e99d..2f205a9d0bd 100644 --- a/code/modules/uplink/uplink_items/stealthy.dm +++ b/code/modules/uplink/uplink_items/stealthy.dm @@ -65,7 +65,6 @@ desc = "This box contains a guide on how to craft masterful works of origami, allowing you to transform normal pieces of paper into \ perfectly aerodynamic (and potentially lethal) paper airplanes." item = /obj/item/storage/box/syndie_kit/origami_bundle - progression_minimum = 10 MINUTES cost = 4 surplus = 0 purchasable_from = ~UPLINK_NUKE_OPS //clown ops intentionally left in, because that seems like some s-tier shenanigans. diff --git a/config/blanks.json b/config/blanks.json index 299fa67a594..f3b38d67bdb 100644 --- a/config/blanks.json +++ b/config/blanks.json @@ -545,7 +545,7 @@ "
", "
By writing and signing this form, you consent to the processing of your personal data by Nanotrasen Corporation.

", "
", - "

Name of offical to take action:

", + "

Name of official to take action:

", "

[___________________________________]

", "

Official Decision:

", "

[___________________________________]

", diff --git a/config/config.txt b/config/config.txt index 3b3e0d0746e..3208cf84e92 100644 --- a/config/config.txt +++ b/config/config.txt @@ -136,11 +136,14 @@ VOTE_PERIOD 600 ## players' votes default to "No vote" (otherwise, default to "No change") # DEFAULT_NO_VOTE -## disable abandon mob -NORESPAWN - -## Respawn delay (deciseconds), which doesn't allow to return to lobby (default 10 minutes) -#RESPAWN_DELAY 6000 +## Determines if players can respawn after death +## 0 = Cannot respawn (default) +## 1 = Can respawn +## 2 = Can respawn if choosing a different character +ALLOW_RESPAWN 0 + +## Respawn delay (deciseconds), which doesn't allow to return to lobby +RESPAWN_DELAY 0 ## set a hosted by name for unix platforms HOSTEDBY Yournamehere diff --git a/html/changelogs/archive/2023-10.yml b/html/changelogs/archive/2023-10.yml index 4acbbb235a8..28708d8221c 100644 --- a/html/changelogs/archive/2023-10.yml +++ b/html/changelogs/archive/2023-10.yml @@ -252,3 +252,119 @@ - bugfix: fixes gender shaping and height offsets on underwear - bugfix: female gender shaping now works with digi jumpsuits - bugfix: fixed rainbow jumpsuit digi sprite +2023-10-07: + GoldenAlpharex: + - bugfix: The round end report will no longer expose people's ckeys for the achievements + they obtained through the round, nor when they're contractor support agents. + LT3: + - bugfix: Adjusted Void Raptor shutters and firelocks in the pharmacy, hallway and + HoP line + - balance: Hypovial capacity now matches bottle capacity + - bugfix: Broken and placeholder hypovials can no longer be printed in the ChemMaster + Melbert: + - qol: AI, cyborg, and PAI camera (photo taking) behavior now uses balloon alerts + and has sound effects associated + - refactor: Refactored AI, cyborg, and PAI camera (photo taking) code + - bugfix: fixed being unable to print photos as a cyborg when below 50% toner, even + though photos only take 5% + SkyratBot: + - bugfix: Engineering borgs can no longer grab and drop their own iron/glass sheet + module. + - bugfix: It is no longer possible to chasm yourself on the geode. Again. + - rscadd: Fish analyzers can now be used to perform fish scanning experiments. + - balance: They can now be singularly bought as a goodie pack for 125 cr each, instead + of a crate of three for 500 cr. + - bugfix: Borgs will no longer become permanently upside-down if tipped over by + multiple people at the same time. + - balance: Despite earlier reports suggesting that the famous lethality of the Regal + Condor was largely a myth, there has been rumors that the gun has once again + started to display its true killing potential on any station that it 'manifests'. + - bugfix: The AI can no longer turn you off if you shapeshift into a robot. + - bugfix: Blood once again appears as small drops instead of splatters during minor + bleeding. + - bugfix: you are now made a ghost faster if you get gibbed + - bugfix: fixed bad food not having bad food reagents + - rscadd: The laser carbine, a weak but fully automatic sidegrade to the normal + laser gun, can now be ordered from cargo. + - bugfix: Adminheal will now properly clear negative mutations as intended. + - bugfix: Ice whelps can now use spells given to them by admins, and people who + have polymorphed into ice whelps can now polymorph back to normal. + - bugfix: Fixed silent catwalks. + - rscadd: Fake moustaches are now poorly slapped on top of what you're wearing + jjpark-kb: + - rscadd: ashwalker nest is now in the NE corner of lavaland + neocloudy: + - bugfix: MetaStation disposal pipes from Cargo to Disposals/the rest of the station + are working again. + nikothedude: + - rscadd: Synthetic wounds! Blunt, Pierce, Slash, Burn, Muscle. See PR 23733 for + more information + - rscadd: Robodrobe now has 2 chilled hercuri sprays for treating synthetic burn + wounds + - rscadd: Robodrobe now has 2 pairs of black gloves to let robotics painlessly meld + T3 synthetic blunt wounds + - balance: 'Synthetic damage multiplier: 1.3 -> 1.0' + - rscadd: '3 new cargo packs to science: 2 chilled hercuri, a synth trauma kit, + and synth medicine' + - balance: Quadruple amputee can now be picked with frail + - rscadd: Interdyne/DS2 now have advanced synthetic trauma kits in their medbays +2023-10-08: + LT3: + - image: Text alignment on ID cards slightly adjusted + Melbert: + - bugfix: Fixed an error from reading an ID card closely when you can't read + - config: Adds a config option for player respawning that enables respawns, but + forces you pick a new character. + - config: '"NORESPAWN" has been replaced with "ALLOW_RESPAWN 0". Unlimited respawns + is "ALLOW_RESPAWN 1" and character limited respawns is "ALLOW_RESPAWN 2".' + SkyratBot: + - bugfix: Fix bodies now lose fire stacks while husked. + - bugfix: Flesh Worms will move smoothly more consistently. + - balance: You can now remove and replace power cells from PDAs (with screwdriver). + - balance: PDAs now drain their power cells harder, and also take into account active + programs & their flashlight being on. + - balance: PDAs running out of charge now turn their flashlights off. + - qol: allows janitor keys to be stored in janitor wintercoats and janibets + - bugfix: PDA flashlights wont cause the cell to constantly drain faster and faster. + - bugfix: People who are irremediably bald can still grow a beard with barber aid. + - qol: Added slapcrafting to unloaded tech shells, click on them with ingredients + to quickly craft your shell. + - qol: gives empty fireaxe and mech removal crowbars cabinets directional helpers + - bugfix: fixed a PDA's messenger TGUI issue with handling of destroyed recipients. + - qol: '"prison" intercoms have been renamed to "receive-only" intercoms to make + it clearer they cannot transmit.' + - refactor: Rust Walkers, Ash Spirits, Flesh Stalkers, and The Maid in the Mirror + now use the basic mob framework. Please report any unusual behaviour. + - spellcheck: '"offical" has been officially corrected to "official" in several + official locations.' + - refactor: Sloths are now basic mobs, however their overall sluggish behavior shouldn't + have changed much- let us know if anything is broken. + - refactor: Refactored goats into basic mobs! Not much should have changed beyond + their endless desire to retaliate should you attack them, they're still just + as good as chomping away plant life as ever. + - qol: Miners can now tag monster spawners (necropolis tendrils, animal dens, demonic + portals, and netherworld links) by using their mining scanner on it, which updates + their GPS tag (and/or gives them one) to give it a numerical designation and + a short identifier for what it's spawning. + oranges: + - rscadd: Dogs now react to centrist grillers more realistically +2023-10-09: + Nerev4r: + - image: The crew's knowledge of origami and papercrafting has been extended to + making paper masks. Find them in the loadout, or just make them! + SkyratBot: + - qol: Supermatter shards can now be fastened with right click too. Now, just don't + forget to use a wrench. + - bugfix: Slaughter/Laughter demon melee cooldowns have been fixed and now attack + at the regular player character attack speed + - balance: The chemical gun and PKA pressure mod traitor items are now purchasable + within 15 minutes of the round starting rather than 20/30. + - balance: All preset bundle kits, the cash briefcase, the makarov, the revolver, + the throwing weapon kit, c4, the detomatix cartridge, the large EMP bomb, gorillas, + advanced mimery tome, pie cannon, clown car, His Grace, and the origami kit + are now all purchasable at the start of a round. + - refactor: ice demons have been refactored into basic mbos. please report any bugs + - rscadd: ice demons now have a unique trophy + - bugfix: Spider types get properly checked again. + nikothedude: + - bugfix: Borers work now diff --git a/icons/obj/card.dmi b/icons/obj/card.dmi index 4172a0a3641..a5e34e9cc27 100644 Binary files a/icons/obj/card.dmi and b/icons/obj/card.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index d89ee6e5d64..fe74b6c11c5 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/machines/bitrunning.dmi b/icons/obj/machines/bitrunning.dmi index a910a16b35c..b3f8ad63a6c 100644 Binary files a/icons/obj/machines/bitrunning.dmi and b/icons/obj/machines/bitrunning.dmi differ diff --git a/icons/obj/mining_zones/artefacts.dmi b/icons/obj/mining_zones/artefacts.dmi index f3f7d00e4ee..d4c603834d2 100644 Binary files a/icons/obj/mining_zones/artefacts.dmi and b/icons/obj/mining_zones/artefacts.dmi differ diff --git a/icons/obj/pipes_n_cables/!pipe_gas_overlays.dmi b/icons/obj/pipes_n_cables/!pipe_gas_overlays.dmi new file mode 100644 index 00000000000..0262adcaeb2 Binary files /dev/null and b/icons/obj/pipes_n_cables/!pipe_gas_overlays.dmi differ diff --git a/icons/obj/pipes_n_cables/!pipes_bitmask.dmi b/icons/obj/pipes_n_cables/!pipes_bitmask.dmi new file mode 100644 index 00000000000..97643036fbe Binary files /dev/null and b/icons/obj/pipes_n_cables/!pipes_bitmask.dmi differ diff --git a/icons/obj/pipes_n_cables/pipe_template_pieces.dmi b/icons/obj/pipes_n_cables/pipe_template_pieces.dmi new file mode 100644 index 00000000000..d0d2f7ff7bb Binary files /dev/null and b/icons/obj/pipes_n_cables/pipe_template_pieces.dmi differ diff --git a/icons/obj/pipes_n_cables/pipes_bitmask.dmi b/icons/obj/pipes_n_cables/pipes_bitmask.dmi deleted file mode 100644 index 7a382fb55c5..00000000000 Binary files a/icons/obj/pipes_n_cables/pipes_bitmask.dmi and /dev/null differ diff --git a/icons/obj/weapons/guns/energy.dmi b/icons/obj/weapons/guns/energy.dmi index 97b75335b91..e45c5ee4869 100644 Binary files a/icons/obj/weapons/guns/energy.dmi and b/icons/obj/weapons/guns/energy.dmi differ diff --git a/icons/obj/weapons/guns/projectiles.dmi b/icons/obj/weapons/guns/projectiles.dmi index e1c70c4f5ad..3c2d3ff452c 100644 Binary files a/icons/obj/weapons/guns/projectiles.dmi and b/icons/obj/weapons/guns/projectiles.dmi differ diff --git a/modular_skyrat/master_files/code/datums/components/grillable.dm b/modular_skyrat/master_files/code/datums/components/grillable.dm new file mode 100644 index 00000000000..42146559af1 --- /dev/null +++ b/modular_skyrat/master_files/code/datums/components/grillable.dm @@ -0,0 +1,9 @@ +/datum/component/grillable + /// What type of pollutant we spread around as we are grilleed, can be none + var/pollutant_type + +/datum/component/grillable/Initialize(cook_result, required_cook_time, positive_result, use_large_steam_sprite, list/added_reagents, pollutant_type) + . = ..() + if(. == COMPONENT_INCOMPATIBLE) + return + src.pollutant_type = pollutant_type diff --git a/modular_skyrat/master_files/code/game/objects/items/cards_ids.dm b/modular_skyrat/master_files/code/game/objects/items/cards_ids.dm index b28befb741e..9b43fccfc3a 100644 --- a/modular_skyrat/master_files/code/game/objects/items/cards_ids.dm +++ b/modular_skyrat/master_files/code/game/objects/items/cards_ids.dm @@ -11,23 +11,6 @@ icon_state = "card_goldgen" assigned_icon_state = null -// COLOURABLE -/obj/item/card/id/advanced/colourable - name = "colourable identification card" - desc = "A failed prototype for customizable ID cards, it looks.. strange." // Read: I'm too lazy to implement this properly - icon_state = "id_card" - assigned_icon_state = null // Built into the sprite itself. - greyscale_config = /datum/greyscale_config/id_card - greyscale_colors = "#FF0000#00FF00#0000FF" - -/obj/item/card/id/advanced/colourable/Initialize(mapload) - . = ..() - AddElement(/datum/element/gags_recolorable) - -/obj/item/card/id/advanced/colourable/examine(mob/user) - . = ..() - . += span_info("You could change its colours with a spray can!") - // DS2 /obj/item/card/id/advanced/prisoner/ds2 name = "syndicate prisoner card" diff --git a/modular_skyrat/master_files/code/modules/antagonists/traitor/objectives/kill_pet.dm b/modular_skyrat/master_files/code/modules/antagonists/traitor/objectives/kill_pet.dm index 68865d44b21..422a2d16c01 100644 --- a/modular_skyrat/master_files/code/modules/antagonists/traitor/objectives/kill_pet.dm +++ b/modular_skyrat/master_files/code/modules/antagonists/traitor/objectives/kill_pet.dm @@ -9,8 +9,8 @@ JOB_CHIEF_MEDICAL_OFFICER = /mob/living/simple_animal/pet/cat/runtime, JOB_CHIEF_ENGINEER = /mob/living/simple_animal/parrot/poly, JOB_QUARTERMASTER = list( - /mob/living/simple_animal/sloth/citrus, - /mob/living/simple_animal/sloth/paperwork, + /mob/living/basic/sloth/citrus, + /mob/living/basic/sloth/paperwork, /mob/living/simple_animal/hostile/gorilla/cargo_domestic, ), // Non-heads like the warden, these are automatically medium-risk at minimum diff --git a/modular_skyrat/master_files/code/modules/jobs/job_types/roboticist.dm b/modular_skyrat/master_files/code/modules/jobs/job_types/roboticist.dm index d90c994c6ad..8c62f0a30f1 100644 --- a/modular_skyrat/master_files/code/modules/jobs/job_types/roboticist.dm +++ b/modular_skyrat/master_files/code/modules/jobs/job_types/roboticist.dm @@ -3,3 +3,19 @@ satchel = /obj/item/storage/backpack/satchel/science/robo duffelbag = /obj/item/storage/backpack/duffelbag/science/robo messenger = /obj/item/storage/backpack/messenger/science/robo + +/datum/job/roboticist + description = "Build cyborgs, mechs, AIs, and maintain them all. Create MODsuits for those that wish. Try to remind medical that you're \ + actually a lot better at treating synthetic crew members than them." + +/datum/job/roboticist/New() + . = ..() + + mail_goodies += list( + /obj/item/healthanalyzer/advanced = 15, + // if we decide later to let sci have access to the hand drill, let robos get it from here + /obj/item/storage/pill_bottle/liquid_solder = 6, + /obj/item/storage/pill_bottle/system_cleaner = 6, + /obj/item/storage/pill_bottle/nanite_slurry = 6, + /obj/item/reagent_containers/spray/hercuri/chilled = 8, + ) diff --git a/modular_skyrat/master_files/code/modules/mob/living/basic/icemoon/ice_demon.dm b/modular_skyrat/master_files/code/modules/mob/living/basic/icemoon/ice_demon.dm new file mode 100644 index 00000000000..0c8f44b3118 --- /dev/null +++ b/modular_skyrat/master_files/code/modules/mob/living/basic/icemoon/ice_demon.dm @@ -0,0 +1,3 @@ +// crusher loot /obj/item/crusher_trophy/ice_demon_cube -> /obj/item/crusher_trophy/demon_core +/mob/living/basic/mining/ice_demon + crusher_loot = /obj/item/crusher_trophy/demon_core diff --git a/modular_skyrat/master_files/icons/mob/clothing/mask.dmi b/modular_skyrat/master_files/icons/mob/clothing/mask.dmi index db9c50ab844..07bef00e9c4 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/mask.dmi and b/modular_skyrat/master_files/icons/mob/clothing/mask.dmi differ diff --git a/modular_skyrat/master_files/icons/obj/card.dmi b/modular_skyrat/master_files/icons/obj/card.dmi index a0d282967d0..b24180795bb 100644 Binary files a/modular_skyrat/master_files/icons/obj/card.dmi and b/modular_skyrat/master_files/icons/obj/card.dmi differ diff --git a/modular_skyrat/master_files/icons/obj/clothing/masks.dmi b/modular_skyrat/master_files/icons/obj/clothing/masks.dmi index c9e746f0506..7deb40b8d85 100644 Binary files a/modular_skyrat/master_files/icons/obj/clothing/masks.dmi and b/modular_skyrat/master_files/icons/obj/clothing/masks.dmi differ diff --git a/modular_skyrat/modules/ashwalkers/code/effects/ash_rituals.dm b/modular_skyrat/modules/ashwalkers/code/effects/ash_rituals.dm index ba1dd931c3a..7b38a565698 100644 --- a/modular_skyrat/modules/ashwalkers/code/effects/ash_rituals.dm +++ b/modular_skyrat/modules/ashwalkers/code/effects/ash_rituals.dm @@ -198,7 +198,7 @@ /datum/ash_ritual/summon_icemoon_creature/ritual_success(obj/effect/ash_rune/success_rune) . = ..() var/mob_type = pick( - /mob/living/simple_animal/hostile/asteroid/ice_demon, + /mob/living/basic/mining/ice_demon, /mob/living/basic/mining/ice_whelp, /mob/living/basic/mining/lobstrosity, /mob/living/simple_animal/hostile/asteroid/polarbear, diff --git a/modular_skyrat/modules/cortical_borer/code/cortical_borer_abilities.dm b/modular_skyrat/modules/cortical_borer/code/cortical_borer_abilities.dm index 8a239f9c9a5..fae00851ad4 100644 --- a/modular_skyrat/modules/cortical_borer/code/cortical_borer_abilities.dm +++ b/modular_skyrat/modules/cortical_borer/code/cortical_borer_abilities.dm @@ -50,7 +50,7 @@ name = "Open Chemical Injector" button_icon_state = "chemical" -/datum/action/cooldown/borer/inject_chemical/Trigger(trigger_flags) +/datum/action/cooldown/borer/inject_chemical/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -141,7 +141,7 @@ name = "Open Evolution Tree" button_icon_state = "newability" -/datum/action/cooldown/borer/evolution_tree/Trigger(trigger_flags) +/datum/action/cooldown/borer/evolution_tree/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -230,7 +230,7 @@ name = "Learn Focus" button_icon_state = "getfocus" -/datum/action/cooldown/borer/learn_focus/Trigger(trigger_flags) +/datum/action/cooldown/borer/learn_focus/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -268,7 +268,7 @@ button_icon_state = "bloodchem" chemical_evo_points = 5 -/datum/action/cooldown/borer/learn_bloodchemical/Trigger(trigger_flags) +/datum/action/cooldown/borer/learn_bloodchemical/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -314,7 +314,7 @@ button_icon_state = "bloodlevel" chemical_evo_points = 1 -/datum/action/cooldown/borer/upgrade_chemical/Trigger(trigger_flags) +/datum/action/cooldown/borer/upgrade_chemical/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -349,7 +349,7 @@ button_icon_state = "level" stat_evo_points = 1 -/datum/action/cooldown/borer/upgrade_stat/Trigger(trigger_flags) +/datum/action/cooldown/borer/upgrade_stat/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -379,7 +379,7 @@ name = "Toggle Hiding" button_icon_state = "hide" -/datum/action/cooldown/borer/toggle_hiding/Trigger(trigger_flags) +/datum/action/cooldown/borer/toggle_hiding/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -401,7 +401,7 @@ cooldown_time = 12 SECONDS button_icon_state = "fear" -/datum/action/cooldown/borer/fear_human/Trigger(trigger_flags) +/datum/action/cooldown/borer/fear_human/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -464,7 +464,7 @@ cooldown_time = 5 SECONDS button_icon_state = "blood" -/datum/action/cooldown/borer/check_blood/Trigger(trigger_flags) +/datum/action/cooldown/borer/check_blood/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -485,7 +485,7 @@ cooldown_time = 10 SECONDS button_icon_state = "host" -/datum/action/cooldown/borer/choosing_host/Trigger(trigger_flags) +/datum/action/cooldown/borer/choosing_host/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -593,7 +593,7 @@ cooldown_time = 30 SECONDS button_icon_state = "speak" -/datum/action/cooldown/borer/force_speak/Trigger(trigger_flags) +/datum/action/cooldown/borer/force_speak/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -628,7 +628,7 @@ button_icon_state = "reproduce" chemical_cost = 100 -/datum/action/cooldown/borer/produce_offspring/Trigger(trigger_flags) +/datum/action/cooldown/borer/produce_offspring/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -692,7 +692,7 @@ button_icon_state = "revive" chemical_cost = 200 -/datum/action/cooldown/borer/revive_host/Trigger(trigger_flags) +/datum/action/cooldown/borer/revive_host/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -732,7 +732,7 @@ button_icon_state = "willing" chemical_cost = 150 -/datum/action/cooldown/borer/willing_host/Trigger(trigger_flags) +/datum/action/cooldown/borer/willing_host/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE @@ -765,7 +765,7 @@ button_icon_state = "hiding" chemical_cost = 100 -/datum/action/cooldown/borer/stealth_mode/Trigger(trigger_flags) +/datum/action/cooldown/borer/stealth_mode/Trigger(trigger_flags, atom/target) var/mob/living/basic/cortical_borer/cortical_owner = owner var/in_stealth = (cortical_owner.upgrade_flags & BORER_STEALTH_MODE) if(in_stealth) @@ -794,7 +794,7 @@ button_icon_state = "reproduce" chemical_cost = 150 -/datum/action/cooldown/borer/empowered_offspring/Trigger(trigger_flags) +/datum/action/cooldown/borer/empowered_offspring/Trigger(trigger_flags, atom/target) . = ..() if(!.) return FALSE diff --git a/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm b/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm new file mode 100644 index 00000000000..97b52485b4b --- /dev/null +++ b/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm @@ -0,0 +1,76 @@ +/obj/item/clothing/mask/paper + name = "paper mask" + desc = "It's true. Once you wear a mask for so long, you forget about who you are. Wonder if that happens with shitty paper ones." + icon = 'modular_skyrat/master_files/icons/obj/clothing/masks.dmi' + worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/mask.dmi' + icon_state = "mask_paper" + clothing_flags = MASKINTERNALS + flags_inv = HIDEFACIALHAIR|HIDESNOUT + w_class = WEIGHT_CLASS_SMALL + /// Whether or not the mask is currently being layered over (or under!) hair. + var/wear_over_hair = TRUE + unique_reskin = list( + "Blank" = "mask_paper", + "Neutral" = "mask_neutral", + "Eye" = "mask_eye", + "Sleep" = "mask_sleep", + "Heart" = "mask_heart", + "Core" = "mask_core", + "Plus" = "mask_plus", + "Square" = "mask_square", + "Bullseye" = "mask_bullseye", + "Vertical" = "mask_vertical", + "Horizontal" = "mask_horizontal", + "X" = "mask_x", + "Bug" = "mask_bug", + "Double" = "mask_double", + "Mark" = "mask_mark", + "Line" = "mask_line", + "Minus" = "mask_minus", + "Four" = "mask_four", + "Diamond" = "mask_diamond", + "Cat" = "mask_cat", + "Big Eye" = "mask_bigeye", + "Good" = "mask_good", + "Bad" = "mask_bad", + "Happy" = "mask_happy", + "Sad" = "mask_sad", + ) + +/obj/item/clothing/mask/paper/Initialize(mapload) + . = ..() + register_context() + if(wear_over_hair) + alternate_worn_layer = BACK_LAYER + +/obj/item/clothing/mask/paper/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + context[SCREENTIP_CONTEXT_ALT_LMB] = "Change Mask Face" + return CONTEXTUAL_SCREENTIP_SET + +/obj/item/clothing/mask/paper/reskin_obj(mob/user) + . = ..() + user.update_worn_mask() + current_skin = null //so we can infinitely reskin + +/obj/item/clothing/mask/paper/proc/adjust_mask(mob/living/carbon/human/user) + if(!istype(user)) + return + if(!user.incapacitated()) + wear_over_hair = !wear_over_hair + if(wear_over_hair) + alternate_worn_layer = BACK_LAYER + to_chat(user, "You sweep your hair over the mask.") + else + alternate_worn_layer = initial(alternate_worn_layer) + to_chat(user, "You sweep your hair under the mask.") + + user.update_body_parts() + user.update_inv_ears(0) + user.update_worn_mask() + +/obj/item/clothing/mask/paper/verb/toggle() + set category = "Object" + set name = "Adjust Mask" + set src in usr + adjust_mask(usr) diff --git a/modular_skyrat/modules/implants/code/augments_chest.dm b/modular_skyrat/modules/implants/code/augments_chest.dm index 23079322874..87e817da379 100644 --- a/modular_skyrat/modules/implants/code/augments_chest.dm +++ b/modular_skyrat/modules/implants/code/augments_chest.dm @@ -1,3 +1,7 @@ +// for readability's sake, define here to match the healthscan() proc's use of it +// if someone updates that upstream, fix that here too, wouldja? +#define SCANNER_VERBOSE 1 + /obj/item/organ/internal/cyberimp/chest/scanner name = "internal health analyzer" desc = "An advanced health analyzer implant, designed to directly interface with a host's body and relay scan information to the brain on command." @@ -6,14 +10,21 @@ icon_state = "internal_HA" implant_overlay = null implant_color = null - actions_types = list(/datum/action/item_action/organ_action/use) + actions_types = list(/datum/action/item_action/organ_action/use/internal_analyzer) w_class = WEIGHT_CLASS_SMALL -/obj/item/organ/internal/cyberimp/chest/scanner/ui_action_click(owner, action) - if(istype(action, /datum/action/item_action/organ_action/use)) - if(organ_flags & ORGAN_FAILING) - to_chat(owner, span_warning("Your health analyzer relays an error! It can't interface with your body in its current condition!")) - return - else - healthscan(owner, owner, 1, TRUE) - chemscan(owner, owner) +/datum/action/item_action/organ_action/use/internal_analyzer + desc = "LMB: Health scan. RMB: Chemical scan. Requires implanted analyzer to not be failing due to EMPs or other causes. Does not provide treatment assistance." + +/datum/action/item_action/organ_action/use/internal_analyzer/Trigger(trigger_flags) + . = ..() + var/obj/item/organ/internal/cyberimp/chest/scanner/our_scanner = target + if(our_scanner.organ_flags & ORGAN_FAILING) + to_chat(owner, span_warning("Your health analyzer relays an error! It can't interface with your body in its current condition!")) + return + if(trigger_flags & TRIGGER_SECONDARY_ACTION) + chemscan(owner, owner) + else + healthscan(owner, owner, SCANNER_VERBOSE, TRUE) + +#undef SCANNER_VERBOSE diff --git a/modular_skyrat/modules/layer_shift/code/mob_movement.dm b/modular_skyrat/modules/layer_shift/code/mob_movement.dm index 2bc2ed4cdee..740b3e2289e 100644 --- a/modular_skyrat/modules/layer_shift/code/mob_movement.dm +++ b/modular_skyrat/modules/layer_shift/code/mob_movement.dm @@ -6,34 +6,73 @@ //#define MOB_LAYER 4 // This is a byond standard define #define MOB_LAYER_SHIFT_MAX 4.05 -/mob/living/verb/layershift_up() +/mob/living/verb/shift_layer_up() set name = "Shift Layer Upwards" set category = "IC" if(incapacitated()) to_chat(src, span_warning("You can't do that right now!")) - return + return FALSE if(layer >= MOB_LAYER_SHIFT_MAX) to_chat(src, span_warning("You cannot increase your layer priority any further.")) - return + return FALSE layer = min(((layer * MOB_LAYER_MULTIPLIER) + MOB_LAYER_SHIFT_INCREMENT) / MOB_LAYER_MULTIPLIER, MOB_LAYER_SHIFT_MAX) var/layer_priority = round(layer * MOB_LAYER_MULTIPLIER - MOB_LAYER * MOB_LAYER_MULTIPLIER, MOB_LAYER_SHIFT_INCREMENT) // Just for text feedback to_chat(src, span_notice("Your layer priority is now [layer_priority].")) -/mob/living/verb/layershift_down() + return TRUE + + +/mob/living/verb/shift_layer_down() set name = "Shift Layer Downwards" set category = "IC" if(incapacitated()) to_chat(src, span_warning("You can't do that right now!")) - return + return FALSE if(layer <= MOB_LAYER_SHIFT_MIN) to_chat(src, span_warning("You cannot decrease your layer priority any further.")) - return + return FALSE layer = max(((layer * MOB_LAYER_MULTIPLIER) - MOB_LAYER_SHIFT_INCREMENT) / MOB_LAYER_MULTIPLIER, MOB_LAYER_SHIFT_MIN) var/layer_priority = round(layer * MOB_LAYER_MULTIPLIER - MOB_LAYER * MOB_LAYER_MULTIPLIER, MOB_LAYER_SHIFT_INCREMENT) // Just for text feedback to_chat(src, span_notice("Your layer priority is now [layer_priority].")) + + return TRUE + + +/datum/emote/living/shift_layer_up + key = "shiftlayerup" + key_third_person = "shiftlayerup" + message = null + mob_type_blacklist_typecache = list(/mob/living/brain) + cooldown = 0.25 SECONDS + +/datum/emote/living/shift_layer_up/run_emote(mob/user, params, type_override, intentional) + if(!can_run_emote(user)) + to_chat(user, span_warning("You can't change layer at this time.")) + return FALSE + + var/mob/living/layer_shifter = user + + return layer_shifter.shift_layer_up() + + +/datum/emote/living/shift_layer_down + key = "shiftlayerdown" + key_third_person = "shiftlayerdown" + message = null + mob_type_blacklist_typecache = list(/mob/living/brain) + cooldown = 0.25 SECONDS + +/datum/emote/living/shift_layer_down/run_emote(mob/user, params, type_override, intentional) + if(!can_run_emote(user)) + to_chat(user, span_warning("You can't change layer at this time.")) + return FALSE + + var/mob/living/layer_shifter = user + + return layer_shifter.shift_layer_down() diff --git a/modular_skyrat/modules/loadouts/loadout_items/loadout_datum_masks.dm b/modular_skyrat/modules/loadouts/loadout_items/loadout_datum_masks.dm index a92764d3074..d0052806a13 100644 --- a/modular_skyrat/modules/loadouts/loadout_items/loadout_datum_masks.dm +++ b/modular_skyrat/modules/loadouts/loadout_items/loadout_datum_masks.dm @@ -130,6 +130,10 @@ GLOBAL_LIST_INIT(loadout_masks, generate_loadout_items(/datum/loadout_item/mask) name = "Joy Mask" item_path = /obj/item/clothing/mask/joy +/datum/loadout_item/mask/paper + name = "Paper Mask" + item_path = /obj/item/clothing/mask/paper + /datum/loadout_item/mask/lollipop name = "Lollipop" item_path = /obj/item/food/lollipop diff --git a/modular_skyrat/modules/medical/attributions.txt b/modular_skyrat/modules/medical/attributions.txt new file mode 100644 index 00000000000..f57c3fa0db5 --- /dev/null +++ b/modular_skyrat/modules/medical/attributions.txt @@ -0,0 +1,2 @@ +robotic_slash_T1.ogg, robotic_slash_T2.ogg, and robotic_slash_T3.ogg adapated from CGEffex's Bug Zapper2.wav (CC Attribution 4.0) +https://freesound.org/people/CGEffex/sounds/107004/ diff --git a/modular_skyrat/modules/medical/code/cargo/packs.dm b/modular_skyrat/modules/medical/code/cargo/packs.dm new file mode 100644 index 00000000000..0de1f24eb16 --- /dev/null +++ b/modular_skyrat/modules/medical/code/cargo/packs.dm @@ -0,0 +1,36 @@ +/datum/supply_pack/science/chilled_hercuri + name = "Chilled Hercuri Pack" + desc = "Contains 2 pre-chilled bottles of hercuri, 100u each. Useful for dealing with severely burnt synthetics!" + cost = CARGO_CRATE_VALUE * 2.5 + contains = list(/obj/item/reagent_containers/spray/hercuri/chilled = 2) + crate_name = "chilled hercuri crate" + + access_view = FALSE + access = FALSE + access_any = FALSE + +/datum/supply_pack/science/synth_treatment_kits + name = "Synthetic Treatment Kits" + desc = "Contains 2 treatment kits for synthetic lifeforms, filled with everything you need to treat an inorganic wound!" + cost = CARGO_CRATE_VALUE * 4.5 + contains = list(/obj/item/storage/backpack/duffelbag/synth_treatment_kit = 2) + crate_name = "synthetic treatment kits crate" + + access_view = FALSE + access = FALSE + access_any = FALSE + +/datum/supply_pack/science/synth_healing_chems + name = "Synthetic Medicine Pack" + desc = "Contains a variety of synthetic-exclusive medicine. 2 pill bottles of liquid solder, 2 of nanite slurry, 2 of system cleaner." + cost = CARGO_CRATE_VALUE * 7 // rarely made, so it should be expensive(?) + contains = list( + /obj/item/storage/pill_bottle/liquid_solder = 2, + /obj/item/storage/pill_bottle/nanite_slurry = 2, + /obj/item/storage/pill_bottle/system_cleaner = 2 + ) + crate_name = "synthetic medicine crate" + + access_view = FALSE + access = FALSE + access_any = FALSE diff --git a/modular_skyrat/modules/medical/code/medkit.dm b/modular_skyrat/modules/medical/code/medkit.dm new file mode 100644 index 00000000000..8ea40ae54bd --- /dev/null +++ b/modular_skyrat/modules/medical/code/medkit.dm @@ -0,0 +1,177 @@ +/obj/item/storage/backpack/duffelbag/synth_treatment_kit + name = "synthetic treatment kit" + desc = "A \"surgical\" duffel bag containing everything you need to treat the worst and best of inorganic wounds." + icon = 'modular_skyrat/master_files/icons/obj/clothing/backpacks.dmi' + worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/back.dmi' + lefthand_file = 'modular_skyrat/master_files/icons/mob/inhands/clothing/backpack_lefthand.dmi' + righthand_file = 'modular_skyrat/master_files/icons/mob/inhands/clothing/backpack_righthand.dmi' + icon_state = "duffel_robo" + inhand_icon_state = "duffel_robo" + +/obj/item/storage/backpack/duffelbag/synth_treatment_kit/PopulateContents() // yes, this is all within the storage capacity + // Slash/Pierce wound tools - can reduce intensity of electrical damage (wires can fix generic burn damage) + new /obj/item/stack/cable_coil(src) + new /obj/item/stack/cable_coil(src) + new /obj/item/stack/cable_coil(src) + new /obj/item/wirecutters(src) + // Blunt/Brute tools + new /obj/item/weldingtool/largetank(src) // Used for repairing blunt damage or heating metal at T3 blunt + new /obj/item/screwdriver(src) // Used for fixing T1 blunt or securing internals of T2/3 blunt + new /obj/item/bonesetter(src) + // Clothing items + new /obj/item/clothing/head/utility/welding(src) + new /obj/item/clothing/gloves/color/black(src) // Protects from T3 mold metal step + new /obj/item/clothing/glasses/hud/diagnostic(src) // When worn, generally improves wound treatment quality + // Reagent containers + new /obj/item/reagent_containers/spray/hercuri/chilled(src) // Highly effective (specifically coded to be) against burn wounds + // Generic medical items + new /obj/item/stack/medical/gauze/twelve(src) + new /obj/item/healthanalyzer(src) + new /obj/item/healthanalyzer/simple(src) // Buffs wound treatment and gives details of wounds it scans + // "Ghetto" tools, things you shouldnt ideally use but you might have to + new /obj/item/stack/medical/bone_gel(src) // Ghetto T2/3 option for securing internals + new /obj/item/plunger(src) // Can be used to mold heated metal at T3 + +// a treatment kit with extra space and more tools/upgraded tools, like a crowbar, insuls, a reinforced plunger, a crowbar and wrench +/obj/item/storage/backpack/duffelbag/synth_treatment_kit/trauma + name = "synthetic trauma kit" + desc = "A \"surgical\" duffel bag containing everything you need to treat the worst and best of inorganic wounds. This one has extra tools and space \ + for treatment of the WORST of the worst! However, it's highly specialized interior means it can ONLY hold synthetic repair tools." + storage_type = /datum/storage/duffel/synth_trauma_kit + +/datum/storage/duffel/synth_trauma_kit + exception_max = 6 + max_slots = 27 + max_total_storage = 35 + +/datum/storage/duffel/synth_trauma_kit/New(atom/parent, max_slots, max_specific_storage, max_total_storage, numerical_stacking, allow_quick_gather, allow_quick_empty, collection_mode, attack_hand_interact) + . = ..() + + var/static/list/exception_cache = typecacheof(list( + // Mainly just stacks, with the exception of pill bottles and sprays + /obj/item/stack/cable_coil, + /obj/item/stack/medical/gauze, + /obj/item/reagent_containers/spray, + /obj/item/stack/medical/bone_gel, + /obj/item/rcd_ammo, + /obj/item/storage/pill_bottle, + )) + + var/static/list/can_hold_list = list( + // Stacks + /obj/item/stack/cable_coil, + /obj/item/stack/medical/gauze, + /obj/item/stack/medical/bone_gel, + // Reagent containers, for synth medicine + /obj/item/reagent_containers/spray, + /obj/item/storage/pill_bottle, + /obj/item/reagent_containers/pill, + /obj/item/reagent_containers/cup, + /obj/item/reagent_containers/syringe, + // Tools, including tools you might not want to use but might have to (hemostat/retractor/etc) + /obj/item/screwdriver, + /obj/item/wrench, + /obj/item/crowbar, + /obj/item/weldingtool, + /obj/item/bonesetter, + /obj/item/wirecutters, + /obj/item/hemostat, + /obj/item/retractor, + /obj/item/cautery, + /obj/item/plunger, + // RCD stuff - RCDs can easily treat the 1st step of T3 blunt + /obj/item/construction/rcd, + /obj/item/rcd_ammo, + // Clothing items + /obj/item/clothing/gloves, + /obj/item/clothing/glasses/hud/health, + /obj/item/clothing/glasses/hud/diagnostic, + /obj/item/clothing/glasses/welding, + /obj/item/clothing/glasses/sunglasses, // still provides some welding protection + /obj/item/clothing/head/utility/welding, + /obj/item/clothing/mask/gas/welding, + // Generic health items + /obj/item/healthanalyzer, + ) + exception_hold = exception_cache + + // We keep the type list and the typecache list separate... + var/static/list/can_hold_cache = typecacheof(can_hold_list) + can_hold = can_hold_cache + + //...So we can run this without it generating a line for every subtype. + can_hold_description = generate_hold_desc(can_hold_list) + +/obj/item/storage/backpack/duffelbag/synth_treatment_kit/trauma/PopulateContents() // yes, this is all within the storage capacity + // Slash/Pierce wound tools - can reduce intensity of electrical damage (wires can fix generic burn damage) + new /obj/item/stack/cable_coil(src) + new /obj/item/stack/cable_coil(src) + new /obj/item/stack/cable_coil(src) + new /obj/item/wirecutters(src) + // Blunt/Brute tools + new /obj/item/weldingtool/hugetank(src) // Used for repairing blunt damage or heating metal at T3 blunt + new /obj/item/screwdriver(src) // Used for fixing T1 blunt or securing internals of T2/3 blunt + new /obj/item/wrench(src) // Same as screwdriver for T2/3 + new /obj/item/crowbar(src) // Ghetto fixing option for T2/3 blunt + new /obj/item/bonesetter(src) + // Clothing items + new /obj/item/clothing/head/utility/welding(src) + new /obj/item/clothing/gloves/color/black(src) // Protects from T3 mold metal step + new /obj/item/clothing/gloves/color/yellow(src) // Protects from electrical damage and crowbarring a blunt wound + new /obj/item/clothing/glasses/hud/diagnostic(src) // When worn, generally improves wound treatment quality + // Reagent containers + new /obj/item/reagent_containers/spray/hercuri/chilled(src) // Highly effective (specifically coded to be) against burn wounds + // Generic medical items + new /obj/item/stack/medical/gauze/twelve(src) + new /obj/item/healthanalyzer(src) + new /obj/item/healthanalyzer/simple(src) // Buffs wound treatment and gives details of wounds it scans + // "Ghetto" tools, things you shouldnt ideally use but you might have to + new /obj/item/stack/medical/bone_gel(src) // Ghetto T2/3 option for securing internals + new /obj/item/plunger/reinforced(src) // Can be used to mold heated metal at T3 + +// advanced tools, an RCD, chems, etc etc. dont give this one to the crew early in the round +/obj/item/storage/backpack/duffelbag/synth_treatment_kit/trauma/advanced + name = "advanced synth trauma kit" + desc = "An \"advanced\" \"surgical\" duffel bag containing absolutely everything you need to treat the worst and best of inorganic wounds. \ + This one has extra tools and space for treatment of the ones even worse than the WORST of the worst! However, its highly specialized interior \ + means it can ONLY hold synthetic repair tools." + + storage_type = /datum/storage/duffel/synth_trauma_kit/advanced + +/datum/storage/duffel/synth_trauma_kit/advanced + exception_max = 10 + max_slots = 31 + max_total_storage = 48 + +/obj/item/storage/backpack/duffelbag/synth_treatment_kit/trauma/advanced/PopulateContents() // yes, this is all within the storage capacity + // Slash/Pierce wound tools - can reduce intensity of electrical damage (wires can fix generic burn damage) + new /obj/item/stack/cable_coil(src) + new /obj/item/stack/cable_coil(src) + new /obj/item/stack/cable_coil(src) + new /obj/item/stack/cable_coil(src) + new /obj/item/crowbar/power(src) // jaws of life - wirecutters and crowbar + // Blunt/Brute tools + new /obj/item/weldingtool/experimental(src) // Used for repairing blunt damage or heating metal at T3 blunt + new /obj/item/screwdriver/power(src) // drill - screwdriver and wrench + new /obj/item/construction/rcd/loaded(src) // lets you instantly heal T3 blunt step 1 + new /obj/item/bonesetter(src) + // Clothing items + new /obj/item/clothing/head/utility/welding(src) + new /obj/item/clothing/gloves/combat(src) // insulated AND heat-resistant + new /obj/item/clothing/glasses/hud/diagnostic(src) // When worn, generally improves wound treatment quality + // Reagent containers + new /obj/item/reagent_containers/spray/hercuri/chilled(src) // Highly effective (specifically coded to be) against burn wounds + new /obj/item/reagent_containers/spray/hercuri/chilled(src) // 2 of them + new /obj/item/storage/pill_bottle/nanite_slurry(src) // Heals blunt/burn + new /obj/item/storage/pill_bottle/liquid_solder(src) // Heals brain damage + new /obj/item/storage/pill_bottle/system_cleaner(src) // Heals toxin damage and purges chems + // Generic medical items + new /obj/item/stack/medical/gauze/twelve(src) + new /obj/item/healthanalyzer/advanced(src) // advanced, not a normal analyzer + new /obj/item/healthanalyzer/simple(src) // Buffs wound treatment and gives details of wounds it scans + // "Ghetto" tools, things you shouldn't ideally use but you might have to + new /obj/item/stack/medical/bone_gel(src) // Ghetto T2/3 option for securing internals + new /obj/item/plunger/reinforced(src) // Can be used to mold heated metal at T3 blunt + +/obj/item/storage/backpack/duffelbag/synth_treatment_kit/trauma/advanced/unzipped + zipped_up = FALSE diff --git a/modular_skyrat/modules/medical/code/sprays.dm b/modular_skyrat/modules/medical/code/sprays.dm new file mode 100644 index 00000000000..8e2371e3f28 --- /dev/null +++ b/modular_skyrat/modules/medical/code/sprays.dm @@ -0,0 +1,12 @@ +/obj/item/reagent_containers/spray/hercuri/chilled + name = "chilled hercuri spray" // effective at cooling low-temperature burns but also is more efficienct at cooling high-temperature + desc = "A medical spray bottle. This one contains hercuri, a medicine used to negate the effects of dangerous high-temperature environments. \ + This one comes pre-chilled, making it especially good at cooling synthetic burns! \n\ + It has a bold warning label near the nozzle: ONLY USE IN EMERGENCIES! WILL CAUSE FREEZING! SECONDARY EFFECT ONLY USEFUL ON LIVING SYNTHS! INEFFECTIVE ON DECEASED! \n\ + There's a smaller warning label on the body of the spray: IN EVENT OF RUNAWAY ENDOTHERMY, APPLY SYSTEM CLEANER!" + var/starting_temperature = 100 + +/obj/item/reagent_containers/spray/hercuri/chilled/add_initial_reagents() + . = ..() + + reagents.chem_temp = starting_temperature diff --git a/modular_skyrat/modules/medical/code/wounds/muscle.dm b/modular_skyrat/modules/medical/code/wounds/muscle.dm index c1f9c3fc4c3..35cc54c7099 100644 --- a/modular_skyrat/modules/medical/code/wounds/muscle.dm +++ b/modular_skyrat/modules/medical/code/wounds/muscle.dm @@ -33,13 +33,14 @@ Overwriting of base procs */ /datum/wound/muscle/wound_injury(datum/wound/old_wound = null, attack_direction) - if(limb.held_index && victim.get_item_for_held_index(limb.held_index) && (disabling || prob(30 * severity))) - var/obj/item/I = victim.get_item_for_held_index(limb.held_index) - if(istype(I, /obj/item/offhand)) - I = victim.get_inactive_held_item() + var/obj/item/held_item = victim.get_item_for_held_index(limb.held_index || 0) + if(held_item && (disabling || prob(30 * severity))) + if(istype(held_item, /obj/item/offhand)) + held_item = victim.get_inactive_held_item() - if(I && victim.dropItemToGround(I)) - victim.visible_message(span_danger("[victim] drops [I] in shock!"), span_warning("The force on your [parse_zone(limb.body_zone)] causes you to drop [I]!"), vision_distance=COMBAT_MESSAGE_RANGE) + if(held_item && victim.dropItemToGround(held_item)) + victim.visible_message(span_danger("[victim] drops [held_item] in shock!"), \ + span_warning("The force on your [parse_zone(limb.body_zone)] causes you to drop [held_item]!"), vision_distance=COMBAT_MESSAGE_RANGE) return ..() @@ -173,3 +174,9 @@ id = "torn muscle" /datum/status_effect/wound/muscle/severe id = "ruptured tendon" + +/datum/status_effect/wound/muscle/robotic/moderate + id = "worn servo" + +/datum/status_effect/wound/muscle/robotic/severe + id = "severed hydraulic" diff --git a/modular_skyrat/modules/medical/code/wounds/synth/blunt/robotic_blunt.dm b/modular_skyrat/modules/medical/code/wounds/synth/blunt/robotic_blunt.dm new file mode 100644 index 00000000000..52995365b01 --- /dev/null +++ b/modular_skyrat/modules/medical/code/wounds/synth/blunt/robotic_blunt.dm @@ -0,0 +1,398 @@ +/// The multiplier put against our movement effects if our victim has the determined reagent +#define ROBOTIC_WOUND_DETERMINATION_MOVEMENT_EFFECT_MOD 0.7 +/// The multiplier of stagger intensity on hit if our victim has the determined reagent +#define ROBOTIC_WOUND_DETERMINATION_STAGGER_MOVEMENT_MULT 0.7 + +/// The multiplier put against our movement effects if our limb is grasped +#define ROBOTIC_BLUNT_GRASPED_MOVEMENT_MULT 0.7 + +/datum/wound/blunt/robotic + name = "Robotic Blunt (Screws and bolts) Wound" + wound_flags = (ACCEPTS_GAUZE|SPLINT_OVERLAY|CAN_BE_GRASPED) + + default_scar_file = METAL_SCAR_FILE + + /// If we suffer severe head booboos, we can get brain traumas tied to them + var/datum/brain_trauma/active_trauma + /// What brain trauma group, if any, we can draw from for head wounds + var/brain_trauma_group + /// If we deal brain traumas, when is the next one due? + var/next_trauma_cycle + /// How long do we wait +/- 20% for the next trauma? + var/trauma_cycle_cooldown + + /// The ratio stagger score will be multiplied against for determining the final chance of moving away from the attacker. + var/stagger_movement_chance_ratio = 1 + /// The ratio stagger score will be multiplied against for determining the amount of pixelshifting we will do when we are hit. + var/stagger_shake_shift_ratio = 0.05 + + /// The ratio of stagger score to shake duration during a stagger() call + var/stagger_score_to_shake_duration_ratio = 0.1 + + /// In the stagger aftershock, the stagger score will be multiplied against for determining the chance of dropping held items. + var/stagger_drop_chance_ratio = 1.25 + /// In the stagger aftershock, the stagger score will be multiplied against for determining the chance of falling over. + var/stagger_fall_chance_ratio = 1 + + /// In the stagger aftershock, the stagger score will be multiplied against for determining how long we are knocked down for. + var/stagger_aftershock_knockdown_ratio = 0.5 + /// In the stagger after shock, the stagger score will be multiplied against this (if caused by movement) for determining how long we are knocked down for. + var/stagger_aftershock_knockdown_movement_ratio = 0.1 + + /// If the victim stops moving before the aftershock, aftershock effects will be multiplied against this. + var/aftershock_stopped_moving_score_mult = 0.1 + + /// The ratio damage applied will be multiplied against for determining our stagger score. + var/chest_attacked_stagger_mult = 2.5 + /// The minimum score an attack must do to trigger a stagger. + var/chest_attacked_stagger_minimum_score = 5 + /// The ratio of damage to stagger chance on hit. + var/chest_attacked_stagger_chance_ratio = 2 + + /// The base score given to stagger() when we successfully stagger on a move. + var/base_movement_stagger_score = 30 + /// The base chance of moving to trigger stagger(). + var/chest_movement_stagger_chance = 1 + + /// The base duration of a stagger()'s sprite shaking. + var/base_stagger_shake_duration = 1.5 SECONDS + /// The base duration of a stagger()'s sprite shaking if caused by movement. + var/base_stagger_movement_shake_duration = 1.5 SECONDS + + /// The ratio of stagger score to camera shake chance. + var/stagger_camera_shake_chance_ratio = 0.75 + /// The base duration of a stagger's aftershock's camerashake. + var/base_aftershock_camera_shake_duration = 1.5 SECONDS + /// The base strength of a stagger's aftershock's camerashake. + var/base_aftershock_camera_shake_strength = 0.5 + + /// The amount of x and y pixels we will be shaken around by during a movement stagger. + var/movement_stagger_shift = 1 + + /// If we are currently oscillating. If true, we cannot stagger(). + var/oscillating = FALSE + + /// % chance for hitting our limb to fix something. + var/percussive_maintenance_repair_chance = 10 + /// Damage must be under this to proc percussive maintenance. + var/percussive_maintenance_damage_max = 7 + /// Damage must be over this to proc percussive maintenance. + var/percussive_maintenance_damage_min = 0 + + /// The time, in world time, that we will be allowed to do another movement shake. Useful because it lets us prioritize attacked shakes over movement shakes. + var/time_til_next_movement_shake_allowed = 0 + + /// The percent our limb must get to max possible damage by burn damage alone to count as malleable if it has no T2 burn wound. + var/limb_burn_percent_to_max_threshold_for_malleable = 0.8 // must be 75% to max damage by burn damage alone + + /// The last time our victim has moved. Used for determining if we should increase or decrease the chance of having stagger aftershock. + var/last_time_victim_moved = 0 + + processes = TRUE + +/datum/wound_pregen_data/blunt_metal + abstract = TRUE + required_limb_biostate = BIO_METAL + wound_series = WOUND_SERIES_METAL_BLUNT_BASIC + required_wounding_types = list(WOUND_BLUNT) + +/datum/wound_pregen_data/blunt_metal/generate_scar_priorities() + return list("[BIO_METAL]") + +/datum/wound/blunt/robotic/set_victim(new_victim) + if(victim) + UnregisterSignal(victim, COMSIG_MOVABLE_MOVED) + UnregisterSignal(victim, COMSIG_MOB_AFTER_APPLY_DAMAGE) + if(new_victim) + RegisterSignal(new_victim, COMSIG_MOVABLE_MOVED, PROC_REF(victim_moved)) + RegisterSignal(new_victim, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(victim_attacked)) + + return ..() + +/datum/wound/blunt/robotic/get_limb_examine_description() + return span_warning("This limb looks loosely held together.") + +// this wound is unaffected by cryoxadone and pyroxadone +/datum/wound/blunt/robotic/on_xadone(power) + return + +/datum/wound/blunt/robotic/wound_injury(datum/wound/old_wound, attack_direction) + . = ..() + + // hook into gaining/losing gauze so crit bone wounds can re-enable/disable depending if they're slung or not + if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group) + processes = TRUE + active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND) + next_trauma_cycle = world.time + (rand(100-WOUND_BONE_HEAD_TIME_VARIANCE, 100+WOUND_BONE_HEAD_TIME_VARIANCE) * 0.01 * trauma_cycle_cooldown) + + var/obj/item/held_item = victim.get_item_for_held_index(limb.held_index || 0) + if(held_item && (disabling || prob(30 * severity))) + if(istype(held_item, /obj/item/offhand)) + held_item = victim.get_inactive_held_item() + if(held_item && victim.dropItemToGround(held_item)) + victim.visible_message(span_danger("[victim] drops [held_item] in shock!"), span_warning("The force on your [limb.plaintext_zone] causes you to drop [held_item]!"), vision_distance=COMBAT_MESSAGE_RANGE) + +/datum/wound/blunt/robotic/remove_wound(ignore_limb, replaced) + . = ..() + + QDEL_NULL(active_trauma) + +/datum/wound/blunt/robotic/handle_process(seconds_per_tick, times_fired) + . = ..() + + if (!victim || IS_IN_STASIS(victim)) + return + + if (limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group && world.time > next_trauma_cycle) + if (active_trauma) + QDEL_NULL(active_trauma) + else + active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND) + next_trauma_cycle = world.time + (rand(100-WOUND_BONE_HEAD_TIME_VARIANCE, 100+WOUND_BONE_HEAD_TIME_VARIANCE) * 0.01 * trauma_cycle_cooldown) + +/// If true, allows our superstructure to be modified if we are T3. RCDs can always fix our superstructure. +/datum/wound/blunt/robotic/proc/limb_malleable() + if (!isnull(get_overheat_wound())) + return TRUE + var/burn_damage_to_max = (limb.burn_dam / limb.max_damage) // only exists for the weird case where it cant get a overheat wound + if (burn_damage_to_max >= limb_burn_percent_to_max_threshold_for_malleable) + return TRUE + return FALSE + +/// If we have one, returns a robotic overheat wound of severe severity or higher. Null otherwise. +/datum/wound/blunt/robotic/proc/get_overheat_wound() + RETURN_TYPE(/datum/wound/burn/robotic/overheat) + for (var/datum/wound/found_wound as anything in limb.wounds) + var/datum/wound_pregen_data/pregen_data = found_wound.get_pregen_data() + if (pregen_data.wound_series == WOUND_SERIES_METAL_BURN_OVERHEAT && found_wound.severity >= WOUND_SEVERITY_SEVERE) // meh solution but whateva + return found_wound + return null + +/// If our victim is lying down and is attacked in the chest, effective oscillation damage is multiplied against this. +#define OSCILLATION_ATTACKED_LYING_DOWN_EFFECT_MULT 0.5 + +/// If the attacker is wearing a diag hud, chance of percussive maintenance succeeding is multiplied against this. +#define PERCUSSIVE_MAINTENANCE_DIAG_HUD_CHANCE_MULT 1.5 +/// If our wound has been scanned by a wound analyzer, chance of percussive maintenance succeeding is multiplied against this. +#define PERCUSSIVE_MAINTENANCE_WOUND_SCANNED_CHANCE_MULT 1.5 +/// If the attacker is NOT our victim, chance of percussive maintenance succeeding is multiplied against this. +#define PERCUSSIVE_MAINTENANCE_ATTACKER_NOT_VICTIM_CHANCE_MULT 2.5 + +/// Signal handler proc to when our victim has damage applied via apply_damage(), which is a external attack. +/datum/wound/blunt/robotic/proc/victim_attacked(datum/source, damage, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) + SIGNAL_HANDLER + + if (def_zone != limb.body_zone) // use this proc since receive damage can also be called for like, chems and shit + return + if(!victim) + return + + var/effective_damage = (damage - blocked) + + var/obj/item/stack/gauze = limb.current_gauze + if(gauze) + effective_damage *= gauze.splint_factor + + switch (limb.body_zone) + + if(BODY_ZONE_CHEST) + var/oscillation_mult = 1 + if (victim.body_position == LYING_DOWN) + oscillation_mult *= OSCILLATION_ATTACKED_LYING_DOWN_EFFECT_MULT + var/oscillation_damage = effective_damage + var/stagger_damage = oscillation_damage * chest_attacked_stagger_mult + if (victim.has_status_effect(/datum/status_effect/determined)) + oscillation_damage *= ROBOTIC_WOUND_DETERMINATION_STAGGER_MOVEMENT_MULT + if ((stagger_damage >= chest_attacked_stagger_minimum_score) && prob(oscillation_damage * chest_attacked_stagger_chance_ratio)) + stagger(stagger_damage * oscillation_mult, attack_direction, attacking_item, shift = stagger_damage * stagger_shake_shift_ratio) + + if(!uses_percussive_maintenance() || damage < percussive_maintenance_damage_min || damage > percussive_maintenance_damage_max || damagetype != BRUTE || sharpness) + return + var/success_chance_mult = 1 + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + success_chance_mult *= PERCUSSIVE_MAINTENANCE_WOUND_SCANNED_CHANCE_MULT + var/mob/living/user + if (isatom(attacking_item)) + var/atom/attacking_atom = attacking_item + user = attacking_atom.loc // nullable + + if (istype(user)) + if (HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD)) + success_chance_mult *= PERCUSSIVE_MAINTENANCE_DIAG_HUD_CHANCE_MULT + + if (user != victim) + success_chance_mult *= PERCUSSIVE_MAINTENANCE_ATTACKER_NOT_VICTIM_CHANCE_MULT // encourages people to get other people to beat the shit out of their limbs + if (prob(percussive_maintenance_repair_chance * success_chance_mult)) + handle_percussive_maintenance_success(attacking_item, user) + else + handle_percussive_maintenance_failure(attacking_item, user) + +#undef OSCILLATION_ATTACKED_LYING_DOWN_EFFECT_MULT +#undef PERCUSSIVE_MAINTENANCE_DIAG_HUD_CHANCE_MULT +#undef PERCUSSIVE_MAINTENANCE_WOUND_SCANNED_CHANCE_MULT +#undef PERCUSSIVE_MAINTENANCE_ATTACKER_NOT_VICTIM_CHANCE_MULT + +/// The percent, in decimal, of a stagger's shake() duration, that will be used in a addtimer() to queue aftershock(). +#define STAGGER_PERCENT_OF_SHAKE_DURATION_TO_AFTERSHOCK_DELAY 0.65 // 1 = happens at the end, .5 = happens halfway through + +/// Causes an oscillation, which 1. has a chance to move our victim away from the attacker, and 2. after a delay, calls aftershock(). +/datum/wound/blunt/robotic/proc/stagger(stagger_score, attack_direction, obj/item/attacking_item, from_movement, shake_duration = base_stagger_shake_duration, shift, knockdown_ratio = stagger_aftershock_knockdown_ratio) + if (oscillating) + return + + var/self_message = "Your [limb.plaintext_zone] oscillates" + var/message = "[victim]'s [limb.plaintext_zone] oscillates" + if (attacking_item) + message += " from the impact" + else if (from_movement) + message += " from the movement" + message += "!" + self_message += "! You might be able to avoid an aftershock by stopping and waiting..." + + if (isnull(attack_direction)) + attack_direction = get_dir(victim, attacking_item) + + if (!isnull(attack_direction) && prob(stagger_score * stagger_movement_chance_ratio)) + to_chat(victim, span_warning("The force of the blow sends you reeling!")) + var/turf/target_loc = get_step(victim, attack_direction) + victim.Move(target_loc) + + victim.visible_message(span_warning(message), ignored_mobs = victim) + to_chat(victim, span_warning(self_message)) + victim.balloon_alert(victim, "oscillation! stop moving") + + victim.Shake(pixelshiftx = shift, pixelshifty = shift, duration = shake_duration) + var/aftershock_delay = (shake_duration * STAGGER_PERCENT_OF_SHAKE_DURATION_TO_AFTERSHOCK_DELAY) + var/knockdown_time = stagger_score * knockdown_ratio + addtimer(CALLBACK(src, PROC_REF(aftershock), stagger_score, attack_direction, attacking_item, world.time, knockdown_time), aftershock_delay) + oscillating = TRUE + +#undef STAGGER_PERCENT_OF_SHAKE_DURATION_TO_AFTERSHOCK_DELAY + +#define AFTERSHOCK_GRACE_THRESHOLD_PERCENT 0.33 // lower mult = later grace period = more forgiving + +/** + * Timer proc from stagger(). + * + * Based on chance, causes items to be dropped, knockdown to be applied, and/or screenshake to occur. + * Chance is massively reduced if the victim isn't moving. + */ +/datum/wound/blunt/robotic/proc/aftershock(stagger_score, attack_direction, obj/item/attacking_item, stagger_starting_time, knockdown_time) + if (!still_exists()) + return FALSE + + var/message = "The oscillations from your [limb.plaintext_zone] spread, " + var/limb_message = "causing " + var/limb_affected + + var/stopped_moving_grace_threshold = (world.time - ((world.time - stagger_starting_time) * AFTERSHOCK_GRACE_THRESHOLD_PERCENT)) + var/victim_stopped_moving = (last_time_victim_moved <= stopped_moving_grace_threshold) + if (victim_stopped_moving) + stagger_score *= aftershock_stopped_moving_score_mult + + if (prob(stagger_score * stagger_drop_chance_ratio)) + limb_message += "your hands" + victim.drop_all_held_items() + limb_affected = TRUE + + if (prob(stagger_score * stagger_fall_chance_ratio)) + if (limb_affected) + limb_message += " and " + limb_message += "your legs" + victim.Knockdown(knockdown_time) + limb_affected = TRUE + + if (prob(stagger_score * stagger_camera_shake_chance_ratio)) + if (limb_affected) + limb_message += " and " + limb_message += "your head" + shake_camera(victim, base_aftershock_camera_shake_duration, base_aftershock_camera_shake_strength) + limb_affected = TRUE + + if (limb_affected) + message += "[limb_message] to shake uncontrollably!" + else + message += "but pass harmlessly" + if (victim_stopped_moving) + message += " thanks to your stillness" + message += "." + + to_chat(victim, span_danger(message)) + victim.balloon_alert(victim, "oscillation over") + + oscillating = FALSE + +#undef AFTERSHOCK_GRACE_THRESHOLD_PERCENT + +/// Called when percussive maintenance succeeds at its random roll. +/datum/wound/blunt/robotic/proc/handle_percussive_maintenance_success(attacking_item, mob/living/user) + victim.visible_message(span_green("[victim]'s [limb.plaintext_zone] rattles from the impact, but looks a lot more secure!"), \ + span_green("Your [limb.plaintext_zone] rattles into place!")) + remove_wound() + +/// Called when percussive maintenance fails at its random roll. +/datum/wound/blunt/robotic/proc/handle_percussive_maintenance_failure(attacking_item, mob/living/user) + to_chat(victim, span_warning("Your [limb.plaintext_zone] rattles around, but you don't sense any sign of improvement.")) + +/// If our victim has no gravity, the effects of movement are multiplied by this. +#define VICTIM_MOVED_NO_GRAVITY_EFFECT_MULT 0.5 +/// If our victim is resting, or is walking and isnt forced to move, the effects of movement are multiplied by this. +#define VICTIM_MOVED_CAREFULLY_EFFECT_MULT 0.25 + +/// Signal handler proc that applies movements affect to our victim if they were moved. +/datum/wound/blunt/robotic/proc/victim_moved(datum/source, atom/old_loc, dir, forced, list/old_locs) + SIGNAL_HANDLER + + var/overall_mult = 1 + + var/obj/item/stack/gauze = limb.current_gauze + if (gauze) + overall_mult *= gauze.splint_factor + if (!victim.has_gravity(get_turf(victim))) + overall_mult *= VICTIM_MOVED_NO_GRAVITY_EFFECT_MULT + else if (victim.body_position == LYING_DOWN || (!forced && victim.move_intent == MOVE_INTENT_WALK)) + overall_mult *= VICTIM_MOVED_CAREFULLY_EFFECT_MULT + if (victim.has_status_effect(/datum/status_effect/determined)) + overall_mult *= ROBOTIC_WOUND_DETERMINATION_MOVEMENT_EFFECT_MOD + if (limb.grasped_by) + overall_mult *= ROBOTIC_BLUNT_GRASPED_MOVEMENT_MULT + + overall_mult *= get_buckled_movement_consequence_mult(victim.buckled) + + if (limb.body_zone == BODY_ZONE_CHEST) + var/stagger_chance = chest_movement_stagger_chance * overall_mult + if (prob(stagger_chance)) + stagger(base_movement_stagger_score, shake_duration = base_stagger_movement_shake_duration, from_movement = TRUE, shift = movement_stagger_shift, knockdown_ratio = stagger_aftershock_knockdown_movement_ratio) + + last_time_victim_moved = world.time + +#undef VICTIM_MOVED_NO_GRAVITY_EFFECT_MULT +#undef VICTIM_MOVED_CAREFULLY_EFFECT_MULT + +/// If our victim is buckled to a generic object, movement effects will be multiplied against this. +#define VICTIM_BUCKLED_BASE_MOVEMENT_EFFECT_MULT 0.5 +/// If our victim is buckled to a medical bed (e.g. rollerbed), movement effects will be multiplied against this. +#define VICTIM_BUCKLED_ROLLER_BED_MOVEMENT_EFFECT_MULT 0.05 + +/// Returns a multiplier to our movement effects based on what our victim is buckled to. +/datum/wound/blunt/robotic/proc/get_buckled_movement_consequence_mult(atom/movable/buckled_to) + if (!buckled_to) + return 1 + + if (istype(buckled_to, /obj/structure/bed/medical)) + return VICTIM_BUCKLED_ROLLER_BED_MOVEMENT_EFFECT_MULT + else + return VICTIM_BUCKLED_BASE_MOVEMENT_EFFECT_MULT + +#undef VICTIM_BUCKLED_BASE_MOVEMENT_EFFECT_MULT +#undef VICTIM_BUCKLED_ROLLER_BED_MOVEMENT_EFFECT_MULT + +/// If this wound can be treated in its current state by just hitting it with a low force object. Exists for conditional logic, e.g. "Should we respond +/// to percussive maintenance right now?". Critical blunt uses this to only react when the limb is malleable and superstructure is broken. +/datum/wound/blunt/robotic/proc/uses_percussive_maintenance() + return FALSE + +#undef ROBOTIC_WOUND_DETERMINATION_MOVEMENT_EFFECT_MOD +#undef ROBOTIC_WOUND_DETERMINATION_STAGGER_MOVEMENT_MULT + +#undef ROBOTIC_BLUNT_GRASPED_MOVEMENT_MULT diff --git a/modular_skyrat/modules/medical/code/wounds/synth/blunt/robotic_blunt_T1.dm b/modular_skyrat/modules/medical/code/wounds/synth/blunt/robotic_blunt_T1.dm new file mode 100644 index 00000000000..9cd2ae0adbb --- /dev/null +++ b/modular_skyrat/modules/medical/code/wounds/synth/blunt/robotic_blunt_T1.dm @@ -0,0 +1,65 @@ +/datum/wound/blunt/robotic/moderate + name = "Loosened Screws" + desc = "Various semi-external fastening instruments have loosened, causing components to jostle, inhibiting limb control." + treat_text = "Recommend topical re-fastening of instruments with a screwdriver, though percussive maintenance via low-force bludgeoning may suffice - \ + albeit at risk of worsening the injury." + examine_desc = "appears to be loosely secured" + occur_text = "jostles awkwardly and seems to slightly unfasten" + severity = WOUND_SEVERITY_MODERATE + simple_treat_text = "Bandaging the wound will reduce the impact until it's screws are secured - which is faster if done by \ + someone else, a roboticist, an engineer, or with a diagnostic HUD." + homemade_treat_text = "In a pinch, percussive maintenance can reset the screws - the chance of which is increased if done by someone else or \ + with a diagnostic HUD!" + status_effect_type = /datum/status_effect/wound/blunt/robotic/moderate + treatable_tools = list(TOOL_SCREWDRIVER) + interaction_efficiency_penalty = 1.2 + limp_slowdown = 2.5 + limp_chance = 30 + threshold_penalty = 20 + can_scar = FALSE + a_or_from = "from" + +/datum/wound_pregen_data/blunt_metal/loose_screws + abstract = FALSE + wound_path_to_generate = /datum/wound/blunt/robotic/moderate + viable_zones = list(BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + threshold_minimum = 30 + +/datum/wound/blunt/robotic/moderate/uses_percussive_maintenance() + return TRUE + +/datum/wound/blunt/robotic/moderate/treat(obj/item/potential_treater, mob/user) + if (potential_treater.tool_behaviour == TOOL_SCREWDRIVER) + fasten_screws(potential_treater, user) + return TRUE + + return ..() + +/// The main treatment for T1 blunt. Uses a screwdriver, guaranteed to always work, better with a diag hud. Removes the wound. +/datum/wound/blunt/robotic/moderate/proc/fasten_screws(obj/item/screwdriver_tool, mob/user) + if (!screwdriver_tool.tool_start_check()) + return + + var/delay_mult = 1 + + if (user == victim) + delay_mult *= 3 + + if (HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD)) + delay_mult *= 0.5 + + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + delay_mult *= 0.5 + + var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") + var/your_or_other = (user == victim ? "your" : "[victim]'s") + victim.visible_message(span_notice("[user] begins fastening the screws of [their_or_other] [limb.plaintext_zone]..."), \ + span_notice("You begin fastening the screws of [your_or_other] [limb.plaintext_zone]...")) + + if (!screwdriver_tool.use_tool(target = victim, user = user, delay = (10 SECONDS * delay_mult), volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + return + + victim.visible_message(span_green("[user] finishes fastening [their_or_other] [limb.plaintext_zone]!"), \ + span_green("You finish fastening [your_or_other] [limb.plaintext_zone]!")) + + remove_wound() diff --git a/modular_skyrat/modules/medical/code/wounds/synth/blunt/robotic_blunt_T2.dm b/modular_skyrat/modules/medical/code/wounds/synth/blunt/robotic_blunt_T2.dm new file mode 100644 index 00000000000..68bac1fe12b --- /dev/null +++ b/modular_skyrat/modules/medical/code/wounds/synth/blunt/robotic_blunt_T2.dm @@ -0,0 +1,52 @@ +/datum/wound/blunt/robotic/secures_internals/severe + name = "Detached Fastenings" + desc = "Various fastening devices are extremely loose and solder has disconnected at multiple points, causing significant jostling of internal components and \ + noticable limb dysfunction." + treat_text = "Fastening of bolts and screws by a qualified technician (though bone gel may suffice in the absence of one) followed by re-soldering." + examine_desc = "jostles with every move, solder visibly broken" + occur_text = "visibly cracks open, solder flying everywhere" + severity = WOUND_SEVERITY_SEVERE + + simple_treat_text = "If on the chest, walk, grasp it, splint, rest or buckle yourself to something to reduce movement effects. \ + Afterwards, get someone else, ideally a robo/engi to screwdriver/wrench it, and then re-solder it!" + homemade_treat_text = "If unable to screw/wrench, bone gel can, over time, secure inner components at risk of corrossion. \ + Alternatively, crowbar the limb open to expose the internals - this will make it easier to re-secure them, but has a high risk of shocking you, \ + so use insulated gloves. This will cripple the limb, so use it only as a last resort!" + + wound_flags = (ACCEPTS_GAUZE|MANGLES_EXTERIOR|SPLINT_OVERLAY|CAN_BE_GRASPED) + treatable_by = list(/obj/item/stack/medical/bone_gel) + status_effect_type = /datum/status_effect/wound/blunt/robotic/severe + treatable_tools = list(TOOL_WELDER, TOOL_CROWBAR) + + interaction_efficiency_penalty = 2 + limp_slowdown = 6 + limp_chance = 60 + + brain_trauma_group = BRAIN_TRAUMA_MILD + trauma_cycle_cooldown = 1.5 MINUTES + + threshold_penalty = 40 + + base_movement_stagger_score = 40 + + chest_attacked_stagger_chance_ratio = 5 + chest_attacked_stagger_mult = 3 + + chest_movement_stagger_chance = 3 + + stagger_aftershock_knockdown_ratio = 0.3 + stagger_aftershock_knockdown_movement_ratio = 0.2 + + a_or_from = "from" + + ready_to_secure_internals = TRUE + ready_to_resolder = FALSE + + scar_keyword = "bluntsevere" + +/datum/wound_pregen_data/blunt_metal/fastenings + abstract = FALSE + + wound_path_to_generate = /datum/wound/blunt/robotic/secures_internals/severe + + threshold_minimum = 65 diff --git a/modular_skyrat/modules/medical/code/wounds/synth/blunt/robotic_blunt_T3.dm b/modular_skyrat/modules/medical/code/wounds/synth/blunt/robotic_blunt_T3.dm new file mode 100644 index 00000000000..aa85498108a --- /dev/null +++ b/modular_skyrat/modules/medical/code/wounds/synth/blunt/robotic_blunt_T3.dm @@ -0,0 +1,385 @@ +/datum/wound/blunt/robotic/secures_internals/critical + name = "Collapsed Superstructure" + desc = "The superstructure has totally collapsed in one or more locations, causing extreme internal oscillation with every move and massive limb dysfunction" + treat_text = "Reforming of superstructure via either RCD or manual molding, followed by typical treatment of loosened internals. \ + To manually mold, the limb must be aggressively grabbed and welded held to it to make it malleable (though attacking it til thermal overload may be adequate) \ + followed by firmly grasping and molding the limb with heat-resistant gloves." + occur_text = "caves in on itself, damaged solder and shrapnel flying out in a miniature explosion" + examine_desc = "has caved in, with internal components visible through gaps in the metal" + severity = WOUND_SEVERITY_CRITICAL + + disabling = TRUE + + simple_treat_text = "If on the chest, walk, grasp it, splint, rest or buckle yourself to something to reduce movement effects. \ + Afterwards, get someone, ideally a robo/engi to firmly grasp the limb and hold a welder to it. Then, have them use their hands to mold the metal - \ + careful though, it's hot! An RCD can skip all this, but is hard to come by. Afterwards, have them screw/wrench and then re-solder the limb!" + + homemade_treat_text = "The metal can be made malleable by repeated application of a welder, to a severe burn. Afterwards, a plunger can reset the metal, \ + as can percussive maintenance. After the metal is reset, if unable to screw/wrench, bone gel can, over time, secure inner components at risk of corrossion. \ + Alternatively, crowbar the limb open to expose the internals - this will make it easier to re-secure them, but has a high risk of shocking you, \ + so use insulated gloves. This will cripple the limb, so use it only as a last resort!" + + interaction_efficiency_penalty = 2.8 + limp_slowdown = 8 + limp_chance = 80 + threshold_penalty = 60 + + brain_trauma_group = BRAIN_TRAUMA_SEVERE + trauma_cycle_cooldown = 2.5 MINUTES + + scar_keyword = "bluntcritical" + + status_effect_type = /datum/status_effect/wound/blunt/robotic/critical + + sound_effect = 'sound/effects/wounds/crack2.ogg' + + wound_flags = (ACCEPTS_GAUZE|MANGLES_EXTERIOR|SPLINT_OVERLAY|CAN_BE_GRASPED) + treatable_by = list(/obj/item/stack/medical/bone_gel) + status_effect_type = /datum/status_effect/wound/blunt/robotic/critical + treatable_tools = list(TOOL_WELDER, TOOL_CROWBAR) + + base_movement_stagger_score = 55 + + base_aftershock_camera_shake_duration = 1.75 SECONDS + base_aftershock_camera_shake_strength = 1 + + chest_attacked_stagger_chance_ratio = 6.5 + chest_attacked_stagger_mult = 4 + + chest_movement_stagger_chance = 14 + + aftershock_stopped_moving_score_mult = 0.3 + + stagger_aftershock_knockdown_ratio = 0.5 + stagger_aftershock_knockdown_movement_ratio = 0.3 + + percussive_maintenance_repair_chance = 3 + percussive_maintenance_damage_max = 6 + + regen_time_needed = 60 SECONDS + gel_damage = 20 + + ready_to_secure_internals = FALSE + ready_to_resolder = FALSE + + a_or_from = "a" + + /// Has the first stage of our treatment been completed? E.g. RCDed, manually molded... + var/superstructure_remedied = FALSE + +/datum/wound_pregen_data/blunt_metal/superstructure + abstract = FALSE + wound_path_to_generate = /datum/wound/blunt/robotic/secures_internals/critical + threshold_minimum = 125 + +/datum/wound/blunt/robotic/secures_internals/critical/item_can_treat(obj/item/potential_treater) + if(!superstructure_remedied) + if(istype(potential_treater, /obj/item/construction/rcd)) + return TRUE + if(limb_malleable() && istype(potential_treater, /obj/item/plunger)) + return TRUE + return ..() + +/datum/wound/blunt/robotic/secures_internals/critical/check_grab_treatments(obj/item/potential_treater, mob/user) + if(potential_treater.tool_behaviour == TOOL_WELDER && (!superstructure_remedied && !limb_malleable())) + return TRUE + return ..() + +/datum/wound/blunt/robotic/secures_internals/critical/treat(obj/item/item, mob/user) + if(!superstructure_remedied) + if(istype(item, /obj/item/construction/rcd)) + return rcd_superstructure(item, user) + if(uses_percussive_maintenance() && istype(item, /obj/item/plunger)) + return plunge(item, user) + if(item.tool_behaviour == TOOL_WELDER && !limb_malleable() && isliving(victim.pulledby)) + var/mob/living/living_puller = victim.pulledby + if (living_puller.grab_state >= GRAB_AGGRESSIVE) // only let other people do this + return heat_metal(item, user) + return ..() + +/datum/wound/blunt/robotic/secures_internals/critical/try_handling(mob/living/carbon/human/user) + if(user.pulling != victim || user.zone_selected != limb.body_zone) + return FALSE + + if(superstructure_remedied || !limb_malleable()) + return FALSE + + if(user.grab_state < GRAB_AGGRESSIVE) + to_chat(user, span_warning("You must have [victim] in an aggressive grab to manipulate [victim.p_their()] [lowertext(name)]!")) + return TRUE + + user.visible_message(span_danger("[user] begins softly pressing against [victim]'s collapsed [limb.plaintext_zone]..."), \ + span_notice("You begin softly pressing against [victim]'s collapsed [limb.plaintext_zone]..."), \ + ignored_mobs = victim) + to_chat(victim, span_userdanger("[user] begins pressing against your collapsed [limb.plaintext_zone]!")) + + var/delay_mult = 1 + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + delay_mult *= 0.75 + + if(!do_after(user, 8 SECONDS, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + return + mold_metal(user) + return TRUE + +/// If the user turns combat mode on after they start to mold metal, our limb takes this much brute damage. +#define MOLD_METAL_SABOTAGE_BRUTE_DAMAGE 30 // really punishing +/// Our limb takes this much brute damage on a failed mold metal attempt. +#define MOLD_METAL_FAILURE_BRUTE_DAMAGE 5 +/// If the user's hand is unprotected from heat when they mold metal, we do this much burn damage to it. +#define MOLD_METAL_HAND_BURNT_BURN_DAMAGE 5 +/// Gloves must be above or at this threshold to cause the user to not be burnt apon trying to mold metal. +#define MOLD_METAL_HEAT_RESISTANCE_THRESHOLD 1000 // less than the black gloves max resist +/** + * Standard treatment for 1st step of T3, after the limb has been made malleable. Done via aggrograb. + * High chance to work, very high with robo/engi wires and diag hud. + * Can be sabotaged by switching to combat mode. + * Deals brute to the limb on failure. + * Burns the hand of the user if its not insulated. + */ +/datum/wound/blunt/robotic/secures_internals/critical/proc/mold_metal(mob/living/carbon/human/user) + var/chance = 60 + + var/knows_wires = FALSE + if (HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) + chance *= 2 + knows_wires = TRUE + else if (HAS_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) + chance *= 1.25 + knows_wires = TRUE + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + chance *= 2 + if (HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD)) + if (knows_wires) + chance *= 1.25 + else + chance *= 2 + + var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") + var/your_or_other = (user == victim ? "your" : "[victim]'s") + + if ((user != victim && user.combat_mode)) + user.visible_message(span_bolddanger("[user] molds [their_or_other] [limb.plaintext_zone] into a really silly shape! What a goofball!"), \ + span_danger("You maliciously mold [victim]'s [limb.plaintext_zone] into a weird shape, damaging it in the process!"), ignored_mobs = victim) + to_chat(victim, span_userdanger("[user] molds your [limb.plaintext_zone] into a weird shape, damaging it in the process!")) + + limb.receive_damage(brute = MOLD_METAL_SABOTAGE_BRUTE_DAMAGE, wound_bonus = CANT_WOUND, damage_source = user) + else if (prob(chance)) + user.visible_message(span_green("[user] carefully molds [their_or_other] [limb.plaintext_zone] into the proper shape!"), \ + span_green("You carefully mold [victim]'s [limb.plaintext_zone] into the proper shape!"), ignored_mobs = victim) + to_chat(victim, span_green("[user] carefully molds your [limb.plaintext_zone] into the proper shape!")) + to_chat(user, span_green("[capitalize(your_or_other)] [limb.plaintext_zone] has been molded into the proper shape! Your next step is to use a screwdriver/wrench to secure your internals.")) + set_superstructure_status(TRUE) + else + user.visible_message(span_danger("[user] accidentally molds [their_or_other] [limb.plaintext_zone] into the wrong shape!"), \ + span_danger("You accidentally mold [your_or_other] [limb.plaintext_zone] into the wrong shape!"), ignored_mobs = victim) + to_chat(victim, span_userdanger("[user] accidentally molds your [limb.plaintext_zone] into the wrong shape!")) + + limb.receive_damage(brute = MOLD_METAL_FAILURE_BRUTE_DAMAGE, damage_source = user, wound_bonus = CANT_WOUND) + + var/sufficiently_insulated_gloves = FALSE + var/obj/item/clothing/gloves/worn_gloves = user.gloves + if ((worn_gloves?.heat_protection & HANDS) && worn_gloves?.max_heat_protection_temperature && worn_gloves.max_heat_protection_temperature >= MOLD_METAL_HEAT_RESISTANCE_THRESHOLD) + sufficiently_insulated_gloves = TRUE + + if (sufficiently_insulated_gloves || HAS_TRAIT(user, TRAIT_RESISTHEAT) || HAS_TRAIT(user, TRAIT_RESISTHEATHANDS)) + return + + to_chat(user, span_danger("You burn your hand on [victim]'s [limb.plaintext_zone]!")) + var/obj/item/bodypart/affecting = user.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm") + affecting?.receive_damage(burn = MOLD_METAL_HAND_BURNT_BURN_DAMAGE, damage_source = limb) + +#undef MOLD_METAL_SABOTAGE_BRUTE_DAMAGE +#undef MOLD_METAL_FAILURE_BRUTE_DAMAGE +#undef MOLD_METAL_HAND_BURNT_BURN_DAMAGE +#undef MOLD_METAL_HEAT_RESISTANCE_THRESHOLD + +/** + * A "safe" way to give our victim a T2 burn wound. Requires an aggrograb, and a welder. This is required to mold metal, the 1st step of treatment. + * Guaranteed to work. After a delay, causes a T2 burn wound with no damage. + * Can be sabotaged by enabling combat mode to cause a T3. + */ +/datum/wound/blunt/robotic/secures_internals/critical/proc/heat_metal(obj/item/welder, mob/living/user) + if (!welder.tool_use_check()) + return TRUE + + var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") + var/your_or_other = (user == victim ? "your" : "[victim]'s") + + user?.visible_message(span_danger("[user] carefully holds [welder] to [their_or_other] [limb.plaintext_zone], slowly heating it..."), \ + span_warning("You carefully hold [welder] to [your_or_other] [limb.plaintext_zone], slowly heating it..."), ignored_mobs = victim) + + var/delay_mult = 1 + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + delay_mult *= 0.75 + + if (!welder.use_tool(target = victim, user = user, delay = 10 SECONDS * delay_mult, volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + return TRUE + + var/wound_path = /datum/wound/burn/robotic/overheat/severe + if (user != victim && user.combat_mode) + wound_path = /datum/wound/burn/robotic/overheat/critical // it really isnt that bad, overheat wounds are a bit funky + user.visible_message(span_danger("[user] heats [victim]'s [limb.plaintext_zone] aggressively, overheating it far beyond the necessary point!"), \ + span_danger("You heat [victim]'s [limb.plaintext_zone] aggressively, overheating it far beyond the necessary point!"), ignored_mobs = victim) + to_chat(victim, span_userdanger("[user] heats your [limb.plaintext_zone] aggressively, overheating it far beyond the necessary point!")) + + var/datum/wound/burn/robotic/overheat/overheat_wound = new wound_path + overheat_wound.apply_wound(limb, wound_source = welder) + + to_chat(user, span_green("[capitalize(your_or_other)] [limb.plaintext_zone] is now heated, allowing it to be molded! Your next step is to have someone physically reset the superstructure with their hands.")) + return TRUE + +/// Cost of an RCD to quickly fix our broken in raw matter +#define ROBOTIC_T3_BLUNT_WOUND_RCD_COST 25 +/// Cost of an RCD to quickly fix our broken in silo material +#define ROBOTIC_T3_BLUNT_WOUND_RCD_SILO_COST ROBOTIC_T3_BLUNT_WOUND_RCD_COST / 4 + +/// The "premium" treatment for 1st step of T3. Requires an RCD. Guaranteed to work, but can cause damage if delay is high. +/datum/wound/blunt/robotic/secures_internals/critical/proc/rcd_superstructure(obj/item/construction/rcd/treating_rcd, mob/user) + if (!treating_rcd.tool_use_check()) + return TRUE + + var/has_enough_matter = (treating_rcd.get_matter(user) > ROBOTIC_T3_BLUNT_WOUND_RCD_COST) + var/silo_has_enough_materials = (treating_rcd.get_silo_iron() > ROBOTIC_T3_BLUNT_WOUND_RCD_SILO_COST) + + if (!silo_has_enough_materials && has_enough_matter) + return TRUE + + var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") + var/your_or_other = (user == victim ? "your" : "[victim]'s") + + var/base_time = 10 SECONDS + var/delay_mult = 1 + var/knows_wires = FALSE + if (victim == user) + delay_mult *= 3 // real slow + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + delay_mult *= 0.75 + if (HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) + delay_mult *= 0.5 + knows_wires = TRUE + else if (HAS_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) + delay_mult *= 0.5 // engis are accustomed to using RCDs + knows_wires = TRUE + if (HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD)) + if (knows_wires) + delay_mult *= 0.85 + else + delay_mult *= 0.5 + + var/final_time = (base_time * delay_mult) + var/misused = (final_time > base_time) // if we damage the limb when we're done + + if (user) + var/misused_text = (misused ? "unsteadily " : "") + + var/message = "[user]'s RCD whirs to life as it begins [misused_text]replacing the damaged superstructure of [their_or_other] [limb.plaintext_zone]..." + var/self_message = "Your RCD whirs to life as it begins [misused_text]replacing the damaged superstructure of [your_or_other] [limb.plaintext_zone]..." + + if (misused) // warning span if misused, notice span otherwise + message = span_danger(message) + self_message = span_danger(self_message) + else + message = span_notice(message) + self_message = span_notice(self_message) + + user.visible_message(message, self_message) + + if (!treating_rcd.use_tool(target = victim, user = user, delay = final_time, volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + return TRUE + playsound(get_turf(treating_rcd), 'sound/machines/ping.ogg', 75) // celebration! we did it + set_superstructure_status(TRUE) + + var/use_amount = (silo_has_enough_materials ? ROBOTIC_T3_BLUNT_WOUND_RCD_SILO_COST : ROBOTIC_T3_BLUNT_WOUND_RCD_COST) + treating_rcd.useResource(use_amount, user) + + if (user) + var/misused_text = (misused ? ", though it replaced a bit more than it should've..." : "!") + var/message = "[user]'s RCD lets out a small ping as it finishes replacing the superstructure of [their_or_other] [limb.plaintext_zone][misused_text]" + var/self_message = "Your RCD lets out a small ping as it finishes replacing the superstructure of [your_or_other] [limb.plaintext_zone][misused_text]" + if (misused) + message = span_danger(message) + self_message = span_danger(self_message) + else + message = span_green(message) + self_message = span_green(self_message) + + user.visible_message(message, self_message) + if (misused) + limb.receive_damage(brute = 10, damage_source = treating_rcd, wound_bonus = CANT_WOUND) + // the double message is fine here, since the first message also tells you if you fucked up and did some damage + to_chat(user, span_green("The superstructure has been reformed! Your next step is to secure the internals via a screwdriver/wrench.")) + return TRUE + +#undef ROBOTIC_T3_BLUNT_WOUND_RCD_COST +#undef ROBOTIC_T3_BLUNT_WOUND_RCD_SILO_COST + +/** + * Goofy but practical, this is the superior ghetto self-tend of T3's first step compared to percussive maintenance. + * Still requires the limb to be malleable, but has a high chance of success and doesn't burn your hand, but gives worse bonuses for wires/HUD. + */ +/datum/wound/blunt/robotic/secures_internals/critical/proc/plunge(obj/item/plunger/treating_plunger, mob/user) + if (!treating_plunger.tool_use_check()) + return TRUE + + var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") + var/your_or_other = (user == victim ? "your" : "[victim]'s") + user?.visible_message(span_notice("[user] begins plunging at the dents on [their_or_other] [limb.plaintext_zone] with [treating_plunger]..."), \ + span_green("You begin plunging at the dents on [your_or_other] [limb.plaintext_zone] with [treating_plunger]...")) + + var/delay_mult = 1 + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + delay_mult *= 0.75 + + delay_mult /= treating_plunger.plunge_mod + + if (!treating_plunger.use_tool(target = victim, user = user, delay = 8 SECONDS * delay_mult, volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + return TRUE + + var/success_chance = 80 + if (victim == user) + success_chance *= 0.6 + + if (HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) + success_chance *= 1.25 + else if (HAS_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) + success_chance *= 1.1 + if (HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD)) + success_chance *= 1.25 // its kinda alien to do this, so even people with the wires get the full bonus of diag huds + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + success_chance *= 1.5 + + if (prob(success_chance)) + user?.visible_message(span_green("[victim]'s [limb.plaintext_zone] lets out a sharp POP as [treating_plunger] forces it into its normal position!"), \ + span_green("[victim]'s [limb.plaintext_zone] lets out a sharp POP as your [treating_plunger] forces it into its normal position!")) + to_chat(user, span_green("[capitalize(your_or_other)] [limb.plaintext_zone]'s structure has been reset to it's proper position! Your next step is to secure it with a screwdriver/wrench, though bone gel would also work.")) + set_superstructure_status(TRUE) + else + user?.visible_message(span_danger("[victim]'s [limb.plaintext_zone] splinters from [treating_plunger]'s plunging!"), \ + span_danger("[capitalize(your_or_other)] [limb.plaintext_zone] splinters from your [treating_plunger]'s plunging!")) + limb.receive_damage(brute = 5, damage_source = treating_plunger) + + return TRUE + +/datum/wound/blunt/robotic/secures_internals/critical/handle_percussive_maintenance_success(attacking_item, mob/living/user) + var/your_or_other = (user == victim ? "your" : "[victim]'s") + victim.visible_message(span_green("[victim]'s [limb.plaintext_zone] gets smashed into a proper shape!"), \ + span_green("Your [limb.plaintext_zone] gets smashed into a proper shape!")) + + var/user_message = "[capitalize(your_or_other)] [limb.plaintext_zone]'s superstructure has been reset! Your next step is to screwdriver/wrench the internals, \ + though if you're desperate enough to use percussive maintenance, you might want to either use a crowbar or bone gel..." + to_chat(user, span_green(user_message)) + + set_superstructure_status(TRUE) + +/datum/wound/blunt/robotic/secures_internals/critical/handle_percussive_maintenance_failure(attacking_item, mob/living/user) + to_chat(victim, span_danger("Your [limb.plaintext_zone] only deforms more from the impact...")) + limb.receive_damage(brute = 1, damage_source = attacking_item, wound_bonus = CANT_WOUND) + +/datum/wound/blunt/robotic/secures_internals/critical/uses_percussive_maintenance() + return (!superstructure_remedied && limb_malleable()) + +/// Transitions our steps by setting both superstructure and secure internals readiness. +/datum/wound/blunt/robotic/secures_internals/critical/proc/set_superstructure_status(remedied) + superstructure_remedied = remedied + ready_to_secure_internals = remedied diff --git a/modular_skyrat/modules/medical/code/wounds/synth/blunt/secures_internals.dm b/modular_skyrat/modules/medical/code/wounds/synth/blunt/secures_internals.dm new file mode 100644 index 00000000000..9dd515813ef --- /dev/null +++ b/modular_skyrat/modules/medical/code/wounds/synth/blunt/secures_internals.dm @@ -0,0 +1,388 @@ +/// A subtype of blunt wounds that has a "secure internals" step +/datum/wound/blunt/robotic/secures_internals + /// Our current counter for gel + gauze regeneration + var/regen_time_elapsed = 0 SECONDS + /// Time needed for gel to secure internals. + var/regen_time_needed = 30 SECONDS + + /// If we have used bone gel to secure internals. + var/gelled = FALSE + /// Total brute damage taken over the span of [regen_time_needed] deciseconds when we gel our limb. + var/gel_damage = 10 // brute in total + + /// If we are ready to begin screwdrivering or gelling our limb. + var/ready_to_secure_internals = FALSE + /// If our external plating has been torn open and we can access our internals without a tool + var/crowbarred_open = FALSE + /// If internals are secured, and we are ready to weld our limb closed and end the wound + var/ready_to_resolder = TRUE + +/datum/wound/blunt/robotic/secures_internals/handle_process(seconds_per_tick, times_fired) + . = ..() + + if (!victim || IS_IN_STASIS(victim)) + return + + if (gelled) + regen_time_elapsed += ((seconds_per_tick SECONDS) / 2) + if(victim.body_position == LYING_DOWN) + if(SPT_PROB(30, seconds_per_tick)) + regen_time_elapsed += 1 SECONDS + if(victim.IsSleeping() && SPT_PROB(30, seconds_per_tick)) + regen_time_elapsed += 1 SECONDS + + var/effective_damage = ((gel_damage / (regen_time_needed / 10)) * seconds_per_tick) + var/obj/item/stack/gauze = limb.current_gauze + if (gauze) + effective_damage *= gauze.splint_factor + limb.receive_damage(effective_damage, wound_bonus = CANT_WOUND, damage_source = src) + if(effective_damage && prob(33)) + var/gauze_text = (gauze?.splint_factor ? ", although the [gauze] helps to prevent some of the leakage" : "") + to_chat(victim, span_danger("Your [limb.plaintext_zone] sizzles as some gel leaks and warps the exterior metal[gauze_text]...")) + + if(regen_time_elapsed > regen_time_needed) + if(!victim || !limb) + qdel(src) + return + to_chat(victim, span_green("The gel within your [limb.plaintext_zone] has fully hardened, allowing you to re-solder it!")) + gelled = FALSE + ready_to_resolder = TRUE + ready_to_secure_internals = FALSE + set_disabling(FALSE) + +/datum/wound/blunt/robotic/secures_internals/modify_desc_before_span(desc) + . = ..() + + var/use_exclamation = FALSE + + if (!limb.current_gauze) // gauze covers it up + if (crowbarred_open) + . += ", [span_notice("and is violently torn open, internals visible to the outside")]" + use_exclamation = TRUE + if (gelled) + . += ", [span_notice("with fizzling blue surgical gel leaking out of the cracks")]" + use_exclamation = TRUE + if (use_exclamation) + . += "!" + +/datum/wound/blunt/robotic/secures_internals/get_scanner_description(mob/user) + . = ..() + + var/to_add = get_wound_status() + if (!isnull(to_add)) + . += "\nWound status: [to_add]" + +/datum/wound/blunt/robotic/secures_internals/get_simple_scanner_description(mob/user) + . = ..() + + var/to_add = get_wound_status() + if (!isnull(to_add)) + . += "\nWound status: [to_add]" + +/// Returns info specific to the dynamic state of the wound. +/datum/wound/blunt/robotic/secures_internals/proc/get_wound_status(mob/user) + if (crowbarred_open) + . += "The limb has been torn open, allowing ease of access to internal components, but also disabling it. " + if (gelled) + . += "Bone gel has been applied, causing progressive corrosion of the metal, but eventually securing the internals. " + +/datum/wound/blunt/robotic/secures_internals/item_can_treat(obj/item/potential_treater, mob/user) + if (potential_treater.tool_behaviour == TOOL_WELDER || potential_treater.tool_behaviour == TOOL_CAUTERY) + if (ready_to_resolder) + return TRUE + + if (ready_to_secure_internals) + if (item_can_secure_internals(potential_treater)) + return TRUE + + return ..() + +/datum/wound/blunt/robotic/secures_internals/treat(obj/item/potential_treater, mob/user) + if (ready_to_secure_internals) + if (istype(potential_treater, /obj/item/stack/medical/bone_gel)) + return apply_gel(potential_treater, user) + else if (!crowbarred_open && potential_treater.tool_behaviour == TOOL_CROWBAR) + return crowbar_open(potential_treater, user) + else if (item_can_secure_internals(potential_treater)) + return secure_internals_normally(potential_treater, user) + else if (ready_to_resolder && (potential_treater.tool_behaviour == TOOL_WELDER) || (potential_treater.tool_behaviour == TOOL_CAUTERY)) + return resolder(potential_treater, user) + + return ..() + +/// Returns TRUE if the item can be used in our 1st step (2nd if T3) of repairs. +/datum/wound/blunt/robotic/secures_internals/proc/item_can_secure_internals(obj/item/potential_treater) + return (potential_treater.tool_behaviour == TOOL_SCREWDRIVER || potential_treater.tool_behaviour == TOOL_WRENCH || istype(potential_treater, /obj/item/stack/medical/bone_gel)) + +#define CROWBAR_OPEN_SELF_TEND_DELAY_MULT 2 +#define CROWBAR_OPEN_KNOWS_ROBO_WIRES_DELAY_MULT 0.5 +#define CROWBAR_OPEN_KNOWS_ENGI_WIRES_DELAY_MULT 0.5 +#define CROWBAR_OPEN_HAS_DIAG_HUD_DELAY_MULT 0.5 +#define CROWBAR_OPEN_WOUND_SCANNED_DELAY_MULT 0.5 +/// If our limb is essential, damage dealt to it by tearing it open will be multiplied against this. +#define CROWBAR_OPEN_ESSENTIAL_LIMB_DAMAGE_MULT 1.5 + +/// The "power" put into electrocute_act whenever someone gets shocked when they crowbar open our limb +#define CROWBAR_OPEN_SHOCK_POWER 20 +/// The brute damage done to this limb (doubled on essential limbs) when it is crowbarred open +#define CROWBAR_OPEN_BRUTE_DAMAGE 20 + +/** + * Available during the "secure internals" step of T2 and T3. Requires a crowbar. Low-quality ghetto option. + * + * Tears open the limb, exposing internals. This massively increases the chance of secure internals succeeding, and removes the self-tend malice. + * + * Deals significant damage to the limb, and shocks the user (causing failure) if victim is alive, this limb is wired, and user is not insulated. + */ +/datum/wound/blunt/robotic/secures_internals/proc/crowbar_open(obj/item/crowbarring_item, mob/living/user) + if (!crowbarring_item.tool_start_check()) + return TRUE + + var/delay_mult = 1 + if (user == victim) + delay_mult *= CROWBAR_OPEN_SELF_TEND_DELAY_MULT + + var/knows_wires = FALSE + if (HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) + delay_mult *= CROWBAR_OPEN_KNOWS_ROBO_WIRES_DELAY_MULT + knows_wires = TRUE + else if (HAS_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) + delay_mult *= CROWBAR_OPEN_KNOWS_ENGI_WIRES_DELAY_MULT + knows_wires = TRUE + if (HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD)) + if (knows_wires) + delay_mult *= (CROWBAR_OPEN_HAS_DIAG_HUD_DELAY_MULT * 1.5) + else + delay_mult *= CROWBAR_OPEN_HAS_DIAG_HUD_DELAY_MULT + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + delay_mult *= CROWBAR_OPEN_WOUND_SCANNED_DELAY_MULT + + var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") + var/your_or_other = (user == victim ? "your" : "[victim]'s") + + var/self_message = span_warning("You start prying open [your_or_other] [limb.plaintext_zone] with [crowbarring_item]...") + + user?.visible_message(span_bolddanger("[user] starts prying open [their_or_other] [limb.plaintext_zone] with [crowbarring_item]!"), self_message, ignored_mobs = list(victim)) + + var/victim_message + if (user != victim) // this exists so we can do a userdanger + victim_message = span_userdanger("[user] starts prying open your [limb.plaintext_zone] with [crowbarring_item]!") + else + victim_message = self_message + to_chat(victim, victim_message) + + playsound(get_turf(crowbarring_item), 'sound/machines/airlock_alien_prying.ogg', 30, TRUE) + if (!crowbarring_item.use_tool(target = victim, user = user, delay = (7 SECONDS * delay_mult), volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + return TRUE + + var/limb_can_shock = (victim.stat != DEAD && limb.biological_state & BIO_WIRED) + var/stunned = FALSE + + var/message + + if (user && limb_can_shock) + var/electrocute_flags = (SHOCK_KNOCKDOWN|SHOCK_NO_HUMAN_ANIM|SHOCK_SUPPRESS_MESSAGE) + var/stun_chance = 100 + + if (HAS_TRAIT(user, TRAIT_SHOCKIMMUNE)) + stun_chance = 0 + + else if (iscarbon(user)) // doesn't matter if we're shock immune, it's set to 0 anyway + var/mob/living/carbon/carbon_user = user + if (carbon_user.gloves) + stun_chance *= carbon_user.gloves.siemens_coefficient + + if (ishuman(user)) + var/mob/living/carbon/human/human_user = user + stun_chance *= human_user.physiology.siemens_coeff + stun_chance *= carbon_user.dna.species.siemens_coeff + + if (stun_chance && prob(stun_chance)) + electrocute_flags &= ~SHOCK_KNOCKDOWN + electrocute_flags &= ~SHOCK_NO_HUMAN_ANIM + stunned = TRUE + + message = span_boldwarning("[user] is shocked by [their_or_other] [limb.plaintext_zone], [user.p_their()] crowbar slipping as [user.p_they()] briefly convulse!") + self_message = span_userdanger("You are shocked by [your_or_other] [limb.plaintext_zone], causing your crowbar to slip out!") + if (user != victim) + victim_message = span_userdanger("[user] is shocked by your [limb.plaintext_zone] in [user.p_their()] efforts to tear it open!") + + var/shock_damage = CROWBAR_OPEN_SHOCK_POWER + if (limb.current_gauze) + shock_damage *= limb.current_gauze.splint_factor // always good to let gauze do something + user.electrocute_act(shock_damage, limb, flags = electrocute_flags) + + if (!stunned) + var/other_shock_text = "" + var/self_shock_text = "" + if (!limb_can_shock) + other_shock_text = ", and is striken by golden bolts of electricity" + self_shock_text = ", but are immediately shocked by the electricity contained within" + message = span_boldwarning("[user] tears open [their_or_other] [limb.plaintext_zone] with [user.p_their()] crowbar[other_shock_text]!") + self_message = span_warning("You tear open [your_or_other] [limb.plaintext_zone] with your crowbar[self_shock_text]!") + if (user != victim) + victim_message = span_userdanger("Your [limb.plaintext_zone] fragments and splinters as [user] tears it open with [user.p_their()] crowbar!") + + playsound(get_turf(crowbarring_item), 'sound/effects/bang.ogg', 35, TRUE) // we did it! + to_chat(user, span_green("You've torn [your_or_other] [limb.plaintext_zone] open, heavily damaging it but making it a lot easier to screwdriver the internals!")) + var/damage = CROWBAR_OPEN_BRUTE_DAMAGE + if (limb_essential()) // can't be disabled + damage *= CROWBAR_OPEN_ESSENTIAL_LIMB_DAMAGE_MULT + limb.receive_damage(brute = CROWBAR_OPEN_BRUTE_DAMAGE, wound_bonus = CANT_WOUND, damage_source = crowbarring_item) + set_torn_open(TRUE) + + if (user == victim) + victim_message = self_message + + user.visible_message(message, self_message, ignored_mobs = list(victim)) + to_chat(victim, victim_message) + return TRUE + +#undef CROWBAR_OPEN_SELF_TEND_DELAY_MULT +#undef CROWBAR_OPEN_KNOWS_ROBO_WIRES_DELAY_MULT +#undef CROWBAR_OPEN_KNOWS_ENGI_WIRES_DELAY_MULT +#undef CROWBAR_OPEN_HAS_DIAG_HUD_DELAY_MULT +#undef CROWBAR_OPEN_WOUND_SCANNED_DELAY_MULT +#undef CROWBAR_OPEN_ESSENTIAL_LIMB_DAMAGE_MULT + +#undef CROWBAR_OPEN_BRUTE_DAMAGE +#undef CROWBAR_OPEN_SHOCK_POWER + +/// Sets [crowbarred_open] to the new value. If we werent originally disabling, or if we arent currently and we're torn open, we set disabling to true. +/datum/wound/blunt/robotic/secures_internals/proc/set_torn_open(torn_open_state) + // if we aren't disabling but we were torn open, OR if we aren't disabling by default + var/should_update_disabling = ((!disabling && torn_open_state) || !initial(disabling)) + + crowbarred_open = torn_open_state + if(should_update_disabling) + set_disabling(torn_open_state) + +/// If, on a secure internals attempt, we have less than this chance to succeed, we warn the user. +#define SECURE_INTERNALS_CONFUSED_CHANCE_THRESHOLD 25 +#define SECURE_INTERNALS_FAILURE_BRUTE_DAMAGE 5 + +/** + * The primary way of performing the secure internals step for T2/T3. Uses a screwdriver/wrench. Very hard to do by yourself, or without a diag hud/wire knowledge. + * Roboticists/engineers have a very high chance of succeeding. + * Deals some brute damage on failure, but moves to the final step of treatment (re-soldering) on success. + * + * If [crowbarred_open], made far more likely and remove the self-tend malice. + */ +/datum/wound/blunt/robotic/secures_internals/proc/secure_internals_normally(obj/item/securing_item, mob/user) + if (!securing_item.tool_start_check()) + return TRUE + + var/chance = 10 + var/delay_mult = 1 + + if (user == victim) + if (!crowbarred_open) + chance *= 0.2 + delay_mult *= 2 + + var/knows_wires = FALSE + if (crowbarred_open) + chance *= 4 // even self-tends get a high chance of success if torn open! + if (HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) + chance *= 8 // almost guaranteed if its not self surgery - guaranteed with diag hud + delay_mult *= 0.75 + knows_wires = TRUE + else if (HAS_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) + chance *= 5.5 + delay_mult *= 0.85 + knows_wires = TRUE + if (HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD)) + if (knows_wires) + chance *= 1.25 // ((10 * 8) * 1.25) = 100% + else + chance *= 4 + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + chance *= 1.5 // youre not intended to fix this by yourself this way + delay_mult *= 0.8 + + var/confused = (chance < SECURE_INTERNALS_CONFUSED_CHANCE_THRESHOLD) // generate chance beforehand, so we can use this var + + var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") + var/your_or_other = (user == victim ? "your" : "[victim]'s") + user?.visible_message(span_notice("[user] begins the delicate operation of securing the internals of [their_or_other] [limb.plaintext_zone]..."), \ + span_notice("You begin the delicate operation of securing the internals of [your_or_other] [limb.plaintext_zone]...")) + if (confused) + to_chat(user, span_warning("You are confused by the layout of [your_or_other] [limb.plaintext_zone]! A diagnostic hud would help, as would knowing robo/engi wires! You could also tear the limb open with a crowbar, or get someone else to help.")) + + if (!securing_item.use_tool(target = victim, user = user, delay = (10 SECONDS * delay_mult), volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + return TRUE + + if (prob(chance)) + user?.visible_message(span_green("[user] finishes securing the internals of [their_or_other] [limb.plaintext_zone]!"), \ + span_green("You finish securing the internals of [your_or_other] [limb.plaintext_zone]!")) + to_chat(user, span_green("[capitalize(your_or_other)] [limb.plaintext_zone]'s internals are now secure! Your next step is to weld/cauterize it.")) + ready_to_secure_internals = FALSE + ready_to_resolder = TRUE + else + user?.visible_message(span_danger("[user] screws up and accidentally damages [their_or_other] [limb.plaintext_zone]!")) + limb.receive_damage(brute = SECURE_INTERNALS_FAILURE_BRUTE_DAMAGE, damage_source = securing_item, wound_bonus = CANT_WOUND) + + return TRUE + +#undef SECURE_INTERNALS_CONFUSED_CHANCE_THRESHOLD +#undef SECURE_INTERNALS_FAILURE_BRUTE_DAMAGE + +/** + * "Premium" ghetto option of the secure internals step for T2/T3. Requires bone gel. Guaranteed to work. + * Deals damage over time and disables the limb, but finishes the step afterwards. + */ +/datum/wound/blunt/robotic/secures_internals/proc/apply_gel(obj/item/stack/medical/bone_gel/gel, mob/user) + if (gelled) + to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.plaintext_zone] is already filled with bone gel!")) + return TRUE + + var/delay_mult = 1 + if (victim == user) + delay_mult *= 0.5 + + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + delay_mult *= 0.75 + + user.visible_message(span_danger("[user] begins hastily applying [gel] to [victim]'s [limb.plaintext_zone]..."), span_warning("You begin hastily applying [gel] to [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone], disregarding the acidic effect it seems to have on the metal...")) + + if (!do_after(user, (8 SECONDS * delay_mult), target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + return TRUE + + gel.use(1) + if(user != victim) + user.visible_message(span_notice("[user] finishes applying [gel] to [victim]'s [limb.plaintext_zone], emitting a fizzing noise!"), span_notice("You finish applying [gel] to [victim]'s [limb.plaintext_zone]!"), ignored_mobs=victim) + to_chat(victim, span_userdanger("[user] finishes applying [gel] to your [limb.plaintext_zone], and you can hear the sizzling of the metal...")) + else + victim.visible_message(span_notice("[victim] finishes applying [gel] to [victim.p_their()] [limb.plaintext_zone], emitting a funny fizzing sound!"), span_notice("You finish applying [gel] to your [limb.plaintext_zone], and you can hear the sizzling of the metal...")) + + gelled = TRUE + set_disabling(TRUE) + processes = TRUE + return TRUE + +/** + * The final step of T2/T3, requires a welder/cautery. Guaranteed to work. Cautery is slower. + * Once complete, removes the wound entirely. + */ +/datum/wound/blunt/robotic/secures_internals/proc/resolder(obj/item/welding_item, mob/user) + if (!welding_item.tool_start_check()) + return TRUE + + var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") + var/your_or_other = (user == victim ? "your" : "[victim]'s") + victim.visible_message(span_notice("[user] begins re-soldering [their_or_other] [limb.plaintext_zone]..."), \ + span_notice("You begin re-soldering [your_or_other] [limb.plaintext_zone]...")) + + var/delay_mult = 1 + if (welding_item.tool_behaviour == TOOL_CAUTERY) + delay_mult *= 3 // less efficient + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + delay_mult *= 0.75 + + if (!welding_item.use_tool(target = victim, user = user, delay = 7 SECONDS * delay_mult, volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + return TRUE + + victim.visible_message(span_green("[user] finishes re-soldering [their_or_other] [limb.plaintext_zone]!"), \ + span_notice("You finish re-soldering [your_or_other] [limb.plaintext_zone]!")) + remove_wound() + return TRUE diff --git a/modular_skyrat/modules/medical/code/wounds/synth/robotic_burns.dm b/modular_skyrat/modules/medical/code/wounds/synth/robotic_burns.dm new file mode 100644 index 00000000000..24ac18eeab6 --- /dev/null +++ b/modular_skyrat/modules/medical/code/wounds/synth/robotic_burns.dm @@ -0,0 +1,441 @@ +#define OVERHEAT_ON_STASIS_HEAT_MULT 0.25 +/// At 100% hercuri composition, a spray of reagents will have its effective chem temp reduced by this. 50%, reduced by half this, etc. +#define ROBOTIC_BURN_REAGENT_EXPOSURE_HERCURI_MAX_HEAT_DECREMENT 60 +/// At 100% hercuri composition, a spray of reagents will have its heat shock damage reduced by this. 50%, reduced by half this, etc. +#define ROBOTIC_BURN_REAGENT_EXPOSURE_HERCURI_HEAT_SHOCK_MULT_DECREMENT 0.3 + +/datum/wound_pregen_data/burnt_metal + abstract = TRUE + required_limb_biostate = BIO_METAL + required_wounding_types = list(WOUND_BURN) + wound_series = WOUND_SERIES_METAL_BURN_OVERHEAT + +/datum/wound_pregen_data/burnt_metal/generate_scar_priorities() + return list("[BIO_METAL]") + +/datum/wound/burn/robotic/overheat + treat_text = "Introduction of a cold environment or lowering of body temperature." + + simple_desc = "Metals are overheated, increasing damage taken significantly and raising body temperature!" + simple_treat_text = "Ideally cryogenics, but any source of low body temperature can work. Spraying with spray bottles/extinguishers/showers \ + will quickly cool the limb, but cause damage. Hercuri is especially effective in quick cooling. \ + Clothing reduces the water/hercuri that makes it to the metal, and gauze binds it and reduces the damage taken." + homemade_treat_text = "You can also splash any liquid on it for a rather inefficient and damaging coolant!" + + default_scar_file = METAL_SCAR_FILE + + wound_flags = (ACCEPTS_GAUZE|SPLINT_OVERLAY|CAN_BE_GRASPED) // gauze binds the metal and makes it resistant to thermal shock + + processes = TRUE + + /// The virtual temperature of the chassis. Crucial for many things, like our severity, the temp we transfer, our cooling damage, etc. + var/chassis_temperature + + /// The lower bound of the chassis_temperature we can start with. + var/starting_temperature_min = (BODYTEMP_NORMAL + 200) + /// The upper bound of the chassis_temperature we can start with. + var/starting_temperature_max = (BODYTEMP_NORMAL + 250) + + /// If [chassis_temperature] goes below this, we reduce in severity. + var/cooling_threshold = (BODYTEMP_NORMAL + 3) + /// If [chassis_temperature] goes above this, we increase in severity. + var/heating_threshold = (BODYTEMP_NORMAL + 300) + + /// The buffer in kelvin we will subtract from the chassis_temperature of a wound we demote to. + var/cooling_demote_buffer = 60 + /// The buffer in kelvin we will add to the chassis_temperature of a wound we promote to. + var/heating_promote_buffer = 60 + + /// The coefficient of heat transfer we will use when shifting our temp to the victim's. + var/bodytemp_coeff = 0.04 + /// For every degree below normal bodytemp, we will multiply our incoming temperature by 1 + degrees * this. Allows incentivization of freezing yourself instead of just waiting. + var/bodytemp_difference_expose_bonus_ratio = 0.035 + /// The coefficient of heat transfer we will use when shifting our victim's temp to ours. + var/outgoing_bodytemp_coeff = 0 + /// The mult applied to heat output when we are on a important limb, e.g. head/torso. + var/important_outgoing_mult = 1.2 + /// The coefficient of heat transfer we will use when shifting our temp to a turf. + var/turf_coeff = 0.02 + + /// The maximum temperature we can cause by heating our victim. + var/max_outgoing_temperature = BODYTEMP_HEAT_WOUND_LIMIT - 1 + + /// If we are hit with burn damage, the damage will be multiplied against this to determine the effective heat we get. + var/incoming_damage_heat_coeff = 3 + + /// The coefficient of heat transfer we will use when receiving heat from reagent contact. + var/base_reagent_temp_coefficient = 0.02 + + /// The ratio of temp shift -> brute damage. Careful with this value, it can make stuff really really nasty. + var/heat_shock_delta_to_damage_ratio = 0.12 + /// The minimum heat difference we must have on reagent contact to cause heat shock damage. + var/heat_shock_minimum_delta = 5 + + /// If we are sprayed with a extinguisher/shower with obscuring clothing on (think clothing that prevents surgery), the effect is multiplied against this. + var/sprayed_with_reagent_clothed_mult = 0.15 + + /// The wound we demote to when we go below cooling threshold. If null, removes us. + var/datum/wound/burn/robotic/demotes_to + /// The wound we promote to when we go above heating threshold. + var/datum/wound/burn/robotic/promotes_to + + /// The color of the light we will generate. + var/light_color + /// The power of the light we will generate. + var/light_power + /// The range of the light we will generate. + var/light_range + + /// The glow we have attached to our victim, to simulate our limb glowing. + var/obj/effect/dummy/lighting_obj/moblight/mob_glow + +/datum/wound/burn/robotic/overheat/New(temperature) + chassis_temperature = (isnull(temperature) ? get_random_starting_temperature() : temperature) + + return ..() + +/datum/wound/burn/robotic/overheat/Destroy() + QDEL_NULL(mob_glow) + return ..() + +/datum/wound/burn/robotic/overheat/set_victim(mob/living/new_victim) + if (victim) + QDEL_NULL(mob_glow) + UnregisterSignal(victim, COMSIG_MOB_AFTER_APPLY_DAMAGE) + UnregisterSignal(victim, COMSIG_ATOM_AFTER_EXPOSE_REAGENTS) + if (new_victim) + mob_glow = new_victim.mob_light(light_range, light_power, light_color) + mob_glow.set_light_on(TRUE) + RegisterSignal(new_victim, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(victim_attacked)) + RegisterSignal(new_victim, COMSIG_ATOM_AFTER_EXPOSE_REAGENTS, PROC_REF(victim_exposed_to_reagents)) + + return ..() + +/datum/wound/burn/robotic/overheat/proc/get_random_starting_temperature() + return LERP(starting_temperature_min, starting_temperature_max, rand()) // LERP since we deal with decimals + +/datum/wound/burn/robotic/get_limb_examine_description() + return span_warning("The metal on this limb is glowing radiantly.") + +/datum/wound/burn/robotic/overheat/handle_process(seconds_per_tick, times_fired) + if (isnull(victim)) + var/turf/our_turf = get_turf(limb) + if (!isnull(our_turf)) + expose_temperature(our_turf.GetTemperature(), (turf_coeff * seconds_per_tick)) + return + if (outgoing_bodytemp_coeff <= 0) + return + var/statis_mult = 1 + if (IS_IN_STASIS(victim)) // stasis heavily reduces the ingoing and outgoing transfer of heat + statis_mult *= OVERHEAT_ON_STASIS_HEAT_MULT + + var/difference_from_average = max((BODYTEMP_NORMAL - victim.bodytemperature), 0) + var/difference_mult = 1 + (difference_from_average * bodytemp_difference_expose_bonus_ratio) + if (expose_temperature(victim.bodytemperature, (bodytemp_coeff * seconds_per_tick * statis_mult * difference_mult))) + return + var/mult = outgoing_bodytemp_coeff + if (limb_essential()) + mult *= important_outgoing_mult + var/adjustment_allowed = max((max_outgoing_temperature - victim.bodytemperature), 0) + var/amount_to_adjust = min((((chassis_temperature - victim.bodytemperature) * mult) * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick * statis_mult), adjustment_allowed) + victim.adjust_bodytemperature(amount_to_adjust) + +/// Signal proc for when our victim is externally attacked. Increases chassis temp based on burn damage received. +/datum/wound/burn/robotic/overheat/proc/victim_attacked(datum/source, damage, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) + SIGNAL_HANDLER + + if (def_zone != limb.body_zone) // use this proc since receive damage can also be called for like, chems and shit + return + + if (!victim) + return + + if (damagetype != BURN) + return + + if (wound_bonus == CANT_WOUND) + return + + var/effective_damage = (damage - blocked) + if (effective_damage <= 0) + return + + expose_temperature((chassis_temperature + effective_damage), incoming_damage_heat_coeff) + +/** + * Signal proc for when our victim is exposed to reagents, obviously. + * + * Equalizes temp to the reagent temp, but also causes thermal shock. Basically, does damage based on the temp differential. + * Clothes reduce the effects massively. Hercuri reduces the thermal shock and gets a special temp buff. + */ +/datum/wound/burn/robotic/overheat/proc/victim_exposed_to_reagents(datum/signal_source, list/reagents, datum/reagents/source, methods, volume_modifier, show_message) + SIGNAL_HANDLER + + var/reagent_coeff = base_reagent_temp_coefficient + if (!get_location_accessible(victim, limb.body_zone)) + if (ishuman(victim)) + // hi! its niko! small rant + // this proc has no goddamn reason to be on human, it could so easily just have used a proc on carbon that would get the required bodyparts to check + // but no. it had to hardcode the list in the proc itself so its impossible to modularly fix this + // so instead we just say fuck it and hope to god only human subtypes get this wound + // tldr; ryll why + var/mob/living/carbon/human/human_victim = victim + for (var/obj/item/clothing/iter_clothing as anything in human_victim.get_clothing_on_part(limb)) + if (iter_clothing.clothing_flags & THICKMATERIAL) + return + + reagent_coeff *= sprayed_with_reagent_clothed_mult + + if (istype(source.my_atom, /obj/effect/particle_effect/water/extinguisher)) // this used to be a lot, lot more modular, but sadly reagent temps/volumes and shit are horribly inconsistant + expose_temperature(source.chem_temp, (2.55 * reagent_coeff), TRUE) + return + + if (istype(source.my_atom, /obj/machinery/shower)) + expose_temperature(source.chem_temp, (15 * volume_modifier * reagent_coeff), TRUE) + return + + var/total_reagent_amount = 0 + var/hercuri_amount = 0 + for (var/datum/reagent/iterated_reagent as anything in reagents) + total_reagent_amount += reagents[iterated_reagent] + if (iterated_reagent.type == /datum/reagent/medicine/c2/hercuri) + hercuri_amount = reagents[iterated_reagent] + + var/hercuri_percent = (hercuri_amount / total_reagent_amount) + + var/hercuri_chem_temp_increment = (ROBOTIC_BURN_REAGENT_EXPOSURE_HERCURI_MAX_HEAT_DECREMENT * hercuri_percent) + var/local_chem_temp = max(source.chem_temp - hercuri_chem_temp_increment, 0) + + var/heat_shock_damage_mult = 1 - (ROBOTIC_BURN_REAGENT_EXPOSURE_HERCURI_HEAT_SHOCK_MULT_DECREMENT * hercuri_percent) + + expose_temperature(local_chem_temp, (reagent_coeff * volume_modifier * total_reagent_amount), TRUE, heat_shock_damage_mult = heat_shock_damage_mult) + +/// Adjusts chassis_temperature by the delta between temperature and itself, multiplied by coeff. +/// If heat_shock is TRUE, limb will receive brute damage based on the delta. +/datum/wound/burn/robotic/overheat/proc/expose_temperature(temperature, coeff = 0.02, heat_shock = FALSE, heat_shock_damage_mult = 1) + var/temp_delta = (temperature - chassis_temperature) * coeff + + var/unclamped_new_temperature = (chassis_temperature + temp_delta) + var/clamped_new_temperature + var/heat_adjustment_used + + if(temp_delta > 0) + clamped_new_temperature = min(min(chassis_temperature + max(temp_delta, 1), temperature), heating_threshold) + heat_adjustment_used = (clamped_new_temperature / unclamped_new_temperature) + else + clamped_new_temperature = max(max(chassis_temperature + min(temp_delta, -1), temperature), cooling_threshold) + heat_adjustment_used = (unclamped_new_temperature / clamped_new_temperature) + + if (heat_shock && abs(temp_delta) > heat_shock_minimum_delta) + var/gauze_mult = 1 + var/obj/item/stack/gauze = limb.current_gauze + if (gauze) + gauze_mult *= (gauze.splint_factor) * 0.4 // very very effective + + if (limb.grasped_by) + gauze_mult *= 0.7 // hold it down yourself + + if (victim) + var/gauze_or_not = (!isnull(gauze) ? ", but [gauze] helps to keep it together" : "") + var/clothing_text = (!get_location_accessible(victim, limb.body_zone) ? ", [victim.p_their()] clothing absorbing some of the liquid" : "") + victim.visible_message(span_warning("[victim]'s [limb.plaintext_zone] strains from the thermal shock[clothing_text][gauze_or_not]!")) + playsound(victim, 'sound/items/welder.ogg', 25) + + var/damage = (((abs(temp_delta) * heat_shock_delta_to_damage_ratio) * gauze_mult) * heat_shock_damage_mult) * heat_adjustment_used + limb.receive_damage(brute = damage, wound_bonus = CANT_WOUND) + + chassis_temperature = clamped_new_temperature // can only be decimal or 1, so it can only reduce the intensity of the adjustment + + return check_temperature() + +/// Removes, demotes, or promotes ourselves to a new wound type if our temperature is past a heating/cooling threshold. +/datum/wound/burn/robotic/overheat/proc/check_temperature() + if (chassis_temperature <= cooling_threshold) + if (demotes_to) + victim.visible_message(span_green("[victim]'s [limb.plaintext_zone] turns a more pleasant thermal color as it cools down a little..."), span_green("Your [limb.plaintext_zone] seems to cool down a little!")) + replace_wound(new demotes_to(cooling_threshold - cooling_demote_buffer)) + return TRUE + else + victim.visible_message(span_green("[victim]'s [limb.plaintext_zone] simmers gently as it returns to its usual colors!"), span_green("Your [limb.plaintext_zone] simmers gently as it returns to its usual colors!")) + remove_wound() + return TRUE + else if (promotes_to && chassis_temperature >= heating_threshold) + victim.visible_message(span_danger("[victim]'s [limb.plaintext_zone] brightens as it overheats further!"), span_userdanger("Your [limb.plaintext_zone] sizzles and brightens as it overheats further!")) + replace_wound(new promotes_to(heating_threshold + heating_promote_buffer)) + return TRUE + +/// Returns a string with our temperature and heating/cooling thresholds, for use in health analyzers. +/datum/wound/burn/robotic/overheat/proc/get_wound_status_info() + var/current_temp_celcius = round(chassis_temperature - T0C, 0.1) + var/current_temp_fahrenheit = round(chassis_temperature * 1.8-459.67, 0.1) + + var/cool_celcius = round(cooling_threshold - T0C, 0.1) + var/cool_fahrenheit = round(cooling_threshold * 1.8-459.67, 0.1) + + var/heat_celcius = round(heating_threshold - T0C, 0.1) + var/heat_fahrenheit = round(heating_threshold * 1.8-459.67, 0.1) + + return "Its current temperature is [span_blue("[current_temp_celcius ] °C ([current_temp_fahrenheit] °F)")], \ + and needs to cool to [span_nicegreen("[cool_celcius] °C ([cool_fahrenheit] °F)")], but \ + will worsen if heated to [span_purple("[heat_celcius] °C ([heat_fahrenheit] °F)")]." + +/datum/wound/burn/robotic/overheat/get_scanner_description(mob/user) + . = ..() + + . += "\nWound status: [get_wound_status_info()]" + +/datum/wound/burn/robotic/overheat/get_simple_scanner_description(mob/user) + . = ..() + + . += "\nWound status: [get_wound_status_info()]" + +// this wound is unaffected by cryoxadone and pyroxadone +/datum/wound/burn/robotic/overheat/on_xadone(power) + return + +/datum/wound/burn/robotic/overheat/moderate + name = "Transient Overheating" + desc = "External metals have exceeded lower-bound thermal limits and have lost some structural integrity, increasing damage taken as well as the chance to \ + sustain additional wounds." + occur_text = "lets out a slight groan as it turns a dull shade of thermal red" + examine_desc = "is glowing a dull thermal red and giving off heat" + treat_text = "Reduction of body temperature to expedite the passive heat dissipation - or, if thermal shock is to be risked, application of a fire extinguisher/shower." + severity = WOUND_SEVERITY_MODERATE + + damage_multiplier_penalty = 1.15 //1.15x damage taken + + starting_temperature_min = (BODYTEMP_NORMAL + 350) + starting_temperature_max = (BODYTEMP_NORMAL + 400) + + cooling_threshold = (BODYTEMP_NORMAL + 100) + heating_threshold = (BODYTEMP_NORMAL + 500) + + cooling_demote_buffer = 60 + heating_promote_buffer = 100 + + a_or_from = "from" + + // easy to get + threshold_penalty = 30 + + status_effect_type = /datum/status_effect/wound/burn/robotic/moderate + + sound_volume = 20 + + outgoing_bodytemp_coeff = 0.0056 + bodytemp_coeff = 0.006 + + base_reagent_temp_coefficient = 0.03 + heat_shock_delta_to_damage_ratio = 0.2 + + promotes_to = /datum/wound/burn/robotic/overheat/severe + + light_color = COLOR_RED + light_power = 0.1 + light_range = 0.5 + + can_scar = FALSE + +/datum/wound_pregen_data/burnt_metal/transient_overheat + abstract = FALSE + + wound_path_to_generate = /datum/wound/burn/robotic/overheat/moderate + + threshold_minimum = 30 + +/datum/wound/burn/robotic/overheat/severe + name = "Thermal Overload" + desc = "Exterior plating has surpassed critical thermal levels, causing significant failure in structural integrity and overheating of internal systems." + occur_text = "sizzles, the externals turning a dull shade of orange" + examine_desc = "appears discolored and polychromatic, parts of it glowing a dull orange" + treat_text = "Isolation from physical hazards, and accommodation of passive heat dissipation - active cooling may be used, but temperature differentials significantly \ + raise the risk of thermal shock." + severity = WOUND_SEVERITY_SEVERE + + a_or_from = "from" + + threshold_penalty = 65 + + status_effect_type = /datum/status_effect/wound/burn/robotic/severe + damage_multiplier_penalty = 1.25 // 1.25x damage taken + + starting_temperature_min = (BODYTEMP_NORMAL + 550) + starting_temperature_max = (BODYTEMP_NORMAL + 600) + + heating_promote_buffer = 150 + + cooling_threshold = (BODYTEMP_NORMAL + 375) + heating_threshold = (BODYTEMP_NORMAL + 800) + + outgoing_bodytemp_coeff = 0.0053 + bodytemp_coeff = 0.004 + + base_reagent_temp_coefficient = 0.03 + heat_shock_delta_to_damage_ratio = 0.2 + + demotes_to = /datum/wound/burn/robotic/overheat/moderate + promotes_to = /datum/wound/burn/robotic/overheat/critical + + light_color = COLOR_BRIGHT_ORANGE + light_power = 0.8 + light_range = 0.5 + + scar_keyword = "burnsevere" + +/datum/wound_pregen_data/burnt_metal/severe + abstract = FALSE + wound_path_to_generate = /datum/wound/burn/robotic/overheat/severe + threshold_minimum = 80 + +/datum/wound/burn/robotic/overheat/critical + name = "Runaway Exothermy" + desc = "Carapace is beyond melting point, causing catastrophic structural integrity failure as well as massively heating up the subject." + occur_text = "turns a bright shade of radiant white as it sizzles and melts" + examine_desc = "is a blinding shade of white, almost melting from the heat" + treat_text = "Immediate confinement to cryogenics, as rapid overheating and physical vulnerability may occur. Active cooling is not advised, \ + since the thermal shock may be lethal with such a temperature differential." + severity = WOUND_SEVERITY_CRITICAL + + a_or_from = "from" + + sound_effect = 'sound/effects/wounds/sizzle2.ogg' + + threshold_penalty = 100 + + status_effect_type = /datum/status_effect/wound/burn/robotic/critical + + damage_multiplier_penalty = 1.5 //1.5x damage taken + + starting_temperature_min = (BODYTEMP_NORMAL + 1050) + starting_temperature_max = (BODYTEMP_NORMAL + 1100) + + cooling_demote_buffer = 100 + + cooling_threshold = (BODYTEMP_NORMAL + 775) + heating_threshold = INFINITY + + outgoing_bodytemp_coeff = 0.0055 // burn... BURN... + bodytemp_coeff = 0.0025 + + base_reagent_temp_coefficient = 0.03 + heat_shock_delta_to_damage_ratio = 0.2 + + max_outgoing_temperature = BODYTEMP_HEAT_WOUND_LIMIT // critical CAN cause wounds, but only barely + + demotes_to = /datum/wound/burn/robotic/overheat/severe + + wound_flags = (MANGLES_EXTERIOR|ACCEPTS_GAUZE|SPLINT_OVERLAY|CAN_BE_GRASPED) + + light_color = COLOR_VERY_SOFT_YELLOW + light_power = 1.3 + light_range = 1.5 + + scar_keyword = "burncritical" + +/datum/wound_pregen_data/burnt_metal/critical + abstract = FALSE + wound_path_to_generate = /datum/wound/burn/robotic/overheat/critical + threshold_minimum = 140 + +#undef OVERHEAT_ON_STASIS_HEAT_MULT +#undef ROBOTIC_BURN_REAGENT_EXPOSURE_HERCURI_MAX_HEAT_DECREMENT diff --git a/modular_skyrat/modules/medical/code/wounds/synth/robotic_muscle.dm b/modular_skyrat/modules/medical/code/wounds/synth/robotic_muscle.dm new file mode 100644 index 00000000000..4e91c58f7f6 --- /dev/null +++ b/modular_skyrat/modules/medical/code/wounds/synth/robotic_muscle.dm @@ -0,0 +1,47 @@ +/datum/wound/muscle/robotic + sound_effect = 'sound/effects/wounds/blood1.ogg' + +/datum/wound_pregen_data/muscle/robotic + required_limb_biostate = (BIO_METAL) + +/datum/wound/muscle/robotic/moderate + name = "Overworked Servo" + desc = "A servo has been overworked, and will operate with reduced efficiency until rested." + treat_text = "A tight splint on the affected limb, as well as plenty of rest and sleep." + examine_desc = "appears to be moving sluggishly" + occur_text = "jitters for a moment before moving sluggishly" + severity = WOUND_SEVERITY_MODERATE + interaction_efficiency_penalty = 1.5 + limp_slowdown = 2 + limp_chance = 30 + threshold_penalty = 15 + status_effect_type = /datum/status_effect/wound/muscle/robotic/moderate + regen_ticks_needed = 90 + +/datum/wound_pregen_data/muscle/robotic/servo + abstract = FALSE + wound_path_to_generate = /datum/wound/muscle/robotic/moderate + threshold_minimum = 35 + +/datum/wound/muscle/robotic/severe + name = "Exhausted Piston" + sound_effect = 'sound/effects/wounds/blood2.ogg' + desc = "An important hydraulic piston has been critically overused, resulting in total dysfunction until it recovers." + treat_text = "A tight splint on the affected limb, as well as plenty of rest and sleep." + examine_desc = "is stiffly limp, the extremities splayed out widely" + occur_text = "goes completely stiff, seeming to lock into position" + severity = WOUND_SEVERITY_SEVERE + interaction_efficiency_penalty = 2 + limp_slowdown = 5 + limp_chance = 40 + threshold_penalty = 35 + disabling = TRUE + status_effect_type = /datum/status_effect/wound/muscle/robotic/severe + regen_ticks_needed = 150 + +/datum/wound_pregen_data/muscle/robotic/hydraulic + abstract = FALSE + + wound_path_to_generate = /datum/wound/muscle/robotic/severe + threshold_minimum = 80 + diff --git a/modular_skyrat/modules/medical/code/wounds/synth/robotic_pierce.dm b/modular_skyrat/modules/medical/code/wounds/synth/robotic_pierce.dm new file mode 100644 index 00000000000..b7e4f259e5d --- /dev/null +++ b/modular_skyrat/modules/medical/code/wounds/synth/robotic_pierce.dm @@ -0,0 +1,146 @@ +// Pierce +// Slow to rise but high damage overall +// Hard-ish to fix +/datum/wound/electrical_damage/pierce + heat_differential_healing_mult = 0.01 + simple_desc = "Electrical conduits have been pierced open, resulting in a fault that slowly intensifies, but with extreme maximum voltage!" + +/datum/wound_pregen_data/electrical_damage/pierce + abstract = TRUE + wound_series = WOUND_SERIES_WIRE_PIERCE_ELECTRICAL_DAMAGE + required_wounding_types = list(WOUND_PIERCE) + +/datum/wound/burn/electrical_damage/pierce/get_limb_examine_description() + return span_warning("The metal on this limb is pierced open.") + +/datum/wound/electrical_damage/pierce/moderate + name = "Punctured Capacitor" + desc = "A major capacitor has been broken open, causing slow but noticable electrical damage." + occur_text = "shoots out a short stream of sparks" + examine_desc = "is shuddering gently, movements a little weak" + treat_text = "Replacing of damaged wiring, though repairs via wirecutting instruments or sutures may suffice, albeit at limited efficiency. In case of emergency, \ + subject may be subjected to high temperatures to allow solder to reset." + + sound_effect = 'modular_skyrat/modules/medical/sound/robotic_slash_T1.ogg' + + severity = WOUND_SEVERITY_MODERATE + + sound_volume = 30 + + threshold_penalty = 30 + + intensity = 10 SECONDS + processing_full_shock_threshold = 7 MINUTES + + processing_shock_power_per_second_max = 1.2 + processing_shock_power_per_second_min = 1.1 + + processing_shock_stun_chance = 0.5 + processing_shock_spark_chance = 35 + + process_shock_spark_count_max = 1 + process_shock_spark_count_min = 1 + + wirecut_repair_percent = 0.065 // not even faster at this point + wire_repair_percent = 0.026 + + initial_sparks_amount = 1 + + status_effect_type = /datum/status_effect/wound/electrical_damage/pierce/moderate + + a_or_from = "a" + + scar_keyword = "piercemoderate" + +/datum/wound_pregen_data/electrical_damage/pierce/moderate + abstract = FALSE + wound_path_to_generate = /datum/wound/electrical_damage/pierce/moderate + threshold_minimum = 40 + +/datum/wound/electrical_damage/pierce/severe + name = "Penetrated Transformer" + desc = "A major transformer has been pierced, causing slow-to-progess but eventually intense electrical damage." + occur_text = "sputters and goes limp for a moment as it ejects a stream of sparks" + examine_desc = "is shuddering significantly, its servos briefly giving way in a rythmic pattern" + treat_text = "Containment of damaged wiring via gauze, then application of fresh wiring/sutures, or resetting of displaced wiring via wirecutter/retractor." + + sound_effect = 'modular_skyrat/modules/medical/sound/robotic_slash_T2.ogg' + + severity = WOUND_SEVERITY_SEVERE + + sound_volume = 15 + + threshold_penalty = 40 + + intensity = 20 SECONDS + processing_full_shock_threshold = 6.5 MINUTES + + processing_shock_power_per_second_max = 1.6 + processing_shock_power_per_second_min = 1.5 + + processing_shock_stun_chance = 2.5 + processing_shock_spark_chance = 60 + + process_shock_spark_count_max = 2 + process_shock_spark_count_min = 1 + + wirecut_repair_percent = 0.068 + wire_repair_percent = 0.02 + + initial_sparks_amount = 3 + + status_effect_type = /datum/status_effect/wound/electrical_damage/pierce/moderate + + a_or_from = "a" + + scar_keyword = "piercemoderate" + +/datum/wound_pregen_data/electrical_damage/pierce/severe + abstract = FALSE + wound_path_to_generate = /datum/wound/electrical_damage/pierce/severe + threshold_minimum = 60 + +/datum/wound/electrical_damage/pierce/critical + name = "Ruptured PSU" + desc = "The local PSU of this limb has suffered a core rupture, causing a progressive power failure that will slowly intensify into massive electrical damage." + occur_text = "flashes with radiant blue, emitting a noise not unlike a Jacob's Ladder" + examine_desc = "'s PSU is visible, with a sizable hole in the center" + treat_text = "Immediate securing via gauze, followed by emergency cable replacement and securing via wirecutters or hemostat. \ + If the fault has become uncontrollable, extreme heat therapy is recommended." + + severity = WOUND_SEVERITY_CRITICAL + wound_flags = (ACCEPTS_GAUZE|MANGLES_EXTERIOR|CAN_BE_GRASPED|SPLINT_OVERLAY) + + sound_effect = 'modular_skyrat/modules/medical/sound/robotic_slash_T3.ogg' + + sound_volume = 30 + + threshold_penalty = 60 + + intensity = 30 SECONDS + processing_full_shock_threshold = 5.5 MINUTES + + processing_shock_power_per_second_max = 2.2 + processing_shock_power_per_second_min = 2.1 + + processing_shock_stun_chance = 1 + processing_shock_spark_chance = 90 + + process_shock_spark_count_max = 3 + process_shock_spark_count_min = 2 + + wirecut_repair_percent = 0.067 + wire_repair_percent = 0.018 + + initial_sparks_amount = 8 + + status_effect_type = /datum/status_effect/wound/electrical_damage/pierce/moderate + + a_or_from = "a" + + scar_keyword = "piercecritical" + +/datum/wound_pregen_data/electrical_damage/pierce/critical + abstract = FALSE + wound_path_to_generate = /datum/wound/electrical_damage/pierce/critical + threshold_minimum = 110 diff --git a/modular_skyrat/modules/medical/code/wounds/synth/robotic_slash.dm b/modular_skyrat/modules/medical/code/wounds/synth/robotic_slash.dm new file mode 100644 index 00000000000..a28737520b5 --- /dev/null +++ b/modular_skyrat/modules/medical/code/wounds/synth/robotic_slash.dm @@ -0,0 +1,628 @@ +/// How much damage and progress is reduced when on stasis. +#define ELECTRICAL_DAMAGE_ON_STASIS_MULT 0.15 +/// How much damage and progress is reduced when limb is grasped. +#define ELECTRICAL_DAMAGE_GRASPED_MULT 0.7 +/// How much damage and progress is reduced when our victim lies down. +#define ELECTRICAL_DAMAGE_LYING_DOWN_MULT 0.7 +/// How much progress is reduced when our victim is dead. +#define ELECTRICAL_DAMAGE_DEAD_PROGRESS_MULT 0.2 // they'll be resting to, so this is more like 0.1 + +/// Base time for a wirecutter being used. +#define ELECTRICAL_DAMAGE_WIRECUTTER_BASE_DELAY 8 SECONDS +/// Base time for a cable coil being used. +#define ELECTRICAL_DAMAGE_SUTURE_WIRE_BASE_DELAY 0.8 SECONDS +/// Global damage multiplier for the power a given electrical damage wound will add per tick. +#define ELECTRICAL_DAMAGE_POWER_PER_TICK_MULT 1 +/// Global damage multiplier for how much repairing wiring will reduce intensity. Higher is more. +#define ELECTRICAL_DAMAGE_SUTURE_WIRE_HEALING_AMOUNT_MULT 1 + +/// The minimum shock power we must have available to zap our victim. Must be at least one, since electrocute_act fails if its lower. +#define ELECTRICAL_DAMAGE_MINIMUM_SHOCK_POWER_PER_ZAP 1 +/// The maximum burn damage our limb can have before we refuse to let people who havent aggrograbbed the limb repair it with wires. This is so people can opt to just fix the burn damage. +#define ELECTRICAL_DAMAGE_MAX_BURN_DAMAGE_TO_LET_WIRES_REPAIR 5 + +/datum/wound/electrical_damage + name = "Electrical (Wires) Wound" + + simple_treat_text = "Replacing of broken wiring, or repairing via a wirecutter. Bandaging binds the wiring and reduces intensity buildup, \ + as does firmly grasping the limb - both the victim and someone else can do this. Roboticists/Engineers get a bonus to treatment, as do diagnostic HUDs." + homemade_treat_text = "Sutures can repair the wiring at reduced efficiency, as can retractors. In a pinch, high temperatures can repair the wiring!" + + wound_flags = (ACCEPTS_GAUZE|CAN_BE_GRASPED|SPLINT_OVERLAY) + + treatable_tools = list(TOOL_WIRECUTTER, TOOL_RETRACTOR) + treatable_by = list(/obj/item/stack/medical/suture) + treatable_by_grabbed = list(/obj/item/stack/cable_coil) + + default_scar_file = METAL_SCAR_FILE + + processes = TRUE + + /// How many sparks do we spawn when we're gained? + var/initial_sparks_amount = 1 + + /// How much of our damage is reduced if the target is shock immune. Percent. + var/shock_immunity_self_damage_reduction = 75 + + /// Mult for our damage if we are unimportant. + var/limb_unimportant_damage_mult = 0.8 + /// Mult for our progress if we are unimportant. + var/limb_unimportant_progress_mult = 0.8 + + /// The overall "intensity" of this wound. Goes up to [processing_full_shock_threshold], and is used for determining our effect scaling. Measured in deciseconds. + var/intensity + /// The time, in deciseconds, it takes to reach 100% power. + var/processing_full_shock_threshold = 3 MINUTES + /// If [intensity] is at or below this, we remove ourselves. + var/minimum_intensity = 0 + + /// How much shock power we add to [processing_shock_power_this_tick] per tick. Lower bound + var/processing_shock_power_per_second_min = 0.1 + /// How much shock power we add to [processing_shock_power_this_tick] per tick. Upper bound + var/processing_shock_power_per_second_max = 0.2 + + /// In the case we get below 1 power, we add the power to this buffer and use it next tick. + var/processing_shock_power_this_tick = 0 + /// The chance for each processed shock to stun the user. + var/processing_shock_stun_chance = 0 + /// The chance for each processed shock to spark. + var/processing_shock_spark_chance = 30 + /// The chance for each processed shock to message the user. + var/process_shock_message_chance = 80 + + /// Simple mult for how much of real time is added to [intensity]. + var/seconds_per_intensity_mult = 1 + + /// How many sparks we spawn if a shock sparks. Lower bound + var/process_shock_spark_count_min = 1 + /// How many sparks we spawn if a shock sparks. Upper bound + var/process_shock_spark_count_max = 1 + + // Generally should be less fast than wire, but its effectiveness should increase with severity + /// The percent, in decimal, a successful wirecut use will reduce intensity by. + var/wirecut_repair_percent + // Generally should be lower than wirecut + /// The percent, in decimal, a successful wire use will reduce intensity by. + var/wire_repair_percent + + /// The basic multiplier to all our effects. Damage, progress, etc. + var/overall_effect_mult = 1 + + /// The bodyheat our victim must be at or above to start getting passive healing. + var/heat_thresh_to_heal = (BODYTEMP_HEAT_DAMAGE_LIMIT + 30) + /// The mult that heat differences between normal and bodytemp threshold is multiplied against. Controls passive heat healing. + var/heat_differential_healing_mult = 0.08 + + /// Percent chance for a heat repair to give the victim a message. + var/heat_heal_message_chance = 20 + + /// If [get_intensity_mult()] is at or above this, the limb gets disabled. If null, it will never occur. + var/disable_at_intensity_mult + +/datum/wound_pregen_data/electrical_damage + abstract = TRUE + required_limb_biostate = (BIO_WIRED) + required_wounding_types = list(WOUND_SLASH) + wound_series = WOUND_SERIES_WIRE_SLASH_ELECTRICAL_DAMAGE + +/datum/wound_pregen_data/electrical_damage/generate_scar_priorities() + return list("[BIO_METAL]") // wire scars dont exist so we can just use metal + +/datum/wound/burn/electrical_damage/slash/get_limb_examine_description() + return span_warning("The wiring on this limb is slashed open.") + +/datum/wound/electrical_damage/handle_process(seconds_per_tick, times_fired) + . = ..() + + var/base_mult = get_base_mult() + + var/seconds_per_tick_for_intensity = seconds_per_tick * get_progress_mult() + seconds_per_tick_for_intensity = modify_progress_after_progress_mult(seconds_per_tick_for_intensity, seconds_per_tick) + + adjust_intensity(seconds_per_tick_for_intensity SECONDS) + + if (!victim || victim.stat == DEAD) + return + + var/damage_mult = get_damage_mult(victim) + var/intensity_mult = get_intensity_mult() + + damage_mult *= seconds_per_tick + damage_mult *= intensity_mult + + var/picked_damage = LERP(processing_shock_power_per_second_min, processing_shock_power_per_second_max, rand()) + processing_shock_power_this_tick += (picked_damage * damage_mult) + if (processing_shock_power_this_tick <= ELECTRICAL_DAMAGE_MINIMUM_SHOCK_POWER_PER_ZAP) + return + + var/stun_chance = (processing_shock_stun_chance * intensity_mult) * base_mult + var/spark_chance = (processing_shock_spark_chance * intensity_mult) * base_mult + + var/should_stun = SPT_PROB(stun_chance, seconds_per_tick) + var/should_message = SPT_PROB(process_shock_message_chance, seconds_per_tick) + + zap(victim, + processing_shock_power_this_tick, + stun = should_stun, + spark = SPT_PROB(spark_chance, seconds_per_tick), + animation = should_stun, message = FALSE, + message = should_stun, + tell_victim_if_no_message = should_message, + ignore_immunity = TRUE, + jitter_time = seconds_per_tick, + stutter_time = 0, + delay_stun = TRUE, + knockdown = TRUE, + ignore_gloves = TRUE + ) + processing_shock_power_this_tick = 0 + +/// If someone is aggrograbbing us and targetting our limb, intensity progress is multiplied against this. +#define LIMB_AGGROGRABBED_PROGRESS_MULT 0.5 + +/// Returns the multiplier used by our intensity progress. Intensity increment is multiplied against this. +/datum/wound/electrical_damage/proc/get_progress_mult() + var/progress_mult = get_base_mult() * seconds_per_intensity_mult + + if (!limb_essential()) + progress_mult *= limb_unimportant_progress_mult + + if (isliving(victim.pulledby)) + var/mob/living/living_puller = victim.pulledby + if (living_puller.grab_state >= GRAB_AGGRESSIVE && living_puller.zone_selected == limb.body_zone) + progress_mult *= LIMB_AGGROGRABBED_PROGRESS_MULT // they're holding it down + + if (victim.stat == DEAD) + progress_mult *= ELECTRICAL_DAMAGE_DEAD_PROGRESS_MULT // doesnt totally stop it but slows it down a lot + + return progress_mult +#undef LIMB_AGGROGRABBED_PROGRESS_MULT + +/// Returns the multiplier used by the damage we deal. +/datum/wound/electrical_damage/proc/get_damage_mult(mob/living/target) + SHOULD_BE_PURE(TRUE) + + var/damage_mult = get_base_mult() + + if (!limb_essential()) + damage_mult *= limb_unimportant_damage_mult + + return damage_mult * ELECTRICAL_DAMAGE_POWER_PER_TICK_MULT + +/// Returns the global multiplier used by both progress and damage. +/datum/wound/electrical_damage/proc/get_base_mult() + var/base_mult = 1 + + if (victim) + if (IS_IN_STASIS(victim)) + base_mult *= ELECTRICAL_DAMAGE_ON_STASIS_MULT + if (victim.body_position == LYING_DOWN) + base_mult *= ELECTRICAL_DAMAGE_LYING_DOWN_MULT + if (limb.grasped_by) + base_mult *= ELECTRICAL_DAMAGE_GRASPED_MULT + + if (victim.has_status_effect(/datum/status_effect/determined)) + base_mult *= WOUND_DETERMINATION_BLEED_MOD + + if (HAS_TRAIT(victim, TRAIT_SHOCKIMMUNE)) // it'd be a bit cheesy to just become immune to this, so it only makes it a lot lot better + base_mult *= shock_immunity_self_damage_reduction + + var/splint_mult = (limb.current_gauze ? limb.current_gauze.splint_factor : 1) + base_mult *= splint_mult + + return overall_effect_mult * base_mult + +/// Is called after seconds_for_intensity is modified by get_progress_mult(). +/datum/wound/electrical_damage/proc/modify_progress_after_progress_mult(seconds_for_intensity, seconds_per_tick) + if (!victim) + return seconds_for_intensity + + return seconds_for_intensity - (get_heat_healing() * seconds_per_tick) + +/// Returns how many deciseconds progress should be reduced by, based on the current heat of our victim's body. +/datum/wound/electrical_damage/proc/get_heat_healing(do_message = prob(heat_heal_message_chance)) + var/healing_amount = max((victim.bodytemperature - heat_thresh_to_heal), 0) * heat_differential_healing_mult + if (do_message && healing_amount) + to_chat(victim, span_notice("You feel the solder within your [limb.plaintext_zone] reform and repair your [name]...")) + + return healing_amount + +/// Changes intensity by the given amount, and then updates our status, removing ourselves if fixed. +/datum/wound/electrical_damage/proc/adjust_intensity(to_adjust) + intensity = clamp((intensity + to_adjust), 0, processing_full_shock_threshold) + + if (disable_at_intensity_mult) + set_disabling(get_intensity_mult() >= disable_at_intensity_mult) + + remove_if_fixed() + +/datum/wound/electrical_damage/wound_injury(datum/wound/electrical_damage/old_wound, attack_direction) + . = ..() + + if (old_wound) + intensity = max(intensity, old_wound.intensity) + processing_shock_power_this_tick = old_wound.processing_shock_power_this_tick + + do_sparks(initial_sparks_amount, FALSE, victim) + +/datum/wound/electrical_damage/modify_desc_before_span(desc, mob/user) + . = ..() + + if (limb.current_gauze) + return + + var/intensity_mult = get_intensity_mult() + if (intensity_mult < 0.2 || (victim.stat == DEAD)) + return + + . += ", and " + + var/extra + switch (intensity_mult) + if (0.2 to 0.4) + extra += "[span_deadsay("is letting out some sparks")]" + if (0.4 to 0.6) + extra += "[span_deadsay("is sparking quite a bit")]" + if (0.6 to 0.8) + extra += "[span_deadsay("is practically hemorrhaging sparks")]" + if (0.8 to 1) + extra += "[span_deadsay("has golden bolts of electricity constantly striking the surface")]" + + . += extra + +/datum/wound/electrical_damage/get_scanner_description(mob/user) + . = ..() + + . += "\nWound status: [get_wound_status_info()]" + +/datum/wound/electrical_damage/get_simple_scanner_description(mob/user) + . = ..() + + . += "\nWound status: [get_wound_status_info()]" + +/// Returns a string with our fault intensity and threshold to removal for use in health analyzers. +/datum/wound/electrical_damage/proc/get_wound_status_info() + return "Fault intensity is currently at [span_bold("[get_intensity_mult() * 100]")]%. It must be reduced to [span_blue("[minimum_intensity]")]% to remove the wound." + +// this wound is unaffected by cryoxadone and pyroxadone +/datum/wound/electrical_damage/on_xadone(power) + return + +/datum/wound/electrical_damage/item_can_treat(obj/item/potential_treater, mob/user) + if (istype(potential_treater, /obj/item/stack/cable_coil) && ((user.pulling == victim && user.grab_state >= GRAB_AGGRESSIVE) || (limb.burn_dam <= ELECTRICAL_DAMAGE_MAX_BURN_DAMAGE_TO_LET_WIRES_REPAIR))) + return TRUE // if we're aggrograbbed, or relatively undamaged, go ahead. else, we dont want to impede normal treatment + + return ..() + +/datum/wound/electrical_damage/treat(obj/item/treating_item, mob/user) + if (treating_item.tool_behaviour == TOOL_WIRECUTTER || treating_item.tool_behaviour == TOOL_RETRACTOR) + return wirecut(treating_item, user) + + if (istype(treating_item, /obj/item/stack/medical/suture) || istype(treating_item, /obj/item/stack/cable_coil)) + return suture_wires(treating_item, user) + + return ..() + +/** + * The "trauma" treatment, done with cables/sutures. Sutures get a debuff. + * Low self-tend penalty. + * Very fast, but low value. Eats up wires for breakfast. + * Has limited wire/HUD bonuses. If you're a robo, use a wirecutter instead. + */ +/datum/wound/electrical_damage/proc/suture_wires(obj/item/stack/suturing_item, mob/living/carbon/human/user) + if (!suturing_item.tool_start_check()) + return TRUE + + var/is_suture = (istype(suturing_item, /obj/item/stack/medical/suture)) + + var/change = (processing_full_shock_threshold * wire_repair_percent) * ELECTRICAL_DAMAGE_SUTURE_WIRE_HEALING_AMOUNT_MULT + var/delay_mult = 1 + if (user == victim) + delay_mult *= 1.5 + if (is_suture) + delay_mult *= 2 + var/obj/item/stack/medical/suture/suture_item = suturing_item + var/obj/item/stack/medical/suture/base_suture = /obj/item/stack/medical/suture + change += (suture_item.heal_brute - initial(base_suture.heal_brute)) + + // as this is the trauma treatment, there are less bonuses + // if youre doing this, youre probably doing this on-the-spot + if (HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) + delay_mult *= 0.8 + else if (HAS_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) + delay_mult *= 0.9 + if (HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD)) + delay_mult *= 0.8 + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + change *= 1.2 + + var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") + var/your_or_other = (user == victim ? "your" : "[victim]'s") + var/replacing_or_suturing = (is_suture ? "repairing some" : "replacing") + while (suturing_item.tool_start_check()) + user?.visible_message(span_danger("[user] begins [replacing_or_suturing] wiring within [their_or_other] [limb.plaintext_zone] with [suturing_item]..."), \ + span_notice("You begin [replacing_or_suturing] wiring within [your_or_other] [limb.plaintext_zone] with [suturing_item]...")) + if (!suturing_item.use_tool(target = victim, user = user, delay = ELECTRICAL_DAMAGE_SUTURE_WIRE_BASE_DELAY * delay_mult, amount = 1, volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + return TRUE + + if (user != victim && user.combat_mode) + user?.visible_message(span_danger("[user] mangles some of [their_or_other] [limb.plaintext_zone]'s wiring!"), \ + span_danger("You mangle some of [your_or_other] [limb.plaintext_zone]'s wiring!"), ignored_mobs = victim) + to_chat(victim, span_userdanger("[capitalize(your_or_other)] mangles some of your [limb.plaintext_zone]'s wiring!")) + adjust_intensity(change * 2) + else + var/repairs_or_replaces = (is_suture ? "repairs" : "replaces") + var/repair_or_replace = (is_suture ? "repair" : "replace") + user?.visible_message(span_notice("[user] [repairs_or_replaces] some of [their_or_other] [limb.plaintext_zone]'s wiring!"), \ + span_notice("You [repair_or_replace] some of [your_or_other] [limb.plaintext_zone]'s wiring!")) + adjust_intensity(-change) + victim.balloon_alert(user, "intensity reduced to [get_intensity_mult() * 100]%") + + if (fixed()) + return TRUE + return TRUE + +/** + * The "proper" treatment, done with wirecutters/retractors. Retractors get a debuff. + * High self-tend penalty. + * Slow, but high value. + * Has high wire/HUD bonuses. The ideal treatment for a robo. + */ +/datum/wound/electrical_damage/proc/wirecut(obj/item/wirecutting_tool, mob/living/carbon/human/user) + if (!wirecutting_tool.tool_start_check()) + return TRUE + + var/is_retractor = (wirecutting_tool.tool_behaviour == TOOL_RETRACTOR) + + var/change = (processing_full_shock_threshold * wirecut_repair_percent) + var/delay_mult = 1 + if (user == victim) + delay_mult *= 2.5 + if (is_retractor) + delay_mult *= 2 + change *= 0.8 + var/knows_wires = FALSE + if (HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) + delay_mult *= 0.9 + change *= 1.7 + knows_wires = TRUE + else if (HAS_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) + change *= 1.35 + knows_wires = TRUE + if (HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD)) + if (knows_wires) + delay_mult *= 0.9 + else + delay_mult *= 0.75 + if (HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + delay_mult *= 0.8 + + var/their_or_other = (user == victim ? "[user.p_their()]" : "[victim]'s") + var/your_or_other = (user == victim ? "your" : "[victim]'s") + while (wirecutting_tool.tool_start_check()) + user?.visible_message(span_danger("[user] begins resetting misplaced wiring within [their_or_other] [limb.plaintext_zone]..."), \ + span_notice("You begin resetting misplaced wiring within [your_or_other] [limb.plaintext_zone]...")) + if (!wirecutting_tool.use_tool(target = victim, user = user, delay = ELECTRICAL_DAMAGE_WIRECUTTER_BASE_DELAY * delay_mult, volume = 50, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + return TRUE + + if (user != victim && user.combat_mode) + user?.visible_message(span_danger("[user] mangles some of [their_or_other] [limb.plaintext_zone]'s wiring!"), \ + span_danger("You mangle some of [your_or_other] [limb.plaintext_zone]'s wiring!"), ignored_mobs = victim) + to_chat(victim, span_userdanger("[capitalize(your_or_other)] mangles some of your [limb.plaintext_zone]'s wiring!")) + adjust_intensity(change * 2) + else + user?.visible_message(span_notice("[user] resets some of [their_or_other] [limb.plaintext_zone]'s wiring!"), \ + span_notice("You reset some of [your_or_other] [limb.plaintext_zone]'s wiring!")) + adjust_intensity(-change) + victim.balloon_alert(user, "intensity reduced to [get_intensity_mult() * 100]%") + + if (fixed()) + return TRUE + return TRUE + +/// If fixed() is true, we remove ourselves and return TRUE. FALSE otherwise. +/datum/wound/electrical_damage/proc/remove_if_fixed() + if (fixed()) + to_chat(victim, span_green("Your [limb.plaintext_zone] has recovered from its [name]!")) + remove_wound() + return TRUE + return FALSE + +/// Should we remove ourselves? +/datum/wound/electrical_damage/proc/fixed() + return (intensity <= minimum_intensity || isnull(limb)) + +/// Returns the multiplier we apply to our outgoing damage based off our current intensity. Is always between 0-1. +/datum/wound/electrical_damage/proc/get_intensity_mult() + return (min((intensity / processing_full_shock_threshold), 1)) + +/// Wrapper for electrocute_act +/datum/wound/electrical_damage/proc/zap( + mob/living/target, + damage, + coeff = 1, + stun, + spark = TRUE, + animation = TRUE, + message = TRUE, + ignore_immunity = FALSE, + delay_stun = FALSE, + knockdown = FALSE, + ignore_gloves = FALSE, + tell_victim_if_no_message = TRUE, + jitter_time = 20 SECONDS, + stutter_time = 4 SECONDS, +) + + var/flags = NONE + if (!stun) + flags |= SHOCK_NOSTUN + if (!animation) + flags |= SHOCK_NO_HUMAN_ANIM + if (!message) + flags |= SHOCK_SUPPRESS_MESSAGE + if (tell_victim_if_no_message && target == victim) + to_chat(target, span_warning("Your [limb.plaintext_zone] short-circuits and zaps you!")) + if (ignore_immunity) + flags |= SHOCK_IGNORE_IMMUNITY + if (delay_stun) + flags |= SHOCK_DELAY_STUN + if (knockdown) + flags |= SHOCK_KNOCKDOWN + if (ignore_gloves) + flags |= SHOCK_NOGLOVES + + target.electrocute_act(damage, limb, coeff, flags, jitter_time, stutter_time) + if (spark) + do_sparks(rand(process_shock_spark_count_min, process_shock_spark_count_max), FALSE, victim) + +// Slash +// Fast to rise, but lower damage overall +// Also a bit easy to treat +/datum/wound/electrical_damage/slash + simple_desc = "Wiring has been slashed open, resulting in a fault that quickly intensifies!" + +/datum/wound/electrical_damage/slash/moderate + name = "Frayed Wiring" + desc = "Internal wiring has suffered a slight abrasion, causing a slow electrical fault that will intensify over time." + occur_text = "lets out a few sparks, as a few frayed wires stick out" + examine_desc = "has a few frayed wires sticking out" + treat_text = "Replacing of damaged wiring, though repairs via wirecutting instruments or sutures may suffice, albeit at limited efficiency. In case of emergency, \ + subject may be subjected to high temperatures to allow solder to reset." + + sound_effect = 'modular_skyrat/modules/medical/sound/robotic_slash_T1.ogg' + + severity = WOUND_SEVERITY_MODERATE + + sound_volume = 30 + + threshold_penalty = 20 + + intensity = 10 SECONDS + processing_full_shock_threshold = 3 MINUTES + + processing_shock_power_per_second_max = 0.5 + processing_shock_power_per_second_min = 0.4 + + processing_shock_stun_chance = 0 + processing_shock_spark_chance = 30 + + process_shock_spark_count_max = 1 + process_shock_spark_count_min = 1 + + wirecut_repair_percent = 0.085 // not even faster at this point + wire_repair_percent = 0.035 + + initial_sparks_amount = 1 + + status_effect_type = /datum/status_effect/wound/electrical_damage/slash/moderate + + a_or_from = "from" + + scar_keyword = "slashmoderate" + +/datum/wound_pregen_data/electrical_damage/slash/moderate + abstract = FALSE + wound_path_to_generate = /datum/wound/electrical_damage/slash/moderate + threshold_minimum = 35 + +/datum/wound/electrical_damage/slash/severe + name = "Severed Conduits" + desc = "A number of wires have been completely cut, resulting in electrical faults that will intensify at a worrying rate." + occur_text = "sends some electrical fiber in the direction of the blow, beginning to profusely spark" + examine_desc = "has multiple severed wires visible to the outside" + treat_text = "Containment of damaged wiring via gauze, then application of fresh wiring/sutures, or resetting of displaced wiring via wirecutter/retractor." + + sound_effect = 'modular_skyrat/modules/medical/sound/robotic_slash_T2.ogg' + + severity = WOUND_SEVERITY_SEVERE + + sound_volume = 15 + + threshold_penalty = 30 + + intensity = 10 SECONDS + processing_full_shock_threshold = 2 MINUTES + + processing_shock_power_per_second_max = 0.7 + processing_shock_power_per_second_min = 0.6 + + processing_shock_stun_chance = 0 + processing_shock_spark_chance = 60 + + process_shock_spark_count_max = 2 + process_shock_spark_count_min = 1 + + wirecut_repair_percent = 0.1 + wire_repair_percent = 0.032 + + initial_sparks_amount = 3 + + status_effect_type = /datum/status_effect/wound/electrical_damage/slash/severe + + a_or_from = "from" + + scar_keyword = "slashsevere" + +/datum/wound_pregen_data/electrical_damage/slash/severe + abstract = FALSE + wound_path_to_generate = /datum/wound/electrical_damage/slash/severe + threshold_minimum = 60 + +/datum/wound/electrical_damage/slash/critical + name = "Systemic Fault" + desc = "A significant portion of the power distribution network has been cut open, resulting in massive power loss and runaway electrocution." + occur_text = "lets out a violent \"zhwarp\" sound as angry electric arcs attack the surrounding air" + examine_desc = "has lots of wires mauled wires sticking out" + treat_text = "Immediate securing via gauze, followed by emergency cable replacement and securing via wirecutters or retractor. \ + If the fault has become uncontrollable, extreme heat therapy is recommended." + + severity = WOUND_SEVERITY_CRITICAL + wound_flags = (ACCEPTS_GAUZE|MANGLES_INTERIOR|CAN_BE_GRASPED|SPLINT_OVERLAY) + + sound_effect = 'modular_skyrat/modules/medical/sound/robotic_slash_T3.ogg' + + sound_volume = 30 + + threshold_penalty = 50 + + intensity = 10 SECONDS + processing_full_shock_threshold = 1.25 MINUTES + + processing_shock_power_per_second_max = 1.3 + processing_shock_power_per_second_min = 1.1 + + processing_shock_stun_chance = 5 + processing_shock_spark_chance = 90 + + process_shock_spark_count_max = 3 + process_shock_spark_count_min = 2 + + wirecut_repair_percent = 0.12 + wire_repair_percent = 0.03 + + initial_sparks_amount = 8 + + status_effect_type = /datum/status_effect/wound/electrical_damage/slash/critical + + a_or_from = "a" + + scar_keyword = "slashcritical" + +/datum/wound_pregen_data/electrical_damage/slash/critical + abstract = FALSE + wound_path_to_generate = /datum/wound/electrical_damage/slash/critical + threshold_minimum = 100 + +#undef ELECTRICAL_DAMAGE_ON_STASIS_MULT +#undef ELECTRICAL_DAMAGE_GRASPED_MULT +#undef ELECTRICAL_DAMAGE_LYING_DOWN_MULT +#undef ELECTRICAL_DAMAGE_DEAD_PROGRESS_MULT + +#undef ELECTRICAL_DAMAGE_WIRECUTTER_BASE_DELAY +#undef ELECTRICAL_DAMAGE_SUTURE_WIRE_BASE_DELAY + +#undef ELECTRICAL_DAMAGE_MINIMUM_SHOCK_POWER_PER_ZAP +#undef ELECTRICAL_DAMAGE_MAX_BURN_DAMAGE_TO_LET_WIRES_REPAIR +#undef ELECTRICAL_DAMAGE_POWER_PER_TICK_MULT +#undef ELECTRICAL_DAMAGE_SUTURE_WIRE_HEALING_AMOUNT_MULT diff --git a/modular_skyrat/modules/medical/code/wounds/wound_effects.dm b/modular_skyrat/modules/medical/code/wounds/wound_effects.dm new file mode 100644 index 00000000000..8f9aef16210 --- /dev/null +++ b/modular_skyrat/modules/medical/code/wounds/wound_effects.dm @@ -0,0 +1,33 @@ +/datum/status_effect/wound/blunt/robotic/moderate + id = "unsecure_moderate" + +/datum/status_effect/wound/blunt/robotic/severe + id = "unsecure_severe" + +/datum/status_effect/wound/blunt/robotic/critical + id = "unsecure_critical" + +/datum/status_effect/wound/electrical_damage/slash/moderate + id = "electric_slash_moderate" + +/datum/status_effect/wound/electrical_damage/slash/severe + id = "electric_slash_severe" + +/datum/status_effect/wound/electrical_damage/slash/critical + id = "electric_slash_critical" + +/datum/status_effect/wound/electrical_damage/pierce/moderate + id = "electric_pierce_moderate" + +/datum/status_effect/wound/electrical_damage/pierce/severe + id = "electric_pierce_severe" + +/datum/status_effect/wound/electrical_damage/pierce/critical + id = "electric_pierce_critical" + +/datum/status_effect/wound/burn/robotic/moderate + id = "overheated" +/datum/status_effect/wound/burn/robotic/severe + id = "warpedmetal" +/datum/status_effect/wound/burn/robotic/critical + id = "demagnetizedmetal" diff --git a/modular_skyrat/modules/medical/readme.md b/modular_skyrat/modules/medical/readme.md new file mode 100644 index 00000000000..6ab0af32ddf --- /dev/null +++ b/modular_skyrat/modules/medical/readme.md @@ -0,0 +1,51 @@ + + +https://github.com/Skyrat-SS13/Skyrat-tg/pull/2336 +https://github.com/Skyrat-SS13/Skyrat-tg/pull/23733 + +## Skyrat Medical Update + +Module ID: SKYRAT_MEDICAL_UPDATE + +### Description: + +Various changes to the medical system, from adding bandage overlays, to new wounds, to modularized procs. + + + +### TG Proc/File Changes: + +- code/_DEFINES/wounds.dm: Added muscle/synth wound series, added them to the global list of wound series +- cat2_medicine_reagents.dm: /datum/reagent/medicine/c2/hercuri/on_mob_life, Allowed hercuri to affect synthetics, also changed hercuri process flags for this purpose +- quirks.dm: Commented out the quadruple_amputee/frail blacklist as frail can now apply to prosthetics + + +### Modular Overrides: + +- N/A + + +### Defines: + +- Many local synthetic wound defines + + +### Included files that are not contained in this module: + +- strings/wounds/metal_scar_desc.json -- Required to be here for _string_lists.dm usage + + +### Credits: + +Azarak - Original medical update, muscle wounds, bandage overlays +Niko - Synthetic wounds +TG coding/Skyrat coding channels and community - Support, ideas, reviews + + diff --git a/modular_skyrat/modules/medical/sound/robotic_slash_T1.ogg b/modular_skyrat/modules/medical/sound/robotic_slash_T1.ogg new file mode 100644 index 00000000000..cb7b3d0a79f Binary files /dev/null and b/modular_skyrat/modules/medical/sound/robotic_slash_T1.ogg differ diff --git a/modular_skyrat/modules/medical/sound/robotic_slash_T2.ogg b/modular_skyrat/modules/medical/sound/robotic_slash_T2.ogg new file mode 100644 index 00000000000..4fad2583575 Binary files /dev/null and b/modular_skyrat/modules/medical/sound/robotic_slash_T2.ogg differ diff --git a/modular_skyrat/modules/medical/sound/robotic_slash_T3.ogg b/modular_skyrat/modules/medical/sound/robotic_slash_T3.ogg new file mode 100644 index 00000000000..f0ea8e22170 Binary files /dev/null and b/modular_skyrat/modules/medical/sound/robotic_slash_T3.ogg differ diff --git a/modular_skyrat/modules/modular_implants/code/nifsofts/dorms.dm b/modular_skyrat/modules/modular_implants/code/nifsofts/dorms.dm index d6f02e394e4..97506d8d69d 100644 --- a/modular_skyrat/modules/modular_implants/code/nifsofts/dorms.dm +++ b/modular_skyrat/modules/modular_implants/code/nifsofts/dorms.dm @@ -1,12 +1,12 @@ /obj/item/disk/nifsoft_uploader/dorms - name = "Grimoire Purpura" + name = "Grimoire Libidine" loaded_nifsoft = /datum/nifsoft/summoner/dorms /datum/nifsoft/summoner/dorms - name = "Grimoire Purpura" - program_desc = "Grimoire Purpura, a fork of the Grimoire Caeruleam code, allows users to conveniently access an extensive database of various adult toys. " + name = "Grimoire Libidine" + program_desc = "Grimoire Libidine, a fork of the Grimoire Caeruleam code, allows users to conveniently access an extensive database of various adult toys. " holographic_filter = FALSE //No RGB toys - name_tag = "purpura " + name_tag = "libidine " lewd_nifsoft = TRUE ui_icon = "heart" @@ -62,7 +62,7 @@ purchase_price = 150 /obj/item/disk/nifsoft_uploader/dorms/contract - name = "\improper Purpura Contract" + name = "\improper Libidine Contract" loaded_nifsoft = /datum/nifsoft/hypno reusable = TRUE //This is set to true because of how this handles updating laws ///What laws will be assigned when using the NIFSoft on someone? @@ -93,8 +93,8 @@ return TRUE /datum/nifsoft/hypno - name = "Purpura Contract" - program_desc = "Once installed, the Purpura Contract compells the user to follow the rules stored in the data of the NIFSoft. \n OOC NOTE: This is strictly here for adult roleplay. None of the laws here actually need to be obeyed and you can uninstall this NIFSoft at any time." + name = "Libidine Contract" + program_desc = "Once installed, the Libidine Contract compells the user to follow the rules stored in the data of the NIFSoft. \n OOC NOTE: This is strictly here for adult roleplay. None of the laws here actually need to be obeyed and you can uninstall this NIFSoft at any time." purchase_price = 0 lewd_nifsoft = TRUE ui_icon = "file-contract" diff --git a/modular_skyrat/modules/modular_implants/code/nifsofts/hypnosis.dm b/modular_skyrat/modules/modular_implants/code/nifsofts/hypnosis.dm index 8576b7cbab2..be88ad77cd8 100644 --- a/modular_skyrat/modules/modular_implants/code/nifsofts/hypnosis.dm +++ b/modular_skyrat/modules/modular_implants/code/nifsofts/hypnosis.dm @@ -3,8 +3,8 @@ loaded_nifsoft = /datum/nifsoft/action_granter/hypnosis /datum/nifsoft/action_granter/hypnosis - name = "Purpura Eye" - program_desc = "Based on the hypnotic equipment provided by the LustWish vendor, the purpura eyes NIFSoft allows the user to ensnare others in a hypnotic trance. ((This is intended as a tool for ERP, don't use this for gameplay reasons.))" + name = "Libidine Eye" + program_desc = "Based on the hypnotic equipment provided by the LustWish vendor, the Libidine Eye NIFSoft allows the user to ensnare others in a hypnotic trance. ((This is intended as a tool for ERP, don't use this for gameplay reasons.))" buying_category = NIFSOFT_CATEGORY_FUN lewd_nifsoft = TRUE purchase_price = 150 diff --git a/modular_skyrat/modules/modular_items/code/tailoring.dm b/modular_skyrat/modules/modular_items/code/tailoring.dm index 22bce1ce3df..8d7cf31f58f 100644 --- a/modular_skyrat/modules/modular_items/code/tailoring.dm +++ b/modular_skyrat/modules/modular_items/code/tailoring.dm @@ -6,6 +6,14 @@ reqs = list(/obj/item/clothing/glasses/blindfold = 1) category = CAT_CLOTHING +/datum/crafting_recipe/paper_mask + name = "Paper Mask" + result = /obj/item/clothing/mask/paper + time = 30 + tool_behaviors = list(TOOL_WIRECUTTER) + reqs = list(/obj/item/paper = 5) + category = CAT_CLOTHING + /datum/crafting_recipe/crusader_belt name = "Crusader Belt and Sheath" result = /obj/item/storage/belt/crusader @@ -13,7 +21,7 @@ tool_behaviors = list(TOOL_WIRECUTTER, TOOL_SCREWDRIVER, TOOL_WELDER) //To cut the leather and fasten/weld the sheath detailing time = 30 category = CAT_CLOTHING - + /datum/crafting_recipe/crusader_belt/on_craft_completion(mob/user, atom/result) var/obj/item/storage/belt/crusader/crusader_belt = result crusader_belt.PopulateContents() @@ -54,7 +62,7 @@ reqs = list(/obj/item/clothing/glasses/hud/eyepatch/med = 1) tool_behaviors = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) category = CAT_CLOTHING - + /datum/crafting_recipe/mesonpatch name = "Meson Eyepatch HUD" result = /obj/item/clothing/glasses/hud/eyepatch/meson diff --git a/modular_skyrat/modules/modular_vending/code/wardrobes.dm b/modular_skyrat/modules/modular_vending/code/wardrobes.dm index e5f3e0210e7..103bb2ca975 100644 --- a/modular_skyrat/modules/modular_vending/code/wardrobes.dm +++ b/modular_skyrat/modules/modular_vending/code/wardrobes.dm @@ -61,9 +61,12 @@ /obj/item/clothing/mask/breath = 2, /obj/item/reagent_containers/cup/bottle/morphine = 2, /obj/item/reagent_containers/syringe = 2, + /obj/item/reagent_containers/spray/hercuri/chilled = 2, + /obj/item/clothing/gloves/color/black = 2, // fire resistant, allows the robo to painlessly mold metal. also its down here because its a treatment item /obj/item/bonesetter = 2, // for dislocations /obj/item/stack/medical/gauze = 4, // for ALL wounds /obj/item/healthanalyzer/no_medibot = 2, // disallows medibot use so its not wasted immediately on medibots + /obj/item/healthanalyzer/simple = 2, /obj/item/storage/backpack/science/robo = 2, /obj/item/storage/backpack/satchel/science/robo = 2, /obj/item/storage/backpack/duffelbag/science/robo = 2, diff --git a/modular_skyrat/modules/opposing_force/code/equipment/clothing.dm b/modular_skyrat/modules/opposing_force/code/equipment/clothing.dm index 1756407a2b9..d397c756778 100644 --- a/modular_skyrat/modules/opposing_force/code/equipment/clothing.dm +++ b/modular_skyrat/modules/opposing_force/code/equipment/clothing.dm @@ -86,7 +86,7 @@ /datum/opposing_force_equipment/clothing/nukiemod name = "Blood-Red MODsuit" - item_type = /obj/item/mod/control/pre_equipped/nuclear + item_type = /obj/item/mod/control/pre_equipped/nuclear/unrestricted description = "A suit designed by Gorlex Marauders, offering armor ruled illegal in most of Spinward Stellar." /datum/opposing_force_equipment/clothing/elitemod diff --git a/modular_skyrat/modules/opposing_force/code/items.dm b/modular_skyrat/modules/opposing_force/code/items.dm index 394ec009bee..d185e4e5c91 100644 --- a/modular_skyrat/modules/opposing_force/code/items.dm +++ b/modular_skyrat/modules/opposing_force/code/items.dm @@ -53,10 +53,10 @@ new /obj/item/clothing/gloves/tackler/combat(src) new /obj/item/clothing/shoes/combat(src) new /obj/item/clothing/glasses/sunglasses(src) - new /obj/item/clothing/mask/gas/sechailer/swat(src) + new /obj/item/clothing/mask/gas/syndicate(src) new /obj/item/storage/belt/military(src) new /obj/item/card/id/advanced/chameleon(src) - new /obj/item/mod/control/pre_equipped/nuclear(src) + new /obj/item/mod/control/pre_equipped/nuclear/unrestricted(src) /obj/item/guardiancreator/tech/choose/traitor/opfor allowling = TRUE diff --git a/modular_skyrat/modules/synths/code/bodyparts/limbs.dm b/modular_skyrat/modules/synths/code/bodyparts/limbs.dm index aba679efaef..1126295f1fe 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/limbs.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/limbs.dm @@ -1,5 +1,5 @@ -#define SYNTH_BRUTE_MODIFIER 1.3 -#define SYNTH_BURN_MODIFIER 1.3 +#define SYNTH_BRUTE_MODIFIER 1.0 +#define SYNTH_BURN_MODIFIER 1.0 // Synth bois! /obj/item/bodypart/head/robot/synth diff --git a/modular_skyrat/modules/synths/code/reagents/pill.dm b/modular_skyrat/modules/synths/code/reagents/pill.dm index 15b1fd95085..acf54dbd69e 100644 --- a/modular_skyrat/modules/synths/code/reagents/pill.dm +++ b/modular_skyrat/modules/synths/code/reagents/pill.dm @@ -2,7 +2,7 @@ name = "liquid solder pill" desc = "Used to treat synthetic brain damage." icon_state = "pill21" - list_reagents = list(/datum/reagent/medicine/liquid_solder = 50) + list_reagents = list(/datum/reagent/medicine/liquid_solder = 10) rename_with_volume = TRUE // Lower quantity solder pill. @@ -15,12 +15,12 @@ name = "nanite slurry pill" desc = "Used to repair robotic bodyparts." icon_state = "pill18" - list_reagents = list(/datum/reagent/medicine/nanite_slurry = 19) + list_reagents = list(/datum/reagent/medicine/nanite_slurry = 15) // 20 is OD rename_with_volume = TRUE /obj/item/reagent_containers/pill/system_cleaner name = "system cleaner pill" desc = "Used to detoxify synthetic bodies." icon_state = "pill7" - list_reagents = list(/datum/reagent/medicine/system_cleaner = 50) + list_reagents = list(/datum/reagent/medicine/system_cleaner = 10) rename_with_volume = TRUE diff --git a/modular_skyrat/modules/synths/code/species/synthetic.dm b/modular_skyrat/modules/synths/code/species/synthetic.dm index 08091118909..1630d14e1f2 100644 --- a/modular_skyrat/modules/synths/code/species/synthetic.dm +++ b/modular_skyrat/modules/synths/code/species/synthetic.dm @@ -187,7 +187,7 @@ SPECIES_PERK_ICON = "robot", SPECIES_PERK_NAME = "Synthetic Benefits", SPECIES_PERK_DESC = "Unlike organics, you DON'T explode when faced with a vacuum! Additionally, your chassis is built with such strength as to \ - grant you immunity to OVERpressure! Just make sure that the extreme cold or heat doesn't fry your circuitry. On top of this, synthetics are unable to be wounded!" + grant you immunity to OVERpressure! Just make sure that the extreme cold or heat doesn't fry your circuitry." )) perk_descriptions += list(list( @@ -203,7 +203,7 @@ SPECIES_PERK_NAME = "Synthetic Oddities", SPECIES_PERK_DESC = "[plural_form] are unable to gain nutrition from traditional foods. Instead, you must either consume welding fuel or extend a \ wire from your arm to draw power from an APC. In addition to this, welders and wires are your sutures and mesh and only specific chemicals even metabolize inside \ - of you. This ranges from whiskey, to synthanol, to various obscure medicines." + of you. This ranges from whiskey, to synthanol, to various obscure medicines. Finally, you suffer from a set of wounds exclusive to synthetics." )) return perk_descriptions diff --git a/strings/wounds/metal_scar_desc.json b/strings/wounds/metal_scar_desc.json new file mode 100644 index 00000000000..6064855de11 --- /dev/null +++ b/strings/wounds/metal_scar_desc.json @@ -0,0 +1,67 @@ +{ + "generic": ["general disfigurement"], + + "dislocate": [ + "some slight crookedness" + ], + + "bluntsevere": [ + "an area of slightly crumpled metal", + "some faded cracks on some screws" + ], + + "bluntcritical": [ + "a malformed superstructure", + "some heavily beaten plating" + ], + + "slashmoderate": [ + "a very thin line of solder", + "a few welded cuts" + ], + + "slashsevere": [ + "a pair of soldered, straight cracks", + "an area of freshly replaced metal", + "has some deep welded scratches on the metal" + ], + + "slashcritical": [ + "a matrix of desperately soldered wide cracks", + "some gruesome welding lines", + "a series of deep and wide welded gashes" + ], + + "piercemoderate": [ + "a dot of hardened solder", + "a dot of fresh metal in a small hole" + ], + + "piercesevere": [ + "a wad of hardened solder", + "a small patch of fresh metal in a small hole" + ], + + "piercecritical": [ + "a large splot of hardened solder", + "an inward caving hole leading to fresh metal" + ], + + "burnsevere": [ + "some vaguely discolored metal", + "some burnt ridges", + "a few heat cracks" + ], + + "burncritical": [ + "lots of polychromatic metal on it", + "some heat-warped plating", + "melting marks" + ], + + "dismember": [ + "has some fresh metal around various joints", + "has some solder marks securing various joints", + "has clear re-seating welding marks" + ] +} diff --git a/tgstation.dme b/tgstation.dme index aea653999d7..de8210ad527 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -597,6 +597,7 @@ #include "code\_globalvars\lists\objects.dm" #include "code\_globalvars\lists\poll_ignore.dm" #include "code\_globalvars\lists\quirks.dm" +#include "code\_globalvars\lists\reagents.dm" #include "code\_globalvars\lists\rtd.dm" #include "code\_globalvars\lists\typecache.dm" #include "code\_globalvars\lists\wiremod.dm" @@ -920,6 +921,7 @@ #include "code\datums\ai\basic_mobs\basic_subtrees\move_to_cardinal.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\opportunistic_ventcrawler.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\ranged_skirmish.dm" +#include "code\datums\ai\basic_mobs\basic_subtrees\shapechange_ambush.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\simple_attack_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\simple_find_nearest_target_to_flee.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\simple_find_target.dm" @@ -928,6 +930,7 @@ #include "code\datums\ai\basic_mobs\basic_subtrees\stare_at_thing.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\target_retaliate.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\targeted_mob_ability.dm" +#include "code\datums\ai\basic_mobs\basic_subtrees\teleport_away_from_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\tipped_subtree.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\travel_to_point.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\use_mob_ability.dm" @@ -938,6 +941,7 @@ #include "code\datums\ai\basic_mobs\pet_commands\play_dead.dm" #include "code\datums\ai\basic_mobs\targetting_datums\basic_targetting_datum.dm" #include "code\datums\ai\basic_mobs\targetting_datums\dont_target_friends.dm" +#include "code\datums\ai\basic_mobs\targetting_datums\with_object.dm" #include "code\datums\ai\cursed\cursed_behaviors.dm" #include "code\datums\ai\cursed\cursed_controller.dm" #include "code\datums\ai\cursed\cursed_subtrees.dm" @@ -1105,6 +1109,7 @@ #include "code\datums\components\itembound.dm" #include "code\datums\components\itempicky.dm" #include "code\datums\components\jetpack.dm" +#include "code\datums\components\joint_damage.dm" #include "code\datums\components\jousting.dm" #include "code\datums\components\keep_me_secure.dm" #include "code\datums\components\knockoff.dm" @@ -1119,6 +1124,7 @@ #include "code\datums\components\manual_heart.dm" #include "code\datums\components\mind_linker.dm" #include "code\datums\components\mirv.dm" +#include "code\datums\components\mob_chain.dm" #include "code\datums\components\mob_harvest.dm" #include "code\datums\components\multiple_lives.dm" #include "code\datums\components\mutant_hands.dm" @@ -3030,7 +3036,6 @@ #include "code\modules\antagonists\heretic\magic\void_phase.dm" #include "code\modules\antagonists\heretic\magic\void_pull.dm" #include "code\modules\antagonists\heretic\magic\wave_of_desperation.dm" -#include "code\modules\antagonists\heretic\mobs\maid_in_mirror.dm" #include "code\modules\antagonists\heretic\status_effects\buffs.dm" #include "code\modules\antagonists\heretic\status_effects\debuffs.dm" #include "code\modules\antagonists\heretic\status_effects\ghoul.dm" @@ -3288,6 +3293,7 @@ #include "code\modules\atmospherics\machinery\pipes\layermanifold.dm" #include "code\modules\atmospherics\machinery\pipes\mapping.dm" #include "code\modules\atmospherics\machinery\pipes\multiz.dm" +#include "code\modules\atmospherics\machinery\pipes\pipe_spritesheet_helper.dm" #include "code\modules\atmospherics\machinery\pipes\pipes.dm" #include "code\modules\atmospherics\machinery\pipes\smart.dm" #include "code\modules\atmospherics\machinery\pipes\heat_exchange\he_pipes.dm" @@ -3332,6 +3338,7 @@ #include "code\modules\bitrunning\abilities.dm" #include "code\modules\bitrunning\alerts.dm" #include "code\modules\bitrunning\areas.dm" +#include "code\modules\bitrunning\designs.dm" #include "code\modules\bitrunning\event.dm" #include "code\modules\bitrunning\job.dm" #include "code\modules\bitrunning\turfs.dm" @@ -3340,7 +3347,7 @@ #include "code\modules\bitrunning\components\avatar_connection.dm" #include "code\modules\bitrunning\components\bitrunning_points.dm" #include "code\modules\bitrunning\components\netpod_healing.dm" -#include "code\modules\bitrunning\objects\bit_vendor.dm" +#include "code\modules\bitrunning\objects\byteforge.dm" #include "code\modules\bitrunning\objects\clothing.dm" #include "code\modules\bitrunning\objects\disks.dm" #include "code\modules\bitrunning\objects\hololadder.dm" @@ -3349,6 +3356,7 @@ #include "code\modules\bitrunning\objects\loot_crate.dm" #include "code\modules\bitrunning\objects\netpod.dm" #include "code\modules\bitrunning\objects\quantum_console.dm" +#include "code\modules\bitrunning\objects\vendor.dm" #include "code\modules\bitrunning\orders\disks.dm" #include "code\modules\bitrunning\orders\flair.dm" #include "code\modules\bitrunning\orders\tech.dm" @@ -4458,10 +4466,21 @@ #include "code\modules\mob\living\basic\farm_animals\cow\cow_ai.dm" #include "code\modules\mob\living\basic\farm_animals\cow\cow_moonicorn.dm" #include "code\modules\mob\living\basic\farm_animals\cow\cow_wisdom.dm" +#include "code\modules\mob\living\basic\farm_animals\goat\_goat.dm" +#include "code\modules\mob\living\basic\farm_animals\goat\goat_ai.dm" +#include "code\modules\mob\living\basic\farm_animals\goat\goat_subtypes.dm" +#include "code\modules\mob\living\basic\heretic\ash_spirit.dm" #include "code\modules\mob\living\basic\heretic\fire_shark.dm" +#include "code\modules\mob\living\basic\heretic\flesh_stalker.dm" +#include "code\modules\mob\living\basic\heretic\flesh_worm.dm" #include "code\modules\mob\living\basic\heretic\heretic_summon.dm" +#include "code\modules\mob\living\basic\heretic\maid_in_the_mirror.dm" #include "code\modules\mob\living\basic\heretic\raw_prophet.dm" +#include "code\modules\mob\living\basic\heretic\rust_walker.dm" #include "code\modules\mob\living\basic\heretic\star_gazer.dm" +#include "code\modules\mob\living\basic\icemoon\ice_demon\ice_demon.dm" +#include "code\modules\mob\living\basic\icemoon\ice_demon\ice_demon_abilities.dm" +#include "code\modules\mob\living\basic\icemoon\ice_demon\ice_demon_ai.dm" #include "code\modules\mob\living\basic\icemoon\ice_whelp\ice_whelp.dm" #include "code\modules\mob\living\basic\icemoon\ice_whelp\ice_whelp_abilities.dm" #include "code\modules\mob\living\basic\icemoon\ice_whelp\ice_whelp_ai.dm" @@ -4515,6 +4534,7 @@ #include "code\modules\mob\living\basic\pets\fox.dm" #include "code\modules\mob\living\basic\pets\penguin.dm" #include "code\modules\mob\living\basic\pets\pet.dm" +#include "code\modules\mob\living\basic\pets\sloth.dm" #include "code\modules\mob\living\basic\pets\dog\_dog.dm" #include "code\modules\mob\living\basic\pets\dog\corgi.dm" #include "code\modules\mob\living\basic\pets\dog\dog_subtypes.dm" @@ -4763,10 +4783,8 @@ #include "code\modules\mob\living\simple_animal\bot\SuperBeepsky.dm" #include "code\modules\mob\living\simple_animal\bot\vibebot.dm" #include "code\modules\mob\living\simple_animal\friendly\cat.dm" -#include "code\modules\mob\living\simple_animal\friendly\farm_animals.dm" #include "code\modules\mob\living\simple_animal\friendly\gondola.dm" #include "code\modules\mob\living\simple_animal\friendly\pet.dm" -#include "code\modules\mob\living\simple_animal\friendly\sloth.dm" #include "code\modules\mob\living\simple_animal\friendly\drone\_drone.dm" #include "code\modules\mob\living\simple_animal\friendly\drone\drone_say.dm" #include "code\modules\mob\living\simple_animal\friendly\drone\drone_tools.dm" @@ -4791,7 +4809,6 @@ #include "code\modules\mob\living\simple_animal\guardian\types\support.dm" #include "code\modules\mob\living\simple_animal\hostile\alien.dm" #include "code\modules\mob\living\simple_animal\hostile\dark_wizard.dm" -#include "code\modules\mob\living\simple_animal\hostile\heretic_monsters.dm" #include "code\modules\mob\living\simple_animal\hostile\hostile.dm" #include "code\modules\mob\living\simple_animal\hostile\illusion.dm" #include "code\modules\mob\living\simple_animal\hostile\mimic.dm" @@ -4827,7 +4844,6 @@ #include "code\modules\mob\living\simple_animal\hostile\megafauna\wendigo.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\curse_blob.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\gutlunch.dm" -#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\ice_demon.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\mining_mobs.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\polarbear.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\wolf.dm" @@ -5921,6 +5937,7 @@ #include "modular_skyrat\master_files\code\datums\components\crafting.dm" #include "modular_skyrat\master_files\code\datums\components\damage_tracker.dm" #include "modular_skyrat\master_files\code\datums\components\fullauto.dm" +#include "modular_skyrat\master_files\code\datums\components\grillable.dm" #include "modular_skyrat\master_files\code\datums\components\leash.dm" #include "modular_skyrat\master_files\code\datums\components\shielded_suit.dm" #include "modular_skyrat\master_files\code\datums\components\tippable.dm" @@ -6149,6 +6166,7 @@ #include "modular_skyrat\master_files\code\modules\mob\living\living.dm" #include "modular_skyrat\master_files\code\modules\mob\living\living_defines.dm" #include "modular_skyrat\master_files\code\modules\mob\living\living_movement.dm" +#include "modular_skyrat\master_files\code\modules\mob\living\basic\icemoon\ice_demon.dm" #include "modular_skyrat\master_files\code\modules\mob\living\carbon\death.dm" #include "modular_skyrat\master_files\code\modules\mob\living\carbon\human.dm" #include "modular_skyrat\master_files\code\modules\mob\living\carbon\human_helpers.dm" @@ -6673,6 +6691,7 @@ #include "modular_skyrat\modules\customization\modules\clothing\masks\breath.dm" #include "modular_skyrat\modules\customization\modules\clothing\masks\gas_filter.dm" #include "modular_skyrat\modules\customization\modules\clothing\masks\gasmask.dm" +#include "modular_skyrat\modules\customization\modules\clothing\masks\paper.dm" #include "modular_skyrat\modules\customization\modules\clothing\neck\_neck.dm" #include "modular_skyrat\modules\customization\modules\clothing\neck\cloaks.dm" #include "modular_skyrat\modules\customization\modules\clothing\neck\collars.dm" @@ -7112,11 +7131,24 @@ #include "modular_skyrat\modules\medical\code\carbon_update_icons.dm" #include "modular_skyrat\modules\medical\code\grasp.dm" #include "modular_skyrat\modules\medical\code\health_analyzer.dm" +#include "modular_skyrat\modules\medical\code\medkit.dm" #include "modular_skyrat\modules\medical\code\smartdarts.dm" +#include "modular_skyrat\modules\medical\code\sprays.dm" +#include "modular_skyrat\modules\medical\code\cargo\packs.dm" #include "modular_skyrat\modules\medical\code\wounds\_wounds.dm" #include "modular_skyrat\modules\medical\code\wounds\bleed.dm" #include "modular_skyrat\modules\medical\code\wounds\medical.dm" #include "modular_skyrat\modules\medical\code\wounds\muscle.dm" +#include "modular_skyrat\modules\medical\code\wounds\wound_effects.dm" +#include "modular_skyrat\modules\medical\code\wounds\synth\robotic_burns.dm" +#include "modular_skyrat\modules\medical\code\wounds\synth\robotic_muscle.dm" +#include "modular_skyrat\modules\medical\code\wounds\synth\robotic_pierce.dm" +#include "modular_skyrat\modules\medical\code\wounds\synth\robotic_slash.dm" +#include "modular_skyrat\modules\medical\code\wounds\synth\blunt\robotic_blunt.dm" +#include "modular_skyrat\modules\medical\code\wounds\synth\blunt\robotic_blunt_T1.dm" +#include "modular_skyrat\modules\medical\code\wounds\synth\blunt\robotic_blunt_T2.dm" +#include "modular_skyrat\modules\medical\code\wounds\synth\blunt\robotic_blunt_T3.dm" +#include "modular_skyrat\modules\medical\code\wounds\synth\blunt\secures_internals.dm" #include "modular_skyrat\modules\medical_designs\medical_designs.dm" #include "modular_skyrat\modules\medievalcrate_skyrat\code\vintageitems.dm" #include "modular_skyrat\modules\mentor\code\_globalvars.dm" diff --git a/tgui/packages/tgui/constants.ts b/tgui/packages/tgui/constants.ts index 8bf4b83823f..c038cd6740a 100644 --- a/tgui/packages/tgui/constants.ts +++ b/tgui/packages/tgui/constants.ts @@ -160,7 +160,7 @@ const GASES = [ path: '/datum/gas/nitrogen', name: 'Nitrogen', label: 'N₂', - color: 'red', + color: 'yellow', }, { id: 'co2', diff --git a/tgui/packages/tgui/interfaces/AdminFax.js b/tgui/packages/tgui/interfaces/AdminFax.js index e91130baf39..46e12615922 100644 --- a/tgui/packages/tgui/interfaces/AdminFax.js +++ b/tgui/packages/tgui/interfaces/AdminFax.js @@ -91,7 +91,7 @@ export const FaxMainPanel = (props, context) => { icon="n" mr="7px" width="49%" - onClick={() => setPaperName('Nanotrasen Offical Report')}> + onClick={() => setPaperName('Nanotrasen Official Report')}> Nanotrasen