diff --git a/_maps/RandomRuins/IceRuins/skyrat/icemoon_underground_syndicate_base1_skyrat.dmm b/_maps/RandomRuins/IceRuins/skyrat/icemoon_underground_syndicate_base1_skyrat.dmm index 4bb06861e10..0330ddf8031 100644 --- a/_maps/RandomRuins/IceRuins/skyrat/icemoon_underground_syndicate_base1_skyrat.dmm +++ b/_maps/RandomRuins/IceRuins/skyrat/icemoon_underground_syndicate_base1_skyrat.dmm @@ -872,7 +872,7 @@ /area/ruin/syndicate_lava_base/cargo) "gp" = ( /obj/machinery/light/floor, -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/iron/dark, /area/ruin/syndicate_lava_base/medbay) "gs" = ( diff --git a/_maps/RandomRuins/LavaRuins/lavaland_strong_rock.dmm b/_maps/RandomRuins/LavaRuins/lavaland_strong_rock.dmm index f236a25a6a0..ad90df10167 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_strong_rock.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_strong_rock.dmm @@ -4,7 +4,7 @@ /area/template_noop) "b" = ( /turf/closed/mineral/strong, -/area/template_noop) +/area/lavaland/surface/outdoors) (1,1,1) = {" a diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm index 4cc31bca411..7497b5bb907 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm @@ -3716,7 +3716,7 @@ "OZ" = ( /obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, -/obj/machinery/suit_storage_unit/syndicate, +/obj/machinery/suit_storage_unit/syndicate/lavaland, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/ruin/syndicate_lava_base/engineering) diff --git a/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_arena.dmm b/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_arena.dmm index bce0b173159..47fd82ad043 100644 --- a/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_arena.dmm +++ b/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_arena.dmm @@ -113,10 +113,9 @@ /obj/structure/stone_tile{ dir = 4 }, -/mob/living/simple_animal/hostile/asteroid/hivelord{ +/mob/living/basic/mining/hivelord/no_wander{ color = "red"; name = "gate guardian"; - wander = 0 }, /turf/open/lava/smooth/lava_land_surface{ slowdown = 0 @@ -308,10 +307,9 @@ /obj/structure/stone_tile{ dir = 1 }, -/mob/living/simple_animal/hostile/asteroid/hivelord{ +/mob/living/basic/mining/hivelord/no_wander{ color = "red"; name = "gate guardian"; - wander = 0 }, /turf/open/lava/smooth/lava_land_surface{ slowdown = 0 @@ -627,10 +625,9 @@ /obj/structure/stone_tile{ dir = 1 }, -/mob/living/simple_animal/hostile/asteroid/hivelord{ +/mob/living/basic/mining/hivelord/no_wander{ color = "red"; name = "gate guardian"; - wander = 0 }, /turf/open/indestructible/boss, /area/lavaland/surface/outdoors) @@ -778,10 +775,9 @@ /obj/structure/stone_tile{ dir = 4 }, -/mob/living/simple_animal/hostile/asteroid/hivelord{ +/mob/living/basic/mining/hivelord/no_wander{ color = "red"; name = "gate guardian"; - wander = 0 }, /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 7b81c9e2193..957a669e53c 100644 --- a/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_syndicate_base1_skyrat.dmm +++ b/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_syndicate_base1_skyrat.dmm @@ -1393,7 +1393,7 @@ /turf/open/floor/plating, /area/ruin/syndicate_lava_base/medbay) "oe" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/iron/dark, /area/ruin/syndicate_lava_base/medbay) "oi" = ( diff --git a/_maps/RandomRuins/SpaceRuins/atmosasteroidruin.dmm b/_maps/RandomRuins/SpaceRuins/atmosasteroidruin.dmm index 1d63a1a0070..7e3b7000c42 100644 --- a/_maps/RandomRuins/SpaceRuins/atmosasteroidruin.dmm +++ b/_maps/RandomRuins/SpaceRuins/atmosasteroidruin.dmm @@ -637,7 +637,7 @@ /obj/effect/turf_decal/tile/yellow/half{ dir = 4 }, -/mob/living/simple_animal/hostile/asteroid/hivelord, +/mob/living/basic/mining/hivelord, /turf/open/floor/iron/co2_pressurized, /area/ruin/space/has_grav/atmosasteroid) "RK" = ( diff --git a/_maps/RandomRuins/SpaceRuins/listeningstation.dmm b/_maps/RandomRuins/SpaceRuins/listeningstation.dmm index 256555eca0c..366005b95a6 100644 --- a/_maps/RandomRuins/SpaceRuins/listeningstation.dmm +++ b/_maps/RandomRuins/SpaceRuins/listeningstation.dmm @@ -234,7 +234,6 @@ anchored = 1 }, /obj/machinery/door/window/brigdoor{ - dir = 2; req_access = list("syndicate"); name = "Self Destruct Option" }, @@ -305,9 +304,6 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/listeningstation) "rr" = ( -/obj/machinery/door/airlock{ - name = "Emergency Backup" - }, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -392,7 +388,6 @@ /area/ruin/space/has_grav/listeningstation) "xh" = ( /obj/machinery/computer/records/medical/syndie{ - dir = 2; req_access = list("syndicate") }, /obj/machinery/light/small/directional/north, @@ -813,6 +808,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/mapping_helpers/broken_floor, +/obj/machinery/door/airlock{ + name = "Emergency Backup" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, /turf/open/floor/plating, /area/ruin/space/has_grav/listeningstation) "RK" = ( diff --git a/_maps/RandomRuins/SpaceRuins/prey_pod.dmm b/_maps/RandomRuins/SpaceRuins/prey_pod.dmm index 9089dea664c..6f53409b873 100644 --- a/_maps/RandomRuins/SpaceRuins/prey_pod.dmm +++ b/_maps/RandomRuins/SpaceRuins/prey_pod.dmm @@ -17,7 +17,7 @@ /obj/structure/chair/comfy/shuttle{ dir = 4 }, -/mob/living/simple_animal/hostile/asteroid/hivelord, +/mob/living/basic/mining/hivelord, /turf/open/floor/mineral/titanium/white/airless, /area/ruin/space/has_grav) "p" = ( @@ -32,7 +32,7 @@ /area/ruin/space/has_grav) "D" = ( /obj/structure/chair/comfy/shuttle, -/mob/living/simple_animal/hostile/asteroid/hivelord, +/mob/living/basic/mining/hivelord, /turf/open/floor/mineral/titanium/white/airless, /area/ruin/space/has_grav) "E" = ( @@ -57,7 +57,7 @@ /turf/open/floor/mineral/titanium/white/airless, /area/ruin/space/has_grav) "S" = ( -/mob/living/simple_animal/hostile/asteroid/hivelord, +/mob/living/basic/mining/hivelord, /turf/open/floor/mineral/titanium/white/airless, /area/ruin/space/has_grav) "T" = ( diff --git a/_maps/RandomRuins/SpaceRuins/prison_shuttle.dmm b/_maps/RandomRuins/SpaceRuins/prison_shuttle.dmm index 5aeba75b3bd..6acec2ccc43 100644 --- a/_maps/RandomRuins/SpaceRuins/prison_shuttle.dmm +++ b/_maps/RandomRuins/SpaceRuins/prison_shuttle.dmm @@ -56,7 +56,7 @@ /turf/open/floor/plating/airless, /area/ruin/space/prison_shuttle) "q" = ( -/mob/living/simple_animal/hostile/asteroid/hivelord, +/mob/living/basic/mining/hivelord, /turf/open/misc/asteroid/airless, /area/ruin/space/prison_shuttle) "r" = ( @@ -84,7 +84,7 @@ /turf/open/floor/mineral/titanium/tiled/airless, /area/ruin/space/prison_shuttle) "w" = ( -/mob/living/simple_animal/hostile/asteroid/hivelord, +/mob/living/basic/mining/hivelord, /turf/open/floor/plating/airless, /area/ruin/space/prison_shuttle) "x" = ( diff --git a/_maps/RandomRuins/SpaceRuins/skyrat/syndibase.dmm b/_maps/RandomRuins/SpaceRuins/skyrat/syndibase.dmm index eec3ffec3b3..91d171ca87e 100644 --- a/_maps/RandomRuins/SpaceRuins/skyrat/syndibase.dmm +++ b/_maps/RandomRuins/SpaceRuins/skyrat/syndibase.dmm @@ -164,7 +164,7 @@ /turf/open/floor/iron, /area/ruin/space/has_grav/powered) "pF" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/iron/dark, /area/ruin/space/has_grav/powered) "pL" = ( diff --git a/_maps/RandomRuins/SpaceRuins/skyrat/wreckedhomestead.dmm b/_maps/RandomRuins/SpaceRuins/skyrat/wreckedhomestead.dmm index 3524b7a08a3..afa164d0b27 100644 --- a/_maps/RandomRuins/SpaceRuins/skyrat/wreckedhomestead.dmm +++ b/_maps/RandomRuins/SpaceRuins/skyrat/wreckedhomestead.dmm @@ -84,11 +84,6 @@ /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/iron/airless, /area/ruin/unpowered) -"oa" = ( -/obj/machinery/rnd/bepis, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/iron/airless, -/area/ruin/unpowered) "on" = ( /obj/structure/closet/secure_closet/brig, /obj/structure/window/reinforced/spawner/directional/west, @@ -133,6 +128,11 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron/dark/airless, /area/ruin/unpowered) +"tP" = ( +/obj/machinery/cryo_cell, +/obj/effect/mapping_helpers/burnt_floor, +/turf/open/floor/plating/airless, +/area/ruin/unpowered) "ve" = ( /obj/machinery/atmospherics/components/unary/thermomachine/freezer{ dir = 1 @@ -160,11 +160,6 @@ }, /turf/open/floor/plating/airless, /area/ruin/unpowered) -"Az" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/plating/airless, -/area/ruin/unpowered) "Bf" = ( /turf/closed/wall/mineral/titanium, /area/ruin/unpowered) @@ -1209,7 +1204,7 @@ wY Bf Wp Bf -Az +tP Dh ve mP @@ -1276,7 +1271,7 @@ Wv kN dL Bf -oa +kN Bf Bf Bf diff --git a/_maps/RandomZLevels/SnowCabin.dmm b/_maps/RandomZLevels/SnowCabin.dmm index cf2b35b3663..cf324e6c5bb 100644 --- a/_maps/RandomZLevels/SnowCabin.dmm +++ b/_maps/RandomZLevels/SnowCabin.dmm @@ -426,7 +426,7 @@ /turf/open/floor/iron/white, /area/awaymission/cabin) "bF" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/iron/white, /area/awaymission/cabin) "bG" = ( diff --git a/_maps/RandomZLevels/blackmesa.dmm b/_maps/RandomZLevels/blackmesa.dmm index b9887279a16..892d7d76815 100644 --- a/_maps/RandomZLevels/blackmesa.dmm +++ b/_maps/RandomZLevels/blackmesa.dmm @@ -5008,7 +5008,7 @@ /turf/open/floor/iron/smooth_large, /area/awaymission/black_mesa/entrance_internal_hall) "cPC" = ( -/mob/living/simple_animal/hostile/blob/blobspore/independent, +/mob/living/basic/blob_minion/spore, /obj/structure/blob/normal, /turf/open/floor/engine, /area/awaymission/black_mesa/hecu_zone_test_chambers) @@ -5164,7 +5164,7 @@ /turf/open/floor/iron/smooth_large, /area/awaymission/black_mesa/hecu_zone_external_hall) "dcv" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/iron/smooth_large, /area/awaymission/black_mesa/xen/acid_lake_building) "ddi" = ( @@ -9388,7 +9388,7 @@ /turf/open/floor/iron/white, /area/awaymission/black_mesa/hecu_zone_camp) "ldC" = ( -/mob/living/simple_animal/hostile/blob/blobbernaut/independent, +/mob/living/basic/blob_minion/blobbernaut, /obj/structure/blob/normal, /turf/open/floor/engine, /area/awaymission/black_mesa/hecu_zone_test_chambers) diff --git a/_maps/RandomZLevels/research.dmm b/_maps/RandomZLevels/research.dmm index 324734c4eb9..18429389d87 100644 --- a/_maps/RandomZLevels/research.dmm +++ b/_maps/RandomZLevels/research.dmm @@ -1042,7 +1042,7 @@ /turf/open/floor/iron/white, /area/awaymission/research/interior/cryo) "fc" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/iron/white, /area/awaymission/research/interior/cryo) "fd" = ( @@ -1083,7 +1083,7 @@ /area/awaymission/research/interior/cryo) "fh" = ( /obj/effect/decal/cleanable/blood/drip, -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/iron/white, /area/awaymission/research/interior/cryo) "fk" = ( diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 21b1cddf818..cf218b898be 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -46,6 +46,10 @@ }, /turf/open/floor/iron, /area/station/security/tram) +"ach" = ( +/obj/machinery/netpod, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "acl" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/decal/cleanable/dirt, @@ -104,6 +108,13 @@ /obj/machinery/camera/directional/east, /turf/open/floor/iron, /area/station/service/janitor) +"adl" = ( +/obj/effect/turf_decal/siding/white, +/obj/machinery/light/small/directional/south, +/obj/structure/table/reinforced, +/obj/item/surgery_tray/full/morgue, +/turf/open/floor/iron/small, +/area/station/medical/morgue) "adB" = ( /obj/effect/turf_decal/sand/plating, /turf/open/floor/plating, @@ -1633,6 +1644,10 @@ }, /turf/open/floor/iron/small, /area/station/maintenance/port/lesser) +"aJN" = ( +/obj/structure/window/reinforced/shuttle, +/turf/open/floor/plating, +/area/station/commons/fitness/recreation/entertainment) "aJX" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/airlock{ @@ -3296,6 +3311,11 @@ /obj/effect/spawner/random/engineering/atmospherics_portable, /turf/open/floor/plating, /area/station/maintenance/department/engine) +"bqy" = ( +/turf/open/floor/engine{ + name = "Holodeck Projector Floor" + }, +/area/station/holodeck/rec_center) "bqE" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -3916,6 +3936,30 @@ }, /turf/open/floor/iron, /area/station/security/processing) +"bCh" = ( +/obj/effect/turf_decal/stripes{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes{ + dir = 8 + }, +/obj/machinery/door/airlock/mining{ + name = "Bitrunning Den" + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, +/turf/open/floor/iron/dark/smooth_half{ + dir = 1 + }, +/area/station/bitrunning/den) "bCi" = ( /obj/effect/turf_decal/tile/yellow/opposingcorners, /obj/machinery/atmospherics/components/binary/crystallizer{ @@ -5414,14 +5458,6 @@ /obj/structure/sign/poster/official/random/directional/north, /turf/open/floor/iron/smooth_large, /area/station/science/auxlab/firing_range) -"cgD" = ( -/obj/machinery/door/airlock{ - name = "Mineshaft" - }, -/obj/effect/mapping_helpers/airlock/access/any/service/maintenance, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating/rust, -/area/station/maintenance/fore/greater) "cgM" = ( /turf/open/misc/asteroid, /area/station/maintenance/starboard/greater) @@ -5497,14 +5533,6 @@ }, /turf/open/floor/iron, /area/station/maintenance/port/fore) -"ciL" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable, -/obj/structure/extinguisher_cabinet/directional/north, -/turf/open/floor/iron, -/area/station/cargo/storage) "ciR" = ( /obj/structure/table, /obj/effect/spawner/random/techstorage/command_all, @@ -6112,6 +6140,27 @@ "cvJ" = ( /turf/open/floor/plating, /area/station/maintenance/department/engine/atmos) +"cvP" = ( +/obj/effect/turf_decal/stripes{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/machinery/holopad, +/turf/open/floor/iron/dark/smooth_half{ + dir = 1 + }, +/area/station/bitrunning/den) "cvZ" = ( /obj/structure/closet/secure_closet/evidence, /obj/effect/decal/cleanable/dirt, @@ -7682,6 +7731,12 @@ /obj/effect/spawner/random/structure/steam_vent, /turf/open/floor/plating, /area/station/ai_monitored/turret_protected/aisat/maint) +"cZm" = ( +/obj/effect/landmark/start/hangover, +/turf/open/floor/engine{ + name = "Holodeck Projector Floor" + }, +/area/station/holodeck/rec_center) "cZy" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -8386,10 +8441,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/disposal/incinerator) -"dmz" = ( -/obj/effect/spawner/random/structure/closet_maintenance, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "dmT" = ( /obj/machinery/camera/directional/north{ c_tag = "Xenobiology - Cell 2"; @@ -8519,6 +8570,11 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/station/maintenance/department/engine/atmos) +"doX" = ( +/obj/structure/girder, +/obj/effect/decal/cleanable/glass/plastitanium, +/turf/open/floor/plating, +/area/station/commons/fitness/recreation/entertainment) "dps" = ( /obj/machinery/camera/directional/south{ c_tag = "AI Chamber - Aft"; @@ -8811,6 +8867,15 @@ /obj/structure/sign/warning/electric_shock, /turf/closed/wall, /area/station/maintenance/department/engine) +"dvs" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/glass{ + name = "Holodeck Access" + }, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "dvJ" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/tile/dark_red/fourcorners, @@ -9713,6 +9778,13 @@ /obj/item/wrench, /turf/open/floor/iron/dark, /area/station/science/robotics/lab) +"dNi" = ( +/obj/machinery/power/shuttle_engine/heater{ + dir = 1 + }, +/obj/structure/window/spawner/directional/south, +/turf/open/floor/plating, +/area/station/commons/fitness/recreation/entertainment) "dNq" = ( /turf/closed/wall/r_wall/rust, /area/station/ai_monitored/aisat/exterior) @@ -10352,6 +10424,12 @@ }, /turf/open/floor/iron/dark, /area/station/security/lockers) +"dYf" = ( +/obj/effect/spawner/random/entertainment/arcade{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "dYj" = ( /obj/structure/table, /obj/effect/turf_decal/tile/dark_red, @@ -10943,6 +11021,10 @@ /obj/structure/frame/computer, /turf/open/floor/eighties/red, /area/station/service/abandoned_gambling_den/gaming) +"ejq" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/station/bitrunning/den) "ejt" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -10959,6 +11041,10 @@ /obj/machinery/atmospherics/pipe/layer_manifold/orange/visible, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) +"ejV" = ( +/mob/living/basic/mining/basilisk, +/turf/open/misc/asteroid, +/area/space/nearstation) "eki" = ( /obj/machinery/door/airlock/maintenance{ name = "Maintenance" @@ -11841,6 +11927,11 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/break_room) +"eyz" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/obj/structure/chair/stool/directional/west, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "eyB" = ( /obj/structure/cable, /obj/machinery/door/firedoor, @@ -12568,6 +12659,11 @@ }, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"eKX" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "eLn" = ( /obj/machinery/door/airlock/glass{ name = "Gold Standard Law Firm" @@ -13849,6 +13945,14 @@ }, /turf/open/floor/iron/dark, /area/station/security/interrogation) +"fls" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/duct, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/glass/plastitanium, +/turf/open/floor/plating, +/area/station/maintenance/fore/greater) "flM" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -14320,6 +14424,18 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/stone, /area/station/command/heads_quarters/hos) +"fts" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/computer/order_console/bitrunning{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/end{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "ftv" = ( /obj/effect/turf_decal/tile/dark_red/opposingcorners, /obj/structure/table/reinforced, @@ -17550,6 +17666,14 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth, /area/station/hallway/secondary/command) +"gxZ" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/duct, +/obj/machinery/power/apc/auto_name/directional/west, +/turf/open/floor/plating, +/area/station/maintenance/fore/greater) "gyd" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/window/spawner/directional/east, @@ -17879,6 +18003,13 @@ /obj/machinery/airalarm/directional/south, /turf/open/floor/iron, /area/station/cargo/office) +"gEQ" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/chair/sofa/bench/right{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "gFg" = ( /obj/machinery/computer/cargo/request, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -19426,6 +19557,8 @@ /obj/effect/mapping_helpers/broken_floor, /obj/structure/sign/poster/official/random/directional/north, /obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small/directional/north, +/obj/machinery/camera/directional/west, /turf/open/floor/iron, /area/station/commons) "hem" = ( @@ -20241,16 +20374,6 @@ /obj/effect/turf_decal/stripes/white/line, /turf/open/floor/plating, /area/station/cargo/miningoffice) -"hsK" = ( -/obj/machinery/recycler{ - dir = 8 - }, -/obj/machinery/conveyor{ - dir = 4; - id = "garbage" - }, -/turf/open/floor/plating, -/area/station/service/janitor) "hsO" = ( /obj/structure/cable, /obj/effect/spawner/structure/window, @@ -20689,16 +20812,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) -"hzN" = ( -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/item/radio/intercom/directional/north, -/turf/open/floor/iron, -/area/station/cargo/storage) "hzV" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -21023,12 +21136,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/smooth, /area/station/hallway/secondary/command) -"hFm" = ( -/obj/effect/turf_decal/bot_white, -/obj/structure/rack, -/obj/item/electronics/apc, -/turf/open/floor/iron/smooth_large, -/area/station/cargo/warehouse) "hFx" = ( /turf/open/floor/iron/chapel{ dir = 1 @@ -21174,11 +21281,6 @@ "hJp" = ( /turf/closed/wall/r_wall/rust, /area/station/ai_monitored/turret_protected/ai) -"hJr" = ( -/obj/structure/table, -/obj/effect/decal/cleanable/dirt, -/turf/open/misc/asteroid, -/area/station/maintenance/fore/greater) "hJC" = ( /obj/structure/closet/crate/hydroponics, /obj/item/paper/guides/jobs/hydroponics, @@ -21417,6 +21519,12 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"hNv" = ( +/obj/machinery/netpod, +/obj/machinery/light_switch/directional/north, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "hNA" = ( /obj/effect/turf_decal/tile/brown/opposingcorners, /turf/open/floor/iron, @@ -22684,11 +22792,6 @@ /obj/effect/spawner/random/engineering/atmospherics_portable, /turf/open/floor/plating, /area/station/maintenance/fore/lesser) -"imd" = ( -/obj/effect/turf_decal/sand/plating, -/obj/structure/closet/firecloset, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "imj" = ( /obj/machinery/door/airlock/security/glass{ id_tag = "permaouter"; @@ -23217,6 +23320,10 @@ }, /turf/closed/wall/mineral/titanium/nodiagonal, /area/station/engineering/supermatter) +"iux" = ( +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "iuH" = ( /obj/machinery/atmospherics/pipe/smart/simple/dark/visible, /obj/effect/decal/cleanable/dirt, @@ -23307,8 +23414,9 @@ /turf/open/floor/iron/dark, /area/station/engineering/atmos) "ivO" = ( -/obj/effect/turf_decal/sand/plating, -/obj/structure/reagent_dispensers/fueltank, +/obj/effect/decal/cleanable/dirt, +/obj/structure/girder, +/obj/effect/decal/cleanable/glass/plastitanium, /turf/open/floor/plating, /area/station/maintenance/fore/greater) "ivX" = ( @@ -23730,7 +23838,7 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/aft) "iFi" = ( -/obj/effect/spawner/random/structure/crate, +/obj/effect/spawner/random/vending/colavend, /turf/open/floor/plating/rust, /area/station/maintenance/fore/greater) "iFs" = ( @@ -23815,9 +23923,9 @@ /turf/open/floor/plating, /area/station/maintenance/fore/lesser) "iHs" = ( -/obj/effect/turf_decal/sand/plating, -/obj/effect/spawner/random/engineering/atmospherics_portable, -/turf/open/floor/plating, +/obj/machinery/portable_atmospherics/canister/air, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/plating/rust, /area/station/maintenance/fore/greater) "iHy" = ( /obj/structure/window/reinforced/plasma/spawner/directional/east, @@ -24135,6 +24243,9 @@ /obj/effect/mapping_helpers/airlock/access/any/security/maintenance, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"iMy" = ( +/turf/open/misc/asteroid, +/area/space/nearstation) "iMC" = ( /obj/machinery/flasher/portable, /turf/open/floor/plating, @@ -24353,17 +24464,11 @@ /obj/machinery/airalarm/directional/west, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) -"iQF" = ( -/obj/effect/turf_decal/sand/plating, -/obj/effect/spawner/random/structure/closet_maintenance, -/obj/effect/spawner/random/maintenance, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "iQK" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, /obj/effect/mapping_helpers/broken_floor, +/obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating/rust, /area/station/maintenance/fore/greater) "iQU" = ( @@ -24384,6 +24489,8 @@ "iRv" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/glass/plastitanium, /turf/open/floor/plating, /area/station/maintenance/fore/greater) "iRz" = ( @@ -24428,15 +24535,6 @@ "iSr" = ( /turf/open/floor/iron, /area/station/security/execution/transfer) -"iSB" = ( -/obj/structure/cable, -/obj/machinery/door/airlock{ - name = "Maintenance" - }, -/obj/effect/mapping_helpers/airlock/access/any/service/maintenance, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "iSK" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -24445,13 +24543,6 @@ /obj/structure/sign/warning/pods/directional/west, /turf/open/floor/iron/checker, /area/station/security/breakroom) -"iSO" = ( -/obj/structure/cable, -/obj/machinery/power/apc/auto_name/directional/north, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/duct, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "iSW" = ( /obj/structure/rack, /obj/item/clothing/gloves/boxing/yellow, @@ -24991,8 +25082,13 @@ /turf/open/floor/plating, /area/station/command/heads_quarters/rd) "jbm" = ( -/turf/closed/mineral/random/stationside, -/area/station/maintenance/fore/greater) +/obj/machinery/firealarm/directional/south, +/obj/effect/decal/cleanable/dirt, +/obj/structure/broken_flooring/corner/directional/north, +/obj/structure/sign/poster/official/random/directional/west, +/obj/effect/spawner/random/vending/snackvend, +/turf/open/floor/plating, +/area/station/commons/fitness/recreation/entertainment) "jbr" = ( /obj/structure/table/glass, /obj/item/folder/blue{ @@ -25110,15 +25206,15 @@ /turf/open/floor/plating/rust, /area/station/maintenance/fore/greater) "jey" = ( -/obj/structure/cable, -/obj/machinery/portable_atmospherics/pump, -/turf/open/floor/plating/rust, -/area/station/maintenance/fore/greater) +/obj/machinery/vending/clothing, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "jez" = ( -/obj/structure/cable, -/obj/machinery/portable_atmospherics/canister/air, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "jeC" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -25147,11 +25243,12 @@ /turf/open/floor/plating, /area/station/medical/medbay/lobby) "jeX" = ( -/obj/structure/cable, -/obj/machinery/portable_atmospherics/canister/air, +/obj/machinery/light/small/directional/east, /obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating/rust, -/area/station/maintenance/fore/greater) +/obj/effect/mapping_helpers/broken_floor, +/obj/structure/broken_flooring/singular/directional/west, +/turf/open/floor/plating, +/area/station/commons/fitness/recreation/entertainment) "jfs" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 4 @@ -25794,10 +25891,6 @@ /obj/machinery/light/small/directional/west, /turf/open/floor/iron/smooth_large, /area/station/science/auxlab/firing_range) -"jsn" = ( -/obj/effect/turf_decal/sand/plating, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "jsv" = ( /obj/structure/cable, /obj/machinery/holopad, @@ -26171,12 +26264,6 @@ }, /turf/open/floor/iron/kitchen/small, /area/station/hallway/secondary/service) -"jzl" = ( -/obj/structure/cable, -/obj/effect/turf_decal/sand/plating, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "jzo" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -26225,7 +26312,9 @@ /area/station/hallway/secondary/construction) "jAs" = ( /obj/structure/cable, -/obj/effect/turf_decal/sand/plating, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/spawner/random/structure/closet_maintenance, +/obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/fore/greater) "jAw" = ( @@ -26522,6 +26611,15 @@ /obj/structure/sign/poster/official/random/directional/north, /turf/open/floor/iron/smooth, /area/station/hallway/secondary/command) +"jFc" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/trash/cheesie{ + pixel_x = 7; + pixel_y = 3 + }, +/obj/structure/table, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "jFf" = ( /obj/effect/turf_decal/tile/green/diagonal_centre, /obj/machinery/status_display/ai/directional/north, @@ -27175,6 +27273,13 @@ /obj/effect/spawner/structure/window/reinforced/tinted, /turf/open/floor/plating, /area/station/maintenance/fore/greater) +"jPr" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/duct, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/plating, +/area/station/maintenance/fore/greater) "jQo" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/door/airlock/research/glass{ @@ -27462,6 +27567,16 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/station/security/courtroom) +"jWA" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron, +/area/station/cargo/storage) "jWO" = ( /obj/effect/turf_decal/tile/blue, /obj/machinery/camera/autoname/directional/south, @@ -27469,6 +27584,10 @@ dir = 8 }, /area/station/hallway/secondary/dock) +"jWR" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "jWZ" = ( /obj/machinery/mineral/ore_redemption{ dir = 4; @@ -27531,15 +27650,6 @@ /obj/effect/turf_decal/siding/wideplating/dark/corner, /turf/open/floor/iron, /area/station/security) -"jXE" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable, -/obj/machinery/light/cold/directional/north, -/obj/structure/sign/poster/official/random/directional/north, -/turf/open/floor/iron, -/area/station/cargo/storage) "jXQ" = ( /obj/structure/flora/bush/large/style_random{ pixel_x = -18; @@ -28303,6 +28413,15 @@ /obj/machinery/light/small/directional/east, /turf/open/floor/carpet/orange, /area/station/service/abandoned_gambling_den) +"kmb" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/computer/holodeck{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "kmd" = ( /obj/structure/cable, /obj/machinery/door/airlock/external{ @@ -28367,6 +28486,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer1, /turf/open/floor/iron/dark, /area/station/engineering/atmos) +"kmS" = ( +/obj/machinery/power/shuttle_engine/propulsion{ + dir = 1 + }, +/turf/open/floor/plating, +/area/station/commons/fitness/recreation/entertainment) "kmT" = ( /obj/structure/closet/firecloset, /turf/open/floor/plating, @@ -28381,6 +28506,14 @@ }, /turf/open/floor/iron, /area/station/cargo/storage) +"knt" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/broken_flooring/pile/directional/east, +/turf/open/floor/plating, +/area/station/maintenance/hallway/abandoned_command) "knv" = ( /turf/closed/wall, /area/station/maintenance/department/engine/atmos) @@ -28766,6 +28899,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/cargo/office) +"ktN" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/chair/sofa/bench/left{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "ktZ" = ( /obj/effect/turf_decal/sand/plating, /obj/structure/bookcase/random, @@ -29222,6 +29362,7 @@ "kDq" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/commons) "kDV" = ( @@ -29370,8 +29511,7 @@ }, /area/station/maintenance/department/engine/atmos) "kGz" = ( -/obj/effect/mapping_helpers/broken_floor, -/obj/structure/reagent_dispensers/plumbed, +/obj/structure/girder, /turf/open/floor/plating, /area/station/maintenance/fore/greater) "kGB" = ( @@ -29665,11 +29805,6 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron/showroomfloor, /area/station/commons/toilet/restrooms) -"kKN" = ( -/obj/structure/barricade/wooden, -/obj/effect/decal/cleanable/dirt, -/turf/open/misc/asteroid, -/area/station/maintenance/fore/greater) "kKT" = ( /obj/machinery/computer/camera_advanced/xenobio{ dir = 4 @@ -29866,6 +30001,10 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/station/construction/mining/aux_base) +"kOW" = ( +/obj/effect/mob_spawn/corpse/human/miner, +/turf/open/misc/asteroid, +/area/space/nearstation) "kPa" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -30353,11 +30492,10 @@ /turf/open/floor/grass, /area/station/cargo/storage) "kZf" = ( -/obj/effect/turf_decal/sand/plating, +/obj/structure/cable, /obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/random/trash, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "kZh" = ( /obj/structure/table/glass, /obj/effect/turf_decal/siding/thinplating_new/light{ @@ -30368,10 +30506,11 @@ /area/station/science/cubicle) "kZo" = ( /obj/structure/cable, -/obj/effect/turf_decal/sand/plating, /obj/effect/decal/cleanable/dirt, /obj/machinery/duct, /obj/effect/spawner/random/trash, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/fore/greater) "kZx" = ( @@ -30382,6 +30521,15 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/showroomfloor, /area/station/medical/surgery/theatre) +"kZB" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable, +/obj/structure/extinguisher_cabinet/directional/north, +/obj/machinery/light/cold/directional/north, +/turf/open/floor/iron, +/area/station/cargo/storage) "kZF" = ( /obj/structure/closet/crate/secure{ desc = "A secure crate containing various materials for building a customised test-site."; @@ -30449,6 +30597,19 @@ /obj/machinery/light/small/directional/north, /turf/open/floor/wood, /area/station/service/abandoned_gambling_den) +"lbF" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/turf_decal/stripes, +/obj/effect/turf_decal/trimline/brown/line, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 8 + }, +/obj/machinery/light/small/directional/east, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/smooth_half, +/area/station/bitrunning/den) "lbM" = ( /obj/structure/chair/sofa/bench/right{ dir = 1 @@ -31353,10 +31514,6 @@ /obj/structure/ore_box, /turf/open/floor/plating, /area/station/maintenance/starboard/greater) -"lnT" = ( -/obj/machinery/rnd/bepis, -/turf/open/floor/iron, -/area/station/cargo/storage) "lnZ" = ( /obj/effect/turf_decal/tile/dark_red, /obj/effect/decal/cleanable/dirt, @@ -31469,8 +31626,10 @@ /turf/open/floor/wood/parquet, /area/station/service/library) "lqs" = ( -/turf/closed/wall/rust, -/area/station/maintenance/fore/greater) +/obj/machinery/light/cold/directional/south, +/obj/structure/reagent_dispensers/water_cooler, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "lqt" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -32604,6 +32763,20 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/iron, /area/station/maintenance/starboard/aft) +"lKH" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/stripes, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/obj/machinery/airalarm/directional/west, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/smooth_half, +/area/station/bitrunning/den) "lKK" = ( /obj/effect/mapping_helpers/broken_floor, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -32619,6 +32792,18 @@ /obj/effect/mapping_helpers/airlock/access/any/security/general, /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, +/turf/open/floor/iron/dark/smooth_large, +/area/station/bitrunning/den) "lLr" = ( /obj/machinery/porta_turret/ai{ dir = 4 @@ -32920,12 +33105,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/security/prison/rec) -"lPG" = ( -/obj/machinery/vending/clothing, -/obj/machinery/camera/directional/north, -/obj/machinery/light/small/directional/north, -/turf/open/floor/iron, -/area/station/commons) "lPI" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -32937,6 +33116,16 @@ /obj/machinery/announcement_system, /turf/open/floor/iron/grimy, /area/station/tcommsat/server) +"lPO" = ( +/obj/structure/table, +/obj/item/surgery_tray/full{ + pixel_y = -5 + }, +/obj/item/wirecutters{ + pixel_y = 8 + }, +/turf/open/floor/iron/dark/small, +/area/station/security/execution/education) "lPR" = ( /obj/structure/table, /obj/effect/spawner/random/maintenance, @@ -33796,6 +33985,14 @@ dir = 4 }, /area/station/hallway/secondary/entry) +"meP" = ( +/obj/machinery/airalarm/directional/west, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/entertainment/arcade{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "mfc" = ( /obj/effect/turf_decal/tile/red/opposingcorners, /obj/effect/turf_decal/tile/blue/opposingcorners{ @@ -35273,6 +35470,9 @@ /obj/item/radio/intercom/directional/west, /turf/open/floor/iron/white/small, /area/station/medical/virology) +"mHq" = ( +/turf/closed/wall/r_wall, +/area/station/commons/fitness/recreation/entertainment) "mHZ" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -35543,11 +35743,6 @@ }, /turf/open/floor/iron, /area/station/security/processing) -"mLx" = ( -/obj/structure/rack, -/obj/effect/spawner/random/maintenance/two, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "mLA" = ( /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/west, @@ -36004,6 +36199,11 @@ /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/open/floor/iron/grimy, /area/station/cargo/boutique) +"mUC" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/chair/stool/directional/west, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "mUO" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, @@ -36375,6 +36575,16 @@ /obj/structure/alien/weeds, /turf/open/floor/wood, /area/station/maintenance/starboard/greater) +"ncf" = ( +/obj/machinery/recycler{ + dir = 8 + }, +/obj/machinery/conveyor{ + dir = 4; + id = "garbage" + }, +/turf/open/floor/plating, +/area/station/service/janitor) "ncl" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -36449,10 +36659,6 @@ }, /turf/open/floor/wood/tile, /area/station/commons/vacant_room/commissary) -"net" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron, -/area/station/commons) "neZ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -37501,6 +37707,16 @@ }, /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, +/turf/open/floor/iron/dark/smooth_large, +/area/station/bitrunning/den) "nyi" = ( /turf/closed/wall/rust, /area/station/maintenance/hallway/abandoned_command) @@ -37851,6 +38067,22 @@ /obj/structure/falsewall, /turf/open/floor/plating, /area/station/maintenance/starboard/greater) +"nEl" = ( +/obj/machinery/computer/quantum_console{ + dir = 4 + }, +/obj/machinery/computer/quantum_console{ + dir = 4 + }, +/obj/machinery/computer/quantum_console{ + dir = 4 + }, +/obj/machinery/computer/quantum_console{ + dir = 4 + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "nEo" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -37912,6 +38144,9 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth, /area/station/cargo/drone_bay) +"nFo" = ( +/turf/closed/wall, +/area/station/bitrunning/den) "nFp" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -38330,6 +38565,15 @@ /obj/effect/turf_decal/stripes/red/line, /turf/open/floor/iron/small, /area/station/hallway/primary/central/fore) +"nMX" = ( +/obj/machinery/camera/directional/south{ + c_tag = "Holodeck - Aft"; + name = "holodeck camera" + }, +/turf/open/floor/engine{ + name = "Holodeck Projector Floor" + }, +/area/station/holodeck/rec_center) "nNb" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -38478,6 +38722,10 @@ }, /turf/open/floor/iron/white, /area/station/commons/dorms) +"nPX" = ( +/obj/structure/cable, +/turf/open/floor/iron/smooth_large, +/area/station/cargo/warehouse) "nQa" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, @@ -38553,6 +38801,11 @@ }, /turf/open/floor/plating, /area/station/command/bridge) +"nRo" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/table, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "nRr" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, @@ -39934,6 +40187,11 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/recreation) +"ott" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash, +/turf/open/floor/plating, +/area/station/maintenance/fore/greater) "otG" = ( /obj/structure/filingcabinet/filingcabinet, /obj/machinery/status_display/supply{ @@ -40415,6 +40673,9 @@ /obj/machinery/camera/autoname/directional/east, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) +"oCG" = ( +/turf/closed/wall/rust, +/area/station/bitrunning/den) "oCM" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/broken_flooring/pile/directional/east, @@ -40456,6 +40717,13 @@ /obj/effect/mapping_helpers/airlock/access/any/service/hydroponics, /turf/open/floor/plating, /area/station/maintenance/port/greater) +"oDO" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "oDS" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/firealarm/directional/south, @@ -40470,10 +40738,6 @@ /obj/effect/landmark/start/assistant, /turf/open/floor/iron, /area/station/commons/dorms) -"oEm" = ( -/obj/structure/barricade/wooden, -/turf/open/misc/asteroid, -/area/station/maintenance/fore/greater) "oEr" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -42789,10 +43053,11 @@ /turf/open/floor/iron/diagonal, /area/station/command/heads_quarters/hop) "puC" = ( -/obj/effect/turf_decal/sand/plating, +/obj/machinery/light/small/directional/west, /obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) +/obj/structure/closet/firecloset, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "puD" = ( /obj/structure/bookcase/random/nonfiction, /obj/machinery/newscaster/directional/west, @@ -43069,6 +43334,9 @@ /obj/machinery/camera/autoname/directional/north, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"pzd" = ( +/turf/closed/wall, +/area/station/commons/fitness/recreation/entertainment) "pzn" = ( /obj/structure/table, /obj/effect/turf_decal/siding/wood{ @@ -43573,6 +43841,12 @@ /obj/machinery/light_switch/directional/north, /turf/open/floor/wood, /area/station/commons/fitness/recreation) +"pGX" = ( +/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, +/area/station/commons) "pHe" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/door/firedoor, @@ -43847,11 +44121,6 @@ }, /turf/open/floor/iron/small, /area/station/ai_monitored/command/storage/eva) -"pLk" = ( -/mob/living/basic/mining/basilisk, -/obj/effect/decal/cleanable/dirt, -/turf/open/misc/asteroid, -/area/station/maintenance/fore/greater) "pLl" = ( /obj/effect/spawner/random/vending/snackvend, /obj/effect/turf_decal/tile/red/opposingcorners{ @@ -44074,6 +44343,14 @@ /obj/machinery/duct, /turf/open/floor/iron/kitchen/small, /area/station/hallway/secondary/service) +"pOL" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/glass/plastitanium, +/turf/open/floor/plating, +/area/station/maintenance/fore/greater) "pOX" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -44222,6 +44499,12 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/department/prison) +"pSf" = ( +/obj/machinery/power/apc/auto_name/directional/west, +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "pSm" = ( /obj/effect/mapping_helpers/broken_floor, /obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ @@ -44329,16 +44612,6 @@ /obj/effect/mapping_helpers/airlock/access/all/service/chapel_office, /turf/open/floor/plating, /area/station/maintenance/port/lesser) -"pTr" = ( -/obj/structure/table, -/obj/item/surgery_tray/full{ - pixel_y = -5 - }, -/obj/item/wirecutters{ - pixel_y = 8 - }, -/turf/open/floor/iron/dark/small, -/area/station/security/execution/education) "pTs" = ( /obj/structure/window/spawner/directional/west, /obj/structure/chair/sofa/corp/right{ @@ -44462,6 +44735,11 @@ /obj/machinery/firealarm/directional/west, /turf/open/floor/iron/white, /area/station/science/auxlab/firing_range) +"pVo" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/girder, +/turf/open/floor/plating, +/area/station/maintenance/fore/greater) "pVq" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/trimline/neutral/line{ @@ -46068,10 +46346,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/commons/dorms) -"quf" = ( -/obj/item/kirbyplants/random, -/turf/open/floor/iron, -/area/station/commons) "qui" = ( /obj/machinery/camera/autoname/directional/north, /turf/open/floor/wood/parquet, @@ -46530,6 +46804,15 @@ /obj/structure/barricade/wooden/crude, /turf/open/floor/plating, /area/station/cargo/boutique) +"qBl" = ( +/obj/machinery/camera/directional/north{ + c_tag = "Holodeck - Fore"; + name = "holodeck camera" + }, +/turf/open/floor/engine{ + name = "Holodeck Projector Floor" + }, +/area/station/holodeck/rec_center) "qBy" = ( /obj/effect/turf_decal/plaque{ icon_state = "L5" @@ -49163,6 +49446,10 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) +"rtK" = ( +/obj/item/kirbyplants/random, +/turf/open/floor/iron, +/area/station/commons) "rtQ" = ( /turf/closed/wall/r_wall, /area/station/security/tram) @@ -49192,6 +49479,7 @@ /obj/structure/table/glass, /obj/effect/mapping_helpers/broken_floor, /obj/item/radio/intercom/directional/south, +/obj/machinery/reagentgrinder, /turf/open/floor/iron/white, /area/station/medical/virology) "ruD" = ( @@ -49360,6 +49648,10 @@ "rxu" = ( /obj/structure/table, /obj/machinery/airalarm/directional/south, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = -6 + }, /obj/item/clipboard{ pixel_x = 4; pixel_y = 4 @@ -49510,6 +49802,11 @@ dir = 1 }, /area/station/hallway/secondary/entry) +"rzR" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/holopad, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "rAb" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -49751,6 +50048,11 @@ dir = 4 }, /area/station/hallway/secondary/entry) +"rDl" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/digital_clock/directional/north, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "rDx" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/structure/window/reinforced/spawner/directional/south, @@ -49987,13 +50289,9 @@ /turf/open/floor/iron/white, /area/station/medical/virology) "rGL" = ( -/obj/effect/decal/cleanable/dirt, -/obj/item/picket_sign{ - desc = "Can't you read? it clearly says what it says!"; - name = "DO NOT ENTER" - }, -/turf/open/misc/asteroid, -/area/station/maintenance/fore/greater) +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/station/commons/fitness/recreation/entertainment) "rGN" = ( /obj/effect/spawner/random/structure/crate, /turf/open/floor/plating, @@ -50110,9 +50408,9 @@ /turf/open/floor/engine, /area/station/engineering/gravity_generator) "rIO" = ( -/obj/effect/spawner/random/trash, -/turf/open/misc/asteroid, -/area/station/maintenance/fore/greater) +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "rIS" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron/cafeteria, @@ -50399,6 +50697,16 @@ /obj/effect/spawner/random/entertainment/arcade, /turf/open/floor/iron/cafeteria, /area/station/security/prison/mess) +"rNK" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/glass{ + name = "Holodeck" + }, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "rOb" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -50512,6 +50820,26 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer1, /turf/open/floor/catwalk_floor/iron_white, /area/station/engineering/atmos) +"rPx" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/corner, +/obj/effect/turf_decal/trimline/brown/corner, +/obj/effect/turf_decal/trimline/brown/corner{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 1 + }, +/area/station/bitrunning/den) "rPz" = ( /obj/structure/table/glass, /obj/item/flashlight/lamp/green{ @@ -50984,6 +51312,26 @@ /obj/structure/broken_flooring/singular/directional/east, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) +"rWP" = ( +/obj/effect/turf_decal/stripes{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes{ + dir = 8 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark/smooth_half{ + dir = 1 + }, +/area/station/bitrunning/den) "rWW" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -51122,14 +51470,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"rZu" = ( -/obj/effect/turf_decal/stripes/corner{ - dir = 1 - }, -/obj/effect/decal/cleanable/dirt, -/obj/structure/broken_flooring/pile/directional/east, -/turf/open/floor/plating, -/area/station/maintenance/hallway/abandoned_command) "rZG" = ( /obj/structure/closet/crate/trashcart, /obj/effect/spawner/random/trash/food_packaging, @@ -51766,11 +52106,6 @@ /obj/machinery/camera/autoname/directional/west, /turf/open/floor/iron, /area/station/medical/chemistry) -"skH" = ( -/obj/structure/rack, -/obj/item/flashlight/lantern, -/turf/open/misc/asteroid, -/area/station/maintenance/fore/greater) "skP" = ( /obj/effect/spawner/structure/window, /turf/open/floor/plating, @@ -53707,6 +54042,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/storage) +"sSl" = ( +/obj/machinery/camera/directional/west, +/obj/machinery/status_display/ai/directional/west, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "sSm" = ( /obj/effect/turf_decal/stripes/red/line{ dir = 4 @@ -54326,10 +54667,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"tbM" = ( -/obj/effect/spawner/random/structure/closet_maintenance, -/turf/open/misc/asteroid, -/area/station/maintenance/fore/greater) "tbS" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -54597,7 +54934,7 @@ /turf/open/floor/wood/tile, /area/station/command/heads_quarters/hop) "tgJ" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /obj/effect/turf_decal/stripes/line{ dir = 4 }, @@ -55347,6 +55684,15 @@ }, /turf/open/misc/sandy_dirt, /area/station/security/tram) +"tvN" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/cargo/storage) "tvP" = ( /obj/machinery/suit_storage_unit/captain, /obj/machinery/light/small/directional/south, @@ -55371,13 +55717,6 @@ }, /turf/open/space/basic, /area/space/nearstation) -"twh" = ( -/obj/effect/turf_decal/sand/plating, -/obj/effect/decal/cleanable/dirt, -/obj/structure/table, -/obj/item/stack/sheet/mineral/sandstone, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "twi" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -55458,8 +55797,12 @@ /turf/open/floor/iron/small, /area/station/hallway/primary/central/fore) "twN" = ( -/obj/effect/decal/cleanable/dirt, -/turf/open/misc/asteroid, +/obj/machinery/door/airlock{ + name = "Maintenance" + }, +/obj/effect/mapping_helpers/airlock/access/any/service/maintenance, +/obj/structure/cable, +/turf/open/floor/plating/rust, /area/station/maintenance/fore/greater) "twR" = ( /obj/structure/table/glass, @@ -55851,13 +56194,6 @@ /obj/machinery/shower/directional/west, /turf/open/floor/iron/dark, /area/station/medical/pharmacy) -"tDm" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Maintenance" - }, -/obj/effect/mapping_helpers/airlock/access/all/supply/general, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "tDn" = ( /turf/closed/wall/r_wall, /area/station/maintenance/department/prison) @@ -56124,6 +56460,9 @@ /obj/effect/turf_decal/tile/green/diagonal_centre, /turf/open/floor/iron/diagonal, /area/station/hallway/primary/central/aft) +"tIE" = ( +/turf/closed/wall/mineral/titanium, +/area/station/commons/fitness/recreation/entertainment) "tII" = ( /obj/effect/spawner/random/structure/closet_maintenance, /turf/open/floor/plating, @@ -56209,6 +56548,10 @@ /obj/effect/turf_decal/tile/green/diagonal_centre, /turf/open/floor/iron/diagonal, /area/station/hallway/primary/central/aft) +"tJN" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "tJO" = ( /obj/effect/spawner/structure/window/reinforced/plasma, /obj/machinery/atmospherics/pipe/smart/simple/brown/visible, @@ -56554,6 +56897,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white, /area/station/hallway/primary/starboard) +"tPZ" = ( +/obj/machinery/netpod, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "tQx" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/reagent_dispensers/fueltank, @@ -56604,6 +56953,17 @@ /obj/structure/extinguisher_cabinet/directional/east, /turf/open/floor/iron, /area/station/security/courtroom) +"tRp" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/public/glass{ + name = "Holodeck Door" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ + cycle_id = "holodeck" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "tRw" = ( /obj/structure/disposalpipe/trunk{ dir = 8 @@ -57977,8 +58337,7 @@ /turf/open/floor/iron, /area/station/hallway/primary/central/fore) "unK" = ( -/obj/structure/rack, -/obj/effect/spawner/random/maintenance, +/obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plating, /area/station/maintenance/fore/greater) "unM" = ( @@ -59235,6 +59594,11 @@ }, /turf/open/floor/iron/showroomfloor, /area/station/commons/toilet/auxiliary) +"uJZ" = ( +/obj/structure/window/reinforced/shuttle, +/obj/structure/window/reinforced/shuttle, +/turf/open/floor/plating, +/area/station/commons/fitness/recreation/entertainment) "uKl" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -59334,7 +59698,7 @@ /turf/open/floor/plating, /area/station/hallway/secondary/service) "uMl" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /obj/effect/turf_decal/stripes/line{ dir = 8 }, @@ -59893,6 +60257,11 @@ }, /turf/closed/wall, /area/station/hallway/primary/starboard) +"uWg" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/structure/sign/poster/official/random/directional/west, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "uWl" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -60641,13 +61010,6 @@ /obj/structure/closet/emcloset, /turf/open/floor/iron/small, /area/station/maintenance/starboard/central) -"viR" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/sink/directional/south, -/obj/item/reagent_containers/cup/bucket, -/obj/item/mop, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "viT" = ( /obj/machinery/light/cold/directional/east, /turf/open/floor/iron, @@ -60939,6 +61301,14 @@ /obj/effect/spawner/random/trash, /turf/open/floor/plating, /area/station/maintenance/port/greater) +"vmA" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "vmH" = ( /obj/machinery/door/morgue{ name = "Confession Booth (Chaplain)"; @@ -61260,18 +61630,6 @@ }, /turf/open/floor/catwalk_floor/iron_dark, /area/station/tcommsat/server) -"vra" = ( -/obj/effect/turf_decal/sand/plating, -/obj/effect/decal/cleanable/dirt, -/obj/structure/table, -/obj/item/clothing/under/rank/cargo/miner/lavaland{ - pixel_y = 3 - }, -/obj/item/clothing/suit/hooded/wintercoat/miner{ - pixel_y = 5 - }, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "vrf" = ( /obj/structure/hedge, /obj/machinery/light/small/directional/north, @@ -62344,6 +62702,12 @@ }, /turf/open/floor/iron/small, /area/station/hallway/primary/central/fore) +"vIN" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/chair/stool, +/obj/structure/sign/poster/contraband/random/directional/north, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "vIX" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -62638,11 +63002,6 @@ /obj/machinery/portable_atmospherics/canister/air, /turf/open/floor/plating, /area/station/maintenance/central/greater) -"vMS" = ( -/obj/item/pickaxe, -/obj/effect/decal/cleanable/dirt, -/turf/open/misc/asteroid, -/area/station/maintenance/fore/greater) "vMT" = ( /obj/machinery/hydroponics/soil, /obj/item/food/grown/mushroom/libertycap, @@ -63033,10 +63392,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white/small, /area/station/service/hydroponics) -"vTO" = ( -/mob/living/simple_animal/hostile/asteroid/gutlunch, -/turf/open/misc/asteroid, -/area/station/maintenance/fore/greater) "vTV" = ( /turf/closed/wall/r_wall, /area/station/command/heads_quarters/hos) @@ -63917,10 +64272,6 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/station/hallway/secondary/exit/departure_lounge) -"whS" = ( -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "whX" = ( /obj/structure/disposalpipe/segment, /obj/machinery/door/airlock{ @@ -65196,6 +65547,11 @@ /obj/machinery/computer/arcade/orion_trail/kobayashi, /turf/open/floor/wood/tile, /area/station/maintenance/port/lesser) +"wCD" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "wCH" = ( /obj/effect/turf_decal/stripes/white/line{ dir = 9 @@ -66237,16 +66593,17 @@ dir = 8 }, /obj/structure/table, -/obj/item/stack/medical/gauze{ - pixel_x = -2; - pixel_y = 7 +/obj/item/radio/intercom/directional/south, +/obj/structure/extinguisher_cabinet/directional/west, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = 4 }, /obj/item/stack/medical/gauze{ - pixel_x = 2; - pixel_y = 1 + pixel_x = -2; + pixel_y = 8 }, -/obj/item/radio/intercom/directional/south, -/obj/structure/extinguisher_cabinet/directional/west, +/obj/item/stack/medical/gauze, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) "wSH" = ( @@ -66292,11 +66649,6 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron/textured_half, /area/station/security/prison/work) -"wTn" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/random/structure/crate, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "wTs" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/sign/poster/official/random/directional/north, @@ -66832,6 +67184,14 @@ /obj/structure/grille, /turf/closed/wall/mineral/titanium/nodiagonal, /area/station/engineering/atmos) +"xaj" = ( +/obj/machinery/light/cold/directional/west, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/entertainment/arcade{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "xam" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -69163,11 +69523,6 @@ /obj/item/reagent_containers/cup/glass/drinkingglass, /turf/open/floor/iron/cafeteria, /area/station/security/prison/mess) -"xGS" = ( -/obj/effect/turf_decal/sand/plating, -/obj/structure/reagent_dispensers/watertank, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "xGT" = ( /obj/effect/turf_decal/tile/dark_red/opposingcorners, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, @@ -70044,6 +70399,11 @@ /obj/structure/barricade/wooden/crude, /turf/open/floor/plating, /area/station/service/abandoned_gambling_den/gaming) +"xRX" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash/graffiti, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "xRZ" = ( /obj/effect/turf_decal/siding/wood, /turf/open/floor/grass, @@ -70712,13 +71072,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) -"yaJ" = ( -/obj/effect/turf_decal/siding/white, -/obj/machinery/light/small/directional/south, -/obj/structure/table/reinforced, -/obj/item/surgery_tray/full/morgue, -/turf/open/floor/iron/small, -/area/station/medical/morgue) "yaL" = ( /turf/closed/wall, /area/station/commons/vacant_room/commissary) @@ -70849,24 +71202,6 @@ /obj/effect/turf_decal/stripes/white/line, /turf/open/floor/noslip/tram_plate, /area/station/maintenance/department/medical/central) -"ycz" = ( -/obj/effect/turf_decal/sand/plating, -/obj/effect/decal/cleanable/dirt, -/obj/structure/table, -/obj/item/stack/sheet/mineral/coal{ - pixel_x = 6; - pixel_y = 13 - }, -/obj/item/stack/sheet/mineral/coal{ - pixel_x = 1; - pixel_y = 8 - }, -/obj/item/stack/sheet/mineral/coal{ - pixel_x = -2; - pixel_y = -1 - }, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "ycC" = ( /turf/closed/wall/r_wall, /area/station/command/bridge) @@ -70910,8 +71245,15 @@ /turf/open/floor/wood/tile, /area/station/command/bridge) "ydt" = ( -/turf/open/misc/asteroid, -/area/station/maintenance/fore/greater) +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/public/glass{ + name = "Holodeck Door" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ + cycle_id = "holodeck" + }, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation/entertainment) "ydu" = ( /obj/structure/cable, /obj/structure/disposalpipe/sorting/mail{ @@ -70940,6 +71282,11 @@ "yea" = ( /turf/closed/wall, /area/station/service/chapel/office) +"yec" = ( +/obj/structure/girder, +/obj/effect/decal/cleanable/glass/plastitanium, +/turf/open/floor/plating, +/area/station/maintenance/fore/greater) "yee" = ( /obj/item/kirbyplants/random, /obj/machinery/light_switch/directional/west, @@ -71137,9 +71484,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/maintenance/department/science/xenobiology) -"yfX" = ( -/turf/open/floor/plating/rust, -/area/station/maintenance/fore/greater) "yfY" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -71440,6 +71784,7 @@ "yju" = ( /obj/effect/spawner/random/structure/closet_maintenance, /obj/effect/spawner/random/maintenance, +/obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/fore/greater) "yjD" = ( @@ -71557,6 +71902,12 @@ "ylD" = ( /turf/closed/wall, /area/station/maintenance/starboard/greater) +"ylH" = ( +/obj/machinery/quantum_server, +/obj/effect/turf_decal/delivery, +/obj/machinery/light/cold/directional/west, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "ylJ" = ( /obj/effect/spawner/structure/window/reinforced/tinted, /turf/open/floor/plating, @@ -83003,7 +83354,7 @@ uzJ mQh nJU ppk -lnT +uzJ ovQ oRr poM @@ -83248,12 +83599,12 @@ slY ueX slY ueX -slY -ueX -slY -slY -slY -slY +nFo +oCG +nFo +nFo +nFo +nFo lxy hzm jTA @@ -83503,15 +83854,15 @@ slY gOK slY hfc -slY -viR jBb -kPW -kwY -whS -dmz -slY -hzN +iNE +nFo +ach +lKH +ylH +nEl +ejq +tvN lRc moz kee @@ -83760,15 +84111,15 @@ slY gPN gZk iNE -ueX -mLx kwY -slY -slY -kwY -slY -slY -jXE +kPW +nFo +tPZ +rPx +cvP +rWP +bCh +jWA lTv oem oem @@ -83837,7 +84188,7 @@ grn lSI lce vKU -pTr +lPO vfc rtQ rtQ @@ -84017,14 +84368,14 @@ slY gPN slY hff -jCo -hff -jCo -slY -wTn -whS kPW -tDm +hfc +nFo +hNv +lbF +lLq +nyf +ejq jkS lTN mRD @@ -84276,13 +84627,13 @@ slY jCo slY slY -jCi -slY -slY -slY -slY -slY -ciL +nFo +nFo +nFo +nFo +nFo +nFo +kZB lUz ohj ohj @@ -84531,8 +84882,8 @@ sjq sNz hyO roi -slY -hFm +jCi +nPX hAN jMb kzI @@ -84542,7 +84893,7 @@ iUN jlv sRR odX -odX +fts nyE uzJ axj @@ -103291,7 +103642,7 @@ xqC gMK dYo oAC -rZu +knt uPt hyZ hFO @@ -104588,7 +104939,7 @@ xmO sHe nFW mEy -hsK +ncf nFA kBH onR @@ -105091,14 +105442,14 @@ nyi rvp rvp uIT -xqC +uIT wSZ tdI hHE nNi hPs xmO -sJR +ott sIA jPq kaF @@ -105344,18 +105695,18 @@ dDB dDB aJq aJq -jbm -jbm -jbm -jbm -jbm -xmO -xmO +pzd +pzd +pzd +pzd +pzd +mHq +mHq +mHq +mHq xmO xmO -xmO -xmO -jsn +oTL sIS nFW sRL @@ -105601,17 +105952,17 @@ dDB dDB aJq aJq +pzd +dYf +xaj +meP +uWg +sSl +pSf jbm -jbm -jbm -jbm -jbm -jbm -jbm -jbm -tbM +pzd iFi -iQF +jej jej jAs nFW @@ -105858,18 +106209,18 @@ dDB aJq aJq aJq -jbm -vTO -jbm -jbm -twN -jbm -jbm +pzd +vIN +eyz +mUC +rIO +rzR +kZf lqs -xGS -yfX +pzd +nFW twN -tDB +nFW nFW nFW tBL @@ -106111,23 +106462,23 @@ dDB dDB dDB dDB -dDB aJq aJq aJq -jbm -oEm -jbm -jbm -oEm -jbm -twN -nFW +aJq +pzd +rDl +ktN +gEQ +rIO +jWR +vmA +rIO rGL puC kZf jey -nFW +pzd hek wXt ndZ @@ -106360,34 +106711,34 @@ aJq aJq aJq aJq +hwJ +blb +blb +blb +blb +blb +blb +blb +blb +hwJ aJq aJq -dDB -dDB -dDB -dDB -dDB -dDB -dDB -aJq -aJq -aJq -jbm -twN -ydt -twN -twN -twN -twN -cgD -twN -jsn -oTL +pzd +eKX +jFc +nRo +tJN +wCD +kmb +oDO +rNK +oDO +oDO jez -nFW -lPG -wXt -net +dvs +wYC +pGX +wYC kDq kDq ldB @@ -106445,7 +106796,7 @@ ntW bgA byq pOX -yaJ +adl kFY aQm qEz @@ -106617,36 +106968,36 @@ aJq aJq aJq aJq -hwJ -blb -blb -blb -blb -blb -blb -blb -blb -hwJ aJq -jbm -jbm -ydt -jbm -jbm +dDB +dDB +dDB +dDB +dDB +dDB +dDB +dDB +tIE +aJN +doX +aJN ydt -jbm -skH -lqs -imd -rIO -pLK +rGL +rGL +tRp +rGL +rGL +rGL +rGL +xRX +iux jeX -nFW +pzd qhq tDq rnn udZ -quf +rtK uct lzR wYC @@ -106882,21 +107233,21 @@ dDB dDB dDB dDB -aJq -aJq -aJq -jbm +tIE +tIE +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +tIE +nFW twN -ydt -jbm -jbm -kKN -jbm -jbm -jbm -jbm -sJR -jzl nFW nFW nFW @@ -107138,20 +107489,20 @@ dDB dDB dDB dDB -dDB -aJq -aJq -aJq -jbm -oEm -jbm -jbm -jbm -ydt -jbm -jbm -jbm -jbm +kmS +dNi +tIE +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +tIE iHs iQK tDB @@ -107395,22 +107746,22 @@ dDB dDB dDB dDB -dDB -aJq -aJq -jbm -jbm -twN -jbm -jbm -jbm -twN -twh -ycz -jbm -jbm -jbm -iRv +kmS +dNi +tIE +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +doX +iHs +pLK bjX nFW nFW @@ -107652,22 +108003,22 @@ dDB dDB dDB dDB -dDB -aJq -aJq -jbm -twN -twN -jbm -jbm -jbm -puC -ydt -vra -jbm -nFW -nFW -iSB +kmS +dNi +tIE +bqy +bqy +cZm +bqy +bqy +bqy +bqy +bqy +bqy +bqy +doX +pVo +iRv nFW nFW mjk @@ -107909,22 +108260,22 @@ dDB dDB dDB dDB -dDB -dDB -aJq -jbm -pLk -twN -jbm -jbm -jbm -ydt -puC -hJr -jbm -nFW +tIE +tIE +tIE +qBl +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +nMX +doX ivO -pLK +iRv nFW sJR sJR @@ -108166,22 +108517,22 @@ dDB dDB dDB dDB -dDB -dDB -aJq -aJq -jbm -jbm -jbm -jbm -jbm -vMS -puC -jbm -jbm -nFW +kmS +dNi +tIE +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +tIE yju -iRv +pOL jfP nfc jQF @@ -108423,20 +108774,20 @@ dDB dDB dDB dDB -dDB -dDB -dDB -aJq -aJq -aJq -jbm -jbm -jbm -jbm -jbm -jbm -jbm -nFW +kmS +dNi +tIE +bqy +bqy +bqy +bqy +bqy +bqy +bqy +cZm +bqy +bqy +tIE kGz kZo nFW @@ -108680,22 +109031,22 @@ dDB dDB dDB dDB -dDB -dDB -dDB -aJq -aJq -aJq -aJq -aJq -jbm -jbm -jbm -jbm -jbm -jbm -sJR -njm +kmS +dNi +tIE +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +doX +yec +fls nFW nFW nFW @@ -108938,22 +109289,22 @@ dDB dDB dDB dDB -dDB -dDB -dDB -aJq -aJq -aJq -aJq -aJq -jbm -jbm -jbm -jbm -nFW -nFW -iSO -bHA +tIE +tIE +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +bqy +tIE +kGz +jPr +gxZ dxz sJR xwy @@ -109196,18 +109547,18 @@ dDB dDB dDB dDB -dDB -dDB -dDB -aJq -aJq -aJq -aJq -aJq -jbm -jbm -jbm -jbm +tIE +aJN +aJN +aJN +uJZ +aJN +doX +doX +aJN +aJN +aJN +tIE nFW iSW njm @@ -109462,9 +109813,9 @@ hwJ aJq aJq vcE -vcE -vcE -vcE +jIb +pyt +nvS nFW iUy vtL @@ -110488,8 +110839,8 @@ aJq aJq aJq aJq -aJq -weg +iMy +jJy nvS kbY imE @@ -110744,8 +111095,8 @@ aJq aJq aJq aJq -aJq -aJq +iMy +iMy weg jKf nvS @@ -110999,9 +111350,9 @@ dDB dDB aJq aJq -aJq -aJq -aJq +iMy +iMy +iMy aJq weg weg @@ -111256,8 +111607,8 @@ dDB dDB aJq aJq -aJq -aJq +iMy +kOW aJq aJq weg @@ -111513,7 +111864,7 @@ dDB dDB aJq aJq -aJq +ejV aJq aJq aJq diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 15c9aae2b71..809f1335d24 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -3415,15 +3415,11 @@ /area/station/science/robotics/lab) "aPD" = ( /obj/structure/disposalpipe/segment, -/obj/machinery/door/airlock/mining{ - name = "Mining Dock" - }, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ dir = 1 }, /obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/supply/mining, /turf/open/floor/iron, /area/station/cargo/miningoffice) "aPO" = ( @@ -4984,14 +4980,10 @@ /turf/open/floor/iron/grimy, /area/station/command/heads_quarters/hos) "bkr" = ( -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/segment, /obj/machinery/conveyor{ id = "cargodisposals" }, -/obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, /area/station/cargo/sorting) "bkD" = ( @@ -7298,13 +7290,25 @@ /turf/open/floor/plating, /area/station/maintenance/department/science) "bLN" = ( -/obj/structure/disposalpipe/trunk{ - dir = 1 - }, -/obj/machinery/disposal/bin, +/obj/structure/rack, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, -/obj/structure/sign/poster/official/random/directional/south, +/obj/item/storage/toolbox/emergency{ + pixel_x = -3; + pixel_y = 3 + }, +/obj/item/storage/toolbox/emergency, +/obj/item/shovel, +/obj/item/shovel, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/effect/turf_decal/bot, +/obj/machinery/light/small/directional/south, +/obj/machinery/power/apc/auto_name/directional/west, +/obj/machinery/light_switch/directional/west{ + pixel_x = -38 + }, +/obj/machinery/airalarm/directional/south, +/obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/miningoffice) "bLP" = ( @@ -10141,21 +10145,14 @@ /turf/open/floor/iron/dark, /area/station/command/heads_quarters/hop) "cwd" = ( -/obj/structure/rack, -/obj/effect/decal/cleanable/dirt, -/obj/item/storage/toolbox/emergency{ - pixel_x = -3; - pixel_y = 3 +/obj/effect/turf_decal/box/corners, +/obj/effect/turf_decal/box/corners{ + dir = 4 }, -/obj/item/storage/toolbox/emergency, -/obj/item/shovel, -/obj/item/shovel, -/obj/item/pickaxe, -/obj/item/pickaxe, -/obj/effect/turf_decal/bot, -/obj/machinery/light/small/directional/south, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/obj/machinery/light/directional/south, +/obj/effect/landmark/bitrunning/station_reward_spawn, +/turf/open/floor/iron/dark/smooth_large, +/area/station/bitrunning/den) "cwe" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -10208,10 +10205,20 @@ /turf/open/floor/iron, /area/station/engineering/supermatter/room) "cwK" = ( -/obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/effect/decal/cleanable/dirt, -/obj/structure/reagent_dispensers/watertank, -/turf/open/floor/plating, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 4 + }, +/obj/effect/turf_decal/delivery, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/turf/open/floor/iron, /area/station/maintenance/starboard/fore) "cwV" = ( /obj/effect/landmark/start/hangover, @@ -10323,13 +10330,10 @@ /turf/open/floor/iron, /area/station/medical/treatment_center) "cyc" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/tile/purple/half/contrasted, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/obj/machinery/netpod, +/obj/machinery/airalarm/directional/east, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "cyq" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -11086,7 +11090,7 @@ /area/station/tcommsat/computer) "cGV" = ( /turf/closed/wall, -/area/station/cargo/miningoffice) +/area/station/bitrunning/den) "cHb" = ( /obj/machinery/door/firedoor/heavy, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -14006,11 +14010,16 @@ /turf/open/floor/iron/dark, /area/station/science/xenobiology) "dux" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/shaft_miner, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron, +/obj/structure/table, +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 + }, +/obj/item/clipboard, +/obj/item/toy/figure/miner, +/obj/machinery/light/directional/south, +/turf/open/floor/iron/half{ + dir = 1 + }, /area/station/cargo/miningoffice) "duA" = ( /turf/closed/wall/r_wall, @@ -15668,14 +15677,9 @@ /turf/open/floor/plating, /area/station/engineering/supermatter/room) "dPC" = ( -/obj/structure/table, -/obj/machinery/microwave{ - desc = "Cooks and boils stuff, somehow."; - pixel_x = -3; - pixel_y = 5 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, +/obj/structure/closet/secure_closet/miner, +/obj/effect/turf_decal/delivery, +/obj/structure/extinguisher_cabinet/directional/north, /turf/open/floor/iron, /area/station/cargo/miningoffice) "dPD" = ( @@ -16223,13 +16227,11 @@ /turf/open/floor/iron, /area/station/maintenance/port) "dXs" = ( -/obj/structure/table/reinforced, -/obj/effect/decal/cleanable/dirt, -/obj/item/flashlight/lamp, -/obj/structure/cable, -/obj/effect/turf_decal/tile/purple/half/contrasted{ +/obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 4 }, +/obj/structure/table/reinforced, +/obj/item/flashlight/lamp, /turf/open/floor/iron, /area/station/cargo/miningoffice) "dXw" = ( @@ -17230,12 +17232,11 @@ /turf/open/floor/iron/dark, /area/station/command/gateway) "elO" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/brown/half/contrasted{ - dir = 1 - }, +/obj/effect/landmark/event_spawn, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/structure/cable, /turf/open/floor/iron, -/area/station/maintenance/starboard/fore) +/area/station/cargo/miningoffice) "elP" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/turf_decal/tile/yellow/fourcorners, @@ -18719,8 +18720,15 @@ /turf/open/floor/iron, /area/station/hallway/secondary/entry) "eFU" = ( -/obj/effect/decal/cleanable/dirt, /obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) "eGb" = ( @@ -20290,7 +20298,12 @@ /turf/open/floor/iron/dark, /area/station/security/range) "eYt" = ( -/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/computer/order_console/mining, +/obj/item/radio/intercom/directional/west, +/obj/machinery/firealarm/directional/west{ + pixel_y = -9 + }, /turf/open/floor/iron, /area/station/cargo/miningoffice) "eYy" = ( @@ -20483,12 +20496,9 @@ /turf/open/floor/iron/smooth, /area/station/maintenance/department/science/xenobiology) "fbu" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/station/bitrunning/den) "fbA" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -21963,12 +21973,11 @@ /turf/open/floor/iron/grimy, /area/station/service/library) "ftS" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable, -/obj/effect/turf_decal/tile/brown/half/contrasted{ +/obj/structure/disposalpipe/segment{ dir = 4 }, -/turf/open/floor/iron, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/herringbone, /area/station/cargo/miningoffice) "ftU" = ( /obj/structure/cable, @@ -22407,12 +22416,14 @@ /turf/open/floor/iron, /area/station/engineering/storage) "fAj" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/effect/decal/cleanable/dirt/dust, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron, +/turf/open/floor/iron/herringbone, /area/station/cargo/miningoffice) "fAn" = ( /obj/machinery/holopad, @@ -23887,7 +23898,7 @@ /turf/open/floor/iron, /area/station/commons/fitness/recreation) "fUr" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell{ +/obj/machinery/cryo_cell{ dir = 8 }, /turf/open/floor/iron/dark/textured_large, @@ -24579,8 +24590,13 @@ /turf/open/floor/iron, /area/station/service/hydroponics) "gco" = ( +/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ + dir = 8 + }, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, -/obj/effect/turf_decal/tile/brown/half/contrasted, /turf/open/floor/iron, /area/station/cargo/miningoffice) "gcr" = ( @@ -26124,8 +26140,11 @@ /turf/open/floor/iron, /area/station/commons/storage/primary) "guj" = ( -/obj/effect/landmark/start/shaft_miner, /obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/obj/machinery/disposal/bin, /turf/open/floor/iron, /area/station/cargo/miningoffice) "gum" = ( @@ -29336,9 +29355,10 @@ /turf/open/floor/iron/white/smooth_large, /area/station/medical/medbay) "hkn" = ( -/obj/structure/filingcabinet/chestdrawer, -/obj/effect/turf_decal/delivery, -/obj/machinery/airalarm/directional/south, +/obj/structure/disposalpipe/segment, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/miningoffice) "hkt" = ( @@ -29727,6 +29747,22 @@ /obj/item/pen, /turf/open/floor/iron/grimy, /area/station/tcommsat/computer) +"hpB" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 1 + }, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = 4 + }, +/obj/item/storage/toolbox/mechanical, +/obj/item/storage/belt/utility, +/turf/open/floor/iron, +/area/station/cargo/storage) "hpC" = ( /obj/effect/landmark/generic_maintenance_landmark, /obj/structure/cable, @@ -30358,10 +30394,7 @@ /turf/open/floor/glass/reinforced, /area/station/maintenance/department/science/xenobiology) "hzs" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/cargo/miningoffice) "hzx" = ( @@ -32986,10 +33019,13 @@ /turf/open/floor/plating, /area/station/medical/virology) "iio" = ( -/obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/brown/half/contrasted{ - dir = 1 + dir = 8 }, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/miningoffice) "iiy" = ( @@ -34243,14 +34279,12 @@ /turf/open/floor/iron/dark, /area/station/hallway/secondary/entry) "izj" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment, +/obj/effect/decal/cleanable/dirt/dust, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/turf/open/floor/iron, +/turf/open/floor/iron/herringbone, /area/station/cargo/miningoffice) "izo" = ( /obj/structure/table/wood, @@ -35979,11 +36013,12 @@ /turf/open/floor/iron, /area/station/engineering/lobby) "iXd" = ( -/obj/effect/landmark/start/shaft_miner, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 1 }, -/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/shaft_miner, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/miningoffice) "iXj" = ( @@ -36809,7 +36844,9 @@ /turf/open/floor/plating, /area/station/engineering/atmos/mix) "jfO" = ( -/obj/structure/table, +/obj/structure/closet/wardrobe/miner, +/obj/effect/decal/cleanable/dirt, +/obj/item/storage/backpack/satchel/explorer, /obj/effect/turf_decal/bot, /turf/open/floor/iron, /area/station/cargo/miningoffice) @@ -38519,10 +38556,8 @@ /turf/open/floor/iron, /area/station/science/lobby) "jBM" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ - dir = 4 - }, /turf/open/floor/iron, /area/station/cargo/miningoffice) "jCb" = ( @@ -38609,10 +38644,10 @@ /turf/open/floor/wood, /area/station/service/library/abandoned) "jCu" = ( -/obj/machinery/computer/order_console/mining, +/obj/structure/closet/secure_closet/miner, /obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/delivery, /obj/machinery/light/directional/north, -/obj/effect/turf_decal/bot, /turf/open/floor/iron, /area/station/cargo/miningoffice) "jCv" = ( @@ -39263,13 +39298,17 @@ /turf/open/floor/iron/white, /area/station/command/heads_quarters/cmo) "jKY" = ( -/obj/structure/cable, -/obj/effect/turf_decal/bot, -/obj/structure/table, -/obj/item/storage/medkit/regular, -/obj/machinery/power/apc/auto_name/directional/west, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/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, +/turf/open/floor/iron/dark/smooth_large, +/area/station/bitrunning/den) "jLa" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/railing{ @@ -39853,8 +39892,16 @@ /turf/open/floor/iron/white, /area/station/medical/medbay) "jRc" = ( -/obj/machinery/power/apc/auto_name/directional/north, /obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) "jRg" = ( @@ -41458,6 +41505,19 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/aft) +"klh" = ( +/obj/structure/table/glass, +/obj/machinery/status_display/ai/directional/west, +/obj/machinery/newscaster/directional/north, +/obj/effect/turf_decal/siding/dark_red, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = -6 + }, +/obj/item/reagent_containers/cup/bottle/morphine, +/obj/item/reagent_containers/syringe, +/turf/open/floor/iron/dark, +/area/station/security/execution/transfer) "klm" = ( /obj/structure/sign/plaques/kiddie/badger{ pixel_y = 32 @@ -43153,10 +43213,13 @@ /turf/closed/wall, /area/station/hallway/secondary/entry) "kKx" = ( -/obj/effect/turf_decal/loading_area{ +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 + }, +/obj/structure/cable, +/turf/open/floor/iron/half{ dir = 1 }, -/turf/open/floor/iron, /area/station/cargo/miningoffice) "kKy" = ( /obj/machinery/airalarm/directional/east, @@ -43785,8 +43848,15 @@ /turf/open/floor/iron/dark, /area/station/engineering/main) "kTs" = ( -/obj/structure/closet/secure_closet/miner, -/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ + dir = 1 + }, +/obj/effect/landmark/start/shaft_miner, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/miningoffice) "kTy" = ( @@ -44701,18 +44771,6 @@ /mob/living/carbon/human/species/monkey, /turf/open/floor/engine, /area/station/science/genetics) -"lfC" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/table/reinforced, -/obj/item/storage/toolbox/mechanical, -/obj/item/storage/belt/utility, -/obj/effect/turf_decal/tile/brown/half/contrasted{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) "lfD" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/siding/dark_red{ @@ -45089,10 +45147,12 @@ /turf/open/floor/iron, /area/station/maintenance/solars/starboard/fore) "ljQ" = ( -/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/neutral/fourcorners, /obj/effect/turf_decal/loading_area{ dir = 1 }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/miningoffice) "ljS" = ( @@ -45238,8 +45298,11 @@ /obj/structure/disposalpipe/segment{ dir = 9 }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/iron, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/turf/open/floor/iron/herringbone, /area/station/cargo/miningoffice) "llm" = ( /obj/structure/chair/office/tactical{ @@ -49105,13 +49168,10 @@ /turf/closed/wall/r_wall, /area/station/ai_monitored/command/storage/eva) "mlF" = ( -/obj/item/kirbyplants/random, -/obj/structure/sign/poster/official/random/directional/west, -/obj/effect/turf_decal/tile/purple/half/contrasted{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/obj/machinery/computer/quantum_console, +/obj/structure/extinguisher_cabinet/directional/west, +/turf/open/floor/iron/dark/smooth_corner, +/area/station/bitrunning/den) "mlM" = ( /obj/structure/table/wood, /obj/machinery/computer/records/medical/laptop, @@ -49659,11 +49719,9 @@ /turf/open/floor/iron, /area/station/engineering/storage) "mtL" = ( -/obj/structure/closet/secure_closet/miner, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, +/obj/effect/spawner/structure/window/reinforced, /obj/machinery/status_display/evac/directional/north, -/turf/open/floor/iron, +/turf/open/floor/plating, /area/station/cargo/miningoffice) "mtO" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -50419,9 +50477,12 @@ /turf/open/floor/engine, /area/station/maintenance/disposal/incinerator) "mDm" = ( -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/obj/machinery/quantum_server, +/obj/effect/turf_decal/bot/left, +/turf/open/floor/iron/dark/smooth_corner{ + dir = 4 + }, +/area/station/bitrunning/den) "mDo" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -52655,8 +52716,14 @@ /turf/open/floor/plating, /area/station/maintenance/department/chapel) "nhj" = ( -/obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/table, +/obj/machinery/microwave{ + desc = "Cooks and boils stuff, somehow."; + pixel_x = -3; + pixel_y = 5 + }, +/obj/structure/sign/poster/official/random/directional/west, /turf/open/floor/iron, /area/station/cargo/miningoffice) "nhm" = ( @@ -54380,11 +54447,11 @@ /turf/open/floor/iron, /area/station/maintenance/port) "nEE" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/obj/machinery/netpod, +/obj/structure/sign/poster/random/directional/north, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "nEJ" = ( /obj/structure/cable, /obj/effect/turf_decal/trimline/yellow/line, @@ -56752,12 +56819,23 @@ /turf/open/floor/iron, /area/station/security/prison/garden) "okN" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 8 + }, +/obj/effect/decal/cleanable/generic, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/landmark/start/bitrunner, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "okV" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/reagent_dispensers/plumbed{ @@ -57618,11 +57696,10 @@ /turf/open/floor/iron, /area/station/maintenance/port) "owZ" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/effect/turf_decal/tile/purple/half/contrasted, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/table, +/obj/item/storage/medkit/regular, +/obj/machinery/light/directional/west, /turf/open/floor/iron, /area/station/cargo/miningoffice) "oxb" = ( @@ -57869,15 +57946,27 @@ /turf/open/floor/iron/grimy, /area/station/command/heads_quarters/captain/private) "oAV" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 6 +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 }, -/obj/effect/turf_decal/tile/brown/half/contrasted, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/corner{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "oAW" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -61442,7 +61531,19 @@ /turf/open/floor/iron/dark, /area/station/hallway/secondary/exit/departure_lounge) "pxS" = ( -/turf/open/floor/iron, +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 8 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/half{ + dir = 1 + }, /area/station/cargo/miningoffice) "pxT" = ( /obj/effect/spawner/random/structure/crate, @@ -61910,7 +62011,7 @@ /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) "pDy" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell{ +/obj/machinery/cryo_cell{ dir = 8 }, /obj/machinery/status_display/ai/directional/south, @@ -63511,15 +63612,16 @@ /turf/open/floor/iron/dark/corner, /area/station/engineering/atmos/pumproom) "pUs" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 9 +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, +/obj/machinery/door/airlock/mining/glass{ + name = "Bitrunning Den" }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "pUw" = ( /obj/machinery/holopad, /obj/effect/turf_decal/bot, @@ -64740,20 +64842,16 @@ /turf/open/floor/iron/dark, /area/station/command/bridge) "qko" = ( -/obj/structure/table, -/obj/effect/decal/cleanable/dirt, -/obj/item/clipboard, -/obj/item/toy/figure/miner, -/obj/machinery/light/directional/north, -/obj/machinery/light_switch/directional/west{ - pixel_x = -42 +/obj/item/kirbyplants/random, +/obj/effect/turf_decal/tile/brown/half{ + dir = 8 }, -/obj/effect/turf_decal/bot, -/obj/machinery/firealarm/directional/west, -/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ +/obj/machinery/light/directional/west, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/sign/poster/official/random/directional/west, +/turf/open/floor/iron/half{ dir = 1 }, -/turf/open/floor/iron, /area/station/cargo/miningoffice) "qkv" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -64918,9 +65016,11 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/brown/half/contrasted{ - dir = 8 + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 }, /turf/open/floor/iron, /area/station/maintenance/starboard/fore) @@ -65352,13 +65452,21 @@ /turf/open/floor/iron, /area/station/science/xenobiology) "qsF" = ( +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 1 + }, +/obj/machinery/power/apc/auto_name/directional/west, /obj/structure/cable, -/obj/structure/extinguisher_cabinet/directional/west, -/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ - dir = 8 +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 }, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "qsN" = ( /obj/structure/chair{ dir = 4 @@ -68278,9 +68386,7 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) "rgC" = ( -/obj/structure/cable, /obj/structure/table/reinforced, -/obj/effect/decal/cleanable/dirt, /obj/item/folder/yellow, /obj/item/gps/mining, /obj/effect/turf_decal/tile/brown/anticorner/contrasted, @@ -68924,15 +69030,11 @@ /obj/structure/cable, /obj/structure/disposalpipe/segment, /obj/effect/decal/cleanable/dirt, -/obj/machinery/door/airlock/mining{ - name = "Mining Dock" - }, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ dir = 1 }, /obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/supply/mining, /turf/open/floor/iron, /area/station/cargo/miningoffice) "rmI" = ( @@ -69915,6 +70017,9 @@ /area/station/cargo/storage) "rAl" = ( /obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, /obj/machinery/conveyor{ id = "cargodisposals" }, @@ -71219,13 +71324,10 @@ /turf/open/floor/wood, /area/station/maintenance/port/aft) "rQF" = ( -/obj/structure/closet/wardrobe/miner, -/obj/effect/decal/cleanable/dirt, -/obj/item/storage/backpack/satchel/explorer, -/obj/effect/turf_decal/bot, -/obj/item/radio/intercom/directional/south, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/obj/machinery/netpod, +/obj/effect/decal/cleanable/robot_debris, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "rQI" = ( /obj/machinery/airlock_sensor/incinerator_atmos{ pixel_x = 24 @@ -71527,6 +71629,14 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/science/xenobiology) +"rUi" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/loading_area{ + dir = 1 + }, +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/cargo/miningoffice) "rUj" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/preopen{ @@ -72525,8 +72635,12 @@ /turf/open/space/basic, /area/space) "sgK" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/event_spawn, +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 8 + }, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/miningoffice) "sgZ" = ( @@ -73408,11 +73522,7 @@ /area/station/medical/pharmacy) "stf" = ( /obj/structure/disposalpipe/segment, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/purple/half/contrasted{ - dir = 1 - }, -/turf/open/floor/iron, +/turf/open/floor/iron/herringbone, /area/station/cargo/miningoffice) "stp" = ( /obj/machinery/airalarm/directional/west, @@ -74236,6 +74346,7 @@ }, /obj/effect/mapping_helpers/airlock/access/any/supply/mining, /obj/effect/mapping_helpers/airlock/access/any/supply/shipping, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, /turf/open/floor/iron, /area/station/cargo/sorting) "sCY" = ( @@ -74922,8 +75033,6 @@ /turf/open/floor/iron, /area/station/science/robotics/mechbay) "sLg" = ( -/obj/machinery/rnd/bepis, -/obj/effect/turf_decal/box/white, /turf/open/floor/iron, /area/station/cargo/storage) "sLx" = ( @@ -76191,7 +76300,11 @@ /turf/open/floor/iron, /area/station/engineering/supermatter/room) "tcB" = ( -/obj/effect/decal/cleanable/oil, +/obj/machinery/door/airlock/mining{ + name = "Mining Dock" + }, +/obj/effect/mapping_helpers/airlock/access/all/supply/mining, +/obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/miningoffice) "tcG" = ( @@ -76895,14 +77008,11 @@ /turf/open/floor/iron, /area/station/hallway/primary/central/aft) "toy" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ - dir = 4 - }, -/turf/open/floor/iron, +/turf/open/floor/iron/herringbone, /area/station/cargo/miningoffice) "toB" = ( /obj/machinery/light/directional/west, @@ -78959,23 +79069,13 @@ /turf/open/floor/iron/dark, /area/station/science/server) "tNn" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ +/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ dir = 4 }, -/obj/machinery/requests_console/directional/south{ - department = "Mining"; - name = "Mining Requests Console" - }, -/obj/machinery/requests_console/directional/south{ - department = "Mining"; - name = "Mining Requests Console" - }, -/obj/machinery/camera/directional/south{ - c_tag = "Cargo - Mining Dock"; - name = "cargo camera" +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 8 }, -/obj/effect/turf_decal/tile/brown/half/contrasted, /turf/open/floor/iron, /area/station/cargo/miningoffice) "tNq" = ( @@ -81480,7 +81580,8 @@ /turf/open/floor/wood, /area/station/command/heads_quarters/hop) "usJ" = ( -/obj/effect/turf_decal/tile/purple/half/contrasted{ +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/loading_area{ dir = 1 }, /turf/open/floor/iron, @@ -82164,15 +82265,15 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 6 - }, /obj/structure/sign/nanotrasen{ pixel_y = 32 }, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) "uBf" = ( @@ -83165,17 +83266,18 @@ /turf/open/floor/iron, /area/station/commons/storage/primary) "uND" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 9 +/obj/effect/turf_decal/tile/brown/half{ + dir = 4 }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, -/turf/open/floor/iron, -/area/station/maintenance/starboard/fore) +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/machinery/computer/order_console/bitrunning, +/obj/effect/turf_decal/stripes/end, +/turf/open/floor/iron/half{ + dir = 1 + }, +/area/station/cargo/miningoffice) "uNE" = ( /obj/machinery/atmospherics/components/unary/passive_vent{ dir = 4 @@ -83223,12 +83325,12 @@ /turf/open/floor/iron/white, /area/station/science/ordnance/office) "uOk" = ( -/obj/structure/cable, /obj/structure/chair/office{ dir = 4 }, +/obj/effect/turf_decal/tile/brown/half/contrasted, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/purple/half/contrasted, +/obj/effect/landmark/start/shaft_miner, /turf/open/floor/iron, /area/station/cargo/miningoffice) "uOn" = ( @@ -85051,15 +85153,6 @@ }, /turf/open/floor/iron/cafeteria, /area/station/service/cafeteria) -"vmo" = ( -/obj/structure/table/glass, -/obj/item/reagent_containers/cup/bottle/morphine, -/obj/item/reagent_containers/syringe, -/obj/machinery/status_display/ai/directional/west, -/obj/machinery/newscaster/directional/north, -/obj/effect/turf_decal/siding/dark_red, -/turf/open/floor/iron/dark, -/area/station/security/execution/transfer) "vmr" = ( /obj/machinery/airalarm/directional/west, /obj/machinery/disposal/bin, @@ -86451,11 +86544,24 @@ /turf/open/floor/iron, /area/station/command/heads_quarters/hos) "vDj" = ( +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/trimline/brown/line{ + 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/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/purple/half/contrasted, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/obj/machinery/holopad, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "vDm" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -86841,15 +86947,22 @@ /turf/open/floor/plating, /area/station/maintenance/department/security) "vId" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 8 + }, +/obj/item/radio/intercom/directional/south, +/obj/effect/decal/cleanable/oil, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "vIq" = ( /obj/structure/cable, /obj/structure/disposalpipe/junction{ @@ -87188,13 +87301,20 @@ /turf/open/floor/iron, /area/station/security/checkpoint/engineering) "vNV" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/turf_decal/tile/brown/half{ + dir = 8 + }, /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/half{ dir = 1 }, -/turf/open/floor/iron, /area/station/cargo/miningoffice) "vOh" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -88551,6 +88671,7 @@ }, /obj/effect/mapping_helpers/airlock/access/any/supply/shipping, /obj/effect/mapping_helpers/airlock/access/any/supply/mining, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, /turf/open/floor/iron, /area/station/cargo/sorting) "whc" = ( @@ -89749,14 +89870,14 @@ "wuU" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 9 - }, /obj/machinery/firealarm/directional/east, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, /obj/machinery/light/small/directional/east, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) "wuV" = ( @@ -95074,14 +95195,12 @@ /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai) "xMZ" = ( +/obj/effect/spawner/structure/window/reinforced, /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/turf_decal/tile/brown{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) +/turf/open/floor/plating, +/area/station/cargo/sorting) "xNe" = ( /obj/structure/lattice, /obj/structure/grille/broken, @@ -95641,6 +95760,7 @@ /obj/effect/turf_decal/tile/purple/half/contrasted{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/miningoffice) "xVI" = ( @@ -139805,7 +139925,7 @@ oSv ueU cNf wqo -lfC +hpB oSv mOe yhh @@ -140585,12 +140705,12 @@ ohH xhW xhW nPo -kGo -nPo -xhW -xhW -xhW -xhW +xMZ +cGV +cGV +cGV +cGV +cGV uBd wuU vPp @@ -140843,11 +140963,11 @@ rWo qko vNV pxS -xMZ +fbu mlF qsF jKY -tpZ +cGV lDY tpZ kOj @@ -141099,12 +141219,12 @@ uzM aPD stf llj -mDm +ftS fbu mDm vDj cwd -tpZ +cGV qmT tpZ aaa @@ -141361,8 +141481,8 @@ pUs okN oAV vId -qyX -uND +cGV +eFU tpZ aaa lhY @@ -141611,14 +141731,14 @@ fya cSK pok rWo -llJ +uND kKx dux -tcB +cGV nEE cyc rQF -tpZ +cGV eFU tpZ aad @@ -141869,13 +141989,13 @@ krp krp aJE mtL -kKx -iXd -eYt -hzs -tNn +tcB +rWo +cGV +cGV +cGV +cGV cGV -tpZ jRc tpZ aaa @@ -142125,7 +142245,7 @@ jmp iWR gkP krp -kTs +llJ ljQ guj eYt @@ -142133,7 +142253,7 @@ nhj owZ bLN tpZ -elO +eFU tpZ aaa lhY @@ -142383,13 +142503,13 @@ xZC aiF aJE jCu -iio -mDm +rUi +kTs sgK -mDm +iio gco hkn -tpZ +qyX cwK tpZ aaa @@ -142641,9 +142761,9 @@ qrG aJE dPC usJ -nhj -mDm -mDm +iXd +elO +hzs uOk bhJ tpZ @@ -142898,8 +143018,8 @@ vMd tgX jfO jBM +tNn xVv -ftS dXs rgC tDD @@ -146744,7 +146864,7 @@ mSe mSe mSe mSe -vmo +klh lQj xBD mXg diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index f3ff89fcc80..47fcdebb2c1 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -2964,6 +2964,7 @@ /obj/effect/turf_decal/tile/brown/anticorner/contrasted{ dir = 4 }, +/obj/item/radio/intercom/directional/east, /turf/open/floor/iron/dark, /area/station/cargo/miningdock) "aVF" = ( @@ -4457,11 +4458,8 @@ /turf/open/floor/iron/dark, /area/mine/storage) "bsx" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/cargo/miningdock) +/turf/closed/wall, +/area/station/bitrunning/den) "bsG" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/research/glass{ @@ -10026,6 +10024,19 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /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, +/turf/open/floor/iron/dark/smooth_large, +/area/station/bitrunning/den) "cWq" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /obj/effect/turf_decal/tile/green/half/contrasted{ @@ -10699,6 +10710,8 @@ /area/icemoon/underground/explored) "dgf" = ( /obj/machinery/firealarm/directional/north, +/obj/structure/chair, +/obj/effect/landmark/start/bitrunner, /turf/open/floor/iron, /area/station/cargo/storage) "dgl" = ( @@ -12001,6 +12014,13 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/engineering/lobby) +"dAt" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/light_switch/directional/west, +/turf/open/floor/iron, +/area/station/cargo/miningdock) "dAx" = ( /obj/machinery/hydroponics/soil{ pixel_y = 8 @@ -12895,6 +12915,9 @@ /obj/item/pickaxe{ pixel_x = 5 }, +/obj/item/shovel{ + pixel_x = -5 + }, /turf/open/floor/iron, /area/station/cargo/miningdock) "dPy" = ( @@ -12919,6 +12942,20 @@ /obj/effect/mapping_helpers/airlock/access/any/service/maintenance, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"dPW" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/effect/landmark/start/bitrunner, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 1 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "dPX" = ( /obj/structure/sign/warning/docking/directional/east, /obj/effect/turf_decal/weather/snow/corner{ @@ -13175,12 +13212,10 @@ /turf/open/floor/iron/freezer, /area/mine/laborcamp) "dUK" = ( -/obj/machinery/camera/directional/west{ - c_tag = "Mining Dock" - }, -/obj/machinery/computer/security/mining, -/turf/open/floor/iron, -/area/station/cargo/miningdock) +/obj/machinery/netpod, +/obj/machinery/light/small/directional/south, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "dUL" = ( /obj/machinery/door/poddoor/preopen{ id = "maint1" @@ -13210,14 +13245,14 @@ /turf/open/floor/plating, /area/station/maintenance/starboard/aft) "dVs" = ( -/obj/structure/table, -/obj/item/paper_bin{ - pixel_x = 1; - pixel_y = 9 +/obj/structure/cable, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/machinery/quantum_server, +/obj/effect/decal/cleanable/oil/streak, +/turf/open/floor/iron/dark/smooth_corner{ + dir = 4 }, -/obj/machinery/mining_weather_monitor/directional/west, -/turf/open/floor/iron, -/area/station/cargo/miningdock) +/area/station/bitrunning/den) "dVt" = ( /obj/structure/chair/stool/directional/west, /turf/open/floor/iron/checker, @@ -14879,10 +14914,11 @@ /turf/open/floor/iron, /area/station/maintenance/department/medical/central) "ewq" = ( -/obj/machinery/light_switch/directional/north, -/obj/machinery/light/directional/north, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, -/area/station/cargo/miningdock) +/area/station/cargo/storage) "ewz" = ( /obj/structure/window/reinforced/spawner/directional/east, /obj/structure/window/reinforced/spawner/directional/north, @@ -15082,6 +15118,10 @@ /obj/item/toy/sword, /turf/open/floor/iron/checker, /area/station/maintenance/port/fore) +"eAe" = ( +/obj/structure/chair, +/turf/open/floor/iron, +/area/station/cargo/storage) "eAg" = ( /obj/effect/spawner/structure/window/reinforced/tinted, /turf/closed/wall, @@ -16863,6 +16903,7 @@ /area/mine/laborcamp) "feB" = ( /obj/machinery/airalarm/directional/east, +/obj/effect/landmark/event_spawn, /turf/open/floor/iron, /area/station/cargo/miningdock) "feJ" = ( @@ -17577,6 +17618,10 @@ dir = 8 }, /area/station/medical/chem_storage) +"fqY" = ( +/obj/machinery/light/small/directional/north, +/turf/open/floor/iron, +/area/station/cargo/miningdock) "frd" = ( /obj/structure/railing/corner{ dir = 1 @@ -17663,6 +17708,19 @@ }, /turf/open/floor/iron/dark/textured, /area/station/security/range) +"fss" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "fsv" = ( /turf/open/floor/iron, /area/station/hallway/secondary/entry) @@ -18954,11 +19012,10 @@ /turf/open/floor/engine, /area/station/engineering/supermatter/room) "fNx" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/cargo/miningdock) +/obj/structure/cable, +/obj/machinery/computer/quantum_console, +/turf/open/floor/iron/dark/smooth_corner, +/area/station/bitrunning/den) "fNy" = ( /obj/structure/rack, /obj/item/clothing/suit/hooded/wintercoat{ @@ -19971,6 +20028,13 @@ /obj/effect/turf_decal/siding/yellow, /turf/open/floor/iron, /area/station/engineering/storage) +"gfu" = ( +/obj/machinery/light/small/directional/east, +/obj/machinery/computer/order_console/bitrunning{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "gfw" = ( /obj/machinery/light/small/directional/west, /obj/structure/table, @@ -21146,12 +21210,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) -"gzN" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) "gzV" = ( /obj/structure/mineral_door/paperframe{ name = "Meditation Room" @@ -21984,6 +22042,10 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/wood, /area/station/maintenance/aft/greater) +"gMV" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/station/bitrunning/den) "gMZ" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -31736,7 +31798,7 @@ "jRB" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/table_frame, -/obj/item/wirerod, +/obj/item/melee/baton/security/cattleprod, /obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) @@ -33545,7 +33607,7 @@ /turf/open/floor/iron, /area/station/hallway/primary/central) "krx" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /obj/effect/turf_decal/stripes/line{ dir = 10 }, @@ -35229,10 +35291,11 @@ /turf/open/floor/iron/white, /area/station/medical/surgery/aft) "kQL" = ( -/obj/machinery/power/apc/auto_name/directional/north, /obj/structure/cable, +/obj/structure/chair, +/obj/effect/landmark/start/shaft_miner, /turf/open/floor/iron, -/area/station/cargo/miningdock) +/area/station/cargo/storage) "kQM" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 5 @@ -37029,7 +37092,11 @@ /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 8 }, -/obj/machinery/light/small/directional/west, +/obj/machinery/requests_console/directional/west{ + department = "Mining"; + name = "Mining Requests Console" + }, +/obj/effect/mapping_helpers/requests_console/supplies, /turf/open/floor/iron, /area/station/cargo/miningdock) "ltk" = ( @@ -37040,6 +37107,13 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/external, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) +"ltl" = ( +/obj/machinery/airalarm/directional/west, +/obj/effect/landmark/start/bitrunner, +/obj/machinery/light/small/directional/south, +/obj/effect/decal/cleanable/robot_debris, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "lts" = ( /obj/structure/extinguisher_cabinet/directional/south, /obj/effect/turf_decal/tile/blue, @@ -41493,6 +41567,16 @@ /obj/effect/turf_decal/tile/yellow/anticorner/contrasted, /turf/open/floor/iron, /area/station/commons/storage/tools) +"mTi" = ( +/obj/structure/table, +/obj/effect/turf_decal/tile/brown/half/contrasted, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = -6 + }, +/obj/item/food/cheesiehonkers, +/turf/open/floor/iron, +/area/station/cargo/office) "mTm" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/monitored/air_input{ dir = 1 @@ -42038,13 +42122,12 @@ /turf/open/floor/iron, /area/station/engineering/storage) "naO" = ( -/obj/structure/rack, -/obj/item/shovel{ - pixel_x = -5 - }, /obj/effect/turf_decal/tile/brown/anticorner/contrasted{ dir = 8 }, +/obj/machinery/computer/security/mining{ + dir = 1 + }, /turf/open/floor/iron, /area/station/cargo/miningdock) "naP" = ( @@ -43766,16 +43849,17 @@ /turf/closed/wall/r_wall, /area/station/engineering/transit_tube) "nyB" = ( -/obj/structure/table, -/obj/item/folder/yellow, -/obj/item/pen, -/obj/machinery/requests_console/directional/west{ - department = "Mining"; - name = "Mining Requests Console" +/obj/effect/turf_decal/stripes/line{ + dir = 1 }, -/obj/effect/mapping_helpers/requests_console/supplies, -/turf/open/floor/iron, -/area/station/cargo/miningdock) +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 1 + }, +/obj/machinery/holopad, +/obj/effect/decal/cleanable/oil, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "nyC" = ( /turf/open/floor/iron/dark/smooth_half, /area/station/service/chapel) @@ -44814,9 +44898,9 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/airlock/access/all/supply/mining, +/obj/effect/mapping_helpers/airlock/access/all/supply/general, /turf/open/floor/iron, -/area/station/cargo/miningdock) +/area/station/cargo/storage) "nME" = ( /obj/item/clothing/head/utility/hardhat, /turf/open/floor/plating/snowed/icemoon, @@ -48249,12 +48333,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/lobby) -"oQa" = ( -/obj/structure/table, -/obj/item/food/cheesiehonkers, -/obj/effect/turf_decal/tile/brown/half/contrasted, -/turf/open/floor/iron, -/area/station/cargo/office) "oQn" = ( /obj/structure/chair/sofa/corp/left{ dir = 8 @@ -48596,10 +48674,16 @@ /turf/open/floor/iron/freezer, /area/station/commons/toilet) "oVf" = ( -/obj/effect/landmark/start/shaft_miner, +/obj/machinery/door/airlock/mining/glass{ + id_tag = "innercargo"; + name = "Bitrunning Den" + }, /obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, /turf/open/floor/iron, -/area/station/cargo/miningdock) +/area/station/bitrunning/den) "oVt" = ( /obj/machinery/power/apc/auto_name/directional/south, /obj/structure/cable, @@ -49550,7 +49634,6 @@ /obj/machinery/camera/directional/north{ c_tag = "Cargo Bay North" }, -/obj/machinery/vending/wardrobe/cargo_wardrobe, /obj/machinery/light/directional/north, /turf/open/floor/iron, /area/station/cargo/storage) @@ -51960,9 +52043,6 @@ /obj/effect/mapping_helpers/requests_console/supplies, /obj/structure/table, /obj/item/hand_labeler, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, /obj/item/folder/yellow, /turf/open/floor/iron, /area/station/cargo/storage) @@ -53419,13 +53499,20 @@ /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/underground/explored) "qtT" = ( -/obj/machinery/door/airlock/mining/glass{ - name = "Mining Dock" +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 }, -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/supply/mining, -/turf/open/floor/iron, -/area/station/cargo/miningdock) +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/trimline/brown/corner{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "que" = ( /obj/machinery/camera/directional/south{ c_tag = "Chapel South" @@ -54426,6 +54513,13 @@ /area/mine/eva/lower) "qJJ" = ( /obj/machinery/firealarm/directional/east, +/obj/structure/table, +/obj/item/paper_bin{ + pixel_x = 1; + pixel_y = 9 + }, +/obj/item/folder/yellow, +/obj/item/pen, /turf/open/floor/iron, /area/station/cargo/miningdock) "qJT" = ( @@ -55413,8 +55507,6 @@ /turf/open/floor/plating, /area/station/maintenance/fore/lesser) "qYc" = ( -/obj/structure/closet/crate, -/obj/item/radio/intercom/directional/east, /obj/effect/turf_decal/stripes/line{ dir = 1 }, @@ -59422,7 +59514,7 @@ /turf/open/floor/iron/dark, /area/station/engineering/atmos/project) "slK" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /obj/effect/turf_decal/stripes/line{ dir = 6 }, @@ -61688,6 +61780,16 @@ }, /turf/open/floor/iron/smooth, /area/mine/eva) +"sUI" = ( +/obj/structure/rack, +/obj/machinery/light/cold/directional/north, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = -6 + }, +/obj/item/healthanalyzer, +/turf/open/floor/iron/white/textured, +/area/station/security/medical) "sUN" = ( /obj/machinery/power/solar{ id = "starboardsolar"; @@ -61745,6 +61847,14 @@ /obj/item/screwdriver, /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, +/turf/open/floor/iron/dark/smooth_large, +/area/station/bitrunning/den) "sWl" = ( /obj/machinery/door/airlock/command{ name = "Chief Medical Officer" @@ -62896,12 +63006,10 @@ /turf/open/floor/iron, /area/station/service/janitor) "tqC" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/miningdock) +/obj/machinery/netpod, +/obj/machinery/camera/directional/south, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "tqQ" = ( /obj/effect/turf_decal/stripes/corner{ dir = 1 @@ -63425,7 +63533,11 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/event_spawn, +/obj/machinery/door/airlock/mining{ + name = "Mining Dock" + }, +/obj/effect/mapping_helpers/airlock/access/all/supply/mining, +/obj/machinery/door/firedoor, /turf/open/floor/iron, /area/station/cargo/miningdock) "tyK" = ( @@ -68316,10 +68428,7 @@ /turf/open/floor/iron/grimy, /area/station/security/prison/work) "veh" = ( -/obj/machinery/rnd/bepis, -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, +/obj/machinery/vending/wardrobe/cargo_wardrobe, /turf/open/floor/iron, /area/station/cargo/storage) "vek" = ( @@ -68477,9 +68586,10 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/aft) "vgC" = ( -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/cargo/miningdock) +/obj/machinery/netpod, +/obj/item/radio/intercom/directional/south, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "vgD" = ( /obj/structure/rack, /obj/item/stack/sheet/iron/fifty, @@ -70970,10 +71080,10 @@ /turf/open/floor/iron/chapel, /area/station/service/chapel) "vWV" = ( -/obj/structure/chair/office{ - dir = 8 - }, -/obj/effect/landmark/start/shaft_miner, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/power/apc/auto_name/directional/west, /turf/open/floor/iron, /area/station/cargo/miningdock) "vWW" = ( @@ -72873,12 +72983,6 @@ }, /turf/open/floor/iron, /area/mine/laborcamp) -"wzz" = ( -/obj/structure/rack, -/obj/item/healthanalyzer, -/obj/machinery/light/cold/directional/north, -/turf/open/floor/iron/white/textured, -/area/station/security/medical) "wAq" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -74860,12 +74964,6 @@ /obj/structure/cable, /turf/open/floor/iron/white, /area/station/medical/storage) -"xdz" = ( -/obj/effect/turf_decal/stripes/corner{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) "xdA" = ( /obj/effect/turf_decal/siding/white{ dir = 4 @@ -229062,7 +229160,7 @@ bCQ wBb tKI veh -gzN +ajw ajw ajw mmi @@ -229319,7 +229417,7 @@ yjn wBb tKI pVC -xdz +ajw kXs ajw mmi @@ -230359,7 +230457,7 @@ irD irD pzX gdN -pYT +gfu maT bln qjQ @@ -230616,11 +230714,11 @@ iaF ajw ajw ajw -kXr -kXr -bln -qjQ -qjQ +bsx +bsx +gMV +bsx +bsx ojk bVJ dSO @@ -230873,11 +230971,11 @@ qqJ gjP ajw ajw -maT -bln -bln -bln -qjQ +gMV +cWa +sVW +ltl +bsx qYc hxE xtr @@ -231129,12 +231227,12 @@ kXr kXr kXr dgf -ajw -kXr -bln -bln -qjQ -qjQ +eMa +oVf +fss +qtT +tqC +bsx qjQ rVe qjQ @@ -231384,14 +231482,14 @@ mAN vra lZQ wXR -qjQ -aOd -qtT -aOd -qjQ -qjQ -qjQ -tqC +kXr +eAe +eMa +bsx +fNx +dPW +vgC +bsx lti jBf naO @@ -231640,16 +231738,16 @@ kXA kXA oDt kRU -oQa -qjQ +mTi +kXr kQL -vgC -hoD +ewq +bsx dVs nyB dUK -hoD -hoD +bsx +fqY hxE dPn aOd @@ -231898,14 +231996,14 @@ cXl uxl oRy aHC -qjQ +kXr +ghl ewq -oVf -hoD -hoD -vWV -fNx -hoD +bsx +gMV +gMV +bsx +bsx iVA hxE aCh @@ -232156,13 +232254,13 @@ cHb psW psW nMB -hxE -hxE +ewq +ewq tyH hxE hxE -hxE -hxE +vWV +dAt hxE hxE wBV @@ -232412,13 +232510,13 @@ ljl kXA rLu nRq +maT +ajw +eMa aOd -hoD -bsx -hoD qJJ hxE -hoD +iVA hoD hoD abz @@ -232672,8 +232770,8 @@ uuP tue nZh lNG -nZh tue +qjQ hxE feB lis @@ -239546,7 +239644,7 @@ bUx jOQ bxQ bUx -wzz +sUI vxc aKt tDk diff --git a/_maps/map_files/KiloStation2/KiloStation2.dmm b/_maps/map_files/KiloStation2/KiloStation2.dmm index 8e20d8b305b..b02882b427f 100644 --- a/_maps/map_files/KiloStation2/KiloStation2.dmm +++ b/_maps/map_files/KiloStation2/KiloStation2.dmm @@ -762,6 +762,7 @@ /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 4 }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/cargo/drone_bay) "akH" = ( @@ -4436,10 +4437,14 @@ /area/station/maintenance/fore) "byb" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/girder, -/obj/structure/grille, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/camera/directional/west{ + c_tag = "Engineering West" + }, +/obj/structure/cable, +/turf/open/floor/catwalk_floor, +/area/station/bitrunning/den) "bys" = ( /obj/effect/turf_decal/siding/blue{ dir = 5 @@ -4606,6 +4611,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, /turf/open/floor/iron/dark, /area/station/cargo/drone_bay) "bAX" = ( @@ -4852,14 +4860,11 @@ /turf/open/floor/iron/white, /area/station/security/prison/mess) "bFm" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/north, -/obj/effect/mapping_helpers/broken_floor, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/obj/structure/cable, +/obj/effect/decal/cleanable/oil, +/turf/open/floor/catwalk_floor, +/area/station/bitrunning/den) "bFu" = ( /obj/structure/cable, /turf/closed/wall/rust, @@ -7412,7 +7417,7 @@ /turf/open/misc/asteroid/airless, /area/space/nearstation) "cuj" = ( -/mob/living/simple_animal/hostile/asteroid/hivelord, +/mob/living/basic/mining/hivelord, /turf/open/misc/asteroid/airless, /area/space/nearstation) "cup" = ( @@ -8249,15 +8254,16 @@ /turf/open/floor/iron/dark, /area/station/command/heads_quarters/ce) "cLG" = ( -/obj/structure/chair{ - dir = 4 - }, /obj/effect/turf_decal/tile/red{ dir = 1 }, /obj/effect/turf_decal/tile/blue/opposingcorners{ dir = 1 }, +/obj/item/radio/intercom/directional/north, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) "cLL" = ( @@ -8452,7 +8458,7 @@ /area/station/maintenance/starboard) "cQR" = ( /turf/closed/wall, -/area/station/maintenance/department/cargo) +/area/station/bitrunning/den) "cQV" = ( /obj/machinery/door/firedoor, /obj/structure/disposalpipe/segment{ @@ -10089,7 +10095,6 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/structure/cable, /obj/machinery/status_display/evac/directional/north, /obj/effect/turf_decal/tile/red{ dir = 1 @@ -11527,6 +11532,9 @@ dir = 4 }, /obj/effect/turf_decal/tile/red/opposingcorners, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) "dNL" = ( @@ -12329,11 +12337,14 @@ /area/station/science/xenobiology) "ecl" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/closet/emcloset, -/obj/effect/spawner/random/maintenance, -/obj/machinery/light/small/directional/south, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/obj/machinery/netpod, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/machinery/light/directional/south, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "ecE" = ( /turf/closed/wall/rust, /area/station/service/chapel/storage) @@ -12459,6 +12470,11 @@ "eft" = ( /turf/open/floor/iron/dark, /area/station/hallway/primary/fore) +"efB" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor, +/area/station/bitrunning/den) "efG" = ( /turf/closed/wall, /area/station/maintenance/fore) @@ -14363,7 +14379,7 @@ "eMo" = ( /obj/structure/sign/departments/evac, /turf/closed/wall, -/area/station/maintenance/department/cargo) +/area/station/bitrunning/den) "eMr" = ( /obj/effect/turf_decal/tile/purple/half/contrasted, /turf/open/floor/iron/showroomfloor, @@ -14833,7 +14849,6 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/structure/cable, /obj/machinery/camera/directional/north{ c_tag = "Starboad Hallway Custodial Bay"; name = "starboard camera" @@ -16449,6 +16464,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/hallway/primary/starboard) "fuB" = ( @@ -16898,17 +16914,18 @@ }, /area/station/service/chapel) "fBh" = ( -/obj/machinery/door/airlock/maintenance, -/obj/structure/disposalpipe/segment{ - dir = 4 +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/public/glass{ + name = "Departure Lounge" }, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/unres{ +/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ + cycle_id = "departures-entrance" + }, +/obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/turf/open/floor/iron/dark, +/area/station/hallway/secondary/exit/departure_lounge) "fBm" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/window/reinforced/spawner/directional/west, @@ -18778,6 +18795,9 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, /turf/open/floor/iron, /area/station/hallway/primary/starboard) "gev" = ( @@ -20072,6 +20092,14 @@ /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, /area/station/maintenance/port/lesser) +"gzi" = ( +/obj/machinery/computer/quantum_console, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 10 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "gzv" = ( /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 1 @@ -20908,13 +20936,9 @@ /turf/open/space/basic, /area/space/nearstation) "gMA" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/effect/mapping_helpers/broken_floor, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark, +/area/station/bitrunning/den) "gMC" = ( /obj/machinery/suit_storage_unit/engine, /obj/effect/turf_decal/delivery, @@ -23433,12 +23457,12 @@ /turf/open/floor/iron/dark, /area/station/science/ordnance/office) "hDa" = ( -/obj/structure/disposalpipe/segment{ - dir = 9 - }, /obj/structure/cable, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/catwalk_floor, +/area/station/bitrunning/den) "hDy" = ( /obj/structure/grille/broken, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -23559,17 +23583,11 @@ /area/station/maintenance/aft) "hEH" = ( /obj/effect/turf_decal/bot, -/obj/machinery/disposal/bin, -/obj/machinery/light/directional/east, -/obj/structure/extinguisher_cabinet/directional/north, -/obj/structure/disposalpipe/trunk{ - dir = 8 - }, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/turf/open/floor/iron/dark, -/area/station/hallway/secondary/exit/departure_lounge) +/turf/closed/wall, +/area/station/bitrunning/den) "hEI" = ( /obj/machinery/pdapainter/medbay, /obj/effect/turf_decal/tile/neutral/half/contrasted{ @@ -23676,7 +23694,6 @@ /area/station/hallway/primary/fore) "hGC" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/rnd/bepis, /obj/effect/turf_decal/box/white, /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 1 @@ -23697,7 +23714,7 @@ /turf/open/floor/iron/dark, /area/station/hallway/secondary/entry) "hHg" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell{ +/obj/machinery/cryo_cell{ dir = 4 }, /obj/effect/turf_decal/delivery, @@ -23945,7 +23962,6 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/structure/cable, /obj/effect/spawner/random/vending/snackvend, /obj/effect/turf_decal/bot, /obj/machinery/airalarm/directional/north, @@ -28881,16 +28897,16 @@ /turf/open/floor/iron/dark, /area/station/maintenance/department/bridge) "jgI" = ( -/obj/effect/turf_decal/bot, -/obj/structure/closet/crate, -/obj/item/clothing/shoes/jackboots{ - pixel_x = 4; - pixel_y = 4 +/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/effect/turf_decal/box/corners{ + dir = 1 }, -/obj/item/clothing/shoes/jackboots, -/obj/item/clothing/shoes/cowboy/black, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/obj/effect/turf_decal/box/corners{ + dir = 4 + }, +/obj/machinery/light/directional/east, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "jgN" = ( /turf/open/floor/iron/dark, /area/station/service/chapel/funeral) @@ -29122,7 +29138,7 @@ /obj/structure/table, /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/item/storage/toolbox/emergency, -/obj/item/wirerod, +/obj/item/melee/baton/security/cattleprod, /obj/machinery/light/small/directional/north, /obj/item/radio/intercom/directional/east, /turf/open/floor/iron/dark, @@ -29704,6 +29720,9 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) "jwu" = ( @@ -29946,7 +29965,7 @@ /area/station/command/bridge) "jBO" = ( /obj/effect/turf_decal/bot, -/obj/machinery/atmospherics/components/unary/cryo_cell{ +/obj/machinery/cryo_cell{ dir = 4 }, /obj/effect/turf_decal/tile/neutral/half/contrasted{ @@ -30442,7 +30461,6 @@ /turf/open/floor/iron, /area/station/security/courtroom) "jJB" = ( -/obj/structure/cable, /obj/effect/landmark/start/hangover, /obj/structure/disposalpipe/sorting/mail/flip{ dir = 8; @@ -34131,7 +34149,6 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/structure/cable, /obj/item/kirbyplants/organic/plant21, /obj/structure/extinguisher_cabinet/directional/north, /obj/effect/turf_decal/tile/red{ @@ -34752,14 +34769,9 @@ /turf/open/floor/iron/dark, /area/station/maintenance/port/greater) "lfu" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable, -/obj/effect/decal/cleanable/dirt, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/obj/machinery/computer/order_console/bitrunning, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "lfz" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ @@ -35052,7 +35064,6 @@ /obj/structure/disposalpipe/segment{ dir = 10 }, -/obj/structure/cable, /obj/effect/spawner/random/vending/colavend, /obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral/half/contrasted, @@ -36364,6 +36375,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) "lFC" = ( @@ -39033,7 +39047,7 @@ /obj/item/wirecutters{ pixel_y = 5 }, -/obj/item/wirerod, +/obj/item/melee/baton/security/cattleprod, /obj/effect/turf_decal/bot, /turf/open/floor/iron/dark, /area/station/security/interrogation) @@ -41451,7 +41465,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/disposalpipe/segment, -/obj/structure/cable, /obj/effect/turf_decal/tile/blue{ dir = 4 }, @@ -41896,10 +41909,6 @@ "nwf" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/obj/structure/cable, /obj/effect/turf_decal/tile/blue{ dir = 4 }, @@ -43142,13 +43151,14 @@ /turf/open/floor/iron/dark, /area/station/service/chapel/funeral) "nTd" = ( -/obj/structure/cable, -/obj/effect/decal/cleanable/dirt, -/obj/structure/disposalpipe/segment{ +/obj/machinery/quantum_server, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 6 }, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "nTo" = ( /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating/airless, @@ -44835,12 +44845,12 @@ /area/station/cargo/warehouse) "ozz" = ( /obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/effect/mapping_helpers/broken_floor, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/catwalk_floor, +/area/station/bitrunning/den) "ozO" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, @@ -45688,6 +45698,14 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/engineering/supermatter/room) +"oQt" = ( +/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/effect/turf_decal/box/corners{ + dir = 8 + }, +/obj/effect/turf_decal/box/corners, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "oQv" = ( /obj/structure/bookcase/random, /obj/structure/cable, @@ -45868,15 +45886,15 @@ /turf/open/floor/iron/dark, /area/station/command/bridge) "oSX" = ( -/obj/structure/table, -/obj/item/paper_bin{ - pixel_x = -4; - pixel_y = 4 - }, -/obj/item/pen, /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 8 }, +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/structure/extinguisher_cabinet/directional/north, +/obj/effect/turf_decal/box, /turf/open/floor/iron/dark, /area/station/hallway/secondary/exit/departure_lounge) "oTd" = ( @@ -46539,14 +46557,14 @@ /area/station/medical/medbay/central) "pdZ" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/random/trash/caution_sign, /obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/start/bitrunner, +/obj/effect/decal/cleanable/oil/streak, +/turf/open/floor/catwalk_floor, +/area/station/bitrunning/den) "pem" = ( /obj/structure/transit_tube/curved/flipped{ dir = 4 @@ -49997,15 +50015,17 @@ /turf/open/floor/plating, /area/station/hallway/primary/port) "qih" = ( -/obj/machinery/door/airlock/maintenance, -/obj/structure/cable, -/obj/structure/disposalpipe/segment, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 1 +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 8 }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance, +/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, -/area/station/maintenance/department/cargo) +/area/station/bitrunning/den) "qij" = ( /obj/effect/turf_decal/box/corners, /obj/effect/turf_decal/tile/neutral/anticorner/contrasted, @@ -51862,7 +51882,6 @@ "qRh" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, /obj/structure/disposalpipe/junction/flip, /obj/effect/turf_decal/tile/red{ dir = 1 @@ -53435,7 +53454,6 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/structure/cable, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -54371,6 +54389,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) "rDi" = ( @@ -56262,6 +56283,9 @@ /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 4 }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, /turf/open/floor/iron/dark, /area/station/cargo/drone_bay) "shZ" = ( @@ -58228,6 +58252,8 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/structure/disposalpipe/segment, +/obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/hallway/primary/starboard) "sNe" = ( @@ -61405,10 +61431,14 @@ /turf/open/floor/plating, /area/station/maintenance/starboard) "tNa" = ( -/obj/structure/closet/firecloset, /obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/obj/machinery/netpod, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 5 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "tNe" = ( /obj/structure/disposalpipe/junction, /obj/structure/cable, @@ -61460,13 +61490,9 @@ /turf/open/floor/iron/showroomfloor, /area/station/science/ordnance) "tNQ" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, /obj/effect/turf_decal/tile/neutral/half/contrasted, -/turf/open/floor/iron/dark, -/area/station/hallway/secondary/exit/departure_lounge) +/turf/closed/wall, +/area/station/bitrunning/den) "tNW" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -62356,7 +62382,6 @@ /turf/open/floor/iron/dark/telecomms, /area/station/science/server) "ucm" = ( -/obj/structure/cable, /obj/structure/disposalpipe/segment{ dir = 9 }, @@ -63829,13 +63854,14 @@ /area/station/hallway/secondary/entry) "uAc" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/rack, -/obj/item/stack/sheet/iron/twenty, -/obj/item/stack/sheet/glass{ - amount = 20 +/obj/machinery/netpod, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 }, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/obj/item/radio/intercom/directional/south, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "uAe" = ( /obj/structure/chair{ dir = 8 @@ -68421,12 +68447,13 @@ /turf/closed/wall/rust, /area/station/maintenance/fore) "vUp" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Drone Bay Maintenance" - }, -/obj/effect/mapping_helpers/airlock/access/all/supply/general, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, +/obj/machinery/door/airlock/mining/glass, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, /turf/open/floor/plating, -/area/station/maintenance/department/cargo) +/area/station/bitrunning/den) "vUr" = ( /obj/structure/table/glass, /obj/item/crowbar{ @@ -69826,17 +69853,15 @@ /turf/open/floor/iron/showroomfloor, /area/station/security/brig) "wpn" = ( -/obj/item/kirbyplants/organic/plant21, -/obj/item/radio/intercom/directional/north, /obj/machinery/status_display/ai/directional/west, /obj/effect/turf_decal/tile/neutral/half/contrasted, -/turf/open/floor/iron/dark, -/area/station/hallway/secondary/exit/departure_lounge) +/turf/closed/wall, +/area/station/bitrunning/den) "wpu" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 }, -/mob/living/simple_animal/hostile/asteroid/hivelord, +/mob/living/basic/mining/hivelord, /turf/open/floor/plating, /area/station/cargo/warehouse) "wpw" = ( @@ -70490,7 +70515,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, -/mob/living/simple_animal/hostile/asteroid/hivelord, +/mob/living/basic/mining/hivelord, /turf/open/floor/plating, /area/station/cargo/warehouse) "wAz" = ( @@ -70526,6 +70551,11 @@ /obj/machinery/telecomms/broadcaster/preset_left, /turf/open/floor/circuit/green/telecomms/mainframe, /area/station/tcommsat/server) +"wAZ" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/catwalk_floor, +/area/station/bitrunning/den) "wBf" = ( /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, @@ -71094,7 +71124,7 @@ /area/station/maintenance/fore) "wJn" = ( /turf/closed/wall/rust, -/area/station/maintenance/department/cargo) +/area/station/bitrunning/den) "wJo" = ( /turf/open/floor/plating, /area/station/maintenance/department/security) @@ -75260,7 +75290,7 @@ /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai_upload) "ycp" = ( -/mob/living/simple_animal/hostile/asteroid/hivelord, +/mob/living/basic/mining/hivelord, /turf/open/misc/asteroid/lowpressure, /area/space/nearstation) "ycr" = ( @@ -115103,10 +115133,10 @@ jnp tOy wJn wJn -fBh cQR cQR -pIl +cQR +fBh pIl mbE eHY @@ -115616,7 +115646,7 @@ pHE bmX dwh cQR -wJn +gzi pdZ ecl wJn @@ -116131,10 +116161,10 @@ bHR xTH wJn lfu -cQR +wAZ cQR eMo -pIl +fBh pIl mbE iSw @@ -116388,7 +116418,7 @@ yaF jAl cQR bFm -wJn +efB wpn cLG jwn @@ -116902,7 +116932,7 @@ kVD cQb cQR jgI -cQR +oQt hEH oSX kdO @@ -117160,7 +117190,7 @@ tOy cQR cQR cQR -vOW +cQR wJe sMh iCW diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index cfa13aef72e..af7f222ea55 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -3335,12 +3335,18 @@ /turf/open/floor/iron, /area/station/hallway/primary/starboard) "bje" = ( -/obj/structure/closet/emcloset, -/obj/structure/disposalpipe/segment{ - dir = 5 +/obj/effect/turf_decal/box/corners{ + dir = 8 }, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) +/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" = ( /obj/machinery/rnd/production/techfab/department/service, /obj/effect/turf_decal/trimline/brown/warning{ @@ -4526,7 +4532,6 @@ "bDS" = ( /obj/structure/chair/office/light, /obj/structure/cable, -/obj/item/stamp/head/cmo, /turf/open/floor/iron/white, /area/station/command/heads_quarters/cmo) "bDW" = ( @@ -4681,9 +4686,8 @@ /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/obj/effect/mapping_helpers/airlock/access/all/supply/mining, -/obj/effect/landmark/navigate_destination, +/obj/effect/mapping_helpers/airlock/access/any/supply/mining, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, /turf/open/floor/iron, /area/station/cargo/miningoffice) "bHb" = ( @@ -4697,6 +4701,10 @@ /obj/effect/turf_decal/tile/brown/anticorner/contrasted{ dir = 1 }, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = 4 + }, /turf/open/floor/iron, /area/station/cargo/miningoffice) "bHr" = ( @@ -6085,6 +6093,15 @@ "clq" = ( /turf/open/floor/carpet, /area/station/security/detectives_office) +"cly" = ( +/obj/machinery/computer/quantum_console, +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/effect/decal/cleanable/cobweb, +/obj/machinery/camera/directional/north{ + c_tag = "Mining Dock" + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "clA" = ( /obj/structure/sign/departments/cargo, /turf/closed/wall, @@ -7193,13 +7210,14 @@ /turf/open/floor/plating, /area/station/security/brig) "cGL" = ( +/obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/sorting/mail/flip{ - dir = 1 +/obj/structure/cable, +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 8 }, -/obj/effect/mapping_helpers/mail_sorting/supply/disposals, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) +/turf/open/floor/iron, +/area/station/cargo/miningoffice) "cGV" = ( /obj/machinery/air_sensor/plasma_tank, /turf/open/floor/engine/plasma, @@ -8266,7 +8284,7 @@ /obj/item/bedsheet/red, /obj/machinery/airalarm/directional/east, /obj/machinery/flasher/directional/north{ - id = "IsolationCell" + id = "IsolationFlash" }, /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/floor/iron/white, @@ -8861,6 +8879,13 @@ /obj/structure/window/spawner/directional/south, /turf/open/floor/iron, /area/station/engineering/atmos) +"dob" = ( +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 4 + }, +/obj/machinery/computer/order_console/bitrunning, +/turf/open/floor/iron, +/area/station/cargo/miningoffice) "dox" = ( /obj/structure/rack, /obj/item/screwdriver{ @@ -9294,7 +9319,12 @@ /turf/open/floor/iron/cafeteria, /area/station/engineering/atmos) "dwA" = ( -/obj/structure/disposalpipe/segment, +/obj/effect/spawner/random/maintenance, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, /turf/open/floor/plating, /area/station/maintenance/port/fore) "dwJ" = ( @@ -9389,6 +9419,16 @@ }, /turf/open/floor/plating, /area/station/science/lab) +"dzh" = ( +/obj/machinery/quantum_server, +/obj/effect/turf_decal/bot/left, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 6 + }, +/obj/machinery/light/directional/north, +/obj/item/radio/intercom/directional/north, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "dzw" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -10967,6 +11007,9 @@ /obj/item/clipboard, /obj/item/toy/figure/cmo, /obj/structure/cable, +/obj/item/stamp/head/cmo{ + pixel_x = -9 + }, /turf/open/floor/iron/white, /area/station/command/heads_quarters/cmo) "edq" = ( @@ -11026,12 +11069,14 @@ /turf/open/floor/plating, /area/station/cargo/sorting) "edP" = ( -/obj/structure/disposalpipe/segment, /obj/effect/turf_decal/stripes/line{ dir = 8 }, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, /turf/open/floor/plating, /area/station/maintenance/port/fore) "edQ" = ( @@ -11943,6 +11988,7 @@ /turf/open/floor/iron, /area/station/maintenance/starboard/greater) "esK" = ( +/obj/machinery/firealarm/directional/east, /obj/structure/cable, /obj/machinery/light/small/directional/east, /turf/open/floor/iron/dark, @@ -12459,10 +12505,21 @@ /turf/open/floor/iron, /area/station/hallway/primary/aft) "eEb" = ( +/obj/effect/turf_decal/trimline/brown/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/corner{ + dir = 8 + }, /obj/structure/cable, -/obj/effect/mapping_helpers/broken_floor, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/airlock/mining{ + name = "Bitrunning Den" + }, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, +/turf/open/floor/iron/dark/textured_half, +/area/station/bitrunning/den) "eEf" = ( /obj/machinery/camera/directional/north{ c_tag = "Bar - Backroom" @@ -14976,12 +15033,9 @@ /turf/open/floor/iron, /area/station/maintenance/disposal/incinerator) "fBl" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, +/obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, -/area/station/maintenance/port/fore) +/area/station/bitrunning/den) "fBo" = ( /obj/machinery/door/window/left/directional/north{ dir = 8; @@ -15629,7 +15683,8 @@ name = "Mining Dock Maintenance" }, /obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/all/supply/mining, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, +/obj/effect/mapping_helpers/airlock/access/any/supply/mining, /turf/open/floor/plating, /area/station/maintenance/port/fore) "fNI" = ( @@ -16141,9 +16196,6 @@ /obj/structure/cable, /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /turf/open/floor/iron/white, /area/station/medical/medbay/central) "fYC" = ( @@ -16537,6 +16589,12 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/starboard) +"ghJ" = ( +/obj/machinery/netpod, +/obj/machinery/light/directional/west, +/obj/machinery/airalarm/directional/south, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "ghK" = ( /obj/structure/rack, /obj/item/tank/internals/oxygen, @@ -17322,11 +17380,9 @@ /turf/closed/wall, /area/station/commons/storage/primary) "guZ" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/segment, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) +/obj/machinery/netpod, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "gva" = ( /obj/effect/turf_decal/delivery, /turf/open/floor/iron, @@ -18215,14 +18271,18 @@ /area/station/medical/abandoned) "gMg" = ( /obj/structure/table, -/obj/item/storage/medkit/regular, -/obj/item/reagent_containers/cup/bottle/epinephrine, -/obj/item/reagent_containers/cup/bottle/multiver, -/obj/item/reagent_containers/syringe, /obj/structure/extinguisher_cabinet/directional/west, /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 8 }, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = -6 + }, +/obj/item/storage/medkit/regular, +/obj/item/reagent_containers/cup/bottle/multiver, +/obj/item/reagent_containers/cup/bottle/epinephrine, +/obj/item/reagent_containers/syringe, /turf/open/floor/iron/white, /area/station/security/medical) "gMt" = ( @@ -18438,8 +18498,10 @@ /turf/open/space/basic, /area/space/nearstation) "gQv" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/sorting/mail/flip{ + dir = 1 }, /turf/open/floor/plating, /area/station/maintenance/port/fore) @@ -20012,7 +20074,6 @@ }, /obj/item/mod/module/plasma_stabilizer, /obj/item/mod/module/thermal_regulator, -/obj/item/mod/module/signlang_radio, /turf/open/floor/iron/dark, /area/station/medical/storage) "hwg" = ( @@ -20456,6 +20517,23 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/primary/starboard) +"hDd" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 8 + }, +/obj/machinery/firealarm/directional/south, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark/textured_half, +/area/station/bitrunning/den) "hDe" = ( /obj/machinery/portable_atmospherics/canister/plasma, /turf/open/floor/engine/plasma, @@ -24512,6 +24590,21 @@ /obj/machinery/duct, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"iUV" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/bitrunner, +/obj/machinery/holopad, +/turf/open/floor/iron/dark/textured_half, +/area/station/bitrunning/den) "iVi" = ( /obj/machinery/door/airlock{ id_tag = "Cabin6"; @@ -25905,7 +25998,6 @@ /turf/open/floor/iron/dark, /area/station/engineering/storage/tech) "jty" = ( -/obj/machinery/vending/wardrobe/cargo_wardrobe, /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 8 }, @@ -26880,14 +26972,14 @@ /turf/open/floor/plating, /area/station/maintenance/starboard/aft) "jJp" = ( +/obj/machinery/button/flasher{ + id = "IsolationFlash"; + pixel_x = -23; + pixel_y = 8 + }, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/status_display/door_timer{ - id = "IsolationCell"; - name = "Isolation Cell"; - pixel_x = -32 - }, /turf/open/floor/iron, /area/station/security/execution/transfer) "jJC" = ( @@ -29618,12 +29710,16 @@ /turf/open/floor/engine, /area/station/science/explab) "kHU" = ( -/obj/structure/reagent_dispensers/watertank, -/obj/structure/disposalpipe/segment{ +/obj/effect/turf_decal/box/corners, +/obj/effect/turf_decal/box/corners{ dir = 4 }, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) +/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, +/turf/open/floor/iron/dark/smooth_large, +/area/station/bitrunning/den) "kIG" = ( /obj/structure/rack, /obj/effect/spawner/random/maintenance/two, @@ -32798,6 +32894,9 @@ "lUe" = ( /obj/structure/reagent_dispensers/fueltank, /obj/structure/sign/poster/contraband/random/directional/north, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, /turf/open/floor/plating, /area/station/maintenance/port/fore) "lUj" = ( @@ -34563,6 +34662,9 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/mapping_helpers/broken_floor, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/plating, /area/station/maintenance/port/fore) "mzu" = ( @@ -34621,9 +34723,8 @@ /turf/open/floor/iron/dark, /area/station/hallway/primary/port) "mAy" = ( -/obj/machinery/computer/order_console/mining, -/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ - dir = 8 +/obj/effect/turf_decal/tile/brown{ + dir = 4 }, /turf/open/floor/iron, /area/station/cargo/miningoffice) @@ -38208,7 +38309,6 @@ dir = 4 }, /obj/structure/sign/poster/official/random/directional/north, -/obj/item/mod/module/signlang_radio, /turf/open/floor/iron/dark/corner{ dir = 1 }, @@ -38336,6 +38436,9 @@ /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/item/storage/toolbox/emergency, /obj/effect/spawner/random/maintenance, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, /turf/open/floor/plating, /area/station/maintenance/port/fore) "nMF" = ( @@ -39498,6 +39601,14 @@ /obj/item/toy/cattoy, /turf/open/floor/plating, /area/station/medical/abandoned) +"oif" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "oip" = ( /obj/machinery/door/firedoor, /obj/structure/disposalpipe/segment, @@ -41912,7 +42023,6 @@ /obj/effect/mapping_helpers/airlock/access/all/medical/coroner, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/segment, /turf/open/floor/iron/dark, /area/station/medical/morgue) "pdX" = ( @@ -45122,10 +45232,11 @@ /turf/open/floor/iron/dark, /area/station/command/bridge) "qlr" = ( -/obj/structure/cable, -/obj/effect/landmark/event_spawn, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/cargo/miningoffice) "qlG" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -46158,6 +46269,21 @@ /obj/structure/sign/warning/docking, /turf/closed/wall, /area/station/hallway/secondary/entry) +"qHC" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/textured_half, +/area/station/bitrunning/den) "qHK" = ( /obj/effect/spawner/random/structure/grille, /turf/open/floor/plating, @@ -46240,7 +46366,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/iron/dark/textured, /area/station/medical/cryo) "qIS" = ( @@ -47441,6 +47567,13 @@ /obj/machinery/portable_atmospherics/canister/nitrous_oxide, /turf/open/floor/iron/dark, /area/station/science/ordnance/storage) +"raL" = ( +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 4 + }, +/obj/machinery/computer/order_console/mining, +/turf/open/floor/iron, +/area/station/cargo/miningoffice) "raT" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -49532,10 +49665,14 @@ /turf/open/floor/plating, /area/station/maintenance/port/fore) "rNV" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/segment{ - dir = 6 +/obj/machinery/door/airlock/maintenance{ + name = "Mining Dock Maintenance" }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, +/obj/effect/mapping_helpers/airlock/access/any/supply/mining, /turf/open/floor/plating, /area/station/maintenance/port/fore) "rOz" = ( @@ -49774,12 +49911,8 @@ /turf/open/floor/plating, /area/station/service/chapel) "rSa" = ( -/obj/effect/decal/cleanable/blood/tracks{ - dir = 4 - }, -/obj/effect/spawner/random/structure/grille, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) +/turf/closed/wall, +/area/station/bitrunning/den) "rSi" = ( /obj/effect/landmark/start/chief_engineer, /obj/structure/chair/office/light{ @@ -53088,6 +53221,24 @@ /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, /area/station/maintenance/port) +"taq" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark, +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/obj/machinery/power/apc/auto_name/directional/west, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/textured_half, +/area/station/bitrunning/den) "tar" = ( /obj/machinery/medical_kiosk, /obj/effect/turf_decal/tile/blue/half/contrasted, @@ -54073,12 +54224,10 @@ /turf/open/floor/iron/cafeteria, /area/station/service/kitchen) "ttG" = ( -/obj/item/clothing/gloves/color/rainbow, -/obj/item/clothing/shoes/sneakers/rainbow, -/obj/item/clothing/under/color/rainbow, -/obj/item/clothing/head/soft/rainbow, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) +/obj/machinery/netpod, +/obj/effect/decal/cleanable/robot_debris, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "ttM" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -54902,9 +55051,6 @@ /obj/item/mod/module/plasma_stabilizer{ pixel_x = 16 }, -/obj/item/mod/module/signlang_radio{ - pixel_x = 16 - }, /obj/item/mod/module/thermal_regulator{ pixel_x = 16 }, @@ -55680,6 +55826,16 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/port) +"tWj" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/tile/brown{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/cargo/miningoffice) "tWq" = ( /obj/effect/spawner/random/trash/janitor_supplies, /obj/effect/mapping_helpers/broken_floor, @@ -56808,7 +56964,6 @@ /obj/effect/turf_decal/tile/red/half/contrasted{ dir = 1 }, -/obj/machinery/firealarm/directional/east, /turf/open/floor/iron/dark, /area/station/security/execution/education) "urs" = ( @@ -57267,9 +57422,9 @@ /turf/open/floor/iron/dark, /area/station/security/execution/education) "uyj" = ( -/obj/machinery/rnd/bepis, -/obj/effect/turf_decal/stripes/end{ - dir = 4 +/obj/machinery/vending/wardrobe/cargo_wardrobe, +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 8 }, /turf/open/floor/iron, /area/station/cargo/storage) @@ -57566,9 +57721,7 @@ dir = 4; id = "garbage" }, -/obj/machinery/recycler{ - dir = 8 - }, +/obj/machinery/recycler, /turf/open/floor/plating, /area/station/maintenance/disposal) "uEO" = ( @@ -59763,7 +59916,7 @@ "vpU" = ( /obj/effect/spawner/random/structure/crate, /obj/structure/disposalpipe/segment{ - dir = 4 + dir = 5 }, /turf/open/floor/plating, /area/station/maintenance/port/fore) @@ -63745,7 +63898,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 8 }, -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/iron/dark/textured, /area/station/medical/cryo) "wKu" = ( @@ -64862,7 +65015,8 @@ }, /obj/structure/cable, /obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/supply/mining, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, +/obj/effect/mapping_helpers/airlock/access/any/supply/mining, /turf/open/floor/iron, /area/station/cargo/miningoffice) "xel" = ( @@ -65411,15 +65565,15 @@ /turf/open/floor/iron/dark, /area/station/science/genetics) "xoc" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Mining Dock Maintenance" - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/disposalpipe/segment, -/obj/effect/mapping_helpers/airlock/access/all/supply/mining, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/cargo/miningoffice) "xor" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, @@ -84439,10 +84593,10 @@ nmg vEV jPp jXu -aaa -aaa -aaa -pnI +rSa +rSa +rSa +hKg bUm kRe qRa @@ -84696,9 +84850,9 @@ jXu kXA ufv jXu -aaa -aaa -aaa +cly +taq +ghJ hKg hKg fQW @@ -84953,10 +85107,10 @@ jXu jXu hWS jXu -jXu -jXu -jXu -jXu +dzh +iUV +guZ +fBl qvY kRe wxh @@ -85209,11 +85363,11 @@ lBm qKy ybN edP -dwA -bje jXu +bje +qHC ttG -jXu +fBl pPh aFd nVG @@ -85466,11 +85620,11 @@ vfv cTQ xte mzs -sHu -kHU -jXu -jXu jXu +kHU +hDd +rSa +rSa jpG kRe nVG @@ -85722,11 +85876,11 @@ gYE uEC wgw twr -uuD -qlr +bSm +jXu fBl eEb -jXu +rSa ouc dSG cLj @@ -85979,12 +86133,12 @@ pQu vEH jXu lUe -uuD +gQv rNV cGL -guZ xoc -xyz +xoc +tWj xyz kdC btt @@ -86236,11 +86390,11 @@ eNU aQE jXu nME -iUE -gQv -jXu -jXu +dwA jXu +dob +qlr +raL mAy cLj kRe @@ -86493,10 +86647,10 @@ jXu jXu jXu jXu -uuD -gQv +bSm +jXu +jXu jXu -fhn jXu lJo xJV @@ -86750,10 +86904,10 @@ mVS xxp twr sxn -uuD +oif vpU twr -rSa +fhn jXu jXu fNH diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm index 5f7a19198bb..e26ac494a0f 100644 --- a/_maps/map_files/Mining/Lavaland.dmm +++ b/_maps/map_files/Mining/Lavaland.dmm @@ -1508,6 +1508,13 @@ /obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance, /turf/open/floor/plating, /area/mine/maintenance/public/north) +"jk" = ( +/obj/structure/table, +/obj/item/storage/box/bandages{ + pixel_y = 6 + }, +/turf/open/floor/iron/white, +/area/mine/laborcamp/production) "jm" = ( /obj/machinery/door/airlock/public/glass{ name = "Showers" @@ -1932,6 +1939,17 @@ }, /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) +"lA" = ( +/obj/machinery/recycler{ + dir = 8 + }, +/obj/machinery/conveyor{ + dir = 4; + id = "mining_disposals" + }, +/obj/effect/turf_decal/sand/plating/volcanic, +/turf/open/floor/plating/lavaland_atmos, +/area/mine/maintenance/service/disposals) "lC" = ( /obj/structure/stone_tile/block/cracked{ dir = 1 @@ -2170,19 +2188,6 @@ }, /turf/open/indestructible/boss, /area/lavaland/surface/outdoors) -"mu" = ( -/obj/structure/table, -/obj/item/storage/pill_bottle/epinephrine{ - pixel_x = -2; - pixel_y = 4 - }, -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 10 - }, -/turf/open/floor/iron/white/smooth_corner{ - dir = 8 - }, -/area/mine/medical) "mv" = ( /obj/structure/stone_tile{ dir = 4 @@ -5391,10 +5396,6 @@ }, /turf/open/floor/iron/dark, /area/mine/laborcamp/security) -"HE" = ( -/obj/structure/table, -/turf/open/floor/iron/white, -/area/mine/laborcamp/production) "HF" = ( /obj/structure/stone_tile{ dir = 1 @@ -5809,6 +5810,23 @@ dir = 1 }, /area/mine/living_quarters) +"JQ" = ( +/obj/structure/table, +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 10 + }, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = 4 + }, +/obj/item/storage/pill_bottle/epinephrine{ + pixel_x = -6; + pixel_y = 4 + }, +/turf/open/floor/iron/white/smooth_corner{ + dir = 8 + }, +/area/mine/medical) "JR" = ( /obj/structure/stone_tile, /obj/structure/stone_tile{ @@ -6772,17 +6790,6 @@ }, /turf/open/floor/plating, /area/mine/production) -"PL" = ( -/obj/machinery/recycler{ - dir = 8 - }, -/obj/machinery/conveyor{ - dir = 4; - id = "mining_disposals" - }, -/obj/effect/turf_decal/sand/plating/volcanic, -/turf/open/floor/plating/lavaland_atmos, -/area/mine/maintenance/service/disposals) "PR" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/carpet/executive, @@ -23744,7 +23751,7 @@ aj aj eR Kw -HE +jk ff mU Fv @@ -36321,7 +36328,7 @@ pU mA su xG -PL +lA Sd pU aj @@ -39439,7 +39446,7 @@ yp yp Dz LG -mu +JQ It Xp Ss diff --git a/_maps/map_files/NSSJourney/NSSJourney.dmm b/_maps/map_files/NSSJourney/NSSJourney.dmm index 19299f10006..eac9b009558 100644 --- a/_maps/map_files/NSSJourney/NSSJourney.dmm +++ b/_maps/map_files/NSSJourney/NSSJourney.dmm @@ -1472,6 +1472,7 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/mapping_helpers/airlock/access/any/security/general, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/security/brig) "akV" = ( @@ -5107,7 +5108,6 @@ /turf/open/floor/iron/dark, /area/station/service/hydroponics) "azV" = ( -/obj/machinery/rnd/bepis, /obj/effect/turf_decal/stripes/line{ dir = 6 }, @@ -16385,6 +16385,10 @@ /obj/effect/turf_decal/tile/yellow{ dir = 1 }, +/obj/item/storage/toolbox/mechanical{ + pixel_x = -2; + pixel_y = -1 + }, /turf/open/floor/iron, /area/station/cargo/miningdock) "bmv" = ( @@ -18316,11 +18320,7 @@ /turf/open/floor/iron, /area/station/cargo/miningdock) "bsc" = ( -/obj/structure/rack, -/obj/item/storage/toolbox/mechanical{ - pixel_x = -2; - pixel_y = -1 - }, +/obj/machinery/computer/order_console/bitrunning, /turf/open/floor/iron, /area/station/cargo/miningdock) "bsd" = ( @@ -20315,7 +20315,7 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber{ dir = 1 }, -/turf/open/floor/iron/dark, +/turf/open/floor/iron/dark/airless, /area/station/science/ordnance/freezerchamber) "byb" = ( /obj/effect/decal/cleanable/dirt, @@ -20993,7 +20993,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 6 }, -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/iron/dark, /area/station/medical/cryo) "bBn" = ( @@ -21112,12 +21112,14 @@ /turf/open/floor/plating, /area/station/engineering/atmos) "bBG" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4{ +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 }, -/turf/open/floor/iron, -/area/station/cargo/miningdock) +/obj/effect/decal/cleanable/dirt, +/obj/machinery/quantum_server, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "bBK" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 4 @@ -21657,6 +21659,10 @@ /area/station/science/ordnance/storage) "bDo" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4{ + dir = 4 + }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/miningdock) "bDq" = ( @@ -21842,7 +21848,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 10 }, -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/iron/dark, /area/station/medical/cryo) "bEc" = ( @@ -23065,6 +23071,13 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/mapping_helpers/airlock/access/any/medical/virology, +/obj/machinery/door_buttons/access_button{ + idDoor = "virology_airlock_exterior"; + idSelf = "virology_airlock_control"; + name = "Virology Access Button"; + req_access = list("virology"); + pixel_x = -24 + }, /turf/open/floor/iron, /area/station/medical/virology) "bHZ" = ( @@ -24279,7 +24292,7 @@ dir = 8 }, /obj/machinery/light/directional/south, -/turf/open/floor/iron/dark, +/turf/open/floor/iron/dark/airless, /area/station/science/ordnance/freezerchamber) "bMu" = ( /obj/machinery/door/poddoor/incinerator_ordmix, @@ -24300,7 +24313,7 @@ /obj/machinery/atmospherics/pipe/heat_exchanging/simple/layer2{ dir = 9 }, -/turf/open/floor/iron/dark, +/turf/open/floor/iron/dark/airless, /area/station/science/ordnance/freezerchamber) "bMx" = ( /obj/effect/decal/cleanable/dirt, @@ -25121,10 +25134,19 @@ /turf/open/floor/iron/smooth_large, /area/station/engineering/gravity_generator) "bPZ" = ( -/obj/structure/table, +/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, -/turf/open/floor/iron/dark, -/area/station/maintenance/port/aft) +/obj/machinery/light/small/directional/south, +/obj/effect/turf_decal/box/corners{ + dir = 1 + }, +/obj/effect/turf_decal/box/corners{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "bQa" = ( /obj/effect/spawner/random/maintenance, /obj/structure/trash_pile, @@ -25275,6 +25297,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/mapping_helpers/airlock/access/any/medical/virology, +/obj/machinery/door_buttons/access_button{ + idDoor = "virology_airlock_interior"; + idSelf = "virology_airlock_control"; + name = "Virology Access Button"; + pixel_x = -24; + req_access = list("virology"); + pixel_y = 6 + }, /turf/open/floor/iron, /area/station/medical/virology) "bQJ" = ( @@ -25356,6 +25386,9 @@ dir = 1 }, /obj/effect/decal/cleanable/dirt, +/obj/structure/chair{ + dir = 8 + }, /turf/open/floor/plating, /area/station/maintenance/port/aft) "bRi" = ( @@ -25549,13 +25582,14 @@ /obj/effect/turf_decal/trimline/green/filled/line{ dir = 9 }, -/obj/machinery/door_buttons/access_button{ - idDoor = "virology_airlock_interior"; +/obj/machinery/door_buttons/airlock_controller{ + idExterior = "virology_airlock_exterior"; + idInterior = "virology_airlock_interior"; idSelf = "virology_airlock_control"; - name = "Virology Access Button"; - pixel_x = 8; - req_access = list("virology"); - pixel_y = 24 + name = "Virology Access Console"; + pixel_x = 7; + pixel_y = 26; + req_access = list("virology") }, /turf/open/floor/iron/white, /area/station/medical/virology) @@ -29961,7 +29995,7 @@ /area/station/maintenance/solars/starboard/aft) "cnt" = ( /obj/machinery/camera/directional/west{ - c_tag = "Engineering West" + c_tag = "Bitrunners Den" }, /obj/effect/landmark/start/station_engineer, /obj/effect/turf_decal/tile/yellow{ @@ -31870,7 +31904,7 @@ "cwy" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/table_frame, -/obj/item/wirerod, +/obj/item/melee/baton/security/cattleprod, /obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) @@ -36399,12 +36433,12 @@ /turf/open/floor/iron/dark, /area/station/engineering/main) "eIG" = ( -/obj/structure/chair{ - dir = 8 - }, +/obj/machinery/airalarm/directional/north, +/obj/machinery/netpod, +/obj/effect/turf_decal/stripes/line, /obj/effect/decal/cleanable/dirt, -/turf/open/floor/iron/dark, -/area/station/maintenance/port/aft) +/turf/open/floor/plating, +/area/station/bitrunning/den) "eIN" = ( /obj/effect/turf_decal/trimline/blue/filled/corner{ dir = 8 @@ -36437,6 +36471,12 @@ /obj/structure/chair/stool/directional/south, /turf/open/floor/iron, /area/station/security/prison/visit) +"eJH" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/item/radio/intercom/directional/east, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark, +/area/station/bitrunning/den) "eJI" = ( /obj/effect/turf_decal/delivery, /obj/machinery/door/window{ @@ -36583,6 +36623,10 @@ /obj/structure/sink/directional/east, /turf/open/floor/iron/white, /area/station/science/xenobiology) +"eRu" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/station/bitrunning/den) "eRD" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -37829,15 +37873,6 @@ dir = 10 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door_buttons/airlock_controller{ - idExterior = "virology_airlock_exterior"; - idInterior = "virology_airlock_interior"; - idSelf = "virology_airlock_control"; - name = "Virology Access Console"; - pixel_x = 7; - pixel_y = -26; - req_access = list("virology") - }, /turf/open/floor/iron/white, /area/station/medical/virology) "fSb" = ( @@ -38412,6 +38447,14 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/service/janitor) +"gqG" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/cargo/miningdock) "grP" = ( /obj/machinery/camera/directional/north{ c_tag = "Server Room"; @@ -42204,7 +42247,7 @@ /obj/machinery/atmospherics/pipe/heat_exchanging/simple/layer2{ dir = 5 }, -/turf/open/floor/iron/dark, +/turf/open/floor/iron/dark/airless, /area/station/science/ordnance/freezerchamber) "jLV" = ( /obj/structure/table, @@ -42347,12 +42390,10 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/aft) "jQI" = ( -/obj/structure/chair{ - dir = 4 - }, +/obj/effect/landmark/start/bitrunner, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, -/area/station/maintenance/port/aft) +/area/station/bitrunning/den) "jQY" = ( /obj/effect/landmark/event_spawn, /obj/structure/cable, @@ -42752,6 +42793,10 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/entry) +"kdO" = ( +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron, +/area/station/cargo/miningdock) "kdP" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -42992,6 +43037,14 @@ /obj/machinery/air_sensor/carbon_tank, /turf/open/floor/engine/co2, /area/station/engineering/atmos) +"kqn" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/table, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "kqq" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 4 @@ -43441,9 +43494,8 @@ /turf/open/floor/plating, /area/station/maintenance/port/aft) "kDy" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/station/maintenance/abandon_arcade) +/turf/closed/wall, +/area/station/bitrunning/den) "kES" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable, @@ -43947,6 +43999,16 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/service/hydroponics/garden/abandoned) +"lbU" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/machinery/power/apc/auto_name/directional/east, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark, +/area/station/bitrunning/den) "lcd" = ( /obj/structure/chair/stool/bar/directional/east, /turf/open/floor/wood, @@ -45138,10 +45200,18 @@ /turf/open/floor/iron/white, /area/station/science/ordnance) "meR" = ( -/obj/item/kirbyplants/random/dead, +/obj/machinery/netpod, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, /obj/effect/decal/cleanable/dirt, -/turf/open/floor/iron/dark, -/area/station/maintenance/port/aft) +/obj/machinery/light/small/directional/north, +/obj/machinery/firealarm/directional/north, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/bitrunning/den) "mfT" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -46837,6 +46907,10 @@ /obj/structure/cable, /turf/open/floor/wood, /area/station/maintenance/abandon_cafeteria) +"nJh" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark, +/area/station/bitrunning/den) "nJL" = ( /obj/structure/toilet{ pixel_y = 16 @@ -47319,6 +47393,16 @@ }, /turf/open/floor/iron/dark, /area/station/maintenance/port/aft) +"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 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "ofM" = ( /obj/structure/cable, /turf/open/floor/iron/white, @@ -51024,6 +51108,15 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/starboard) +"rqS" = ( +/obj/machinery/netpod, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/camera/directional/west{ + c_tag = "Engineering West" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/station/bitrunning/den) "rqU" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 4 @@ -52250,6 +52343,18 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron, /area/station/hallway/primary/central) +"svv" = ( +/obj/machinery/door/airlock/mining{ + name = "Bitrunning Den" + }, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/bitrunning/den) "swA" = ( /obj/machinery/door/firedoor, /obj/structure/cable, @@ -54522,6 +54627,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/security/brig) +"uwG" = ( +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/item/kirbyplants/random/dead, +/turf/open/floor/plating, +/area/station/maintenance/port/aft) "uwN" = ( /obj/structure/closet/l3closet/virology, /obj/effect/turf_decal/stripes/line{ @@ -55157,7 +55270,7 @@ dir = 8 }, /obj/machinery/air_sensor/ordnance_freezer_chamber, -/turf/open/floor/iron/dark, +/turf/open/floor/iron/dark/airless, /area/station/science/ordnance/freezerchamber) "uZR" = ( /obj/effect/turf_decal/trimline/green/filled/line, @@ -55705,6 +55818,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/yellow/visible, /turf/open/floor/iron, /area/station/science/ordnance) +"vzv" = ( +/obj/machinery/computer/quantum_console{ + dir = 1 + }, +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "vzN" = ( /obj/structure/filingcabinet/security, /obj/machinery/light/directional/west, @@ -58641,7 +58762,7 @@ /obj/machinery/atmospherics/components/unary/outlet_injector/monitored/ordnance_freezer_chamber_input{ dir = 1 }, -/turf/open/floor/iron/dark, +/turf/open/floor/iron/dark/airless, /area/station/science/ordnance/freezerchamber) "xQe" = ( /obj/effect/turf_decal/stripes/line{ @@ -58921,14 +59042,6 @@ dir = 10 }, /obj/item/kirbyplants/random, -/obj/machinery/door_buttons/access_button{ - idDoor = "virology_airlock_exterior"; - idSelf = "virology_airlock_control"; - name = "Virology Access Button"; - req_access = list("virology"); - pixel_y = -24; - pixel_x = 8 - }, /turf/open/floor/iron/white, /area/station/medical/medbay/aft) "yck" = ( @@ -58976,6 +59089,9 @@ /obj/effect/turf_decal/siding/thinplating/dark{ dir = 1 }, +/obj/structure/chair{ + dir = 4 + }, /turf/open/floor/plating, /area/station/maintenance/port/aft) "ydi" = ( @@ -80743,13 +80859,13 @@ bxy bxy bJd bKm -bxy -xzh -xzh +kDy +kDy +eRu +kDy bCq bLv bLv -bLv bCq bCq bCq @@ -81000,12 +81116,12 @@ bjy bmu nXT bsa -bxy -sUX -sUX +kDy +rqS +nJh +vzv bCq -meR -bRg +uwG cdb bCq vLX @@ -81249,19 +81365,19 @@ jHP bxy oYv bwW -byE +bKp bCo bDk agv byE byE -byE +kdO bsb -bGi -xzh -xzh -bLv +kDy +eIG jQI +bBG +bCq ydd vLX bCq @@ -81514,12 +81630,12 @@ byE bEQ byE bsc -bGi -xzh -xzh -bLv +kDy +meR +jQI bPZ -bRg +bCq +kqn vLX cTF vLX @@ -81766,16 +81882,16 @@ bwX byG byG bAm -bBG bDo bDo bDo -bKp -bGi -xzh -xzh -bLv -eIG +bDo +gqG +svv +lbU +eJH +ofd +bCq bRg bHE bCq @@ -82028,10 +82144,10 @@ mdj rrm axk bxy -bxy kDy kDy -ghE +kDy +kDy ghE imJ vLX diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index d9fff1d8af0..85c22ea665f 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -1966,6 +1966,17 @@ }, /turf/open/floor/catwalk_floor, /area/station/maintenance/floor3/port/fore) +"azj" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 + }, +/obj/effect/turf_decal/arrows{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/disposalpipe/trunk/multiz, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "azu" = ( /obj/structure/table/wood, /obj/item/gun/ballistic/shotgun/doublebarrel, @@ -5545,12 +5556,12 @@ /turf/open/floor/iron/white, /area/station/science/robotics/lab) "brL" = ( -/obj/effect/turf_decal/stripes{ - dir = 6 +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/extinguisher_cabinet/directional/west, +/turf/open/floor/iron/stairs{ + dir = 1 }, -/obj/structure/disposalpipe/segment, -/turf/open/floor/plating, -/area/station/maintenance/floor1/starboard/fore) +/area/station/bitrunning/den) "brN" = ( /obj/effect/spawner/structure/window/hollow/reinforced/directional, /obj/structure/disposalpipe/segment, @@ -5572,9 +5583,14 @@ /turf/open/floor/plating, /area/station/medical/abandoned) "bsq" = ( -/obj/effect/turf_decal/stripes, -/turf/open/floor/plating, -/area/station/maintenance/floor1/starboard/fore) +/obj/machinery/computer/order_console/bitrunning{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/end{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "bsu" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -6347,13 +6363,9 @@ }, /area/station/hallway/floor3/aft) "bAh" = ( -/obj/machinery/door/firedoor/border_only{ - dir = 1 - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor, +/obj/effect/spawner/random/structure/table_or_rack, +/obj/effect/spawner/random/trash/soap, +/turf/open/floor/plating, /area/station/maintenance/floor1/starboard/fore) "bAj" = ( /obj/machinery/conveyor{ @@ -10206,13 +10218,20 @@ /turf/open/floor/engine/vacuum, /area/station/science/ordnance/freezerchamber) "cBT" = ( -/obj/machinery/door/firedoor/border_only{ - dir = 8 +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 }, -/obj/machinery/firealarm/directional/east, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/pod/light, -/area/station/maintenance/floor1/starboard/fore) +/obj/effect/turf_decal/arrows{ + dir = 4 + }, +/obj/structure/railing{ + layer = 3.1 + }, +/obj/effect/decal/cleanable/robot_debris, +/obj/structure/disposalpipe/segment, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "cBU" = ( /obj/structure/window/reinforced/spawner/directional/west, /obj/structure/flora/bush/sunny/style_random, @@ -10322,11 +10341,11 @@ /turf/open/floor/iron/dark/textured, /area/station/medical/pharmacy) "cDe" = ( -/obj/effect/turf_decal/stripes{ - dir = 1 +/obj/machinery/computer/quantum_console{ + dir = 4 }, -/turf/open/floor/plating, -/area/station/maintenance/floor1/starboard/fore) +/turf/open/floor/iron/dark/smooth_corner, +/area/station/bitrunning/den) "cDh" = ( /obj/item/broken_bottle, /turf/open/floor/carpet/neon/simple/pink/nodots, @@ -13156,7 +13175,7 @@ /area/station/maintenance/floor3/port/fore) "dss" = ( /obj/effect/mapping_helpers/broken_floor, -/obj/item/wirerod, +/obj/item/melee/baton/security/cattleprod, /turf/open/floor/plating, /area/station/maintenance/floor1/port/aft) "dsv" = ( @@ -15263,12 +15282,6 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/command/storage/eva) -"dVq" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/turf/open/floor/iron/white, -/area/station/security/medical) "dVt" = ( /obj/structure/railing{ dir = 4 @@ -16795,6 +16808,7 @@ /obj/structure/railing/corner/end{ dir = 1 }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/storage) "eop" = ( @@ -16971,17 +16985,19 @@ /turf/open/floor/catwalk_floor, /area/station/maintenance/floor1/starboard) "erV" = ( -/obj/machinery/door/firedoor/border_only{ +/obj/effect/turf_decal/trimline/brown/line{ dir = 1 }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 5 +/obj/effect/turf_decal/stripes{ + dir = 1 }, -/turf/open/floor/catwalk_floor, -/area/station/maintenance/floor1/starboard/fore) +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/machinery/power/apc/auto_name/directional/west, +/obj/effect/turf_decal/stripes, +/obj/effect/turf_decal/trimline/brown/line, +/turf/open/floor/iron/dark/smooth_half, +/area/station/bitrunning/den) "erY" = ( /obj/machinery/vending/wardrobe/bar_wardrobe, /turf/open/floor/wood, @@ -17113,11 +17129,23 @@ /turf/open/floor/pod/dark, /area/station/maintenance/floor3/starboard) "eul" = ( +/obj/structure/table/reinforced, +/obj/item/storage/toolbox/mechanical{ + pixel_x = -2; + pixel_y = 8 + }, +/obj/item/cigbutt/cigarbutt{ + pixel_x = 7 + }, /obj/effect/turf_decal/stripes{ dir = 8 }, -/turf/open/floor/plating, -/area/station/maintenance/floor1/starboard/fore) +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/obj/effect/decal/cleanable/glass, +/turf/open/floor/iron/dark/smooth_half, +/area/station/bitrunning/den) "euu" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, @@ -20970,12 +20998,13 @@ /turf/open/floor/plating/airless, /area/space) "fCw" = ( -/obj/effect/turf_decal/stripes{ - dir = 4 +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 8 }, -/obj/structure/disposalpipe/trunk/multiz, -/turf/open/floor/plating, -/area/station/maintenance/floor1/starboard/fore) +/obj/machinery/holopad, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "fCx" = ( /obj/structure/rack, /turf/open/floor/pod/dark, @@ -24086,7 +24115,9 @@ dir = 4 }, /obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/storage) "gsp" = ( @@ -25098,6 +25129,7 @@ /area/station/maintenance/floor2/starboard/aft) "gFU" = ( /obj/machinery/computer/exodrone_control_console, +/obj/structure/extinguisher_cabinet/directional/west, /turf/open/floor/iron/dark, /area/station/cargo/drone_bay) "gGe" = ( @@ -28055,9 +28087,12 @@ /turf/open/floor/pod/dark, /area/station/maintenance/floor2/port/fore) "htK" = ( -/obj/effect/spawner/random/maintenance, -/turf/open/floor/pod/light, -/area/station/maintenance/floor1/starboard/fore) +/obj/machinery/netpod, +/obj/structure/railing{ + layer = 3.1 + }, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "htW" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/catwalk_floor/iron, @@ -28655,8 +28690,6 @@ /area/station/maintenance/floor2/port/aft) "hBR" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/light/broken/directional/north, -/obj/item/radio/intercom/directional/north, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/cargo/warehouse) "hBT" = ( @@ -30477,10 +30510,15 @@ /turf/open/floor/iron/dark, /area/station/commons/dorms/room4) "iaJ" = ( -/obj/structure/rack, -/obj/effect/spawner/random/maintenance/two, -/turf/open/floor/pod/light, -/area/station/maintenance/floor1/starboard/fore) +/obj/machinery/netpod, +/obj/effect/decal/cleanable/vomit/old{ + pixel_x = -12; + pixel_y = -13 + }, +/obj/item/radio/intercom/directional/north, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "iaO" = ( /obj/structure/rack, /obj/structure/sign/nanotrasen{ @@ -31458,16 +31496,12 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) "ioi" = ( -/obj/machinery/exoscanner, -/obj/effect/turf_decal/stripes{ - dir = 1 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 1 +/obj/machinery/quantum_server, +/obj/effect/turf_decal/bot/left, +/turf/open/floor/iron/dark/smooth_corner{ + dir = 4 }, -/obj/structure/extinguisher_cabinet/directional/west, -/turf/open/floor/iron/corner, -/area/station/cargo/drone_bay) +/area/station/bitrunning/den) "iom" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -32663,10 +32697,8 @@ /turf/open/floor/catwalk_floor, /area/station/maintenance/floor3/starboard/fore) "iDJ" = ( -/obj/effect/turf_decal/stripes{ - dir = 10 - }, -/obj/effect/mapping_helpers/broken_floor, +/obj/structure/rack, +/obj/item/stack/sheet/leather, /turf/open/floor/plating, /area/station/maintenance/floor1/starboard/fore) "iDP" = ( @@ -34787,9 +34819,14 @@ /turf/open/floor/pod/light, /area/station/maintenance/floor1/starboard/fore) "jhP" = ( -/obj/effect/spawner/random/structure/crate, -/turf/open/floor/pod/light, -/area/station/maintenance/floor1/starboard/fore) +/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, +/turf/open/floor/iron/dark/smooth_large, +/area/station/bitrunning/den) "jhU" = ( /turf/open/floor/iron/white, /area/station/science/robotics/lab) @@ -36140,18 +36177,28 @@ /turf/open/floor/carpet/royalblack, /area/station/service/kitchen/diner) "jAr" = ( -/obj/structure/railing{ +/obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 4 }, -/obj/effect/turf_decal/stripes{ +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 1 +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, +/obj/machinery/door/airlock/mining/glass{ + name = "Bitrunning Den" }, -/turf/open/floor/iron, -/area/station/cargo/storage) +/turf/open/floor/pod/dark, +/area/station/bitrunning/den) +"jAv" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/item/reagent_containers/syringe, +/turf/open/floor/iron/white, +/area/station/security/medical) "jAB" = ( /obj/machinery/light/floor, /turf/open/floor/iron/dark/side{ @@ -37743,6 +37790,9 @@ /area/station/hallway/floor2/fore) "jWJ" = ( /obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, /turf/open/floor/iron, /area/station/cargo/storage) "jWR" = ( @@ -42565,11 +42615,14 @@ /turf/open/floor/iron, /area/station/commons/fitness/recreation) "lgs" = ( -/obj/effect/turf_decal/stripes{ - dir = 5 +/obj/structure/sign/poster/random/directional/north, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/decal/cleanable/oil, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 8 }, -/turf/open/floor/plating, -/area/station/maintenance/floor1/starboard/fore) +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "lgv" = ( /obj/structure/rack, /obj/item/book/manual/nuclear, @@ -42869,11 +42922,6 @@ dir = 1 }, /area/station/medical/chemistry) -"lkI" = ( -/obj/structure/table, -/obj/item/storage/box/donkpockets, -/turf/open/floor/catwalk_floor/iron, -/area/station/cargo/storage) "lkP" = ( /obj/effect/turf_decal/siding/wood{ dir = 4 @@ -46357,6 +46405,13 @@ /obj/structure/flora/bush/flowers_br/style_random, /turf/open/floor/grass, /area/station/security/courtroom) +"meE" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/item/storage/medkit/regular, +/turf/open/floor/iron/white, +/area/station/security/medical) "meH" = ( /obj/machinery/door/airlock/medical{ name = "CMO Quarters" @@ -50885,21 +50940,27 @@ /turf/open/floor/iron/dark, /area/station/hallway/floor3/aft) "nkT" = ( -/obj/effect/turf_decal/siding/thinplating_new/dark{ - dir = 4 +/obj/effect/turf_decal/trimline/brown/line{ + dir = 1 }, -/obj/machinery/door/airlock/hatch{ - name = "Maintenance Access" +/obj/effect/turf_decal/stripes{ + dir = 1 }, -/obj/effect/mapping_helpers/airlock/access/any/supply/general, -/obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/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 }, -/turf/open/floor/pod/dark, -/area/station/maintenance/floor1/starboard/fore) +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/smooth_corner{ + dir = 8 + }, +/area/station/bitrunning/den) "nla" = ( /obj/structure/table/wood, /obj/effect/turf_decal/siding/wood{ @@ -55541,14 +55602,21 @@ /turf/open/floor/iron/dark/side, /area/station/security/checkpoint) "owk" = ( -/obj/structure/cable, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 1 + }, +/obj/effect/turf_decal/stripes{ + dir = 1 + }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/effect/turf_decal/stripes, +/obj/effect/turf_decal/trimline/brown/line, /obj/structure/disposalpipe/segment{ - dir = 4 + dir = 5 }, -/turf/open/floor/catwalk_floor, -/area/station/maintenance/floor1/starboard/fore) +/turf/open/floor/iron/dark/smooth_half, +/area/station/bitrunning/den) "owo" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -55733,6 +55801,9 @@ /obj/structure/sign/warning/biohazard/directional/west, /turf/open/floor/iron/white, /area/station/hallway/floor2/aft) +"oyT" = ( +/turf/closed/wall, +/area/station/bitrunning/den) "oyW" = ( /obj/structure/chair{ dir = 8 @@ -58875,6 +58946,8 @@ }, /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/storage) "pro" = ( @@ -59621,6 +59694,14 @@ /obj/effect/spawner/random/structure/crate, /turf/open/floor/pod/light, /area/station/maintenance/floor1/port/aft) +"pBA" = ( +/obj/machinery/netpod, +/obj/machinery/airalarm/directional/east, +/obj/machinery/airalarm/directional/east, +/obj/machinery/airalarm/directional/east, +/obj/machinery/airalarm/directional/east, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "pBJ" = ( /obj/machinery/navbeacon{ codes_txt = "patrol;next_patrol=1-7"; @@ -59741,7 +59822,6 @@ /area/station/medical/virology) "pCW" = ( /obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/machinery/rnd/bepis, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/cargo/warehouse) @@ -62539,6 +62619,17 @@ dir = 6 }, /area/station/commons/storage/primary) +"qsz" = ( +/obj/structure/table, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = -6 + }, +/obj/item/storage/box/donkpockets{ + pixel_x = 6 + }, +/turf/open/floor/catwalk_floor/iron, +/area/station/cargo/storage) "qsD" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -64295,6 +64386,7 @@ dir = 4 }, /obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/storage) "qOs" = ( @@ -66020,7 +66112,7 @@ /turf/open/floor/iron/dark, /area/station/medical/psychology) "rku" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell{ +/obj/machinery/cryo_cell{ dir = 4 }, /turf/open/floor/iron/dark/textured, @@ -66491,6 +66583,8 @@ dir = 10 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/cargo/storage) "rqK" = ( @@ -67513,7 +67607,7 @@ /area/station/medical/abandoned) "rGF" = ( /obj/effect/turf_decal/bot, -/obj/structure/sign/poster/random/directional/north, +/obj/machinery/light/broken/directional/north, /turf/open/floor/iron/smooth, /area/station/cargo/warehouse) "rGI" = ( @@ -69909,6 +70003,7 @@ /obj/effect/turf_decal/stripes{ dir = 4 }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron, /area/station/cargo/storage) "srz" = ( @@ -71467,11 +71562,16 @@ /turf/open/floor/iron/white, /area/station/science/xenobiology/hallway) "sLq" = ( -/obj/machinery/door/firedoor/border_only{ - dir = 8 +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 4 }, -/turf/open/floor/pod/light, -/area/station/maintenance/floor1/starboard/fore) +/obj/effect/turf_decal/arrows{ + dir = 4 + }, +/obj/machinery/light/directional/north, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "sLE" = ( /obj/machinery/door/airlock/security/glass{ name = "Security Entrance" @@ -78373,10 +78473,18 @@ /turf/open/floor/iron, /area/station/hallway/floor2/aft) "uDm" = ( -/obj/effect/spawner/random/structure/table_or_rack, -/obj/effect/spawner/random/trash/soap, -/turf/open/floor/pod/light, -/area/station/maintenance/floor1/starboard/fore) +/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, +/turf/open/floor/iron/dark/smooth_large, +/area/station/bitrunning/den) "uDr" = ( /obj/machinery/light/small/directional/north, /obj/effect/decal/cleanable/dirt, @@ -81996,13 +82104,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/science/explab) -"vxL" = ( -/obj/structure/table/glass, -/obj/item/storage/medkit/regular, -/obj/item/reagent_containers/syringe, -/obj/item/radio/intercom/directional/south, -/turf/open/floor/iron/white, -/area/station/security/medical) "vxT" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -84080,7 +84181,7 @@ /turf/open/floor/iron, /area/station/hallway/floor2/aft) "waA" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell{ +/obj/machinery/cryo_cell{ dir = 8 }, /obj/structure/sign/poster/official/random/directional/east, @@ -84656,11 +84757,9 @@ /turf/open/floor/iron/dark, /area/station/hallway/floor4/aft) "whN" = ( -/obj/effect/turf_decal/stripes{ - dir = 9 - }, +/obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, -/area/station/maintenance/floor1/starboard/fore) +/area/station/bitrunning/den) "whR" = ( /turf/closed/wall, /area/station/service/bar) @@ -86737,12 +86836,6 @@ }, /turf/open/floor/iron/dark/side, /area/station/security/prison) -"wHC" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/iron/white, -/area/station/security/medical) "wHP" = ( /obj/effect/turf_decal/trimline/brown/filled/line{ dir = 4 @@ -89199,6 +89292,16 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/hallway/floor4/aft) +"xoA" = ( +/obj/structure/table/glass, +/obj/item/radio/intercom/directional/south, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = -6 + }, +/obj/item/storage/medkit/regular, +/turf/open/floor/iron/white, +/area/station/security/medical) "xoF" = ( /obj/effect/turf_decal/trimline/purple/line, /obj/effect/turf_decal/trimline/purple/filled/corner{ @@ -91153,11 +91256,15 @@ /turf/open/floor/catwalk_floor, /area/station/maintenance/floor2/starboard/fore) "xOd" = ( -/obj/machinery/modular_computer/preset/civilian, -/obj/machinery/power/apc/auto_name/directional/north, -/obj/structure/cable, -/turf/open/floor/iron/dark, -/area/station/cargo/drone_bay) +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/shieldgen, +/obj/item/radio/intercom/directional/north, +/turf/open/floor/iron/smooth, +/area/station/cargo/warehouse) "xOe" = ( /obj/machinery/light/cold/no_nightlight/directional/north, /turf/open/floor/engine, @@ -115256,13 +115363,13 @@ owI owI owI owI -oic -oic -whN -eul -iDJ +oyT +oyT +oyT +oyT +oyT bAh -oic +iDJ oic oic oic @@ -115513,14 +115620,14 @@ owI owI owI owI -oic -oic +oyT +oyT cDe -oic -bsq -bAh -htK -oic +ioi +oyT +oyT +oyT +oyT gUS nOj dzo @@ -115770,14 +115877,14 @@ owI owI owI owI -oic -oic +oyT +oyT lgs fCw brL erV uDm -oic +oyT rGF yiZ yiZ @@ -116027,14 +116134,14 @@ owI owI owI owI -oic -oic -sLq +oyT +oyT sLq +azj cBT owk jhP -oic +whN hBR qWJ qWJ @@ -116284,14 +116391,14 @@ owI owI owI owI -oic -oic +oyT +oyT iaJ -oic -oic +pBA +htK nkT -oic -oic +eul +whN rYA eEB lUY @@ -116541,15 +116648,15 @@ owI owI owI owI -oic -oic -oic -oic +oyT +oyT +oyT +oyT +oyT +jAr +whN +oyT xOd -xxQ -ioi -aQK -fve fve aSL iCn @@ -117579,7 +117686,7 @@ aQK aQK cfO jWJ -mnR +bsq mnk mnR aHb @@ -117833,7 +117940,7 @@ xsL sqK rqB prm -jAr +gso gso qOr eoo @@ -118353,7 +118460,7 @@ oCK fgr cJt jfa -lkI +qsz cMA mnR bvf @@ -322959,7 +323066,7 @@ eoL hSJ dBo mXY -vxL +xoA qFI wIn hyR @@ -323215,7 +323322,7 @@ eUU dDR iTd oPA -wHC +jAv hfd qFI iPH @@ -323472,7 +323579,7 @@ rIa bsI oOi dOD -dVq +meE bBg qFI omP diff --git a/_maps/map_files/VoidRaptor/VoidRaptor.dmm b/_maps/map_files/VoidRaptor/VoidRaptor.dmm index c3918c21108..1cdd6f23178 100644 --- a/_maps/map_files/VoidRaptor/VoidRaptor.dmm +++ b/_maps/map_files/VoidRaptor/VoidRaptor.dmm @@ -1531,6 +1531,10 @@ /obj/structure/trash_pile, /turf/open/floor/iron/smooth, /area/station/maintenance/department/engine) +"awG" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/turf/open/floor/iron/smooth_large, +/area/station/cargo/miningdock) "awP" = ( /obj/machinery/mech_bay_recharge_port, /obj/effect/turf_decal/bot, @@ -3260,6 +3264,9 @@ /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 4 }, +/obj/item/storage/box/bandages{ + pixel_y = 8 + }, /turf/open/floor/iron/dark/smooth_edge{ dir = 8 }, @@ -3689,16 +3696,6 @@ }, /turf/open/floor/iron/smooth_large, /area/station/hallway/primary/aft) -"baW" = ( -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 4 - }, -/obj/structure/closet/secure_closet/miner, -/obj/effect/turf_decal/delivery, -/turf/open/floor/iron/smooth_edge{ - dir = 8 - }, -/area/station/cargo/miningdock) "bbh" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -8461,6 +8458,9 @@ dir = 1 }, /area/station/science/explab) +"cBk" = ( +/turf/closed/wall, +/area/station/bitrunning/den) "cBU" = ( /obj/structure/chair/comfy/beige{ dir = 1 @@ -8731,8 +8731,8 @@ pixel_y = 5 }, /obj/machinery/light_switch/directional/east{ - pixel_y = 6; - pixel_x = 23 + pixel_x = 23; + pixel_y = 6 }, /obj/effect/turf_decal/trimline/blue/filled/warning{ dir = 5 @@ -9780,8 +9780,8 @@ /area/station/hallway/primary/fore) "cWB" = ( /obj/machinery/digital_clock{ - pixel_y = 7; - pixel_x = -1 + pixel_x = -1; + pixel_y = 7 }, /turf/closed/wall/r_wall, /area/station/engineering/supermatter/room) @@ -10031,6 +10031,10 @@ /obj/item/multitool, /obj/machinery/airalarm/directional/south, /obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/obj/item/storage/box/bandages{ + pixel_x = 4; + pixel_y = 5 + }, /turf/open/floor/engine, /area/station/tcommsat/computer) "day" = ( @@ -10348,6 +10352,12 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/smooth_large, /area/station/engineering/atmos/pumproom) +"deu" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "dex" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/carpet, @@ -11103,6 +11113,14 @@ }, /turf/open/floor/engine/vacuum, /area/station/science/ordnance/freezerchamber) +"dpw" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 1 + }, +/obj/structure/closet/secure_closet/miner, +/obj/effect/turf_decal/delivery, +/turf/open/floor/iron/smooth_edge, +/area/station/cargo/miningdock) "dpx" = ( /obj/structure/table/wood, /obj/item/storage/crayons, @@ -11908,6 +11926,14 @@ }, /turf/open/floor/plating, /area/station/science/genetics) +"dAV" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/textured, +/area/station/bitrunning/den) "dAX" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -14573,12 +14599,6 @@ dir = 8 }, /area/station/cargo/lobby) -"ejt" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/tile/dark_blue/fourcorners, -/turf/open/floor/iron/dark, -/area/station/medical/medbay/central) "eju" = ( /obj/structure/rack, /obj/effect/spawner/random/clothing/costume, @@ -18708,6 +18728,16 @@ /obj/machinery/atmospherics/pipe/smart/simple/dark/visible, /turf/open/floor/iron/smooth, /area/station/maintenance/disposal/incinerator) +"fth" = ( +/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/effect/turf_decal/box/corners{ + dir = 8 + }, +/obj/effect/turf_decal/box/corners{ + dir = 1 + }, +/turf/open/floor/engine, +/area/station/bitrunning/den) "ftr" = ( /obj/machinery/power/shuttle_engine/heater, /obj/effect/turf_decal/stripes/line{ @@ -18923,12 +18953,6 @@ /obj/structure/table/glass, /turf/open/floor/iron/white/smooth_large, /area/station/medical/medbay/central) -"fxJ" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 8 - }, -/turf/open/floor/iron/smooth_large, -/area/station/cargo/miningdock) "fxO" = ( /obj/structure/displaycase/trophy, /obj/effect/turf_decal/siding/wood{ @@ -19689,6 +19713,12 @@ }, /turf/open/floor/iron/large, /area/station/commons/fitness/recreation/entertainment) +"fKN" = ( +/obj/machinery/cryo_cell, +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/tile/dark_blue/fourcorners, +/turf/open/floor/iron/dark, +/area/station/medical/medbay/central) "fKU" = ( /obj/effect/turf_decal/trimline/brown/filled/warning{ dir = 4 @@ -20501,13 +20531,6 @@ "fXP" = ( /turf/closed/wall/r_wall, /area/station/engineering/atmos/storage/gas) -"fXS" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, -/obj/effect/turf_decal/bot, -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/tile/dark_blue/fourcorners, -/turf/open/floor/iron/dark, -/area/station/medical/medbay/central) "fXZ" = ( /obj/effect/turf_decal/siding/red{ dir = 1 @@ -21691,6 +21714,17 @@ /obj/structure/sign/poster/official/wtf_is_co2, /turf/closed/wall, /area/station/engineering/atmos) +"goP" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/smooth_edge{ + dir = 4 + }, +/area/station/bitrunning/den) "goS" = ( /turf/open/floor/iron/freezer, /area/station/medical/chemistry) @@ -24092,6 +24126,13 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/freezer, /area/station/medical/chemistry) +"gWT" = ( +/obj/machinery/computer/quantum_console{ + dir = 8 + }, +/obj/machinery/light/small/red/directional/east, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "gWV" = ( /obj/effect/turf_decal/trimline/yellow/filled/warning{ dir = 4 @@ -24976,6 +25017,17 @@ /obj/structure/window/spawner/directional/east, /turf/open/misc/beach/sand, /area/station/science/research) +"hjg" = ( +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/table, +/obj/item/plate, +/obj/effect/spawner/random/trash/food_packaging, +/obj/machinery/camera/directional/north{ + c_tag = "Mining Dock" + }, +/obj/structure/cable, +/turf/open/floor/iron/smooth_edge, +/area/station/bitrunning/den) "hji" = ( /obj/effect/turf_decal/trimline/red/filled/line{ dir = 1 @@ -25092,6 +25144,9 @@ /obj/item/storage/medkit/regular, /obj/item/storage/backpack/satchel/explorer, /obj/machinery/light/directional/south, +/obj/item/storage/box/bandages{ + pixel_y = 8 + }, /turf/open/floor/iron/smooth_edge{ dir = 1 }, @@ -26702,6 +26757,15 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/pod/dark, /area/station/service/chapel) +"hJg" = ( +/obj/structure/table, +/obj/item/modular_computer/laptop/preset/civilian{ + pixel_y = 5; + pixel_x = 2 + }, +/obj/structure/cable, +/turf/open/floor/iron/smooth_large, +/area/station/bitrunning/den) "hJx" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/monitored/ordnance_burn_chamber_input{ dir = 4 @@ -26772,6 +26836,18 @@ dir = 8 }, /area/station/engineering/atmos) +"hKK" = ( +/obj/structure/chair/plastic{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 5 + }, +/obj/machinery/computer/security/telescreen/entertainment/directional/east, +/obj/structure/sign/poster/contraband/random/directional/north, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/smooth, +/area/station/bitrunning/den) "hKP" = ( /obj/item/reagent_containers/cup/bucket, /obj/effect/decal/cleanable/cobweb/cobweb2, @@ -26864,14 +26940,14 @@ "hMN" = ( /obj/structure/table/glass, /obj/effect/turf_decal/bot, -/obj/item/storage/box{ - pixel_x = 3; - pixel_y = 3 - }, /obj/item/radio/headset/headset_eng{ pixel_x = -4; pixel_y = 3 }, +/obj/item/storage/box/bandages{ + pixel_x = 4; + pixel_y = 5 + }, /turf/open/floor/iron/smooth_large, /area/station/engineering/lobby) "hMQ" = ( @@ -27225,6 +27301,13 @@ }, /turf/open/floor/iron/white, /area/station/hallway/primary/fore) +"hSf" = ( +/obj/effect/landmark/start/shaft_miner, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/smooth_large, +/area/station/cargo/miningdock) "hSn" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 @@ -27570,22 +27653,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/smooth_large, /area/station/maintenance/department/engine/atmos/lesser) -"hWA" = ( -/obj/machinery/door/airlock/mining{ - name = "Mining Dock" - }, -/obj/effect/mapping_helpers/airlock/access/all/supply/mining, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/structure/disposalpipe/segment, -/turf/open/floor/iron/smooth, -/area/station/cargo/miningdock) "hWF" = ( /obj/effect/turf_decal/trimline/brown/filled/line{ dir = 1 @@ -28114,6 +28181,13 @@ "ifq" = ( /turf/closed/wall/r_wall, /area/station/medical/pharmacy) +"ifS" = ( +/obj/machinery/cryo_cell, +/obj/effect/turf_decal/bot, +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/tile/dark_blue/fourcorners, +/turf/open/floor/iron/dark, +/area/station/medical/medbay/central) "igd" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 8 @@ -28158,13 +28232,6 @@ dir = 4 }, /area/station/commons/fitness/recreation/entertainment) -"ihv" = ( -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 9 - }, -/obj/machinery/rnd/bepis, -/turf/open/floor/iron/smooth, -/area/station/cargo/warehouse) "ihy" = ( /obj/machinery/atmospherics/pipe/bridge_pipe/green/visible, /obj/structure/window/reinforced/plasma/spawner/directional/west, @@ -30164,6 +30231,9 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, +/obj/item/storage/box/bandages{ + pixel_y = 8 + }, /turf/open/floor/iron/freezer, /area/station/medical/treatment_center) "iHi" = ( @@ -30398,6 +30468,13 @@ dir = 8 }, /area/station/engineering/atmos/hfr_room) +"iLb" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark/textured_edge, +/area/station/bitrunning/den) "iLH" = ( /obj/effect/turf_decal/trimline/purple/filled/warning{ dir = 4 @@ -32973,6 +33050,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/edge, /area/station/hallway/primary/central) +"jvw" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/textured_edge{ + dir = 8 + }, +/area/station/bitrunning/den) "jvx" = ( /obj/structure/table/wood, /obj/item/food/breadslice/plain, @@ -35349,6 +35435,14 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/security/warden) +"kdS" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 10 + }, +/obj/machinery/light_switch/directional/west, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/smooth, +/area/station/bitrunning/den) "kek" = ( /obj/effect/turf_decal/trimline/neutral/filled/warning{ dir = 1 @@ -35856,6 +35950,15 @@ }, /turf/open/floor/pod/dark, /area/station/service/chapel/funeral) +"kkC" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 1 + }, +/obj/structure/extinguisher_cabinet/directional/north, +/obj/structure/closet/secure_closet/miner, +/obj/effect/turf_decal/delivery, +/turf/open/floor/iron/smooth_edge, +/area/station/cargo/miningdock) "kkI" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -36252,6 +36355,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/smooth_large, /area/station/hallway/secondary/construction) +"krz" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/trimline/brown/filled/corner{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/smooth_large, +/area/station/cargo/miningdock) "krA" = ( /obj/effect/turf_decal/trimline/brown/filled/corner{ dir = 1 @@ -36284,6 +36396,15 @@ /obj/effect/spawner/random/trash/mess, /turf/open/floor/iron/smooth, /area/station/maintenance/department/science/xenobiology) +"ksB" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 8 + }, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/textured_edge{ + dir = 4 + }, +/area/station/bitrunning/den) "ksD" = ( /obj/effect/turf_decal/trimline/brown/filled/warning{ dir = 6 @@ -37411,6 +37532,15 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"kFL" = ( +/obj/effect/spawner/random/trash/grime, +/obj/effect/turf_decal/trimline/brown/filled/corner{ + dir = 4 + }, +/turf/open/floor/iron/smooth_corner{ + dir = 4 + }, +/area/station/bitrunning/den) "kFS" = ( /obj/effect/mapping_helpers/airlock/access/all/science/rd, /obj/machinery/door/airlock/rd/glass{ @@ -39184,6 +39314,11 @@ }, /turf/open/floor/iron/smooth_large, /area/station/engineering/power_room) +"ldU" = ( +/obj/machinery/netpod, +/obj/machinery/light/small/blacklight/directional/west, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "leb" = ( /obj/structure/cable, /turf/open/floor/iron/smooth_large, @@ -39206,6 +39341,11 @@ }, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/department/crew_quarters/bar) +"leF" = ( +/obj/machinery/quantum_server, +/obj/structure/extinguisher_cabinet/directional/east, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "leI" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 5 @@ -39674,6 +39814,9 @@ dir = 10 }, /obj/machinery/firealarm/directional/south, +/obj/item/storage/box/bandages{ + pixel_y = 8 + }, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) "llF" = ( @@ -40734,6 +40877,10 @@ }, /obj/effect/turf_decal/bot, /obj/item/clothing/glasses/meson/engine, +/obj/item/storage/box/bandages{ + pixel_x = 4; + pixel_y = 5 + }, /turf/open/floor/iron/dark/smooth_large, /area/station/engineering/main) "lAS" = ( @@ -45708,6 +45855,12 @@ /obj/effect/turf_decal/box, /turf/open/floor/plating/airless, /area/space/nearstation) +"mTY" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 5 + }, +/turf/open/floor/iron/dark/textured, +/area/station/bitrunning/den) "mUp" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/trash/mess, @@ -47279,6 +47432,15 @@ }, /turf/open/floor/wood/large, /area/station/hallway/primary/fore) +"nqU" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/trimline/brown/filled/warning{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/smooth_large, +/area/station/cargo/miningdock) "nrb" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -47341,13 +47503,6 @@ }, /turf/open/floor/wood/large, /area/station/commons/fitness/recreation/entertainment) -"nsm" = ( -/obj/effect/turf_decal/loading_area{ - dir = 4 - }, -/obj/effect/landmark/start/shaft_miner, -/turf/open/floor/iron/smooth_large, -/area/station/cargo/miningdock) "nsp" = ( /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 1 @@ -48010,6 +48165,12 @@ dir = 4 }, /area/station/engineering/power_room) +"nAD" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 9 + }, +/turf/open/floor/iron/smooth, +/area/station/cargo/warehouse) "nAH" = ( /turf/closed/wall/r_wall, /area/station/ai_monitored/turret_protected/aisat/atmos) @@ -48040,6 +48201,17 @@ }, /turf/closed/wall/r_wall, /area/station/science/ordnance/burnchamber) +"nBO" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/smooth_edge{ + dir = 8 + }, +/area/station/cargo/miningdock) "nCl" = ( /obj/structure/chair/office/light{ dir = 4 @@ -48315,6 +48487,19 @@ /obj/effect/spawner/random/trash/grille_or_waste, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/science/research/abandoned) +"nGR" = ( +/obj/structure/chair/sofa/corp/right{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 8 + }, +/obj/machinery/light/small/directional/west, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/smooth_edge{ + dir = 4 + }, +/area/station/bitrunning/den) "nGX" = ( /obj/structure/chair/sofa/right/brown{ dir = 8 @@ -50463,6 +50648,13 @@ /obj/machinery/status_display/ai/directional/south, /turf/open/floor/carpet/black, /area/station/service/chapel/office) +"oky" = ( +/obj/effect/turf_decal/trimline/brown/filled/line, +/obj/machinery/computer/order_console/bitrunning, +/turf/open/floor/iron/dark/textured_edge{ + dir = 1 + }, +/area/station/bitrunning/den) "okG" = ( /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -51379,6 +51571,13 @@ dir = 4 }, /area/station/hallway/secondary/command) +"oxn" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 10 + }, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/textured, +/area/station/bitrunning/den) "oxv" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/disposalpipe/segment{ @@ -52052,6 +52251,16 @@ /obj/machinery/light/cold/directional/west, /turf/open/floor/iron/dark/small, /area/station/security/prison/garden) +"oGX" = ( +/obj/structure/table, +/obj/machinery/microwave, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 5 + }, +/obj/machinery/light/small/directional/east, +/obj/structure/sign/poster/contraband/random/directional/east, +/turf/open/floor/iron/smooth, +/area/station/bitrunning/den) "oHc" = ( /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -52912,6 +53121,11 @@ /obj/machinery/firealarm/directional/east, /turf/open/floor/circuit/green, /area/station/ai_monitored/command/nuke_storage) +"oUb" = ( +/obj/machinery/firealarm/directional/west, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/stairs, +/area/station/bitrunning/den) "oUl" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -54690,6 +54904,19 @@ "pqh" = ( /turf/closed/wall, /area/station/cargo/warehouse) +"pqk" = ( +/obj/structure/chair/sofa/corp/left{ + desc = "Looks like someone threw it out. Covered in donut crumbs."; + dir = 4; + name = "couch" + }, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 9 + }, +/obj/structure/sign/poster/contraband/random/directional/west, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/smooth, +/area/station/bitrunning/den) "pql" = ( /obj/machinery/power/apc/auto_name/directional/east, /obj/structure/cable, @@ -55002,6 +55229,9 @@ id = "paramed_dispatch_desk"; name = "Desk Shutters" }, +/obj/item/storage/box/bandages{ + pixel_y = 15 + }, /turf/open/floor/iron/white/smooth_large, /area/station/medical/medbay/lobby) "puQ" = ( @@ -55081,6 +55311,13 @@ /obj/machinery/atmospherics/pipe/layer_manifold/supply/hidden, /turf/closed/wall/r_wall, /area/station/maintenance/disposal/incinerator) +"pws" = ( +/obj/effect/landmark/start/shaft_miner, +/obj/effect/turf_decal/loading_area{ + dir = 1 + }, +/turf/open/floor/iron/smooth_large, +/area/station/cargo/miningdock) "pwB" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/item/radio{ @@ -55698,6 +55935,15 @@ /obj/machinery/light_switch/directional/east, /turf/open/floor/iron/smooth, /area/station/engineering/atmos/storage/gas) +"pFJ" = ( +/obj/item/storage/cans/sixsoda, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 6 + }, +/obj/structure/railing, +/obj/item/radio/intercom/directional/east, +/turf/open/floor/iron/smooth, +/area/station/bitrunning/den) "pGh" = ( /turf/open/floor/iron/white/smooth_large, /area/station/hallway/primary/fore) @@ -56454,17 +56700,6 @@ /obj/structure/cable, /turf/open/floor/iron/smooth, /area/station/maintenance/department/electrical) -"pRu" = ( -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 4 - }, -/obj/structure/closet/secure_closet/miner, -/obj/effect/turf_decal/delivery, -/obj/machinery/light/directional/east, -/turf/open/floor/iron/smooth_edge{ - dir = 8 - }, -/area/station/cargo/miningdock) "pRv" = ( /obj/effect/spawner/random/trash/moisture_trap, /turf/open/floor/iron/smooth, @@ -57824,6 +58059,13 @@ "qgT" = ( /turf/open/floor/iron/white, /area/station/hallway/primary/fore) +"qgY" = ( +/obj/effect/turf_decal/trimline/brown/filled/line, +/obj/structure/railing, +/turf/open/floor/iron/smooth_edge{ + dir = 1 + }, +/area/station/bitrunning/den) "qha" = ( /obj/machinery/chem_heater/withbuffer, /obj/effect/turf_decal/trimline/yellow/filled/line, @@ -57928,6 +58170,14 @@ }, /turf/open/floor/catwalk_floor, /area/station/hallway/secondary/exit/departure_lounge) +"qhU" = ( +/obj/effect/landmark/bitrunning/station_reward_spawn, +/obj/effect/turf_decal/box/corners, +/obj/effect/turf_decal/box/corners{ + dir = 4 + }, +/turf/open/floor/engine, +/area/station/bitrunning/den) "qhX" = ( /obj/effect/landmark/start/medical_doctor, /obj/structure/curtain, @@ -58508,6 +58758,12 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/medical/morgue) +"qpX" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/smooth_large, +/area/station/cargo/miningdock) "qqa" = ( /obj/effect/spawner/random/structure/barricade, /turf/open/floor/iron/smooth, @@ -58808,17 +59064,6 @@ /obj/item/seeds/watermelon/holy, /turf/open/floor/grass, /area/station/service/chapel) -"quF" = ( -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 1 - }, -/obj/effect/turf_decal/loading_area{ - dir = 4 - }, -/obj/structure/extinguisher_cabinet/directional/north, -/obj/effect/landmark/start/shaft_miner, -/turf/open/floor/iron/smooth_edge, -/area/station/cargo/miningdock) "quG" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -59213,6 +59458,23 @@ }, /turf/open/floor/carpet/blue, /area/station/command/bridge) +"qBe" = ( +/obj/machinery/door/airlock/mining{ + name = "Mining Dock" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/disposalpipe/segment, +/obj/effect/mapping_helpers/airlock/access/any/supply/mining, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, +/turf/open/floor/iron/smooth, +/area/station/cargo/miningdock) "qBh" = ( /obj/effect/spawner/random/trash/mopbucket, /obj/effect/decal/cleanable/dirt, @@ -59229,6 +59491,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark/smooth_large, /area/station/command/gateway) +"qBt" = ( +/obj/machinery/netpod, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "qBA" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -61796,6 +62062,18 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/security/prison) +"rnb" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 6 + }, +/obj/structure/trash_pile, +/obj/item/clothing/suit/costume/wellworn_shirt/messy/graphic{ + pixel_x = -5; + pixel_y = 5 + }, +/obj/structure/sign/poster/contraband/random/directional/east, +/turf/open/floor/iron/dark/textured, +/area/station/bitrunning/den) "rne" = ( /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/north, @@ -63094,10 +63372,6 @@ dir = 8 }, /area/station/service/hydroponics) -"rGR" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/smooth_large, -/area/station/cargo/miningdock) "rHc" = ( /obj/effect/turf_decal/trimline/red/filled/line{ dir = 8 @@ -65419,6 +65693,18 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/department/engine/atmos) +"sqL" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/machinery/light/directional/east, +/obj/effect/turf_decal/loading_area{ + dir = 1 + }, +/turf/open/floor/iron/smooth_edge{ + dir = 8 + }, +/area/station/cargo/miningdock) "sqQ" = ( /obj/machinery/power/solar{ id = "aftport"; @@ -70497,6 +70783,25 @@ }, /turf/open/floor/iron/smooth_edge, /area/station/cargo/storage) +"tEI" = ( +/obj/structure/table, +/obj/item/food/ready_donk/mac_n_cheese{ + pixel_y = 3; + pixel_x = 2 + }, +/obj/item/food/ready_donk/nachos_grandes{ + pixel_y = 7 + }, +/obj/item/food/ready_donk/donkhiladas{ + pixel_y = 11; + pixel_x = 1 + }, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 6 + }, +/obj/machinery/airalarm/directional/east, +/turf/open/floor/iron/smooth, +/area/station/bitrunning/den) "tEK" = ( /obj/machinery/atmospherics/pipe/smart/simple/dark/hidden{ dir = 10 @@ -71107,6 +71412,15 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron/white/diagonal, /area/station/medical/medbay/central) +"tOa" = ( +/obj/structure/chair/plastic, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/effect/landmark/start/bitrunner, +/obj/structure/cable, +/turf/open/floor/iron/smooth_large, +/area/station/bitrunning/den) "tOr" = ( /obj/effect/spawner/liquids_spawner, /obj/machinery/light/cold/directional/south, @@ -72023,6 +72337,12 @@ }, /turf/open/floor/iron/smooth_large, /area/station/engineering/atmos) +"ucK" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/smooth_large, +/area/station/cargo/miningdock) "ucR" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -72323,6 +72643,10 @@ /obj/effect/turf_decal/siding/wood{ dir = 9 }, +/obj/item/storage/box/bandages{ + pixel_y = 16; + pixel_x = -6 + }, /turf/open/floor/iron/dark/smooth_large, /area/station/cargo/storage) "uhv" = ( @@ -75333,6 +75657,10 @@ }, /turf/open/floor/catwalk_floor, /area/station/hallway/primary/aft) +"uVw" = ( +/obj/structure/trash_pile, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "uVG" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -76285,13 +76613,6 @@ /obj/machinery/light/small/directional/west, /turf/open/floor/pod/dark, /area/station/service/chapel) -"vkO" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/trimline/brown/filled/corner{ - dir = 1 - }, -/turf/open/floor/iron/smooth_large, -/area/station/cargo/miningdock) "vkT" = ( /obj/structure/table/glass, /obj/effect/turf_decal/tile/blue/full, @@ -76347,10 +76668,10 @@ }, /obj/machinery/requests_console/directional/south{ department = "Engineering"; - name = "Engineering Requests Console"; dir = 4; - pixel_y = 0; - pixel_x = 30 + name = "Engineering Requests Console"; + pixel_x = 30; + pixel_y = 0 }, /obj/effect/mapping_helpers/requests_console/supplies, /obj/effect/mapping_helpers/requests_console/assistance, @@ -76818,6 +77139,22 @@ dir = 8 }, /area/station/hallway/primary/fore) +"vte" = ( +/obj/machinery/door/airlock/mining{ + name = "Bitrunning Den" + }, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/station/cargo/miningdock) "vti" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/preopen{ @@ -77197,6 +77534,11 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/aft/greater) +"vxf" = ( +/obj/machinery/holopad, +/obj/effect/turf_decal/trimline/brown/filled/corner, +/turf/open/floor/iron/smooth_corner, +/area/station/bitrunning/den) "vxv" = ( /mob/living/basic/butterfly, /turf/closed/wall/mineral/iron, @@ -79820,13 +80162,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/smooth, /area/station/science/robotics/mechbay) -"wjo" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/trimline/brown/filled/warning{ - dir = 1 - }, -/turf/open/floor/iron/smooth_large, -/area/station/cargo/miningdock) "wjq" = ( /obj/machinery/camera/directional/east{ c_tag = "Security - Detective's Office" @@ -80873,8 +81208,8 @@ /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ dir = 1; - name = "Exam Room Shutters"; - id = "medexamshutter" + id = "medexamshutter"; + name = "Exam Room Shutters" }, /turf/open/floor/plating, /area/station/medical/exam_room) @@ -82700,6 +83035,11 @@ /obj/machinery/light/cold/directional/west, /turf/open/floor/iron/freezer, /area/station/medical/chemistry) +"wYd" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/curtain/bounty/start_closed, +/turf/open/floor/plating, +/area/station/bitrunning/den) "wYo" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -86243,6 +86583,14 @@ dir = 8 }, /obj/effect/turf_decal/delivery, +/obj/item/storage/box/flashbangs{ + pixel_x = 6; + pixel_y = 6 + }, +/obj/item/storage/box/teargas{ + pixel_x = 6; + pixel_y = -6 + }, /turf/open/floor/engine, /area/station/ai_monitored/security/armory) "ybE" = ( @@ -113302,7 +113650,7 @@ ePK kUZ dYR lxm -fXS +ifS eux iAl wjR @@ -113816,7 +114164,7 @@ qiD kUZ dYR uYT -ejt +fKN pEQ bKZ cUH @@ -125902,7 +126250,7 @@ onP onP onP onP -ihv +nAD vwJ wKg fdP @@ -128980,7 +129328,7 @@ fNX iNa bkF hQq -hWA +qBe odX ipj ekQ @@ -129235,7 +129583,7 @@ xMq oXI ihS cvp -wjo +nqU bcW njG xCF @@ -129492,7 +129840,7 @@ xMq oXI iFV lmY -vkO +krz lon cbP szk @@ -129749,7 +130097,7 @@ xMq oXI oCm jAS -rGR +qpX pmM oXI pjT @@ -130006,7 +130354,7 @@ cbP cbP qtr jAS -rGR +qpX lFU oXI jBq @@ -130262,8 +130610,8 @@ ruV jBM ruV aUO -jAS -fxJ +awG +ucK hkN oXI mXQ @@ -130518,9 +130866,9 @@ ttw cbP cbP cbP -qtr -jAS -jAS +dpw +pws +ucK hwL oXI hwR @@ -130775,9 +131123,9 @@ ttw odJ xMq oXI -quF -nsm -nsm +kkC +pws +hSf llf oXI emO @@ -131033,8 +131381,8 @@ odJ xMq oXI xqM -pRu -baW +sqL +nBO afo oXI pjT @@ -131291,13 +131639,13 @@ xMq oXI oXI oXI +vte oXI oXI -oXI -ttw -ttw -ttw -ttw +qBt +ldU +qBt +cBk ttw ttw xMq @@ -131545,18 +131893,18 @@ xMq xMq xMq xMq -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw +cBk +pqk +nGR +goP +kdS +oUb +dAV +ksB +oxn +wYd +xMq +xMq xMq odJ ttw @@ -131801,17 +132149,17 @@ ttw ttw ttw ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw +xMq +cBk +hjg +hJg +tOa +qgY +fth +iLb +deu +oky +wYd ttw ttw xMq @@ -132056,19 +132404,19 @@ ttw ttw ttw ttw +kUb ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw +xMq +cBk +hKK +kFL +vxf +pFJ +qhU +mTY +jvw +rnb +wYd ttw ttw xMq @@ -132313,21 +132661,21 @@ ttw ttw ttw ttw +kUb ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw +xMq +cBk +cBk +oGX +tEI +cBk +uVw +leF +gWT +cBk +cBk +xMq +xMq xMq odJ ttw @@ -132568,21 +132916,21 @@ ttw ttw ttw ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw +smE +xMq +kUb +xMq +xMq +xMq +cBk +cBk +cBk +cBk +cBk +cBk +cBk +cBk +xMq ttw ttw xMq @@ -132827,21 +133175,21 @@ ttw ttw ttw ttw +kUb ttw ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw +xMq +xMq +xMq +xMq +xMq +xMq +xMq +xMq +xMq +xMq +xMq +xMq xMq odJ ttw @@ -133084,19 +133432,19 @@ ttw ttw ttw ttw +kUb +kUb ttw +xMq ttw ttw +xMq ttw ttw +xMq ttw ttw -ttw -ttw -ttw -ttw -ttw -ttw +xMq ttw ttw xMq @@ -133342,19 +133690,19 @@ ttw ttw ttw ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw -ttw +kUb +kUb +kUb +kUb +kUb +kUb +kUb +kUb +kUb +kUb +kUb +kUb +kUb ttw xMq xqO @@ -133601,16 +133949,16 @@ ttw ttw ttw ttw +xMq ttw ttw +xMq ttw ttw +xMq ttw ttw -ttw -ttw -ttw -ttw +xMq ttw ttw xMq @@ -133858,16 +134206,16 @@ ttw ttw ttw ttw +smE ttw ttw +smE ttw ttw +smE ttw ttw -ttw -ttw -ttw -ttw +smE ttw ttw ttw diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm index a475bd64013..c1740dd6338 100644 --- a/_maps/map_files/debug/runtimestation.dmm +++ b/_maps/map_files/debug/runtimestation.dmm @@ -1763,6 +1763,10 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/science) +"js" = ( +/obj/machinery/quantum_server, +/turf/open/floor/iron, +/area/station/bitrunning/den) "jE" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 8 @@ -2008,6 +2012,10 @@ "wU" = ( /turf/closed/wall/r_wall, /area/station/science/explab) +"yn" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/station/bitrunning/den) "yA" = ( /obj/docking_port/stationary/laborcamp_home{ dir = 8 @@ -2036,12 +2044,21 @@ /obj/machinery/airalarm/directional/north, /turf/open/floor/iron, /area/station/science) +"Ai" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, +/obj/machinery/light/directional/north, +/turf/open/floor/iron, +/area/station/hallway/secondary/entry) "AP" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 8 }, /turf/open/floor/iron, /area/station/science) +"AR" = ( +/turf/open/floor/circuit/green, +/area/station/bitrunning/den) "BD" = ( /obj/structure/closet/secure_closet/chief_medical{ locked = 0 @@ -2058,6 +2075,12 @@ "Ce" = ( /turf/open/floor/iron, /area/station/medical/chemistry) +"Cq" = ( +/obj/machinery/door/airlock, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, +/turf/open/floor/iron, +/area/station/bitrunning/den) "Ct" = ( /obj/structure/closet/syndicate/resources/everything, /turf/open/floor/iron, @@ -2155,6 +2178,10 @@ /obj/effect/mapping_helpers/airalarm/unlocked, /turf/open/floor/iron, /area/station/command/bridge) +"Fk" = ( +/obj/machinery/netpod, +/turf/open/floor/iron, +/area/station/bitrunning/den) "HW" = ( /obj/machinery/airalarm/directional/east, /obj/effect/mapping_helpers/airalarm/unlocked, @@ -2235,6 +2262,9 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron, /area/station/hallway/secondary/entry) +"Ma" = ( +/turf/open/floor/iron, +/area/station/bitrunning/den) "Mh" = ( /obj/structure/cable, /turf/open/floor/iron, @@ -2262,11 +2292,23 @@ /obj/machinery/chem_recipe_debug, /turf/open/floor/iron, /area/station/medical/chemistry) +"Nk" = ( +/obj/structure/table/reinforced, +/obj/machinery/light/directional/south, +/turf/open/floor/iron, +/area/station/bitrunning/den) "Ns" = ( /obj/machinery/door/airlock/public/glass, /obj/structure/cable, /turf/open/floor/iron, /area/station/medical/medbay) +"NQ" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/obj/item/storage/part_replacer/bluespace/tier4, +/turf/open/floor/iron, +/area/station/bitrunning/den) "NZ" = ( /obj/machinery/rnd/production/protolathe/department, /turf/open/floor/iron, @@ -2320,6 +2362,10 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/entry) +"Qs" = ( +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/bitrunning/den) "Qt" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 @@ -2350,6 +2396,11 @@ /obj/effect/turf_decal/tile/blue/half/contrasted, /turf/open/floor/iron, /area/station/command/bridge) +"RS" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, +/turf/open/floor/iron, +/area/station/bitrunning/den) "Sg" = ( /obj/machinery/power/apc/auto_name/directional/west, /obj/effect/turf_decal/stripes/corner, @@ -2391,6 +2442,10 @@ /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 @@ -2425,6 +2480,11 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/main) +"VX" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, +/turf/open/floor/iron, +/area/station/hallway/secondary/entry) "We" = ( /obj/machinery/newscaster/directional/west, /turf/open/floor/iron, @@ -2517,6 +2577,9 @@ }, /turf/open/floor/iron/dark, /area/station/science/explab) +"Yn" = ( +/turf/closed/wall/r_wall, +/area/station/bitrunning/den) "Yy" = ( /obj/machinery/light/directional/north, /obj/machinery/rnd/production/circuit_imprinter/department, @@ -2536,6 +2599,13 @@ /obj/effect/mapping_helpers/airalarm/unlocked, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) +"Zp" = ( +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/cable, +/obj/machinery/airalarm/directional/east, +/obj/machinery/computer/quantum_console, +/turf/open/floor/iron, +/area/station/bitrunning/den) "Zz" = ( /obj/machinery/power/apc/auto_name/directional/west, /obj/effect/turf_decal/stripes/line, @@ -3033,12 +3103,12 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa +Yn +Yn +Yn +Yn +Yn +Yn aa aa aa @@ -3125,12 +3195,12 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa +Yn +UM +AR +Ma +Fk +Yn aa aa aa @@ -3217,12 +3287,12 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa +Yn +UM +AR +Ma +Fk +Yn aa aa aa @@ -3309,12 +3379,12 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa +Yn +js +Ma +NQ +Fk +Yn aa aa aa @@ -3401,12 +3471,12 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa +Yn +Zp +Qs +RS +Nk +Yn aa aa aa @@ -3493,12 +3563,12 @@ em em em em -em -em -em -dY -en -dY +Yn +Yn +Yn +Cq +yn +Yn Tj Tj Tj @@ -3588,7 +3658,7 @@ rK rK vy em -eh +VX eh LW lc @@ -3680,7 +3750,7 @@ qQ qQ ME em -eh +VX eh LW lc @@ -3772,7 +3842,7 @@ qQ qQ ME em -eh +VX eh LW lc @@ -3864,7 +3934,7 @@ qQ qQ CQ em -eh +Ai eh LW lc @@ -3956,7 +4026,7 @@ qQ qQ ME em -eh +VX eh LW lc @@ -4048,7 +4118,7 @@ qQ qQ YL em -eh +VX eh LW lc @@ -4140,7 +4210,7 @@ II gl gD kj -wM +VX wM LW lc diff --git a/_maps/map_files/tramstation/maintenance_modules/barcargoupper_1.dmm b/_maps/map_files/tramstation/maintenance_modules/barcargoupper_1.dmm index a34ab0e6fcf..eab9280b8fa 100644 --- a/_maps/map_files/tramstation/maintenance_modules/barcargoupper_1.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/barcargoupper_1.dmm @@ -1845,10 +1845,10 @@ gb gb gb gb -gb -gb -gb -gb +eJ +eJ +eJ +eJ eJ eJ eJ @@ -1882,10 +1882,10 @@ gb gb gb gb -gb -gb -gb -gb +eJ +eJ +eJ +eJ eJ eJ eJ @@ -1918,7 +1918,7 @@ eJ gb gb gb -eJ +gb eJ eJ eJ diff --git a/_maps/map_files/tramstation/maintenance_modules/barcargoupper_2.dmm b/_maps/map_files/tramstation/maintenance_modules/barcargoupper_2.dmm index f20109536f8..0901318e301 100644 --- a/_maps/map_files/tramstation/maintenance_modules/barcargoupper_2.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/barcargoupper_2.dmm @@ -2000,10 +2000,10 @@ se se se se -se -se -se -se +dx +dx +dx +dx dx dx dx @@ -2037,10 +2037,10 @@ se se se se -se -se -se -se +dx +dx +dx +dx dx dx dx @@ -2073,7 +2073,7 @@ dx se se se -dx +se dx dx dx diff --git a/_maps/map_files/tramstation/maintenance_modules/barcargoupper_3.dmm b/_maps/map_files/tramstation/maintenance_modules/barcargoupper_3.dmm index 63b18a69e75..775e31e6b9d 100644 --- a/_maps/map_files/tramstation/maintenance_modules/barcargoupper_3.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/barcargoupper_3.dmm @@ -1918,10 +1918,10 @@ cK cK cK cK -cK -cK -cK -cK +Hu +Hu +Hu +Hu Hu Hu Hu @@ -1955,10 +1955,10 @@ cK cK cK cK -cK -cK -cK -cK +Hu +Hu +Hu +Hu Hu Hu Hu @@ -1991,7 +1991,7 @@ Hu cK cK cK -Hu +cK Hu Hu Hu diff --git a/_maps/map_files/tramstation/maintenance_modules/barcargoupper_cave_1.dmm b/_maps/map_files/tramstation/maintenance_modules/barcargoupper_cave_1.dmm index 202e850684a..ae78ae6731f 100644 --- a/_maps/map_files/tramstation/maintenance_modules/barcargoupper_cave_1.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/barcargoupper_cave_1.dmm @@ -1079,10 +1079,10 @@ V V V V -V -V -V -V +l +l +l +l l l l @@ -1105,10 +1105,10 @@ V V V V -V -V -V -V +l +l +l +l l l l diff --git a/_maps/map_files/tramstation/maintenance_modules/barcargoupper_cave_2.dmm b/_maps/map_files/tramstation/maintenance_modules/barcargoupper_cave_2.dmm index 939d8bb0aaf..0e8deac0a59 100644 --- a/_maps/map_files/tramstation/maintenance_modules/barcargoupper_cave_2.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/barcargoupper_cave_2.dmm @@ -1013,10 +1013,10 @@ V V l V -V -V -V -V +b +b +b +b b b b @@ -1039,10 +1039,10 @@ V V V V -V -V -V -V +b +b +b +b b b b diff --git a/_maps/map_files/tramstation/maintenance_modules/barcargoupper_cave_3.dmm b/_maps/map_files/tramstation/maintenance_modules/barcargoupper_cave_3.dmm index 5831bc047d3..fb637e9194f 100644 --- a/_maps/map_files/tramstation/maintenance_modules/barcargoupper_cave_3.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/barcargoupper_cave_3.dmm @@ -113,10 +113,6 @@ /obj/effect/turf_decal/sand/plating, /turf/open/floor/plating, /area/station/maintenance/department/cargo) -"y" = ( -/obj/item/gps/mining, -/turf/open/misc/asteroid, -/area/station/asteroid) "z" = ( /obj/item/storage/bag/ore{ pixel_x = 6; @@ -129,6 +125,10 @@ /obj/item/assembly/signaler, /turf/open/misc/asteroid, /area/station/asteroid) +"C" = ( +/obj/item/gps/mining, +/turf/open/misc/asteroid/dug, +/area/station/asteroid) "D" = ( /obj/item/relic, /turf/open/misc/asteroid/dug, @@ -1048,7 +1048,7 @@ b i i I -I +C Y i Y @@ -1100,10 +1100,10 @@ B I I P -y -i -i -i +Q +Q +Q +Q Q Q Q @@ -1126,10 +1126,10 @@ Y Y I Y -i -i -i -i +Q +Q +Q +Q Q Q Q diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 4ef52187a09..7c561db5a62 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -452,18 +452,16 @@ /turf/open/misc/asteroid, /area/station/asteroid) "abN" = ( -/obj/effect/turf_decal/delivery, -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=1"; - location = "QM #6" - }, -/obj/effect/turf_decal/tile/brown/fourcorners, -/mob/living/simple_animal/bot/mulebot{ - home_destination = "QM #6"; - suffix = "#6" +/obj/machinery/firealarm/directional/south, +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/stripes, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 }, -/turf/open/floor/iron, -/area/station/cargo/storage) +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "abO" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -3865,6 +3863,10 @@ /obj/effect/turf_decal/trimline/brown/filled/line{ dir = 8 }, +/obj/effect/landmark/start/bitrunner, +/obj/structure/chair{ + dir = 4 + }, /turf/open/floor/iron, /area/station/cargo/storage) "axG" = ( @@ -9512,6 +9514,18 @@ /obj/effect/turf_decal/tile/brown/fourcorners, /turf/open/floor/iron, /area/station/cargo/sorting) +"cfC" = ( +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/stripes, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "cga" = ( /obj/effect/turf_decal/trimline/neutral/filled/corner{ dir = 8 @@ -10096,7 +10110,7 @@ layer = 3.1; linked_elevator_id = "tram_xeno_lift"; pixel_y = 2; - preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") + preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") }, /turf/closed/wall, /area/station/science/xenobiology) @@ -10723,7 +10737,7 @@ /turf/open/floor/iron, /area/station/engineering/atmos) "cEy" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell{ +/obj/machinery/cryo_cell{ dir = 4 }, /turf/open/floor/iron/dark, @@ -15566,6 +15580,11 @@ /mob/living/simple_animal/bot/cleanbot, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) +"esr" = ( +/obj/machinery/netpod, +/obj/item/radio/intercom/directional/north, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "esA" = ( /obj/machinery/iv_drip, /obj/effect/turf_decal/trimline/blue/filled/line{ @@ -15683,18 +15702,8 @@ /turf/open/floor/wood, /area/station/service/theater) "euR" = ( -/obj/effect/turf_decal/delivery, -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=2"; - location = "QM #3" - }, -/obj/effect/turf_decal/tile/brown/fourcorners, -/mob/living/simple_animal/bot/mulebot{ - home_destination = "QM #3"; - suffix = "#3" - }, -/turf/open/floor/iron, -/area/station/cargo/storage) +/turf/closed/wall, +/area/station/bitrunning/den) "euS" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -16311,6 +16320,15 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron/white, /area/station/science/xenobiology) +"eGU" = ( +/obj/effect/turf_decal/delivery, +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=1"; + location = "QM #4" + }, +/obj/effect/turf_decal/tile/brown/fourcorners, +/turf/open/floor/iron, +/area/station/cargo/warehouse) "eHj" = ( /obj/machinery/vending/tool, /obj/machinery/airalarm/directional/east, @@ -18005,8 +18023,19 @@ /area/station/science/ordnance) "foU" = ( /obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/cargo/storage) +"foV" = ( +/obj/effect/turf_decal/delivery, +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=1"; + location = "QM #5" + }, +/obj/effect/turf_decal/tile/brown/fourcorners, +/turf/open/floor/iron, +/area/station/cargo/warehouse) "foY" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -18643,6 +18672,15 @@ /obj/machinery/light/warm/directional/west, /turf/open/floor/iron, /area/station/cargo/miningdock/cafeteria) +"fDd" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 8 + }, +/obj/structure/chair{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "fDg" = ( /obj/structure/table, /obj/item/clothing/gloves/boxing, @@ -19276,6 +19314,19 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron/freezer, /area/station/commons/toilet) +"fNG" = ( +/obj/effect/turf_decal/delivery, +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=2"; + location = "QM #1" + }, +/obj/effect/turf_decal/tile/brown/fourcorners, +/mob/living/simple_animal/bot/mulebot{ + home_destination = "QM #1"; + suffix = "#1" + }, +/turf/open/floor/iron, +/area/station/cargo/warehouse) "fNR" = ( /obj/structure/closet/lasertag/blue, /obj/effect/landmark/start/hangover/closet, @@ -19678,7 +19729,7 @@ /area/station/security/processing) "fWK" = ( /obj/machinery/computer/atmos_control/oxygen_tank{ - atmos_chambers = list("o2ordance"="Oxygen Supply") + atmos_chambers = list("o2ordance"="Oxygen Supply") }, /obj/effect/turf_decal/stripes/line, /obj/machinery/airalarm/directional/north, @@ -20252,7 +20303,7 @@ }, /obj/machinery/elevator_control_panel/directional/west{ linked_elevator_id = "tram_sci_lift"; - preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") + preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") }, /turf/open/floor/plating/elevatorshaft, /area/station/science/lower) @@ -22348,6 +22399,8 @@ "gUL" = ( /obj/effect/landmark/event_spawn, /obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/storage) "gUO" = ( @@ -22596,6 +22649,15 @@ }, /turf/open/floor/iron, /area/station/command/teleporter) +"haq" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/cargo/storage) "hay" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -23938,7 +24000,6 @@ /obj/effect/turf_decal/siding/thinplating/corner{ dir = 4 }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/cargo/storage) "hDZ" = ( @@ -24725,6 +24786,19 @@ /obj/machinery/telecomms/server/presets/command, /turf/open/floor/iron/dark/telecomms, /area/station/tcommsat/server) +"hSM" = ( +/obj/effect/turf_decal/delivery, +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=1"; + location = "QM #6" + }, +/obj/effect/turf_decal/tile/brown/fourcorners, +/mob/living/simple_animal/bot/mulebot{ + home_destination = "QM #6"; + suffix = "#6" + }, +/turf/open/floor/iron, +/area/station/cargo/warehouse) "hTa" = ( /obj/effect/turf_decal/trimline/neutral/filled/line, /turf/open/floor/iron, @@ -28585,13 +28659,13 @@ /turf/open/floor/iron, /area/station/security/checkpoint/supply) "jnL" = ( -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 1 +/obj/structure/railing{ + layer = 3.1; + dir = 4 }, -/obj/effect/turf_decal/trimline/brown/filled/line, -/obj/machinery/light/small/directional/west, -/turf/open/floor/iron, -/area/station/cargo/storage) +/obj/machinery/netpod, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "jnR" = ( /obj/structure/bed{ dir = 8 @@ -29094,7 +29168,7 @@ /obj/structure/industrial_lift/public, /obj/machinery/elevator_control_panel/directional/west{ linked_elevator_id = "tram_cargo_lift"; - preset_destination_names = list("2"="Lower Deck","3"="Upper Deck"); + preset_destination_names = list("2"="Lower Deck","3"="Upper Deck"); req_access = list("mining") }, /obj/effect/abstract/elevator_music_zone{ @@ -30343,12 +30417,13 @@ /turf/open/floor/iron, /area/station/construction/mining/aux_base) "jTQ" = ( -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/brown/filled/line, -/turf/open/floor/iron, -/area/station/cargo/storage) +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "jUa" = ( /obj/effect/turf_decal/trimline/purple/filled/corner{ dir = 4 @@ -32109,6 +32184,19 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/grimy, /area/station/security/detectives_office) +"kyw" = ( +/obj/effect/turf_decal/delivery, +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=2"; + location = "QM #3" + }, +/obj/effect/turf_decal/tile/brown/fourcorners, +/mob/living/simple_animal/bot/mulebot{ + home_destination = "QM #3"; + suffix = "#3" + }, +/turf/open/floor/iron, +/area/station/cargo/warehouse) "kyF" = ( /obj/structure/table, /obj/item/storage/backpack/duffelbag/sec{ @@ -33508,14 +33596,6 @@ /obj/effect/turf_decal/trimline/neutral/filled/corner, /turf/open/floor/iron, /area/station/hallway/secondary/service) -"kVQ" = ( -/obj/structure/table/glass, -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 1 - }, -/obj/machinery/light/cold/directional/north, -/turf/open/floor/iron/white, -/area/station/security/medical) "kVV" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -34430,6 +34510,7 @@ /area/station/cargo/sorting) "lnh" = ( /obj/machinery/door/poddoor/massdriver_chapel, +/obj/structure/fans/tiny, /turf/open/floor/plating, /area/station/service/chapel/monastery) "lnk" = ( @@ -34953,7 +35034,7 @@ }, /obj/machinery/elevator_control_panel/directional/west{ linked_elevator_id = "tram_perma_lift"; - preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") + preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") }, /turf/open/floor/plating/elevatorshaft, /area/station/security/execution/transfer) @@ -36318,6 +36399,9 @@ /obj/effect/turf_decal/stripes/corner{ dir = 4 }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/storage) "lTP" = ( @@ -37447,6 +37531,8 @@ /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 1 }, +/obj/structure/table, +/obj/machinery/light/dim/directional/north, /turf/open/floor/iron, /area/station/cargo/warehouse) "mng" = ( @@ -37646,14 +37732,26 @@ /turf/open/floor/iron/white, /area/station/medical/storage) "mrg" = ( -/obj/effect/turf_decal/delivery, -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=1"; - location = "QM #4" +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/stripes, +/obj/structure/table/reinforced, +/obj/item/reagent_containers/cup/glass/mug/coco{ + pixel_x = -7; + pixel_y = 7 }, -/obj/effect/turf_decal/tile/brown/fourcorners, -/turf/open/floor/iron, -/area/station/cargo/storage) +/obj/item/reagent_containers/cup/glass/mug/coco{ + pixel_x = -6; + pixel_y = -1 + }, +/obj/item/folder/yellow{ + pixel_x = 5; + pixel_y = 3 + }, +/obj/item/pen{ + pixel_x = 6 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "mrr" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/trimline/neutral/filled/line, @@ -38485,6 +38583,15 @@ /obj/effect/decal/cleanable/blood/old, /turf/open/misc/asteroid/airless, /area/station/asteroid) +"mHT" = ( +/obj/structure/table/glass, +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 1 + }, +/obj/machinery/light/cold/directional/north, +/obj/item/storage/box/bandages, +/turf/open/floor/iron/white, +/area/station/security/medical) "mHX" = ( /obj/effect/turf_decal/trimline/dark_blue/arrow_cw{ dir = 10 @@ -39030,7 +39137,7 @@ }, /obj/machinery/elevator_control_panel/directional/north{ linked_elevator_id = "tram_upper_center_lift"; - preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") + preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") }, /obj/effect/turf_decal/trimline/dark_red/warning{ dir = 1 @@ -39384,6 +39491,24 @@ /obj/effect/turf_decal/trimline/tram/filled/warning, /turf/open/floor/iron, /area/station/hallway/primary/tram/right) +"nbB" = ( +/obj/structure/table, +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 10 + }, +/obj/machinery/power/apc/auto_name/directional/west, +/obj/structure/cable, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = -6 + }, +/obj/item/storage/box/bodybags{ + pixel_x = 3; + pixel_y = 2 + }, +/obj/item/reagent_containers/syringe, +/turf/open/floor/iron/white, +/area/station/medical/medbay/lobby) "nbF" = ( /obj/machinery/power/apc/auto_name/directional/west, /obj/structure/cable, @@ -39610,14 +39735,15 @@ /turf/open/floor/iron, /area/station/maintenance/tram/right) "nfZ" = ( -/obj/effect/turf_decal/delivery, -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=1"; - location = "QM #5" +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/stripes, +/obj/effect/turf_decal/siding/thinplating_new/dark/corner{ + dir = 1 }, -/obj/effect/turf_decal/tile/brown/fourcorners, -/turf/open/floor/iron, -/area/station/cargo/storage) +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "ngg" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden, /obj/effect/spawner/structure/window/reinforced, @@ -40578,6 +40704,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/catwalk_floor, /area/station/maintenance/tram/left) +"nvF" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/station/bitrunning/den) "nvH" = ( /obj/effect/turf_decal/trimline/neutral/filled/corner{ dir = 4 @@ -41917,18 +42047,16 @@ /turf/open/floor/iron/white, /area/station/science/lobby) "nUF" = ( -/obj/effect/turf_decal/delivery, -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=2"; - location = "QM #1" - }, -/obj/effect/turf_decal/tile/brown/fourcorners, -/mob/living/simple_animal/bot/mulebot{ - home_destination = "QM #1"; - suffix = "#1" +/obj/effect/turf_decal/box/corners, +/obj/effect/turf_decal/box/corners{ + dir = 4 }, -/turf/open/floor/iron, -/area/station/cargo/storage) +/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" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -42083,7 +42211,6 @@ /obj/effect/turf_decal/siding/thinplating{ dir = 4 }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/cargo/storage) "nXn" = ( @@ -42998,6 +43125,13 @@ }, /turf/open/floor/engine, /area/station/engineering/supermatter) +"ooe" = ( +/obj/machinery/computer/quantum_console{ + dir = 1 + }, +/obj/machinery/light/directional/south, +/turf/open/floor/iron/dark/smooth_corner, +/area/station/bitrunning/den) "oog" = ( /obj/machinery/disposal/bin, /obj/effect/turf_decal/trimline/yellow/filled/line{ @@ -43555,6 +43689,19 @@ /obj/effect/turf_decal/sand/plating, /turf/open/floor/catwalk_floor, /area/station/solars/starboard/fore) +"oAi" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 8 + }, +/obj/machinery/door/airlock/mining/glass{ + name = "MULE Storage" + }, +/obj/effect/mapping_helpers/airlock/access/all/supply/general, +/turf/open/floor/iron, +/area/station/cargo/warehouse) "oAn" = ( /obj/machinery/airlock_sensor/incinerator_ordmix{ pixel_x = 23; @@ -43944,7 +44091,7 @@ layer = 3.1; linked_elevator_id = "tram_xeno_lift"; pixel_y = 2; - preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") + preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") }, /turf/closed/wall/r_wall, /area/station/science/xenobiology) @@ -44098,6 +44245,15 @@ }, /turf/open/space/openspace, /area/station/solars/port) +"oOP" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/cargo/warehouse) "oOT" = ( /obj/structure/table/wood, /obj/item/food/grown/poppy{ @@ -44770,6 +44926,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/security/courtroom) +"pcI" = ( +/obj/machinery/quantum_server, +/obj/effect/turf_decal/bot/left, +/turf/open/floor/iron/dark/smooth_corner{ + dir = 4 + }, +/area/station/bitrunning/den) "pcO" = ( /obj/effect/turf_decal/bot_white, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -45260,18 +45423,19 @@ /turf/open/floor/plating, /area/station/commons/vacant_room) "plH" = ( -/obj/effect/turf_decal/delivery, -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=2"; - location = "QM #2" +/obj/effect/turf_decal/box/corners{ + dir = 8 }, -/obj/effect/turf_decal/tile/brown/fourcorners, -/mob/living/simple_animal/bot/mulebot{ - home_destination = "QM #2"; - suffix = "#2" +/obj/effect/turf_decal/box/corners{ + dir = 1 }, -/turf/open/floor/iron, -/area/station/cargo/storage) +/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, +/turf/open/floor/iron/dark/smooth_large, +/area/station/bitrunning/den) "plQ" = ( /obj/effect/turf_decal/trimline/red/filled/corner, /obj/structure/disposalpipe/segment{ @@ -45824,6 +45988,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/security/courtroom/holding) +"puo" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 8 + }, +/obj/machinery/light/small/directional/north, +/turf/open/floor/iron, +/area/station/cargo/warehouse) "pur" = ( /obj/effect/turf_decal/trimline/white/line{ dir = 9 @@ -47104,8 +47278,6 @@ dir = 1 }, /obj/effect/decal/cleanable/dirt, -/obj/structure/table, -/obj/machinery/light/dim/directional/north, /turf/open/floor/iron, /area/station/cargo/warehouse) "pOQ" = ( @@ -51650,6 +51822,9 @@ /obj/effect/turf_decal/trimline/brown/filled/line{ dir = 8 }, +/obj/machinery/computer/order_console/bitrunning{ + dir = 4 + }, /turf/open/floor/iron, /area/station/cargo/storage) "rws" = ( @@ -52041,6 +52216,19 @@ /obj/machinery/airalarm/directional/west, /turf/open/floor/iron/dark, /area/station/engineering/supermatter/room) +"rEX" = ( +/obj/effect/turf_decal/delivery, +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=2"; + location = "QM #2" + }, +/obj/effect/turf_decal/tile/brown/fourcorners, +/mob/living/simple_animal/bot/mulebot{ + home_destination = "QM #2"; + suffix = "#2" + }, +/turf/open/floor/iron, +/area/station/cargo/warehouse) "rFW" = ( /obj/effect/turf_decal/delivery/white, /obj/structure/holosign/barrier/atmos/tram, @@ -57052,7 +57240,9 @@ /turf/open/floor/iron/freezer, /area/station/security/prison/shower) "tte" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, /turf/open/floor/iron, /area/station/cargo/storage) "tth" = ( @@ -57274,20 +57464,6 @@ }, /turf/open/floor/iron/cafeteria, /area/station/science/breakroom) -"twW" = ( -/obj/structure/table, -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 10 - }, -/obj/item/storage/box/bodybags{ - pixel_x = 3; - pixel_y = 2 - }, -/obj/item/reagent_containers/syringe, -/obj/machinery/power/apc/auto_name/directional/west, -/obj/structure/cable, -/turf/open/floor/iron/white, -/area/station/medical/medbay/lobby) "txh" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -60114,7 +60290,7 @@ /obj/structure/industrial_lift/public, /obj/machinery/elevator_control_panel/directional/east{ linked_elevator_id = "tram_lower_center_lift"; - preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") + preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") }, /turf/open/floor/plating/elevatorshaft, /area/station/maintenance/tram/mid) @@ -61646,7 +61822,7 @@ /obj/structure/industrial_lift/public, /obj/machinery/elevator_control_panel/directional/south{ linked_elevator_id = "tram_dorm_lift"; - preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") + preset_destination_names = list("2"="Lower Deck","3"="Upper Deck") }, /obj/structure/railing, /turf/open/floor/plating/elevatorshaft, @@ -65108,6 +65284,16 @@ /obj/structure/sign/calendar/directional/east, /turf/open/floor/iron/cafeteria, /area/station/science/breakroom) +"wdw" = ( +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/decal/cleanable/generic, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "wdC" = ( /obj/effect/turf_decal/sand/plating, /turf/open/floor/plating, @@ -67187,6 +67373,11 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/atmos/pumproom) +"wUA" = ( +/obj/machinery/netpod, +/obj/machinery/airalarm/directional/north, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/bitrunning/den) "wUL" = ( /obj/machinery/status_display/evac/directional/north, /obj/machinery/fax{ @@ -68863,16 +69054,19 @@ /turf/closed/wall, /area/station/security/processing) "xDW" = ( -/obj/machinery/door/airlock/mining/glass{ - name = "MULE Storage" - }, /obj/effect/turf_decal/trimline/brown/filled/line{ dir = 1 }, /obj/effect/turf_decal/trimline/brown/filled/line, -/obj/effect/mapping_helpers/airlock/access/all/supply/general, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/airlock/mining/glass{ + name = "Bitrunning Den" + }, +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den, /turf/open/floor/iron, -/area/station/cargo/storage) +/area/station/bitrunning/den) "xDY" = ( /obj/structure/railing{ dir = 8 @@ -69427,6 +69621,17 @@ }, /turf/open/floor/iron, /area/station/security/checkpoint/supply) +"xPI" = ( +/obj/effect/turf_decal/trimline/brown/line, +/obj/effect/turf_decal/stripes, +/obj/effect/turf_decal/siding/thinplating_new/dark{ + dir = 1 + }, +/obj/structure/extinguisher_cabinet/directional/west, +/obj/effect/decal/cleanable/oil/streak, +/obj/effect/landmark/start/bitrunner, +/turf/open/floor/iron/dark/textured_large, +/area/station/bitrunning/den) "xPN" = ( /obj/structure/closet/lasertag/blue, /obj/effect/turf_decal/tile/blue/full, @@ -150947,7 +151152,7 @@ aBK dkO dta mjM -kVQ +mHT vRy gbr kMR @@ -167441,7 +167646,7 @@ kiN xJA gHh cen -twW +nbB iZh dyI tDP @@ -178710,10 +178915,10 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa +euR +euR +euR +euR cTU cTU cTU @@ -178967,10 +179172,10 @@ aaa aaa aaa aaa -aaa -aaa -aaa -aaa +euR +wUA +xPI +ooe cTU vSI vSI @@ -179223,11 +179428,11 @@ aac aaa aaa aaa -cTU -cTU -cTU -cTU -cTU +aaa +euR +esr +cfC +pcI cTU vSI vSI @@ -179480,7 +179685,7 @@ aaa aaa aaa aaa -cTU +euR euR jnL abN @@ -179737,9 +179942,9 @@ aac aaa aaa aaa -cTU +euR plH -jTQ +wdw nfZ cTU exr @@ -179994,7 +180199,7 @@ aac aac aaa aaa -cTU +euR nUF jTQ mrg @@ -180251,10 +180456,10 @@ aac aaa aaa cTU -cTU -ohS +euR +nvF xDW -ohS +nvF cTU nnb pZA @@ -180512,7 +180717,7 @@ blx tAJ lTM axF -axF +fDd rwo dij uax @@ -180767,11 +180972,11 @@ aaa akr tjS hFV -gDr -uax -uax -uax -uax +haq +dzw +dzw +dzw +dzw gUL foU dzw @@ -183334,10 +183539,10 @@ aac aac aac aac -cTU -cTU -cTU -cTU +udQ +udQ +udQ +udQ udQ mmX pxD @@ -183591,10 +183796,10 @@ aac aac aac aac -aac -aac -aaa -aaa +udQ +hSM +foV +eGU udQ fBJ pxD @@ -183848,11 +184053,11 @@ aac aac aac aac -aac -aaa -aaa -aaa udQ +puo +oOP +oOP +oAi pOL kXr aye @@ -184105,10 +184310,10 @@ aac aac aac aac -aaa -aaa -aaa -aaa +udQ +rEX +kyw +fNG udQ kSa cDP @@ -184362,10 +184567,10 @@ aac aac aac aac -aac -aaa -aaa -aaa +udQ +udQ +udQ +udQ udQ aWL tft diff --git a/_maps/safehouses/README.md b/_maps/safehouses/README.md new file mode 100644 index 00000000000..8027ea38e21 --- /dev/null +++ b/_maps/safehouses/README.md @@ -0,0 +1,17 @@ +# Safe House + +## Creating a new safe house + +1. Create a new map inside the `_maps\safe_houses` folder using the TGM format. +2. Create a new dm file inside `modules\bitrunning\virtual_domain\safe_houses` folder.. +4. Place exit and goal landmarks (obj/effect/landmark/bitrunning/..). Generally, 3 exits and 2 goals are ok. +5. Ideally, leave 3 spaces for gear. This has usually been xy [1x1] [1x2] [1x3] + +## Notes + +- Safe houses are intended to be 7x6 in size. You're not technically limited to this, but consider maps other maps might be using this size if you want it to be modular. +- Consider that avatars are not invincible and still require air. If you're making a safe house, it should start with an area that accommodates for this. +- For compatibility, your safe house should have a route open from the top center xy [3x0] of the map. +- If you want a custom safehouse for a custom map with no modularity, no problem. Make whatever sizes you want, just ensure there are exit and goal effects placed. +- Some maps can alter what is spawned into the safehouse by placing objects in the safehouse area. I'm using the left corner, starting from the top, for things like space gear. + diff --git a/_maps/safehouses/TEMPLATES/TEMPLATE.dmm b/_maps/safehouses/TEMPLATES/TEMPLATE.dmm new file mode 100644 index 00000000000..c8e5059f0d0 --- /dev/null +++ b/_maps/safehouses/TEMPLATES/TEMPLATE.dmm @@ -0,0 +1,82 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"c" = ( +/obj/effect/mapping_helpers/airlock/access/all, +/obj/machinery/door/airlock/external/glass, +/obj/structure/fans/tiny, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"p" = ( +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"v" = ( +/obj/effect/bitrunning/exit_spawn, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"N" = ( +/obj/effect/bitrunning/goal_turf, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"R" = ( +/turf/closed/wall, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +R +R +a +a +R +R +"} +(2,1,1) = {" +a +p +p +p +p +R +"} +(3,1,1) = {" +R +p +p +p +v +a +"} +(4,1,1) = {" +c +p +p +p +v +R +"} +(5,1,1) = {" +R +p +p +p +v +a +"} +(6,1,1) = {" +a +p +N +N +p +R +"} +(7,1,1) = {" +R +R +a +a +R +R +"} diff --git a/_maps/safehouses/den.dmm b/_maps/safehouses/den.dmm new file mode 100644 index 00000000000..235d786d6e9 --- /dev/null +++ b/_maps/safehouses/den.dmm @@ -0,0 +1,224 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/structure/chair/office{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/small/directional/south, +/turf/open/floor/pod, +/area/virtual_domain/safehouse) +"c" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/small/directional/east, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"e" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/effect/spawner/random/food_or_drink/snack{ + pixel_x = 4; + pixel_y = 2 + }, +/turf/open/floor/pod/dark, +/area/virtual_domain/safehouse) +"i" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 1; + id = "safehouseshutter" + }, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"l" = ( +/obj/structure/railing/corner/end{ + dir = 4 + }, +/turf/open/floor/pod/dark, +/area/virtual_domain/safehouse) +"p" = ( +/turf/open/floor/pod, +/area/virtual_domain/safehouse) +"r" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 9 + }, +/turf/open/floor/pod/dark, +/area/virtual_domain/safehouse) +"u" = ( +/obj/structure/railing, +/obj/effect/turf_decal/siding/dark, +/obj/structure/sign/poster/contraband/hacking_guide/directional/east, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"z" = ( +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 4 + }, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/pod/light, +/area/virtual_domain/safehouse) +"C" = ( +/turf/closed/wall, +/area/virtual_domain/safehouse) +"D" = ( +/obj/effect/decal/cleanable/generic, +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 1 + }, +/turf/open/floor/pod, +/area/virtual_domain/safehouse) +"E" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 8 + }, +/obj/effect/decal/cleanable/generic, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/pod/light, +/area/virtual_domain/safehouse) +"G" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; + id = "safehouseshutter" + }, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"I" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 5 + }, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/pod/light, +/area/virtual_domain/safehouse) +"J" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 8; + id = "safehouseshutter" + }, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"K" = ( +/obj/effect/spawner/random/vending/colavend, +/obj/machinery/light/small/directional/south, +/turf/open/floor/pod, +/area/virtual_domain/safehouse) +"M" = ( +/turf/open/floor/pod/dark, +/area/virtual_domain/safehouse) +"O" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 8 + }, +/turf/open/floor/pod/dark, +/area/virtual_domain/safehouse) +"R" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 4 + }, +/turf/open/floor/pod/dark, +/area/virtual_domain/safehouse) +"U" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/sign/departments/cargo/directional/west, +/obj/machinery/light/small/directional/west, +/turf/open/floor/pod, +/area/virtual_domain/safehouse) +"W" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "safehouseshutter" + }, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"X" = ( +/obj/machinery/door/airlock/grunge, +/obj/structure/fans/tiny, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"Y" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/machinery/button/door{ + pixel_x = 4; + pixel_y = 4; + id = "safehouseshutter" + }, +/obj/effect/spawner/random/food_or_drink/refreshing_beverage{ + pixel_y = 6; + pixel_x = -10 + }, +/turf/open/floor/pod/dark, +/area/virtual_domain/safehouse) +"Z" = ( +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 4 + }, +/turf/open/floor/pod/dark, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +C +C +C +G +G +C +"} +(2,1,1) = {" +W +U +p +M +K +C +"} +(3,1,1) = {" +C +r +O +O +E +i +"} +(4,1,1) = {" +X +D +Z +R +z +i +"} +(5,1,1) = {" +C +M +l +e +I +i +"} +(6,1,1) = {" +W +c +u +Y +a +C +"} +(7,1,1) = {" +C +C +C +J +J +C +"} diff --git a/_maps/safehouses/dig.dmm b/_maps/safehouses/dig.dmm new file mode 100644 index 00000000000..7fbbd3e5549 --- /dev/null +++ b/_maps/safehouses/dig.dmm @@ -0,0 +1,165 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/turf_decal/sand/plating, +/obj/effect/turf_decal/siding/yellow/corner, +/obj/effect/turf_decal/sand/plating, +/obj/item/flashlight/glowstick{ + on = 1 + }, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"c" = ( +/obj/effect/turf_decal/siding/yellow/corner{ + dir = 8 + }, +/turf/open/misc/asteroid, +/area/virtual_domain/safehouse) +"h" = ( +/obj/effect/turf_decal/loading_area, +/obj/effect/turf_decal/box/corners{ + dir = 8 + }, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"i" = ( +/obj/effect/turf_decal/siding/yellow{ + dir = 8 + }, +/obj/effect/decal/remains/xeno/larva, +/turf/open/misc/asteroid, +/area/virtual_domain/safehouse) +"l" = ( +/obj/structure/table, +/obj/item/coin/gold{ + pixel_x = -6; + pixel_y = 2 + }, +/obj/item/flashlight/lantern{ + pixel_y = 8; + pixel_x = 4; + on = 1 + }, +/turf/open/misc/asteroid, +/area/virtual_domain/safehouse) +"o" = ( +/obj/effect/turf_decal/siding/yellow{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/misc/asteroid, +/area/virtual_domain/safehouse) +"u" = ( +/obj/effect/turf_decal/siding/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/siding/yellow, +/obj/effect/decal/cleanable/oil/streak, +/turf/open/misc/asteroid, +/area/virtual_domain/safehouse) +"x" = ( +/obj/effect/turf_decal/sand/plating, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"A" = ( +/turf/closed/wall/rock, +/area/virtual_domain/safehouse) +"B" = ( +/turf/open/misc/asteroid, +/area/virtual_domain/safehouse) +"H" = ( +/turf/closed/mineral/asteroid, +/area/virtual_domain/safehouse) +"I" = ( +/obj/machinery/door/airlock/maintenance/glass, +/obj/structure/fans/tiny, +/obj/effect/turf_decal/sand/plating, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"M" = ( +/obj/effect/turf_decal/siding/yellow, +/obj/effect/decal/remains/xeno, +/turf/open/misc/asteroid, +/area/virtual_domain/safehouse) +"N" = ( +/obj/effect/turf_decal/sand/plating, +/obj/effect/turf_decal/sand/plating, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"S" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/effect/turf_decal/loading_area, +/obj/effect/turf_decal/box/corners, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"T" = ( +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/misc/asteroid, +/area/virtual_domain/safehouse) +"U" = ( +/obj/effect/turf_decal/siding/yellow{ + dir = 8 + }, +/turf/open/misc/asteroid, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +H +H +A +A +H +H +"} +(2,1,1) = {" +A +N +x +a +H +A +"} +(3,1,1) = {" +A +i +U +u +h +A +"} +(4,1,1) = {" +I +B +B +M +S +A +"} +(5,1,1) = {" +A +l +B +c +o +H +"} +(6,1,1) = {" +A +A +T +T +T +A +"} +(7,1,1) = {" +H +A +H +H +A +A +"} diff --git a/_maps/safehouses/ice.dmm b/_maps/safehouses/ice.dmm new file mode 100644 index 00000000000..a8293f9502a --- /dev/null +++ b/_maps/safehouses/ice.dmm @@ -0,0 +1,254 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/spawner/structure/window/ice, +/turf/open/floor/plating/snowed, +/area/virtual_domain/safehouse) +"c" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 6 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/small/directional/east, +/obj/structure/chair/wood{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"f" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/snowed, +/area/virtual_domain/safehouse) +"g" = ( +/obj/effect/spawner/structure/window/ice, +/obj/structure/barricade/wooden/crude/snow, +/turf/open/floor/plating/snowed, +/area/virtual_domain/safehouse) +"i" = ( +/turf/closed/wall/ice, +/area/virtual_domain/safehouse) +"m" = ( +/obj/effect/turf_decal/weather/snow/corner, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/trimline/dark_blue/line{ + dir = 1 + }, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/pod, +/area/virtual_domain/safehouse) +"n" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/rack, +/obj/item/grown/log, +/obj/item/grown/log, +/obj/item/grown/log, +/obj/item/hatchet/wooden, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"o" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"p" = ( +/obj/structure/railing, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"u" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"v" = ( +/obj/effect/turf_decal/weather/snow/corner, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/trimline/dark_blue/line{ + dir = 5 + }, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/pod, +/area/virtual_domain/safehouse) +"x" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/vending/coffee, +/turf/open/floor/plating/snowed, +/area/virtual_domain/safehouse) +"z" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/generic, +/turf/open/floor/plating/snowed, +/area/virtual_domain/safehouse) +"A" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/obj/structure/railing/corner/end{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/snowed, +/area/virtual_domain/safehouse) +"B" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/snowed, +/area/virtual_domain/safehouse) +"C" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/obj/structure/table/wood, +/obj/item/reagent_containers/cup/glass/coffee{ + pixel_x = 7; + pixel_y = 13 + }, +/obj/item/reagent_containers/cup/glass/coffee/no_lid{ + pixel_x = -4; + pixel_y = 14 + }, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"D" = ( +/obj/effect/turf_decal/weather/snow/corner, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/generic, +/obj/effect/turf_decal/trimline/dark_blue/line{ + dir = 9 + }, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/pod, +/area/virtual_domain/safehouse) +"I" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"L" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 9 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/small/directional/west, +/obj/machinery/smartfridge/drying_rack, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"O" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/door/airlock/freezer, +/obj/structure/fans/tiny, +/turf/open/floor/plating/snowed, +/area/virtual_domain/safehouse) +"S" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 5 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/table/wood, +/obj/item/trash/chips{ + pixel_x = 8; + pixel_y = 15 + }, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"W" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/closet/crate/internals, +/obj/item/tank/internals/oxygen, +/obj/item/tank/internals/oxygen, +/obj/item/tank/internals/oxygen, +/obj/item/clothing/mask/breath, +/obj/item/clothing/mask/breath, +/obj/item/clothing/mask/breath, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"Z" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 10 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +i +i +g +a +i +i +"} +(2,1,1) = {" +i +L +n +W +Z +i +"} +(3,1,1) = {" +a +x +u +I +D +i +"} +(4,1,1) = {" +O +z +B +I +m +i +"} +(5,1,1) = {" +a +f +A +C +v +i +"} +(6,1,1) = {" +i +o +p +S +c +i +"} +(7,1,1) = {" +i +i +g +g +i +i +"} diff --git a/_maps/safehouses/lavaland_boss.dmm b/_maps/safehouses/lavaland_boss.dmm new file mode 100644 index 00000000000..7482846e61f --- /dev/null +++ b/_maps/safehouses/lavaland_boss.dmm @@ -0,0 +1,243 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/turf_decal/trimline/brown/filled/line, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 1 + }, +/area/virtual_domain/safehouse) +"f" = ( +/turf/closed/wall, +/area/virtual_domain/safehouse) +"p" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 5 + }, +/obj/structure/tank_dispenser/oxygen, +/turf/open/floor/iron/dark, +/area/virtual_domain/safehouse) +"v" = ( +/obj/structure/table, +/obj/item/borg/upgrade/modkit/damage{ + pixel_x = 8; + pixel_y = 8 + }, +/obj/item/borg/upgrade/modkit/damage{ + pixel_y = 4; + pixel_x = 8 + }, +/obj/item/borg/upgrade/modkit/damage{ + pixel_x = 8 + }, +/obj/item/borg/upgrade/modkit/range{ + pixel_y = 8 + }, +/obj/item/borg/upgrade/modkit/range{ + pixel_y = 4 + }, +/obj/item/borg/upgrade/modkit/range, +/obj/item/borg/upgrade/modkit/cooldown{ + pixel_x = -8; + pixel_y = 8 + }, +/obj/item/borg/upgrade/modkit/cooldown{ + pixel_x = -8; + pixel_y = 4 + }, +/obj/item/borg/upgrade/modkit/cooldown{ + pixel_x = -8 + }, +/obj/item/reagent_containers/hypospray/medipen/survival/luxury{ + pixel_x = 6; + pixel_y = 6 + }, +/obj/item/reagent_containers/hypospray/medipen/survival/luxury{ + pixel_x = 6 + }, +/turf/open/floor/iron/dark/textured_large, +/area/virtual_domain/safehouse) +"w" = ( +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/obj/machinery/light/directional/east, +/obj/structure/railing, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"A" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 1 + }, +/obj/structure/extinguisher_cabinet/directional/north, +/turf/open/floor/iron/dark/smooth_edge, +/area/virtual_domain/safehouse) +"B" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 10 + }, +/obj/structure/table, +/obj/item/flashlight/lantern{ + pixel_x = 8; + pixel_y = null + }, +/obj/item/flashlight/lantern{ + pixel_y = 4 + }, +/obj/item/flashlight/lantern{ + pixel_x = -8; + pixel_y = 8 + }, +/obj/item/clothing/glasses/meson/night, +/obj/item/clothing/glasses/meson/night, +/obj/item/clothing/glasses/meson/night, +/turf/open/floor/iron/dark, +/area/virtual_domain/safehouse) +"C" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/structure/closet, +/obj/item/gun/ballistic/rocketlauncher/unrestricted, +/obj/item/ammo_casing/rocket, +/obj/item/ammo_casing/rocket, +/obj/item/ammo_casing/rocket, +/obj/item/energy_katana, +/obj/item/ammo_box/magazine/m7mm, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 8 + }, +/area/virtual_domain/safehouse) +"H" = ( +/obj/machinery/door/airlock/external/glass{ + name = "Mining External Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all, +/obj/structure/fans/tiny, +/turf/open/floor/iron/dark/textured_large, +/area/virtual_domain/safehouse) +"K" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 1 + }, +/turf/open/floor/iron/dark/smooth_edge, +/area/virtual_domain/safehouse) +"O" = ( +/obj/item/gun/energy/recharge/kinetic_accelerator{ + pixel_x = -6; + pixel_y = 6 + }, +/obj/item/gun/energy/recharge/kinetic_accelerator{ + pixel_x = -1; + pixel_y = 1 + }, +/obj/item/gun/energy/recharge/kinetic_accelerator{ + pixel_x = 4; + pixel_y = -4 + }, +/obj/structure/closet, +/obj/item/kinetic_crusher, +/obj/item/kinetic_crusher, +/turf/open/floor/iron/dark/textured_large, +/area/virtual_domain/safehouse) +"P" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"S" = ( +/turf/open/floor/iron/dark/textured_large, +/area/virtual_domain/safehouse) +"T" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 6 + }, +/obj/structure/sign/departments/cargo/directional/south, +/obj/structure/closet, +/obj/item/gun/ballistic/automatic/l6_saw/unrestricted, +/obj/item/ammo_box/magazine/sniper_rounds, +/obj/item/gun/ballistic/rifle/sniper_rifle, +/turf/open/floor/iron/dark, +/area/virtual_domain/safehouse) +"X" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 8 + }, +/obj/machinery/suit_storage_unit/mining, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 4 + }, +/area/virtual_domain/safehouse) +"Y" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 8 + }, +/obj/machinery/suit_storage_unit/mining, +/obj/machinery/light/directional/west, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 4 + }, +/area/virtual_domain/safehouse) +"Z" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 9 + }, +/obj/machinery/suit_storage_unit/mining, +/turf/open/floor/iron/dark, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +f +f +f +P +P +f +"} +(2,1,1) = {" +P +Z +Y +X +B +f +"} +(3,1,1) = {" +f +A +S +S +a +P +"} +(4,1,1) = {" +H +K +O +v +a +P +"} +(5,1,1) = {" +f +A +S +S +a +P +"} +(6,1,1) = {" +P +p +w +C +T +f +"} +(7,1,1) = {" +f +f +f +P +P +f +"} diff --git a/_maps/safehouses/mine.dmm b/_maps/safehouses/mine.dmm new file mode 100644 index 00000000000..551e2ca0c00 --- /dev/null +++ b/_maps/safehouses/mine.dmm @@ -0,0 +1,164 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/turf_decal/trimline/brown/filled/line, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 1 + }, +/area/virtual_domain/safehouse) +"f" = ( +/turf/closed/wall, +/area/virtual_domain/safehouse) +"p" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 5 + }, +/obj/structure/tank_dispenser/oxygen, +/turf/open/floor/iron/dark, +/area/virtual_domain/safehouse) +"w" = ( +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/obj/machinery/light/directional/east, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"B" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 10 + }, +/obj/structure/table, +/obj/item/flashlight/lantern{ + pixel_x = 8; + pixel_y = null + }, +/obj/item/flashlight/lantern{ + pixel_y = 4 + }, +/obj/item/flashlight/lantern{ + pixel_x = -8; + pixel_y = 8 + }, +/turf/open/floor/iron/dark, +/area/virtual_domain/safehouse) +"C" = ( +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/obj/structure/railing, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"H" = ( +/obj/machinery/door/airlock/external/glass{ + name = "Mining External Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all, +/obj/structure/fans/tiny, +/turf/open/floor/iron/dark/textured_large, +/area/virtual_domain/safehouse) +"K" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 1 + }, +/turf/open/floor/iron/dark/smooth_edge, +/area/virtual_domain/safehouse) +"P" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"S" = ( +/turf/open/floor/iron/dark/textured_large, +/area/virtual_domain/safehouse) +"T" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 6 + }, +/obj/item/kirbyplants/random, +/obj/structure/sign/departments/cargo/directional/south, +/turf/open/floor/iron/dark, +/area/virtual_domain/safehouse) +"X" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 8 + }, +/obj/machinery/suit_storage_unit/mining, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 4 + }, +/area/virtual_domain/safehouse) +"Y" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 8 + }, +/obj/machinery/suit_storage_unit/mining, +/obj/machinery/light/directional/west, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 4 + }, +/area/virtual_domain/safehouse) +"Z" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 9 + }, +/obj/machinery/suit_storage_unit/mining, +/turf/open/floor/iron/dark, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +f +f +f +P +P +f +"} +(2,1,1) = {" +P +Z +Y +X +B +f +"} +(3,1,1) = {" +f +K +S +S +a +P +"} +(4,1,1) = {" +H +K +S +S +a +P +"} +(5,1,1) = {" +f +K +S +S +a +P +"} +(6,1,1) = {" +P +p +w +C +T +f +"} +(7,1,1) = {" +f +f +f +P +P +f +"} diff --git a/_maps/safehouses/shuttle.dmm b/_maps/safehouses/shuttle.dmm new file mode 100644 index 00000000000..92228c95bd3 --- /dev/null +++ b/_maps/safehouses/shuttle.dmm @@ -0,0 +1,228 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/wall/mineral/titanium, +/area/virtual_domain/safehouse) +"e" = ( +/obj/effect/spawner/structure/window/reinforced/shuttle, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"f" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"g" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/obj/effect/turf_decal/loading_area, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"i" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"k" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/obj/structure/table/reinforced, +/obj/effect/decal/cleanable/dirt, +/obj/item/storage/toolbox/emergency, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"l" = ( +/obj/machinery/light/small/directional/south, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/obj/effect/turf_decal/loading_area, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"q" = ( +/obj/effect/turf_decal/stripes/end, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"r" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"t" = ( +/obj/machinery/power/shuttle_engine/propulsion/burst{ + dir = 8 + }, +/obj/structure/window/reinforced/spawner/directional/east, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/plating/airless, +/area/virtual_domain/safehouse) +"u" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/stripes/line, +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"x" = ( +/obj/effect/turf_decal/tile/neutral/half/contrasted, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/light/small/directional/north, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"y" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/door/airlock/shuttle/glass, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/sand/volcanic, +/obj/structure/fans/tiny, +/turf/open/floor/iron/white, +/area/virtual_domain/safehouse) +"A" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/computer{ + dir = 8; + name = "shuttle console"; + icon_screen = "shuttle" + }, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"E" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/obj/effect/decal/cleanable/generic, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"G" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/machinery/light/small/directional/south, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"H" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"I" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/structure/table/reinforced, +/obj/item/tank/internals/emergency_oxygen{ + pixel_x = 3 + }, +/obj/item/clothing/mask/gas, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"L" = ( +/obj/effect/turf_decal/stripes/end{ + dir = 1 + }, +/obj/effect/turf_decal/sand/volcanic, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"M" = ( +/obj/effect/turf_decal/tile/neutral/half/contrasted, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/light/small/directional/north, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"T" = ( +/obj/effect/turf_decal/tile/neutral/half/contrasted{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"X" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +a +t +e +e +t +a +"} +(2,1,1) = {" +e +L +i +q +l +a +"} +(3,1,1) = {" +a +x +r +u +g +e +"} +(4,1,1) = {" +y +f +r +H +E +a +"} +(5,1,1) = {" +a +M +X +H +T +e +"} +(6,1,1) = {" +e +k +A +I +G +a +"} +(7,1,1) = {" +a +a +e +e +a +a +"} diff --git a/_maps/safehouses/shuttle_space.dmm b/_maps/safehouses/shuttle_space.dmm new file mode 100644 index 00000000000..a5afaa475c6 --- /dev/null +++ b/_maps/safehouses/shuttle_space.dmm @@ -0,0 +1,231 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/spawner/structure/window/reinforced/shuttle, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"b" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"c" = ( +/obj/effect/turf_decal/tile/neutral/half/contrasted, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/light/small/directional/north, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"i" = ( +/turf/closed/wall/mineral/titanium/overspace, +/area/virtual_domain/safehouse) +"l" = ( +/obj/effect/turf_decal/tile/neutral/half/contrasted{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"n" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/computer{ + dir = 8; + name = "shuttle console"; + icon_screen = "shuttle" + }, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"o" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"q" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/obj/structure/table/reinforced, +/obj/effect/decal/cleanable/dirt, +/obj/item/storage/toolbox/emergency, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"r" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/obj/effect/turf_decal/loading_area, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"z" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"A" = ( +/obj/effect/turf_decal/stripes/end{ + dir = 1 + }, +/obj/effect/turf_decal/sand/volcanic, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"B" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/machinery/light/small/directional/south, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"D" = ( +/obj/machinery/light/small/directional/south, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/obj/effect/turf_decal/loading_area, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"E" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/door/airlock/shuttle/glass, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/sand/volcanic, +/obj/structure/fans/tiny, +/turf/open/floor/iron/white, +/area/virtual_domain/safehouse) +"G" = ( +/turf/closed/wall/mineral/titanium, +/area/virtual_domain/safehouse) +"H" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"I" = ( +/obj/effect/turf_decal/tile/neutral/half/contrasted, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/light/small/directional/north, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"L" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/structure/table/reinforced, +/obj/item/tank/internals/emergency_oxygen{ + pixel_x = 3 + }, +/obj/item/clothing/mask/gas, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"N" = ( +/obj/machinery/power/shuttle_engine/propulsion/burst{ + dir = 8 + }, +/obj/structure/window/reinforced/spawner/directional/east, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/plating/airless, +/area/virtual_domain/safehouse) +"O" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"U" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/stripes/line, +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"W" = ( +/obj/effect/turf_decal/stripes/end, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) +"Y" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/obj/effect/decal/cleanable/generic, +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/iron, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +i +N +a +a +N +i +"} +(2,1,1) = {" +a +A +o +W +D +G +"} +(3,1,1) = {" +G +I +H +U +r +a +"} +(4,1,1) = {" +E +z +H +b +Y +G +"} +(5,1,1) = {" +G +c +O +b +l +a +"} +(6,1,1) = {" +a +q +n +L +B +G +"} +(7,1,1) = {" +i +G +a +a +G +i +"} diff --git a/_maps/safehouses/test_only_safehouse.dmm b/_maps/safehouses/test_only_safehouse.dmm new file mode 100644 index 00000000000..c23f8c4a22b --- /dev/null +++ b/_maps/safehouses/test_only_safehouse.dmm @@ -0,0 +1,29 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/obj/effect/landmark/bitrunning/cache_goal_turf, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"d" = ( +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"u" = ( +/turf/open/floor/plating, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +u +d +"} +(2,1,1) = {" +u +d +"} +(3,1,1) = {" +u +d +"} +(4,1,1) = {" +u +a +"} diff --git a/_maps/safehouses/wood.dmm b/_maps/safehouses/wood.dmm new file mode 100644 index 00000000000..0bb6b273fce --- /dev/null +++ b/_maps/safehouses/wood.dmm @@ -0,0 +1,120 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/open/indestructible/hotelwood, +/area/virtual_domain/safehouse) +"i" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"o" = ( +/turf/open/floor/carpet/green, +/area/virtual_domain/safehouse) +"p" = ( +/obj/item/kirbyplants/random/fullysynthetic, +/turf/open/indestructible/hotelwood, +/area/virtual_domain/safehouse) +"s" = ( +/obj/machinery/light/small/directional/east, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"v" = ( +/obj/machinery/light/small/directional/east, +/obj/structure/table/wood, +/obj/item/newspaper, +/turf/open/indestructible/hotelwood, +/area/virtual_domain/safehouse) +"x" = ( +/obj/structure/railing/corner/end{ + dir = 4 + }, +/turf/open/floor/carpet/green, +/area/virtual_domain/safehouse) +"z" = ( +/obj/structure/sign/poster/random/directional/east, +/turf/open/indestructible/hotelwood, +/area/virtual_domain/safehouse) +"G" = ( +/turf/closed/wall/mineral/wood, +/area/virtual_domain/safehouse) +"J" = ( +/obj/structure/railing, +/obj/effect/landmark/bitrunning/cache_goal_turf, +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/turf/open/floor/bitrunning_transport, +/area/virtual_domain/safehouse) +"T" = ( +/obj/effect/landmark/bitrunning/hololadder_spawn, +/turf/open/indestructible/hotelwood, +/area/virtual_domain/safehouse) +"X" = ( +/obj/machinery/door/airlock/wood/glass, +/obj/structure/fans/tiny, +/turf/open/floor/plating, +/area/virtual_domain/safehouse) +"Z" = ( +/obj/machinery/light/small/directional/west, +/turf/open/indestructible/hotelwood, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +G +G +i +G +G +G +"} +(2,1,1) = {" +i +Z +a +a +Z +i +"} +(3,1,1) = {" +G +p +o +o +T +G +"} +(4,1,1) = {" +X +a +o +o +T +G +"} +(5,1,1) = {" +G +a +x +o +T +G +"} +(6,1,1) = {" +i +s +J +z +v +i +"} +(7,1,1) = {" +G +G +i +G +G +G +"} diff --git a/_maps/shuttles/emergency_cere.dmm b/_maps/shuttles/emergency_cere.dmm index c964d37011f..07e236344ab 100644 --- a/_maps/shuttles/emergency_cere.dmm +++ b/_maps/shuttles/emergency_cere.dmm @@ -478,7 +478,7 @@ /turf/open/floor/iron/white, /area/shuttle/escape) "ck" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /obj/effect/turf_decal/tile/blue/half/contrasted{ dir = 1 }, diff --git a/_maps/shuttles/pirate_ex_interdyne.dmm b/_maps/shuttles/pirate_ex_interdyne.dmm index c3f7e186acb..5d2149c049f 100644 --- a/_maps/shuttles/pirate_ex_interdyne.dmm +++ b/_maps/shuttles/pirate_ex_interdyne.dmm @@ -301,7 +301,7 @@ /area/shuttle/pirate) "aW" = ( /obj/effect/turf_decal/tile/dark_blue/opposingcorners, -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/iron/dark, /area/shuttle/pirate) "be" = ( diff --git a/_maps/shuttles/pirate_geode.dmm b/_maps/shuttles/pirate_geode.dmm index eb7f8e5c78f..d2e8f034f48 100644 --- a/_maps/shuttles/pirate_geode.dmm +++ b/_maps/shuttles/pirate_geode.dmm @@ -1,30 +1,26 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE "at" = ( -/obj/structure/grille, -/obj/effect/spawner/structure/window/hollow/survival_pod, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "geodebridge" - }, -/turf/open/misc/dirt{ - planetary_atmos = 0; - initial_gas_mix = "o2=22;n2=82;TEMP=293.15" - }, +/obj/structure/barricade/wooden, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "aM" = ( -/obj/machinery/power/shuttle_engine/huge{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/white/line{ +/obj/structure/table/wood, +/obj/machinery/light/small/blacklight/directional{ dir = 8 }, -/turf/open/floor/plating, +/obj/item/restraints/legcuffs/beartrap, +/obj/item/restraints/legcuffs/beartrap, +/obj/item/restraints/legcuffs/beartrap, +/obj/item/grenade/c4, +/obj/item/grenade/c4, +/obj/item/grenade/c4, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "bY" = ( -/obj/effect/turf_decal/lunar_sand/plating, -/obj/effect/turf_decal/weather/dirt{ - dir = 9 +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 }, -/turf/open/floor/plating, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "cx" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -48,8 +44,8 @@ /turf/open/floor/plating, /area/shuttle/pirate) "ev" = ( -/obj/structure/flora/lunar_plant/style_2, -/turf/open/misc/dirt/jungle, +/obj/machinery/computer/piratepad_control, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "fB" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -67,10 +63,8 @@ /turf/open/floor/plating, /area/shuttle/pirate) "ga" = ( -/obj/item/stack/sheet/bluespace_crystal{ - amount = 2 - }, -/turf/open/misc/dirt/jungle, +/obj/machinery/space_heater, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "ge" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -86,21 +80,22 @@ /turf/open/floor/plating, /area/shuttle/pirate) "gv" = ( -/obj/item/reagent_containers/cup/beaker/large, -/turf/open/misc/dirt/jungle, +/obj/machinery/suit_storage_unit/pirate{ + helmet_type = /obj/item/clothing/head/helmet/space/syndicate/blue; + suit_type = /obj/item/clothing/suit/space/syndicate/blue + }, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "gM" = ( -/obj/structure/barricade/wooden, -/turf/open/misc/dirt, +/obj/structure/flora/lunar_plant/style_2, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "hM" = ( -/obj/item/stack/sheet/bluespace_crystal, -/obj/machinery/button/door{ - id = "geodebridge"; - name = "Window Shutters Control"; - pixel_y = 30 +/obj/machinery/porta_turret/syndicate/teleport{ + dir = 4; + faction = list("pirate") }, -/turf/open/misc/dirt/jungle, +/turf/closed/wall/mineral/plastitanium/nodiagonal, /area/shuttle/pirate) "id" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -159,14 +154,13 @@ /turf/open/floor/plating, /area/shuttle/pirate) "ka" = ( -/obj/machinery/light/small/blacklight/directional{ - dir = 4 - }, -/turf/open/misc/dirt/jungle, +/obj/effect/turf_decal/lunar_sand/plating, +/obj/item/trash/energybar, +/turf/open/floor/plating, /area/shuttle/pirate) "ko" = ( -/obj/machinery/piratepad, -/turf/open/misc/dirt/jungle, +/obj/item/trash/energybar, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "kp" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -198,12 +192,8 @@ /turf/open/floor/plating, /area/shuttle/pirate) "kV" = ( -/obj/item/stack/sheet/bluespace_crystal{ - amount = 2 - }, -/obj/structure/table/wood, -/obj/machinery/reagentgrinder, -/turf/open/misc/dirt/jungle, +/obj/item/reagent_containers/cup/beaker/large, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "lt" = ( /turf/template_noop, @@ -221,20 +211,17 @@ /turf/open/floor/plating, /area/shuttle/pirate) "mv" = ( -/turf/open/misc/dirt, +/obj/machinery/porta_turret/syndicate/teleport{ + dir = 8; + faction = list("pirate") + }, +/turf/closed/wall/mineral/plastitanium/nodiagonal, /area/shuttle/pirate) "nk" = ( -/obj/structure/table/wood, -/obj/machinery/light/small/blacklight/directional{ - dir = 8 +/obj/item/stack/sheet/bluespace_crystal{ + amount = 2 }, -/obj/item/restraints/legcuffs/beartrap, -/obj/item/restraints/legcuffs/beartrap, -/obj/item/restraints/legcuffs/beartrap, -/obj/item/grenade/c4, -/obj/item/grenade/c4, -/obj/item/grenade/c4, -/turf/open/misc/dirt/jungle, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "nD" = ( /obj/machinery/light/small/blacklight/directional{ @@ -315,8 +302,13 @@ /turf/open/floor/plating, /area/shuttle/pirate) "qp" = ( -/obj/structure/reagent_dispensers/fueltank, -/turf/open/misc/dirt/jungle, +/obj/item/stack/sheet/bluespace_crystal, +/obj/machinery/button/door{ + id = "geodebridge"; + name = "Window Shutters Control"; + pixel_y = 30 + }, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "qK" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -343,6 +335,12 @@ }, /turf/open/floor/plating, /area/shuttle/pirate) +"rn" = ( +/obj/structure/closet/crate/miningcar, +/obj/effect/spawner/random/maintenance/three, +/obj/item/mining_scanner, +/turf/open/misc/dirt/station, +/area/shuttle/pirate) "rG" = ( /obj/effect/turf_decal/lunar_sand/plating, /obj/effect/turf_decal/weather/dirt{ @@ -383,6 +381,17 @@ /turf/open/floor/plating, /area/shuttle/pirate) "uH" = ( +/obj/effect/turf_decal/lunar_sand/plating, +/obj/effect/turf_decal/weather/dirt{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/obj/machinery/light/small/blacklight/directional{ + dir = 8 + }, +/obj/effect/spawner/random/trash/mess, /turf/open/floor/plating, /area/shuttle/pirate) "uP" = ( @@ -395,10 +404,21 @@ }, /turf/open/floor/iron/dark, /area/shuttle/pirate) +"vj" = ( +/obj/machinery/computer/shuttle/pirate{ + dir = 8 + }, +/turf/open/misc/dirt/station, +/area/shuttle/pirate) "vl" = ( +/obj/effect/spawner/random/maintenance, +/obj/item/shovel, /obj/structure/closet/crate/miningcar, -/obj/effect/spawner/random/maintenance/three, -/turf/open/misc/dirt/jungle, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/rods{ + amount = 5 + }, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "vP" = ( /obj/structure/table/reinforced, @@ -431,16 +451,24 @@ /turf/open/floor/plating, /area/shuttle/pirate) "wz" = ( -/obj/machinery/computer/piratepad_control, -/turf/open/misc/dirt/jungle, +/obj/effect/turf_decal/lunar_sand/plating, +/obj/effect/turf_decal/weather/dirt{ + dir = 3 + }, +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/obj/effect/decal/cleanable/shreds, +/turf/open/floor/plating, /area/shuttle/pirate) "xg" = ( /obj/structure/grille, /obj/effect/spawner/structure/window/hollow/survival_pod, -/turf/open/misc/dirt{ - planetary_atmos = 0; - initial_gas_mix = "o2=22;n2=82;TEMP=293.15" - }, +/obj/structure/barricade/wooden/crude, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "xN" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -450,8 +478,9 @@ /turf/open/floor/plating, /area/shuttle/pirate) "xS" = ( -/obj/structure/chair/wood, -/turf/open/misc/dirt/jungle, +/obj/structure/sign/poster/contraband/busty_backdoor_xeno_babes_6/directional/north, +/obj/item/stack/ore/silver, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "yh" = ( /obj/structure/cable, @@ -464,8 +493,8 @@ /turf/open/floor/plating, /area/shuttle/pirate) "yz" = ( -/obj/structure/flora/lunar_plant/style_1, -/turf/open/misc/dirt/jungle, +/obj/structure/flora/lunar_plant/style_3, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "zO" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -475,28 +504,21 @@ /turf/open/floor/plating, /area/shuttle/pirate) "zS" = ( -/obj/effect/turf_decal/lunar_sand/plating, -/obj/effect/turf_decal/weather/dirt{ - dir = 5 +/obj/item/stack/sheet/bluespace_crystal{ + amount = 2 }, -/turf/open/floor/plating, +/obj/structure/table/wood, +/obj/machinery/reagentgrinder, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "zZ" = ( -/obj/item/stack/sheet/bluespace_crystal, -/turf/open/misc/dirt/jungle, +/obj/structure/reagent_dispensers/watertank, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "At" = ( -/obj/effect/turf_decal/lunar_sand/plating, -/obj/effect/turf_decal/weather/dirt{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ - dir = 4 - }, -/obj/machinery/light/small/blacklight/directional{ - dir = 8 +/turf/closed/mineral/random/jungle{ + baseturfs = null }, -/turf/open/floor/plating, /area/shuttle/pirate) "AT" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -519,11 +541,13 @@ /turf/open/floor/plating, /area/shuttle/pirate) "BA" = ( -/obj/machinery/airalarm/directional/north, -/obj/structure/table/wood, -/obj/machinery/microwave, -/obj/effect/mapping_helpers/airalarm/all_access, -/turf/open/misc/dirt/jungle, +/obj/structure/closet/crate/cardboard{ + name = "box of climbing hooks" + }, +/obj/item/climbing_hook/syndicate, +/obj/item/climbing_hook/syndicate, +/obj/item/climbing_hook/syndicate, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "BI" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -547,11 +571,8 @@ /turf/closed/wall/mineral/iron, /area/shuttle/pirate) "Ds" = ( -/obj/structure/rack, -/obj/item/storage/box/syringes, -/obj/item/storage/medkit/brute, -/obj/item/storage/medkit/fire, -/turf/open/misc/dirt/jungle, +/obj/machinery/loot_locator, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "Dw" = ( /obj/machinery/power/port_gen/pacman{ @@ -575,14 +596,8 @@ /turf/open/floor/plating, /area/shuttle/pirate) "DT" = ( -/obj/effect/spawner/random/maintenance, -/obj/item/shovel, -/obj/structure/closet/crate/miningcar, -/obj/item/stack/sheet/mineral/coal, -/obj/item/stack/rods{ - amount = 5 - }, -/turf/open/misc/dirt/jungle, +/obj/structure/fluff/minepost, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "Ec" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -614,10 +629,8 @@ /turf/open/floor/plating, /area/shuttle/pirate) "Gj" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 1 - }, -/turf/open/misc/dirt/jungle, +/obj/machinery/piratepad, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "GQ" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -641,12 +654,12 @@ /turf/open/floor/plating, /area/shuttle/pirate) "HJ" = ( -/obj/structure/reagent_dispensers/watertank, -/turf/open/misc/dirt/jungle, +/obj/machinery/shuttle_scrambler, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "HY" = ( -/obj/machinery/loot_locator, -/turf/open/misc/dirt/jungle, +/obj/effect/spawner/random/trash/mess, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "Ig" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -691,6 +704,10 @@ }, /turf/open/floor/iron/dark, /area/shuttle/pirate) +"JK" = ( +/obj/item/stack/sheet/bluespace_crystal, +/turf/open/misc/dirt/station, +/area/shuttle/pirate) "JL" = ( /obj/effect/turf_decal/lunar_sand/plating, /obj/machinery/atmospherics/components/unary/vent_pump/on, @@ -713,9 +730,8 @@ /turf/open/floor/plating, /area/shuttle/pirate) "KK" = ( -/obj/structure/sign/poster/contraband/busty_backdoor_xeno_babes_6/directional/north, -/obj/item/stack/ore/silver, -/turf/open/misc/dirt/jungle, +/obj/structure/reagent_dispensers/fueltank, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "Mc" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -764,17 +780,19 @@ /turf/open/floor/plating, /area/shuttle/pirate) "Nb" = ( -/obj/structure/grille, -/obj/effect/spawner/structure/window/hollow/survival_pod, -/obj/structure/barricade/wooden/crude, -/turf/open/misc/dirt{ - planetary_atmos = 0; - initial_gas_mix = "o2=22;n2=82;TEMP=293.15" - }, +/obj/structure/rack, +/obj/item/storage/box/syringes, +/obj/item/storage/medkit/brute, +/obj/item/storage/medkit/fire, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "NT" = ( -/obj/structure/fluff/minepost, -/turf/open/misc/dirt/jungle, +/obj/effect/turf_decal/lunar_sand/plating, +/obj/effect/turf_decal/weather/dirt{ + dir = 9 + }, +/obj/item/trash/energybar, +/turf/open/floor/plating, /area/shuttle/pirate) "Od" = ( /turf/closed/wall/mineral/iron, @@ -792,33 +810,6 @@ /turf/open/floor/plating, /area/shuttle/pirate) "OP" = ( -/obj/machinery/space_heater, -/turf/open/misc/dirt/jungle, -/area/shuttle/pirate) -"OR" = ( -/obj/machinery/porta_turret/syndicate/teleport{ - faction = list("pirate") - }, -/turf/closed/wall/mineral/iron, -/area/shuttle/pirate) -"OX" = ( -/obj/structure/sign/poster/contraband/bountyhunters, -/turf/closed/wall/mineral/iron, -/area/shuttle/pirate) -"Pq" = ( -/obj/machinery/power/shuttle_engine/large{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/white/line{ - dir = 8 - }, -/turf/open/floor/plating, -/area/shuttle/pirate) -"Pr" = ( -/obj/structure/flora/lunar_plant/style_3, -/turf/open/misc/dirt/jungle, -/area/shuttle/pirate) -"PB" = ( /obj/structure/rack, /obj/item/gun/energy/recharge/kinetic_accelerator{ pixel_y = 5 @@ -841,13 +832,45 @@ /obj/item/borg/upgrade/modkit/indoors{ pixel_y = -5 }, -/turf/open/misc/dirt/jungle, +/turf/open/misc/dirt/station, /area/shuttle/pirate) -"Qg" = ( -/obj/machinery/computer/shuttle/pirate{ +"OR" = ( +/obj/machinery/porta_turret/syndicate/teleport{ + faction = list("pirate") + }, +/turf/closed/wall/mineral/iron, +/area/shuttle/pirate) +"OX" = ( +/obj/structure/sign/poster/contraband/bountyhunters, +/turf/closed/wall/mineral/iron, +/area/shuttle/pirate) +"Pq" = ( +/obj/machinery/power/shuttle_engine/propulsion{ dir = 8 }, -/turf/open/misc/dirt/jungle, +/turf/open/floor/plating, +/area/shuttle/pirate) +"Pr" = ( +/obj/structure/table/wood, +/obj/item/food/energybar{ + pixel_y = 9 + }, +/obj/item/food/energybar, +/turf/open/misc/dirt/station, +/area/shuttle/pirate) +"PB" = ( +/obj/machinery/light/small/blacklight/directional{ + dir = 4 + }, +/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{ @@ -864,8 +887,7 @@ /turf/open/floor/iron/dark, /area/shuttle/pirate) "Rp" = ( -/obj/machinery/shuttle_scrambler, -/turf/open/misc/dirt/jungle, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "Rv" = ( /obj/effect/turf_decal/weather/dirt{ @@ -902,7 +924,8 @@ /turf/open/floor/plating, /area/shuttle/pirate) "Sy" = ( -/turf/open/misc/dirt/jungle, +/obj/structure/chair/wood, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "SP" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -915,8 +938,8 @@ /turf/open/floor/plating, /area/shuttle/pirate) "TC" = ( -/obj/effect/turf_decal/lunar_sand/plating, -/turf/open/floor/plating, +/obj/structure/flora/lunar_plant/style_1, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "Uf" = ( /obj/machinery/power/shuttle_engine/heater{ @@ -940,21 +963,16 @@ /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/shuttle/pirate) "UM" = ( -/obj/item/stack/sheet/bluespace_crystal{ - amount = 2 - }, -/obj/machinery/light/small/blacklight/directional{ - dir = 8 - }, -/turf/open/misc/dirt/jungle, +/obj/structure/grille, +/obj/effect/spawner/structure/window/hollow/survival_pod, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "UY" = ( +/obj/machinery/airalarm/directional/north, /obj/structure/table/wood, -/obj/item/food/energybar{ - pixel_y = 9 - }, -/obj/item/food/energybar, -/turf/open/misc/dirt/jungle, +/obj/machinery/microwave, +/obj/effect/mapping_helpers/airalarm/all_access, +/turf/open/misc/dirt/station, /area/shuttle/pirate) "WR" = ( /obj/effect/turf_decal/lunar_sand/plating, @@ -994,11 +1012,13 @@ /turf/open/floor/plating, /area/shuttle/pirate) "ZF" = ( -/obj/machinery/suit_storage_unit/pirate{ - helmet_type = /obj/item/clothing/head/helmet/space/syndicate/blue; - suit_type = /obj/item/clothing/suit/space/syndicate/blue +/obj/item/stack/sheet/bluespace_crystal{ + amount = 2 + }, +/obj/machinery/light/small/blacklight/directional{ + dir = 8 }, -/turf/open/misc/dirt/jungle, +/turf/open/misc/dirt/station, /area/shuttle/pirate) (1,1,1) = {" @@ -1007,68 +1027,47 @@ lt lt lt lt -lt -lt -lt -yu yu -aM -lt -lt -lt -lt -lt -lt -lt -lt -"} -(2,1,1) = {" -lt -lt -lt -lt -lt yu -Pq jh -uH -uH -uH +yu +yu +yu jh yu -Pq +yu lt lt lt lt lt "} -(3,1,1) = {" +(2,1,1) = {" lt lt lt -jx +mv Od -uH -uH -jx -uH -uH -uH -jx -uH -uH +Pq +Pq +At +Pq +Pq +Pq +At +Pq +Pq Od -jx +mv lt lt lt "} -(4,1,1) = {" +(3,1,1) = {" lt lt -jx -jx +At +At Od Uf Uf @@ -1080,18 +1079,18 @@ Od Uf Uf Od -jx -jx +At +At lt lt "} -(5,1,1) = {" +(4,1,1) = {" lt lt jx jx Od -NT +DT kp Uw Ku @@ -1099,66 +1098,66 @@ ME Dw Uw ZD -NT +DT Od jx jx lt lt "} -(6,1,1) = {" +(5,1,1) = {" lt lt lt jx Od -Sy -zS +Rp +fO IP DM JL DM SP Ih -ga +nk Od jx lt lt lt "} -(7,1,1) = {" +(6,1,1) = {" lt jx jx jx Od -xS -kV +Sy +zS nR WR Oq Mc xN wd -OP +ga Od jx jx jx lt "} -(8,1,1) = {" +(7,1,1) = {" jx jx jx jx Od -KK -gv -Sy -Sy -Sy +xS +kV +ko +Rp +Rp Od Od kM @@ -1169,28 +1168,28 @@ jx jx jx "} -(9,1,1) = {" +(8,1,1) = {" jx jx jx jx Od -ZF -ZF -ZF -Ds -PB +gv +gv +gv +Nb +OP Od -Pr +yz Mm -Sy -vl +Rp +rn Od jx jx jx "} -(10,1,1) = {" +(9,1,1) = {" jx jx Od @@ -1202,58 +1201,58 @@ Od Od Od OX -UY +Pr Mm -ga -DT +nk +vl Od jx jx jx "} -(11,1,1) = {" +(10,1,1) = {" lt jt Od -NT -UM -yz +DT +ZF +TC Od -Rp -nk -HY +HJ +aM +Ds Od -BA +UY Mm -Sy -NT +Rp +DT Od Od Od lt "} -(12,1,1) = {" +(11,1,1) = {" lt -gM -xg -bY +at +UM +NT oa zO Od -Sy -ga -Sy +Rp +nk +Rp Od -Sy +BA Mm -Sy +Rp Dx uk St AT lt "} -(13,1,1) = {" +(12,1,1) = {" lt XB Od @@ -1274,49 +1273,49 @@ Od OR lt "} -(14,1,1) = {" +(13,1,1) = {" lt -mv -Nb +Rp +xg fO pO im Od -ev -rG -Gj +gM +wz +bY Od -Sy -zZ -Sy +HY +JK +Rp lA id St Fx lt "} -(15,1,1) = {" +(14,1,1) = {" lt jx Od -NT -ka -ga +DT +PB +nk Od -wz +ev rG -ko +Gj Od -qp -HJ -Sy -NT +KK +zZ +Rp +DT Od Od Od lt "} -(16,1,1) = {" +(15,1,1) = {" lt jx Od @@ -1337,7 +1336,7 @@ jx jx lt "} -(17,1,1) = {" +(16,1,1) = {" lt jx Od @@ -1345,7 +1344,7 @@ Er YK Qo el -At +uH kx iu iu @@ -1358,14 +1357,14 @@ Od jx lt "} -(18,1,1) = {" +(17,1,1) = {" lt jx Od jD -TC +ka yh -hM +qp oV Hm Mz @@ -1379,18 +1378,18 @@ Cg jx lt "} -(19,1,1) = {" +(18,1,1) = {" lt jx Od Od Od Od -NT -Qg +DT +vj vP vY -NT +DT Rv uP JV @@ -1400,7 +1399,7 @@ Od jx lt "} -(20,1,1) = {" +(19,1,1) = {" lt jx jx @@ -1408,9 +1407,9 @@ jx jx Od Od -at -at -at +Qg +Qg +Qg Od Od Od @@ -1421,18 +1420,18 @@ jx jx lt "} -(21,1,1) = {" +(20,1,1) = {" lt lt jx jx jx jx -jx +hM lt lt lt -jx +hM jx jx jx @@ -1442,7 +1441,7 @@ jx lt lt "} -(22,1,1) = {" +(21,1,1) = {" lt lt lt diff --git a/_maps/shuttles/whiteship_box.dmm b/_maps/shuttles/whiteship_box.dmm index 48d47820df2..cbfdf87ce09 100644 --- a/_maps/shuttles/whiteship_box.dmm +++ b/_maps/shuttles/whiteship_box.dmm @@ -593,7 +593,7 @@ "bs" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /obj/effect/turf_decal/stripes/line{ dir = 9 }, @@ -622,7 +622,7 @@ "bu" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /obj/effect/turf_decal/stripes/line{ dir = 5 }, diff --git a/_maps/templates/battlecruiser_starfury.dmm b/_maps/templates/battlecruiser_starfury.dmm index d3f72900fd4..1e4905ac26e 100644 --- a/_maps/templates/battlecruiser_starfury.dmm +++ b/_maps/templates/battlecruiser_starfury.dmm @@ -3885,7 +3885,7 @@ /turf/open/floor/engine, /area/shuttle/sbc_starfury) "qQ" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, +/obj/machinery/cryo_cell, /turf/open/floor/plating, /area/shuttle/sbc_starfury) "qS" = ( diff --git a/_maps/virtual_domains/README.md b/_maps/virtual_domains/README.md new file mode 100644 index 00000000000..a02d43e1575 --- /dev/null +++ b/_maps/virtual_domains/README.md @@ -0,0 +1,32 @@ +# Making new virtual domains + +## From scratch + +1. Create a new map using TGM format. It can be any size, but please, consider limiting to 75x75 max. +2. Ensure that the map has ONE tile marked with the safehouse bottom left landmark. If you're using modular safehouses, it will need to be a 7x6 area. +4. Provide a way for players to enter your new map via the north door, which is 4th tile over. +5. Enclose your area with a single wall binary closed wall. + +## From an existing map + +1. Create a new map using the existing map's size - give yourself enough room to enclose it with a binary wall. There's no need for any space outside of it, so ensure that it fits and is enclosed, nothing outside of this. +2. Copy and paste the existing map into it. +3. Find an accessible area for a safehouse, 7x6 - or with a custom, just ensure the necessary landmarks are placed. +4. Place a bottom left safehouse landmark somewhere on the map to load the safehouse. + +## BOTH. +1. You need to have one (1) way that the encrypted cache can spawn. This can be from a mob drop, a landmark (place a few, it'll pick one), or a signable landmark if you have a points system. +2. Make note of the size of the map. Make sure this is in the dm file. +3. Create the dm file that defines the map qualities. Examples are in the bitrunning file. + +### Notes + +You shouldn't need to fully enclose your map in 15 tiles of binary filler. Using one solid wall should do the trick. + +Adding some open tile padding around the safehouse is a good touch. About 7 tiles West/East for the visual effect of a larger map. + +If you want to add prep gear, you can do so within the safehouse's area as long you don't overlap with goal turfs or exit spawners. The top left corner is a good spot for this, with respect for the walls, therefore [1, 1], [1, 2], [1, 3] + +You can also create safehouses if you find yourself needing the same gear over and over again. There is a readme for that as well. + +Boss zones should give players pretty ample space, I've been using a 23x23 minimum area. diff --git a/_maps/virtual_domains/ash_drake.dmm b/_maps/virtual_domains/ash_drake.dmm new file mode 100644 index 00000000000..50fbac8696a --- /dev/null +++ b/_maps/virtual_domains/ash_drake.dmm @@ -0,0 +1,1750 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"c" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"e" = ( +/obj/structure/marker_beacon/cerulean, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"f" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"g" = ( +/obj/structure/marker_beacon/lime, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"h" = ( +/obj/machinery/light/small/blacklight/directional/south, +/obj/effect/baseturf_helper/virtual_domain, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/virtual_domain/powered) +"i" = ( +/obj/structure/marker_beacon/jade, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"j" = ( +/obj/structure/marker_beacon/teal, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"l" = ( +/obj/structure/marker_beacon/bronze, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"q" = ( +/mob/living/simple_animal/hostile/megafauna/dragon/virtual_domain, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"s" = ( +/turf/closed/mineral/volcanic/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"u" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"v" = ( +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"G" = ( +/obj/structure/marker_beacon/purple, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"J" = ( +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"L" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"P" = ( +/obj/structure/marker_beacon/fuchsia, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Z" = ( +/obj/effect/mob_spawn/corpse/human/miner, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) + +(1,1,1) = {" +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +u +"} +(2,1,1) = {" +v +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +v +"} +(3,1,1) = {" +v +s +s +s +s +J +J +s +s +J +J +s +s +J +J +J +J +s +s +s +J +J +J +s +s +s +s +s +s +s +s +s +s +J +J +s +s +s +J +J +s +s +J +J +s +v +"} +(4,1,1) = {" +v +s +s +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +a +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +s +v +"} +(5,1,1) = {" +v +s +s +J +a +J +J +J +J +a +J +J +J +J +a +a +J +J +J +J +J +a +a +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +s +s +v +"} +(6,1,1) = {" +v +s +s +J +a +J +J +a +a +a +a +a +a +a +a +a +a +a +a +J +a +a +a +a +a +J +J +J +a +a +J +J +J +a +a +J +a +J +a +a +J +J +J +s +s +v +"} +(7,1,1) = {" +v +s +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +J +s +v +"} +(8,1,1) = {" +v +s +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +s +v +"} +(9,1,1) = {" +v +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +i +a +a +a +a +a +Z +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(10,1,1) = {" +v +s +J +J +J +a +a +a +a +a +a +G +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(11,1,1) = {" +v +s +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(12,1,1) = {" +v +s +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +J +s +v +"} +(13,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +a +a +g +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(14,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(15,1,1) = {" +v +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +h +c +c +c +c +c +L +a +a +J +J +s +v +"} +(16,1,1) = {" +v +s +J +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +c +c +c +c +c +c +a +a +J +J +s +v +"} +(17,1,1) = {" +v +s +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +l +a +a +c +c +c +c +c +c +a +a +J +J +s +v +"} +(18,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +q +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +c +c +c +c +c +c +a +J +J +s +s +v +"} +(19,1,1) = {" +v +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +c +c +c +c +c +c +a +a +J +J +s +v +"} +(20,1,1) = {" +v +s +J +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +c +c +c +c +c +c +a +a +J +J +s +v +"} +(21,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +e +a +a +a +a +a +a +a +a +a +a +a +a +h +c +c +c +c +c +f +a +a +J +s +s +v +"} +(22,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +s +s +v +"} +(23,1,1) = {" +v +s +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +s +s +v +"} +(24,1,1) = {" +v +s +J +J +a +a +a +a +j +a +a +a +a +a +P +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(25,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +J +s +v +"} +(26,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(27,1,1) = {" +v +s +s +J +J +J +a +a +a +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +j +a +a +a +a +a +a +a +J +J +s +v +"} +(28,1,1) = {" +v +s +J +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +J +s +v +"} +(29,1,1) = {" +v +s +J +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +s +v +"} +(30,1,1) = {" +v +s +s +J +J +J +J +a +a +J +J +J +a +a +a +a +J +J +J +a +a +a +J +J +J +a +a +a +J +J +a +a +a +a +a +a +J +J +a +a +a +J +J +s +s +v +"} +(31,1,1) = {" +v +s +s +a +J +J +J +J +J +J +J +J +J +a +a +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +a +a +a +J +J +J +J +J +J +J +J +J +s +v +"} +(32,1,1) = {" +v +s +s +a +J +J +J +J +J +J +J +J +J +J +J +J +J +a +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +s +v +"} +(33,1,1) = {" +v +s +s +s +s +s +J +J +s +s +s +s +J +J +s +s +s +s +s +s +J +J +s +s +s +s +J +J +s +s +s +s +J +J +J +s +s +s +s +s +s +J +J +J +s +v +"} +(34,1,1) = {" +v +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +v +"} +(35,1,1) = {" +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +"} diff --git a/_maps/virtual_domains/beach_bar.dmm b/_maps/virtual_domains/beach_bar.dmm new file mode 100644 index 00000000000..408d3c0cda1 --- /dev/null +++ b/_maps/virtual_domains/beach_bar.dmm @@ -0,0 +1,2932 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"ab" = ( +/obj/machinery/vending/cigarette/beach, +/obj/effect/turf_decal/sand, +/obj/structure/sign/poster/contraband/have_a_puff/directional/west, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"ag" = ( +/turf/open/floor/carpet/red, +/area/virtual_domain/powered) +"as" = ( +/obj/structure/closet/crate/bin, +/obj/item/tank/internals/emergency_oxygen, +/obj/item/trash/candy, +/obj/item/toy/talking/owl, +/obj/effect/turf_decal/sand, +/obj/machinery/light/directional/west, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"aw" = ( +/obj/machinery/grill, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"aE" = ( +/turf/open/floor/pod/light, +/area/virtual_domain/powered) +"aZ" = ( +/obj/machinery/light/small/directional/east, +/obj/structure/closet/crate{ + name = "fuel crate" + }, +/obj/item/stack/sheet/mineral/coal/ten, +/obj/item/stack/sheet/mineral/coal/ten, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"bf" = ( +/mob/living/basic/crab{ + name = "Jonny" + }, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"bC" = ( +/obj/effect/turf_decal/sand, +/mob/living/basic/crab{ + name = "James" + }, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"bM" = ( +/mob/living/basic/crab{ + name = "Jon" + }, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"bQ" = ( +/obj/structure/fluff/beach_umbrella/cap, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"bS" = ( +/obj/machinery/chem_master/condimaster{ + name = "CondiMaster Neo"; + pixel_x = -4 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"cb" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/pill/lsd, +/obj/item/reagent_containers/pill/lsd, +/obj/item/reagent_containers/pill/lsd, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"cv" = ( +/turf/open/floor/carpet/royalblue, +/area/virtual_domain/powered) +"cz" = ( +/obj/effect/turf_decal/sand, +/obj/machinery/jukebox, +/obj/item/coin/gold, +/turf/open/floor/sepia, +/area/virtual_domain/powered) +"cG" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/turf/open/water/beach, +/area/virtual_domain/powered) +"db" = ( +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/vending_refill/cigarette, +/obj/item/vending_refill/boozeomat, +/obj/structure/closet/secure_closet{ + icon_state = "cabinet"; + name = "booze storage"; + req_access = list("bar") + }, +/obj/item/storage/backpack/duffelbag, +/obj/item/etherealballdeployer, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/colocup, +/obj/item/reagent_containers/cup/glass/colocup, +/obj/item/reagent_containers/cup/glass/colocup, +/obj/item/reagent_containers/cup/glass/colocup, +/obj/item/reagent_containers/cup/glass/colocup, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"di" = ( +/obj/machinery/vending/boozeomat, +/obj/effect/mapping_helpers/atom_injector/obj_flag{ + inject_flags = 1; + target_type = /obj/machinery/vending/boozeomat + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"dj" = ( +/turf/open/misc/beach/coast{ + dir = 1 + }, +/area/virtual_domain/powered) +"dx" = ( +/obj/effect/turf_decal/sand, +/obj/effect/turf_decal/stripes/asteroid/line{ + dir = 8 + }, +/turf/open/floor/sepia, +/area/virtual_domain/powered) +"dI" = ( +/obj/machinery/light/directional/south, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"dZ" = ( +/obj/structure/bookcase/random/reference, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"ed" = ( +/obj/machinery/atmospherics/components/tank/air{ + dir = 1 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"er" = ( +/obj/structure/noticeboard/staff, +/turf/closed/wall/mineral/wood/nonmetal, +/area/virtual_domain/powered) +"fc" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/pill/happy, +/obj/item/toy/figure/bartender{ + pixel_x = -8; + pixel_y = -1 + }, +/obj/item/reagent_containers/cup/glass/drinkingglass/virtual_domain{ + pixel_y = 8; + pixel_x = 5 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"fr" = ( +/obj/item/melee/skateboard/hoverboard, +/obj/machinery/light/directional/west, +/turf/open/floor/pod/light, +/area/virtual_domain/powered) +"gh" = ( +/obj/structure/flora/bush/stalky/style_random, +/obj/structure/flora/bush/sparsegrass/style_random, +/turf/open/water/beach, +/area/virtual_domain/powered) +"gl" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"gJ" = ( +/obj/structure/railing{ + dir = 8 + }, +/turf/open/misc/beach/coast{ + dir = 4 + }, +/area/virtual_domain/powered) +"hk" = ( +/obj/structure/reagent_dispensers/watertank, +/turf/open/floor/pod/light, +/area/virtual_domain/powered) +"hE" = ( +/obj/structure/sign/departments/restroom/directional/east, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"hG" = ( +/obj/machinery/door/airlock/sandstone{ + name = "Surfer Shack 1" + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"iz" = ( +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"iR" = ( +/obj/structure/table, +/obj/item/book/manual/wiki/barman_recipes, +/obj/item/reagent_containers/cup/glass/shaker, +/obj/item/reagent_containers/cup/rag, +/obj/machinery/light/small/directional/west, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"jc" = ( +/turf/open/floor/iron/stairs/right, +/area/virtual_domain/powered) +"jg" = ( +/obj/machinery/vending/hydronutrients, +/turf/open/floor/iron/grimy, +/area/virtual_domain/powered) +"jl" = ( +/obj/structure/flora/rock/pile/jungle/style_random, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"jy" = ( +/obj/effect/turf_decal/sand{ + density = 1 + }, +/obj/effect/decal/fakelattice, +/turf/open/floor/pod/light{ + density = 1 + }, +/area/virtual_domain/powered) +"ke" = ( +/obj/structure/marker_beacon/bronze, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"kn" = ( +/obj/effect/turf_decal/sand, +/obj/effect/turf_decal/stripes/asteroid/line{ + dir = 8 + }, +/obj/structure/chair/stool/bar/directional/west, +/turf/open/floor/sepia, +/area/virtual_domain/powered) +"kv" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"kG" = ( +/obj/structure/table, +/obj/machinery/reagentgrinder, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"kK" = ( +/obj/structure/mirror/directional/west, +/obj/structure/sink/kitchen/directional/south, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"kT" = ( +/obj/structure/chair/stool/bar/directional/south, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"lq" = ( +/obj/item/melee/skateboard/hoverboard, +/turf/open/floor/pod/light, +/area/virtual_domain/powered) +"lB" = ( +/obj/item/toy/seashell, +/obj/effect/turf_decal/sand, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"lS" = ( +/turf/open/floor/light/colour_cycle/dancefloor_a, +/area/virtual_domain/powered) +"ml" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"mq" = ( +/obj/structure/closet/secure_closet/freezer/kitchen/all_access, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"mG" = ( +/obj/structure/easel, +/obj/item/canvas/twentythree_twentythree, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"mP" = ( +/turf/open/misc/beach/coast/corner{ + dir = 1 + }, +/area/virtual_domain/powered) +"mX" = ( +/obj/structure/closet/secure_closet/freezer/meat/all_access, +/obj/item/food/meat/rawbacon, +/obj/item/food/meat/rawbacon, +/obj/item/food/meat/rawcutlet, +/obj/item/food/meat/rawcutlet, +/obj/item/food/meat/slab/rawcrab, +/obj/item/food/meat/slab/rawcrab, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"nP" = ( +/obj/item/stack/sheet/iron/fifty, +/obj/effect/mapping_helpers/burnt_floor, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"oE" = ( +/obj/structure/railing/corner{ + dir = 1 + }, +/obj/machinery/light/directional/south, +/turf/open/misc/beach/coast/corner{ + dir = 8 + }, +/area/virtual_domain/powered) +"oP" = ( +/obj/structure/table/wood, +/obj/machinery/reagentgrinder, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"pr" = ( +/turf/template_noop, +/area/template_noop) +"pC" = ( +/obj/machinery/computer/arcade/battle, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"pT" = ( +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"pZ" = ( +/obj/machinery/light/directional/south, +/turf/open/misc/beach/coast{ + dir = 1 + }, +/area/virtual_domain/powered) +"qc" = ( +/obj/structure/extinguisher_cabinet/directional/south, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"qg" = ( +/obj/structure/sign/poster/contraband/space_up/directional/west, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"qR" = ( +/obj/effect/spawner/structure/window, +/obj/structure/curtain, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"qW" = ( +/obj/item/melee/skateboard/hoverboard, +/mob/living/basic/chicken{ + name = "Chicken Joe" + }, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"rc" = ( +/obj/machinery/light/directional/east, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"ri" = ( +/obj/structure/sign/poster/official/fruit_bowl, +/turf/closed/wall/mineral/wood/nonmetal, +/area/virtual_domain/powered) +"rm" = ( +/obj/item/storage/crayons, +/obj/structure/closet/crate/wooden, +/obj/item/canvas/twentythree_twentythree, +/obj/item/canvas/twentythree_twentythree, +/obj/item/canvas/twentythree_twentythree, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"rT" = ( +/obj/item/toy/seashell, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"sT" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"tE" = ( +/obj/machinery/door/airlock/public/glass{ + name = "Resort Casino" + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"tF" = ( +/obj/structure/extinguisher_cabinet/directional/east, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"tZ" = ( +/obj/structure/toilet, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"uc" = ( +/obj/machinery/light/small/directional/east, +/obj/machinery/light/small/directional/east, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/virtual_domain/powered) +"ug" = ( +/obj/structure/closet/secure_closet{ + icon_state = "cabinet"; + name = "bartender's closet"; + req_access = list("bar") + }, +/obj/item/clothing/shoes/sandal{ + desc = "A very fashionable pair of flip-flops."; + name = "flip-flops" + }, +/obj/item/clothing/neck/beads, +/obj/item/clothing/glasses/sunglasses/reagent, +/obj/item/clothing/suit/costume/hawaiian, +/obj/machinery/light/small/directional/east, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"uk" = ( +/obj/structure/closet/crate/hydroponics, +/obj/item/shovel/spade, +/obj/item/reagent_containers/cup/bucket, +/obj/item/cultivator, +/turf/open/floor/iron/grimy, +/area/virtual_domain/powered) +"uq" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/cup/glass/drinkingglass/virtual_domain, +/obj/item/reagent_containers/cup/glass/drinkingglass/virtual_domain{ + pixel_x = -4; + pixel_y = 8 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"uU" = ( +/obj/effect/turf_decal/sand, +/turf/open/floor/sepia, +/area/virtual_domain/powered) +"uV" = ( +/obj/structure/flora/coconuts, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"ve" = ( +/obj/item/toy/dodgeball, +/obj/item/toy/dodgeball, +/obj/item/toy/dodgeball, +/obj/item/toy/dodgeball, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"vp" = ( +/obj/machinery/light/directional/east, +/obj/structure/chair/stool/bar/directional/south, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"vq" = ( +/obj/machinery/oven/range, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"vv" = ( +/obj/structure/chair/stool/directional/south, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"vN" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/pill/morphine, +/obj/item/reagent_containers/pill/morphine, +/obj/item/reagent_containers/pill/morphine, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"vT" = ( +/obj/structure/railing{ + dir = 8 + }, +/turf/open/misc/beach/coast/corner, +/area/virtual_domain/powered) +"wb" = ( +/obj/structure/closet/crate/freezer{ + name = "Cooler" + }, +/obj/item/reagent_containers/cup/glass/ice, +/obj/item/reagent_containers/cup/glass/colocup, +/obj/item/reagent_containers/cup/glass/colocup, +/obj/item/reagent_containers/cup/glass/bottle/beer{ + desc = "Beer advertised to be the best in space."; + name = "Masterbrand Beer" + }, +/obj/item/reagent_containers/cup/glass/bottle/beer{ + desc = "Beer advertised to be the best in space."; + name = "Masterbrand Beer" + }, +/obj/item/reagent_containers/cup/glass/bottle/beer{ + desc = "Beer advertised to be the best in space."; + name = "Masterbrand Beer" + }, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/obj/item/reagent_containers/cup/glass/bottle/beer/light, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"wD" = ( +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"xb" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"xk" = ( +/obj/structure/table/wood/poker, +/obj/item/storage/dice, +/obj/item/stack/spacecash/c1000, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"xq" = ( +/obj/structure/window/reinforced/spawner/directional/west, +/obj/structure/window/reinforced/spawner/directional/south, +/obj/item/megaphone, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"xw" = ( +/turf/open/floor/pod/dark, +/area/virtual_domain/powered) +"xJ" = ( +/obj/structure/closet/cabinet, +/obj/item/storage/backpack/duffelbag, +/obj/item/clothing/under/shorts/blue, +/obj/item/clothing/shoes/sandal{ + desc = "A very fashionable pair of flip-flops."; + name = "flip-flops" + }, +/obj/item/clothing/glasses/sunglasses, +/obj/item/clothing/neck/beads, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"xR" = ( +/obj/structure/window/reinforced/spawner/directional/east, +/obj/structure/window/reinforced/spawner/directional/north{ + layer = 2.9 + }, +/obj/structure/chair/stool/directional/south, +/obj/item/storage/backpack/duffelbag, +/obj/item/clothing/under/shorts/red, +/obj/item/clothing/glasses/sunglasses, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"xW" = ( +/turf/open/space/basic, +/area/space) +"ya" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/pill/zoom, +/obj/item/reagent_containers/pill/zoom, +/obj/item/reagent_containers/pill/zoom, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"yi" = ( +/obj/structure/sink/kitchen/directional/west{ + desc = "A sink used for washing one's hands and face. It looks rusty and home-made"; + name = "old sink" + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"yl" = ( +/obj/item/reagent_containers/cup/glass/colocup{ + pixel_x = -7; + pixel_y = -2 + }, +/obj/item/reagent_containers/cup/glass/colocup{ + pixel_x = 5; + pixel_y = 6 + }, +/obj/item/reagent_containers/cup/glass/bottle/rum{ + pixel_x = 4; + pixel_y = -3 + }, +/turf/open/floor/carpet/red, +/area/virtual_domain/powered) +"ys" = ( +/obj/effect/turf_decal/sand, +/obj/machinery/light/directional/east, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"yv" = ( +/obj/effect/turf_decal/sand, +/obj/machinery/food_cart, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"yB" = ( +/obj/item/instrument/guitar, +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"yU" = ( +/obj/structure/sign/warning/gas_mask/directional/north, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"yX" = ( +/obj/structure/chair/stool/bar/directional/south, +/turf/open/floor/carpet/red, +/area/virtual_domain/powered) +"zn" = ( +/obj/machinery/light/directional/east, +/turf/open/misc/beach/coast{ + dir = 8 + }, +/area/virtual_domain/powered) +"zw" = ( +/obj/structure/punching_bag, +/turf/open/floor/pod/dark, +/area/virtual_domain/powered) +"zI" = ( +/obj/structure/marker_beacon/indigo, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"zU" = ( +/obj/structure/flora/rock/pile/style_random, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Aa" = ( +/obj/effect/turf_decal/sand, +/obj/effect/turf_decal/stripes/asteroid/line{ + dir = 8 + }, +/obj/machinery/light/directional/west, +/turf/open/floor/sepia, +/area/virtual_domain/powered) +"Ae" = ( +/obj/structure/chair, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Al" = ( +/turf/closed/mineral/random/volcanic, +/area/lavaland/surface/outdoors/virtual_domain) +"An" = ( +/obj/structure/marker_beacon/yellow, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Au" = ( +/obj/structure/fluff/beach_umbrella/science, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"AI" = ( +/obj/structure/table/reinforced, +/obj/machinery/reagentgrinder, +/turf/open/floor/pod/light, +/area/virtual_domain/powered) +"AP" = ( +/obj/machinery/chem_dispenser/drinks/beer/fullupgrade{ + dir = 1 + }, +/obj/structure/table/wood, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Br" = ( +/obj/structure/table/wood/poker, +/obj/item/toy/cards/deck/cas{ + pixel_x = -6 + }, +/obj/item/toy/cards/deck/cas/black{ + pixel_x = -6; + pixel_y = 2 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Bu" = ( +/turf/open/misc/beach/coast{ + dir = 8 + }, +/area/virtual_domain/powered) +"Bw" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"BD" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/condiment/saltshaker, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"BJ" = ( +/obj/structure/table/wood/poker, +/obj/item/toy/cards/deck, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"BM" = ( +/turf/closed/wall/mineral/wood/nonmetal, +/area/virtual_domain/powered) +"BQ" = ( +/obj/machinery/seed_extractor, +/turf/open/floor/pod/light, +/area/virtual_domain/powered) +"Cb" = ( +/obj/machinery/light/directional/north, +/mob/living/basic/crab{ + name = "Eddie" + }, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Cv" = ( +/obj/machinery/hydroponics/constructable, +/turf/open/floor/iron/grimy, +/area/virtual_domain/powered) +"CA" = ( +/obj/structure/window/reinforced/spawner/directional/east, +/obj/effect/mob_spawn/ghost_role/human/beach/lifeguard, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"CO" = ( +/obj/machinery/vending/dinnerware, +/obj/machinery/light/directional/east, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Db" = ( +/obj/machinery/barsign/all_access, +/turf/closed/wall/mineral/wood/nonmetal, +/area/virtual_domain/powered) +"Ds" = ( +/obj/machinery/door/airlock/public/glass{ + name = "Resort Lobby" + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Dt" = ( +/obj/machinery/light/directional/east, +/obj/effect/turf_decal/sand, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"DL" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/wall/mineral/sandstone, +/area/virtual_domain/powered) +"Em" = ( +/obj/item/reagent_containers/condiment/enzyme{ + layer = 5 + }, +/obj/item/reagent_containers/cup/beaker{ + pixel_x = 5 + }, +/obj/structure/table, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Et" = ( +/obj/machinery/light/small/directional/east, +/obj/effect/mapping_helpers/burnt_floor, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Ev" = ( +/obj/structure/reagent_dispensers/beerkeg, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"EC" = ( +/obj/structure/sign/warning/gas_mask/directional/west, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"EP" = ( +/obj/machinery/light/directional/north, +/obj/machinery/washing_machine, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Fn" = ( +/turf/closed/wall/mineral/sandstone, +/area/virtual_domain/powered) +"FM" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"FQ" = ( +/obj/structure/table/reinforced, +/obj/item/secateurs, +/obj/item/reagent_containers/cup/bottle/nutrient/ez, +/turf/open/floor/pod/light, +/area/virtual_domain/powered) +"FS" = ( +/obj/effect/turf_decal/sand, +/obj/structure/sign/warning/no_smoking/circle/directional/east, +/obj/machinery/light/directional/east, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"FY" = ( +/obj/structure/mineral_door/wood, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Gh" = ( +/obj/effect/turf_decal/sand, +/obj/structure/sign/poster/contraband/starkist/directional/north, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Gz" = ( +/obj/structure/flora/tree/palm, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"GA" = ( +/obj/structure/window/reinforced/spawner/directional/north, +/obj/structure/window/reinforced/spawner/directional/west, +/obj/item/bikehorn/airhorn, +/obj/structure/table/wood, +/obj/item/storage/medkit/regular, +/obj/item/storage/medkit/brute, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Hs" = ( +/obj/machinery/shower/directional/west, +/turf/open/floor/iron/white, +/area/virtual_domain/powered) +"HF" = ( +/obj/machinery/deepfryer, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Ia" = ( +/obj/structure/urinal/directional/north, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Ii" = ( +/obj/machinery/light/directional/west, +/turf/open/floor/iron/stairs/left, +/area/virtual_domain/powered) +"Ir" = ( +/obj/machinery/vending/cola, +/obj/effect/turf_decal/sand, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Iv" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/condiment/peppermill, +/obj/item/reagent_containers/condiment/soysauce, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"IH" = ( +/obj/item/toy/beach_ball, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"IM" = ( +/obj/machinery/hydroponics/constructable, +/obj/machinery/light/directional/east, +/turf/open/floor/iron/grimy, +/area/virtual_domain/powered) +"IP" = ( +/obj/machinery/vending/snack, +/obj/effect/turf_decal/sand, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Jt" = ( +/obj/item/reagent_containers/cup/glass/bottle/beer, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"JC" = ( +/obj/structure/fluff/beach_umbrella/engine, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"JE" = ( +/obj/structure/closet/secure_closet/freezer/kitchen/all_access, +/obj/item/reagent_containers/condiment/milk, +/obj/item/reagent_containers/condiment/mayonnaise, +/obj/item/reagent_containers/condiment/flour, +/obj/item/reagent_containers/condiment/flour, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"JY" = ( +/obj/structure/flora/rock/style_random, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Kd" = ( +/obj/structure/sign/warning/secure_area, +/turf/closed/wall/mineral/sandstone, +/area/virtual_domain/powered) +"KH" = ( +/obj/structure/mineral_door/wood{ + name = "Croupier's Booth" + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"KZ" = ( +/obj/structure/flora/bush/stalky/style_random, +/turf/open/water/beach, +/area/virtual_domain/powered) +"LD" = ( +/turf/open/floor/plating, +/area/virtual_domain/powered) +"LW" = ( +/obj/item/storage/cans/sixbeer, +/turf/open/floor/carpet/orange, +/area/virtual_domain/powered) +"Mp" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/cup/glass/drinkingglass/virtual_domain{ + pixel_y = 7; + pixel_x = 4 + }, +/obj/item/reagent_containers/cup/glass/drinkingglass/virtual_domain, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Mw" = ( +/obj/structure/chair/sofa/right/brown, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Mz" = ( +/obj/structure/chair/sofa/left/brown, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Nr" = ( +/obj/machinery/light/directional/north, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Nw" = ( +/obj/item/bedsheet/dorms{ + dir = 4 + }, +/obj/structure/bed{ + dir = 4 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"NM" = ( +/obj/structure/closet/crate/hydroponics, +/obj/item/food/grown/ambrosia/vulgaris, +/obj/item/food/grown/ambrosia/vulgaris, +/obj/item/food/grown/ambrosia/vulgaris, +/obj/item/food/grown/ambrosia/vulgaris, +/obj/item/food/grown/ambrosia/vulgaris, +/obj/item/food/grown/ambrosia/vulgaris, +/obj/item/food/grown/ambrosia/vulgaris, +/obj/item/food/grown/ambrosia/vulgaris, +/obj/item/food/grown/ambrosia/vulgaris, +/obj/item/food/grown/ambrosia/vulgaris, +/turf/open/floor/iron/grimy, +/area/virtual_domain/powered) +"NX" = ( +/obj/effect/landmark/bitrunning/loot_signal, +/turf/open/floor/light/colour_cycle/dancefloor_a, +/area/virtual_domain/powered) +"OE" = ( +/obj/effect/mob_spawn/ghost_role/human/beach{ + dir = 4 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"OK" = ( +/obj/structure/sign/warning/gas_mask/directional/north, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"OR" = ( +/obj/machinery/light/directional/south, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"OW" = ( +/obj/structure/sink/kitchen/directional/east{ + desc = "A sink used for washing one's hands and face. It looks rusty and home-made"; + name = "old sink" + }, +/turf/open/floor/pod/light, +/area/virtual_domain/powered) +"OZ" = ( +/obj/structure/marker_beacon/teal, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Pc" = ( +/obj/structure/chair/wood, +/obj/machinery/light/directional/west, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Pg" = ( +/obj/structure/sign/poster/official/high_class_martini/directional/west, +/obj/effect/mob_spawn/ghost_role/human/bartender{ + dir = 4 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"PM" = ( +/obj/machinery/door/airlock/external/ruin, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Qb" = ( +/obj/machinery/griddle, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Qu" = ( +/obj/structure/curtain, +/turf/open/floor/iron/white, +/area/virtual_domain/powered) +"QP" = ( +/obj/structure/extinguisher_cabinet/directional/north, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"QX" = ( +/obj/machinery/chem_dispenser/drinks/fullupgrade{ + dir = 1 + }, +/obj/structure/table/wood, +/obj/machinery/light/small/directional/east, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Rx" = ( +/turf/open/floor/iron/stairs/medium, +/area/virtual_domain/powered) +"RL" = ( +/obj/structure/closet/cabinet, +/obj/item/storage/backpack/duffelbag, +/obj/item/clothing/under/shorts/purple, +/obj/item/clothing/shoes/cookflops{ + desc = "A very fashionable pair of flip flops."; + name = "flip-flops" + }, +/obj/item/clothing/glasses/sunglasses/big, +/obj/item/clothing/neck/beads, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Sg" = ( +/obj/structure/flora/coconuts, +/obj/machinery/light/directional/north, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"SB" = ( +/obj/machinery/door/airlock/sandstone{ + name = "Resort Bathroom" + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"SD" = ( +/obj/machinery/door/airlock/sandstone{ + name = "Bar Access" + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"SY" = ( +/obj/machinery/door/airlock/sandstone{ + name = "Surfer Shack 2" + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"TG" = ( +/turf/open/floor/wood, +/area/virtual_domain/powered) +"TJ" = ( +/obj/structure/fluff/beach_umbrella/security, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"TX" = ( +/obj/structure/sign/poster/contraband/ambrosia_vulgaris/directional/north, +/turf/open/floor/iron/grimy, +/area/virtual_domain/powered) +"Ud" = ( +/obj/effect/turf_decal/sand, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Uh" = ( +/turf/open/floor/iron/stairs/old, +/area/virtual_domain/powered) +"Uq" = ( +/obj/structure/weightmachine/weightlifter, +/turf/open/floor/pod/dark, +/area/virtual_domain/powered) +"UU" = ( +/obj/structure/flora/bush/large/style_random, +/obj/structure/flora/bush/jungle/a/style_random, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Ve" = ( +/obj/machinery/processor, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"VA" = ( +/obj/machinery/computer/slot_machine, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"VH" = ( +/obj/machinery/light/directional/west, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"VX" = ( +/obj/structure/flora/bush/large/style_random, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"We" = ( +/obj/structure/table/wood, +/obj/item/book/manual/wiki/cooking_to_serve_man, +/obj/item/clothing/suit/apron/chef, +/obj/item/clothing/head/utility/chefhat, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Wg" = ( +/obj/structure/dresser, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Ww" = ( +/turf/open/water/beach, +/area/virtual_domain/powered) +"WL" = ( +/obj/machinery/light/directional/north, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"WO" = ( +/obj/structure/flora/bush/jungle/a/style_random, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"WW" = ( +/obj/effect/turf_decal/sand, +/obj/machinery/icecream_vat, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"WX" = ( +/obj/item/toy/plush/lizard_plushie/green{ + name = "Soaks-The-Rays" + }, +/turf/open/floor/carpet/orange, +/area/virtual_domain/powered) +"Xt" = ( +/turf/open/misc/beach/coast/corner{ + dir = 4 + }, +/area/virtual_domain/powered) +"Xv" = ( +/obj/structure/table/wood, +/obj/structure/bedsheetbin, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"XL" = ( +/obj/machinery/light/directional/east, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"XM" = ( +/turf/open/misc/beach/coast, +/area/virtual_domain/powered) +"XP" = ( +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"XT" = ( +/obj/effect/turf_decal/sand, +/obj/structure/sign/departments/botany/directional/south, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Yi" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/obj/item/toy/seashell, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Yq" = ( +/obj/machinery/portable_atmospherics/canister/air, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"YI" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Supply Room" + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"YJ" = ( +/turf/open/floor/carpet/purple, +/area/virtual_domain/powered) +"YN" = ( +/obj/effect/turf_decal/sand, +/obj/machinery/light/directional/west, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Zb" = ( +/obj/structure/sign/poster/official/cohiba_robusto_ad/directional/west, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Zd" = ( +/obj/structure/sign/poster/contraband/space_cola/directional/north, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Zg" = ( +/obj/structure/table, +/obj/machinery/microwave, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Zt" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/pill/morphine, +/obj/item/storage/fancy/donut_box, +/turf/open/floor/wood, +/area/virtual_domain/powered) + +(1,1,1) = {" +pr +pr +pr +pr +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +kv +"} +(2,1,1) = {" +pr +pr +pr +pr +iz +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +iz +"} +(3,1,1) = {" +pr +pr +pr +pr +iz +Al +gl +gl +gl +gl +gl +Al +Al +gl +gl +gl +gl +gl +Al +Al +gl +gl +gl +Al +gl +gl +gl +gl +Al +Al +gl +gl +gl +Al +Al +gl +gl +gl +gl +Al +iz +"} +(4,1,1) = {" +pr +pr +pr +pr +iz +Al +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +Al +iz +"} +(5,1,1) = {" +pr +pr +pr +pr +iz +Al +gl +gl +gl +gl +gl +gl +gl +gl +gl +zI +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +Al +iz +"} +(6,1,1) = {" +pr +pr +pr +pr +iz +Al +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +OZ +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +Al +iz +"} +(7,1,1) = {" +pr +pr +pr +pr +iz +Al +gl +gl +gl +An +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +ke +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +ml +ml +ml +ml +ml +FM +gl +Al +iz +"} +(8,1,1) = {" +pr +pr +pr +pr +iz +Al +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +ml +ml +ml +ml +ml +ml +gl +Al +iz +"} +(9,1,1) = {" +pr +pr +pr +pr +iz +Al +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +gl +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +gl +gl +ml +ml +ml +ml +ml +ml +gl +Al +iz +"} +(10,1,1) = {" +pr +pr +pr +pr +iz +Al +Al +Al +Al +xb +xb +uc +Al +Al +gl +gl +gl +Al +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Al +gl +gl +ml +ml +ml +ml +ml +ml +gl +Al +iz +"} +(11,1,1) = {" +iz +iz +iz +iz +iz +Al +Al +Al +Fn +PM +PM +Fn +Fn +Al +Al +Al +Fn +Fn +Fn +Pc +bf +Bw +Fn +Ev +Pg +iR +kG +di +Fn +DL +Al +gl +ml +ml +ml +ml +ml +ml +gl +Al +iz +"} +(12,1,1) = {" +iz +Al +Al +Al +Al +Al +Al +Al +Fn +pT +LD +LD +Fn +Fn +Kd +Fn +Fn +bQ +cv +wD +Bw +JY +Fn +db +TG +TG +TG +TG +AP +Fn +Al +gl +ml +ml +ml +ml +ml +ml +gl +Al +iz +"} +(13,1,1) = {" +iz +Al +Fn +Fn +Fn +Fn +Fn +Fn +Fn +LD +pT +LD +EC +LD +pT +PM +wD +wD +cv +wD +wD +OR +Fn +ug +TG +TG +TG +TG +QX +Fn +Al +gl +ml +ml +ml +ml +ml +sT +gl +Al +iz +"} +(14,1,1) = {" +iz +Al +Fn +VA +kT +Zb +TG +Fn +Fn +Fn +yU +LD +Et +LD +LD +PM +wD +wD +wD +wD +wD +qc +Fn +Fn +SD +Mp +uq +fc +Fn +Fn +Al +gl +gl +gl +gl +gl +gl +gl +gl +Al +iz +"} +(15,1,1) = {" +iz +Al +Fn +VA +yX +ag +kT +Br +TG +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Gz +wD +Bw +rm +wD +wD +wD +Ii +dx +kn +kn +kn +Aa +Fn +Al +gl +gl +gl +gl +gl +gl +gl +gl +Al +iz +"} +(16,1,1) = {" +iz +Al +Fn +pC +yX +ag +kT +BJ +kT +Fn +as +ab +Ir +IP +YN +uV +wD +wD +wD +mG +vv +Bw +wD +Rx +uU +lS +lS +lS +uU +Fn +Al +gl +gl +gl +gl +gl +gl +gl +gl +Al +iz +"} +(17,1,1) = {" +iz +Al +Fn +Mw +ag +ag +vp +xk +TG +Fn +Ud +Ud +bC +Ud +Ud +wD +IH +wD +wD +Bw +wD +wD +wD +Rx +uU +lS +NX +lS +cz +Fn +Al +gl +gl +gl +gl +gl +gl +gl +gl +Al +iz +"} +(18,1,1) = {" +iz +Al +Fn +Mz +TG +TG +Fn +Fn +KH +Fn +Zd +wD +wD +Bw +wD +VX +wD +UU +wD +wD +wD +wD +wD +Rx +uU +lS +lS +lS +uU +Fn +Al +gl +gl +gl +gl +gl +gl +gl +gl +Al +iz +"} +(19,1,1) = {" +iz +Al +Fn +Fn +tE +tE +Fn +uV +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +jc +uU +uU +uU +uU +uU +Fn +Fn +gl +gl +gl +gl +gl +gl +gl +gl +Al +iz +"} +(20,1,1) = {" +iz +Al +Fn +zU +wD +wD +wD +wD +Dt +Ud +Ud +Ud +Ud +Ud +Ud +Ud +ys +wD +wD +TJ +wb +wD +wD +vT +gJ +gJ +gJ +gJ +gJ +oE +Fn +gl +gl +Al +Al +gl +gl +Al +gl +Al +iz +"} +(21,1,1) = {" +iz +Al +Fn +wD +wD +Bw +wD +wD +BM +BM +BM +We +Zt +BD +Iv +BM +Db +Nr +wD +yl +ag +wD +wD +XM +KZ +Ww +Ww +Ww +cG +dj +Fn +Al +Al +Al +Al +Al +Al +Al +Al +Al +iz +"} +(22,1,1) = {" +iz +Al +Fn +Fn +wD +wD +wD +wD +BM +Zg +VH +TG +TG +TG +TG +mX +BM +wD +wD +Au +wD +rT +wD +XM +Ww +Ww +Ww +Ww +Ww +dj +Fn +Al +iz +iz +iz +iz +iz +iz +iz +iz +iz +"} +(23,1,1) = {" +iz +Al +xb +Fn +Cb +wD +JC +wD +BM +HF +TG +JE +BM +aw +TG +TG +ya +wD +wD +YJ +YJ +wD +wD +XM +Ww +Ww +Ww +Ww +Ww +dj +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(24,1,1) = {" +iz +Al +xb +Fn +wD +Gz +WX +wD +BM +Em +TG +mq +ri +Qb +TG +TG +cb +wD +wD +bQ +wD +wD +wD +XM +Ww +Ww +KZ +KZ +Ww +pZ +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(25,1,1) = {" +iz +Al +xb +Fn +OK +Gz +LW +wD +BM +bS +TG +oP +BM +vq +TG +TG +vN +wD +wD +XP +yB +wD +wD +XM +KZ +Ww +KZ +gh +Ww +dj +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(26,1,1) = {" +iz +Al +xb +Fn +Sg +wD +wD +wD +BM +Ve +rc +yi +TG +TG +TG +CO +BM +wD +Yi +XL +wD +wD +wD +XM +Ww +Ww +Ww +Ww +Ww +dj +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(27,1,1) = {" +iz +Al +Fn +Fn +Bw +wD +wD +wD +BM +BM +BM +BM +FY +BM +BM +BM +er +wD +GA +xq +jy +wD +wD +XM +Ww +cG +Ww +Ww +KZ +dj +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(28,1,1) = {" +iz +Al +Fn +Nr +wD +wD +Bw +wD +YN +Ud +WW +yv +Ud +Ud +Ud +Ud +YN +wD +xR +CA +Uh +wD +qW +XM +Ww +Ww +Ww +Ww +Ww +pZ +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(29,1,1) = {" +iz +Al +Fn +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +wD +Jt +wD +mP +zn +Bu +Bu +Bu +Bu +Xt +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(30,1,1) = {" +iz +Al +Fn +Ds +Ds +Fn +VX +wD +wD +wD +wD +wD +XL +wD +wD +wD +wD +wD +wD +wD +wD +XT +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(31,1,1) = {" +iz +Al +Fn +TG +TG +Fn +Fn +jl +Fn +Fn +qR +Fn +Fn +WO +wD +Bw +wD +wD +wD +wD +bM +Ud +aE +aE +aE +lq +fr +hk +Fn +Al +Al +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(32,1,1) = {" +iz +Al +Fn +TG +TG +TG +Fn +Fn +Fn +dZ +OE +Nw +Fn +Fn +qR +Fn +Fn +wD +wD +wD +Ae +Ud +zw +xw +Uq +aE +aE +aE +Fn +Fn +Al +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(33,1,1) = {" +iz +Al +Fn +EP +TG +TG +TG +TG +hG +TG +TG +TG +Fn +dZ +OE +Nw +Fn +Gz +uV +wD +wD +Ud +xw +xw +xw +aE +aE +aE +OW +Fn +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(34,1,1) = {" +iz +Al +Fn +Xv +TG +hE +TG +TG +Fn +Wg +rc +xJ +Fn +TG +TG +dI +Fn +wD +wD +Bw +wD +lB +zw +xw +Uq +aE +FQ +aE +aE +jg +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(35,1,1) = {" +iz +Al +Fn +Fn +SB +Fn +WL +TG +Fn +Fn +Fn +Fn +Fn +Wg +TG +RL +Fn +Gh +Ud +Ud +Ud +FS +aE +aE +aE +aE +AI +BQ +aE +NM +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(36,1,1) = {" +iz +Al +Fn +kK +TG +Fn +TG +TG +TG +TG +qg +TG +Fn +Fn +SY +Fn +Fn +Ds +Ds +Fn +YI +Fn +Fn +Fn +TX +aE +aE +aE +aE +uk +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(37,1,1) = {" +iz +Al +Fn +Ia +dI +Fn +Fn +Fn +QP +TG +TG +TG +TG +TG +TG +TG +TG +TG +TG +Fn +ve +nP +ed +Fn +Cv +Cv +IM +Cv +Cv +Fn +Fn +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(38,1,1) = {" +iz +Al +Fn +tZ +TG +Qu +Hs +Fn +Fn +Fn +TG +rc +TG +TG +TG +tF +rc +TG +TG +Fn +Yq +aZ +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Al +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(39,1,1) = {" +iz +Al +Fn +Fn +Fn +Fn +Fn +Fn +Al +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Fn +Al +Al +Al +Al +Al +Al +Al +Al +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(40,1,1) = {" +iz +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +Al +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} +(41,1,1) = {" +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +iz +pr +pr +pr +pr +pr +pr +pr +xW +"} diff --git a/_maps/virtual_domains/blood_drunk_miner.dmm b/_maps/virtual_domains/blood_drunk_miner.dmm new file mode 100644 index 00000000000..c3369a1c822 --- /dev/null +++ b/_maps/virtual_domains/blood_drunk_miner.dmm @@ -0,0 +1,1887 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"b" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"c" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"d" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"f" = ( +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile/block/cracked, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"h" = ( +/obj/machinery/light/small/blacklight/directional/south, +/obj/effect/baseturf_helper/virtual_domain, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/virtual_domain/powered) +"i" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile/cracked, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"j" = ( +/obj/structure/marker_beacon/jade, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"k" = ( +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"l" = ( +/obj/structure/stone_tile/block, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"m" = ( +/obj/structure/marker_beacon/olive, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"n" = ( +/obj/structure/marker_beacon/cerulean, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"o" = ( +/obj/structure/marker_beacon/yellow, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"q" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"r" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"s" = ( +/turf/closed/mineral/volcanic/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"t" = ( +/obj/structure/marker_beacon/indigo, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"u" = ( +/obj/structure/stone_tile/cracked, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"v" = ( +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"w" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"x" = ( +/obj/structure/stone_tile, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"y" = ( +/obj/structure/marker_beacon/violet, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"z" = ( +/obj/structure/stone_tile/block, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"A" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"C" = ( +/obj/effect/mob_spawn/corpse/human/miner, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"G" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"H" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"I" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"J" = ( +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"K" = ( +/obj/structure/marker_beacon/teal, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"L" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"O" = ( +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/block{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"P" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"S" = ( +/obj/structure/stone_tile/surrounding/cracked{ + dir = 6 + }, +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/virtual_domain, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"T" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"W" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"X" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Y" = ( +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Z" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) + +(1,1,1) = {" +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +d +"} +(2,1,1) = {" +v +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +v +"} +(3,1,1) = {" +v +s +s +s +s +J +J +s +s +J +J +s +s +J +J +J +J +s +s +s +J +J +J +s +s +s +s +s +s +s +s +s +s +J +J +s +s +s +J +J +s +s +J +J +s +v +"} +(4,1,1) = {" +v +s +s +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +a +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +s +v +"} +(5,1,1) = {" +v +s +s +J +a +J +J +J +J +a +J +J +J +J +a +a +J +J +J +J +J +a +a +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +s +s +v +"} +(6,1,1) = {" +v +s +s +J +a +J +J +a +a +a +a +a +a +a +a +a +a +a +a +J +a +a +a +a +a +J +J +J +a +a +J +J +J +a +a +J +a +J +a +a +J +J +J +s +s +v +"} +(7,1,1) = {" +v +s +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +J +s +v +"} +(8,1,1) = {" +v +s +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +s +v +"} +(9,1,1) = {" +v +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +j +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(10,1,1) = {" +v +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +t +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(11,1,1) = {" +v +s +s +J +J +J +a +a +a +y +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(12,1,1) = {" +v +s +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +C +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +J +s +v +"} +(13,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(14,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +T +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(15,1,1) = {" +v +s +J +J +J +a +a +a +a +a +a +a +a +a +a +X +z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +h +c +c +c +c +c +L +a +a +J +J +s +v +"} +(16,1,1) = {" +v +s +J +J +J +J +a +a +a +a +a +a +a +T +W +a +r +a +i +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +c +c +c +c +c +c +a +a +J +J +s +v +"} +(17,1,1) = {" +v +s +s +J +J +J +a +a +a +a +a +a +a +a +I +b +k +l +x +a +T +k +a +a +a +m +a +a +a +a +a +o +a +a +c +c +c +c +c +c +a +a +J +J +s +v +"} +(18,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +a +P +S +A +O +u +r +k +a +a +a +a +a +a +a +a +a +a +a +c +c +c +c +c +c +a +J +J +s +s +v +"} +(19,1,1) = {" +v +s +J +J +J +a +a +a +a +a +a +a +a +k +G +H +x +f +k +a +Y +T +u +a +a +a +a +a +a +a +a +a +a +a +c +c +c +c +c +c +a +a +J +J +s +v +"} +(20,1,1) = {" +v +s +J +J +J +J +a +a +a +a +a +a +a +Y +x +a +Z +a +z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +c +c +c +c +c +c +a +a +J +J +s +v +"} +(21,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +a +z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +h +c +c +c +c +c +q +a +a +J +s +s +v +"} +(22,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +w +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +s +s +v +"} +(23,1,1) = {" +v +s +J +J +a +a +a +a +a +a +n +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +s +s +v +"} +(24,1,1) = {" +v +s +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +C +a +a +a +a +a +J +J +s +v +"} +(25,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +J +s +v +"} +(26,1,1) = {" +v +s +s +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +K +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(27,1,1) = {" +v +s +s +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +j +a +a +a +a +a +a +a +a +a +J +J +s +v +"} +(28,1,1) = {" +v +s +J +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +J +s +v +"} +(29,1,1) = {" +v +s +J +J +J +J +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +J +J +s +s +v +"} +(30,1,1) = {" +v +s +s +J +J +J +J +a +a +J +J +J +a +a +a +a +J +J +J +a +a +a +J +J +J +a +a +a +J +J +a +a +a +a +a +a +J +J +a +a +a +J +J +s +s +v +"} +(31,1,1) = {" +v +s +s +a +J +J +J +J +J +J +J +J +J +a +a +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +a +a +a +J +J +J +J +J +J +J +J +J +s +v +"} +(32,1,1) = {" +v +s +s +a +J +J +J +J +J +J +J +J +J +J +J +J +J +a +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +J +s +v +"} +(33,1,1) = {" +v +s +s +s +s +s +J +J +s +s +s +s +J +J +s +s +s +s +s +s +J +J +s +s +s +s +J +J +s +s +s +s +J +J +J +s +s +s +s +s +s +J +J +J +s +v +"} +(34,1,1) = {" +v +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +s +v +"} +(35,1,1) = {" +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +"} diff --git a/_maps/virtual_domains/bubblegum.dmm b/_maps/virtual_domains/bubblegum.dmm new file mode 100644 index 00000000000..3381b173539 --- /dev/null +++ b/_maps/virtual_domains/bubblegum.dmm @@ -0,0 +1,2250 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"c" = ( +/obj/effect/mob_spawn/corpse/human/miner, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"d" = ( +/obj/structure/marker_beacon/jade, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"f" = ( +/obj/structure/marker_beacon/burgundy, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"g" = ( +/obj/structure/marker_beacon/teal, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"p" = ( +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"r" = ( +/obj/structure/marker_beacon/fuchsia, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"w" = ( +/obj/machinery/light/small/blacklight/directional/south, +/obj/effect/baseturf_helper/virtual_domain, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/virtual_domain/powered) +"x" = ( +/obj/structure/marker_beacon/olive, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"z" = ( +/obj/structure/marker_beacon/purple, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"A" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"C" = ( +/mob/living/simple_animal/hostile/megafauna/bubblegum/virtual_domain, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"F" = ( +/turf/open/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"G" = ( +/obj/structure/marker_beacon/violet, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"I" = ( +/obj/structure/marker_beacon/bronze, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"M" = ( +/obj/structure/marker_beacon/indigo, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"R" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/open/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"S" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"T" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"W" = ( +/obj/structure/marker_beacon/cerulean, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"X" = ( +/obj/structure/marker_beacon/lime, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Y" = ( +/obj/structure/marker_beacon/yellow, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Z" = ( +/turf/closed/mineral/volcanic/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) + +(1,1,1) = {" +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +R +"} +(2,1,1) = {" +F +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +F +"} +(3,1,1) = {" +F +Z +a +a +Z +Z +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +Z +Z +a +a +a +a +a +a +a +a +Z +Z +a +a +a +a +a +a +Z +Z +Z +F +"} +(4,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(5,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +p +Z +F +"} +(6,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +G +a +a +a +a +a +a +a +a +a +a +a +a +p +p +Z +F +"} +(7,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +x +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +a +a +a +a +p +Z +F +"} +(8,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +Z +a +a +a +Z +Z +F +"} +(9,1,1) = {" +F +Z +a +a +a +a +a +a +p +p +p +p +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +Z +F +"} +(10,1,1) = {" +F +Z +Z +a +a +a +a +a +Z +Z +Z +p +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +Z +F +"} +(11,1,1) = {" +F +Z +Z +a +a +a +a +a +Z +Z +Z +p +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +Z +a +a +a +a +a +a +a +a +p +p +a +a +a +a +a +Z +F +"} +(12,1,1) = {" +F +Z +Z +a +a +a +a +a +p +Z +p +p +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +Z +a +a +a +a +a +a +a +p +a +a +a +a +a +Z +F +"} +(13,1,1) = {" +F +Z +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +Z +Z +a +a +a +a +a +M +a +a +a +a +a +a +a +Z +F +"} +(14,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +Z +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(15,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +c +a +a +a +a +a +a +Z +F +"} +(16,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +I +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(17,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +W +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(18,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(19,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(20,1,1) = {" +F +Z +a +a +a +a +a +z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(21,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +w +S +S +S +S +S +T +a +Z +F +"} +(22,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +S +S +S +S +S +S +a +Z +F +"} +(23,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +C +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +S +S +S +S +S +S +a +Z +F +"} +(24,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +X +a +a +S +S +S +S +S +S +a +Z +F +"} +(25,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +S +S +S +S +S +S +a +Z +F +"} +(26,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +S +S +S +S +S +S +a +Z +F +"} +(27,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +w +S +S +S +S +S +A +a +Z +F +"} +(28,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +f +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(29,1,1) = {" +F +Z +a +a +a +a +a +a +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +r +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(30,1,1) = {" +F +Z +a +a +a +a +a +a +Z +Z +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(31,1,1) = {" +F +Z +a +a +a +a +a +a +Z +Z +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(32,1,1) = {" +F +Z +a +a +a +a +a +a +a +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(33,1,1) = {" +F +Z +a +a +a +a +a +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +d +a +a +a +a +a +a +a +Z +F +"} +(34,1,1) = {" +F +Z +Z +a +a +a +a +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(35,1,1) = {" +F +Z +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +X +a +a +a +a +a +a +a +a +Z +Z +Z +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(36,1,1) = {" +F +Z +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +Z +Z +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(37,1,1) = {" +F +Z +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +Z +F +"} +(38,1,1) = {" +F +Z +a +a +a +p +p +a +a +a +a +a +g +a +a +a +a +Z +a +a +a +a +a +a +p +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +Z +F +"} +(39,1,1) = {" +F +Z +a +a +a +p +p +a +a +a +a +a +a +a +a +a +Z +Z +Z +a +a +a +a +a +p +p +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(40,1,1) = {" +F +Z +a +c +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(41,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Y +a +a +a +a +a +a +a +Z +F +"} +(42,1,1) = {" +F +Z +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +Z +F +"} +(43,1,1) = {" +F +Z +a +Z +Z +Z +Z +a +a +a +a +a +Z +Z +Z +Z +a +a +a +Z +Z +Z +Z +Z +a +a +a +a +a +a +Z +Z +Z +Z +a +a +a +a +a +a +Z +Z +a +a +Z +F +"} +(44,1,1) = {" +F +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +Z +F +"} +(45,1,1) = {" +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +F +"} diff --git a/_maps/virtual_domains/clown_planet.dmm b/_maps/virtual_domains/clown_planet.dmm new file mode 100644 index 00000000000..01d7b88a5ef --- /dev/null +++ b/_maps/virtual_domains/clown_planet.dmm @@ -0,0 +1,2323 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"ai" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small/directional/west, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"aI" = ( +/obj/item/bikehorn/airhorn, +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"aM" = ( +/obj/item/bikehorn, +/turf/open/indestructible/honk, +/area/virtual_domain/powered) +"aP" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/decal/cleanable/food/pie_smudge, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"ba" = ( +/obj/structure/mecha_wreckage/honker, +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"bi" = ( +/obj/item/bikehorn, +/obj/structure/disposalpipe/segment{ + invisibility = 101 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"bp" = ( +/turf/open/indestructible/light, +/area/virtual_domain/powered) +"bq" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"by" = ( +/turf/closed/wall/r_wall, +/area/lavaland/surface/outdoors/virtual_domain) +"bQ" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/obj/effect/turf_decal/tile/red/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"bR" = ( +/obj/item/paper/crumpled/bloody/ruins/lavaland/clown_planet/hope, +/obj/effect/decal/cleanable/blood/old, +/obj/effect/mapping_helpers/no_lava, +/turf/open/floor/noslip, +/area/virtual_domain/powered) +"bU" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"cw" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"cM" = ( +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/structure/disposaloutlet{ + dir = 1 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"cW" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/segment{ + invisibility = 101 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"ed" = ( +/obj/structure/disposalpipe/segment{ + invisibility = 101 + }, +/obj/machinery/light/small/directional/west, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"eE" = ( +/obj/structure/window/reinforced/spawner/directional/south, +/obj/structure/disposalpipe/segment{ + invisibility = 101 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"fh" = ( +/obj/effect/mob_spawn/corpse/human/damaged, +/obj/effect/decal/cleanable/blood/old, +/obj/structure/disposalpipe/segment{ + invisibility = 101 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"gr" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"gy" = ( +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/effect/baseturf_helper/virtual_domain, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"gH" = ( +/obj/item/bikehorn, +/obj/effect/decal/cleanable/dirt, +/turf/open/indestructible/honk, +/area/virtual_domain/powered) +"gK" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"hK" = ( +/obj/item/clothing/head/cone, +/obj/effect/mapping_helpers/no_lava, +/turf/open/floor/noslip, +/area/virtual_domain/powered) +"hY" = ( +/turf/template_noop, +/area/template_noop) +"ij" = ( +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/machinery/disposal/delivery_chute{ + dir = 4 + }, +/turf/open/floor/noslip, +/area/virtual_domain/powered) +"ik" = ( +/turf/open/lava/smooth, +/area/virtual_domain/powered) +"iR" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"ki" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"kn" = ( +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"lj" = ( +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/obj/machinery/disposal/delivery_chute{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"lm" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/machinery/light/small/directional/east, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"lr" = ( +/obj/item/bikehorn, +/obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/segment{ + invisibility = 101 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"lx" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"ly" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"lP" = ( +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"mD" = ( +/turf/open/floor/plating, +/area/virtual_domain/powered) +"mE" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"mF" = ( +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"nE" = ( +/obj/effect/mapping_helpers/no_lava, +/turf/closed/wall/r_wall, +/area/virtual_domain/powered) +"oA" = ( +/obj/effect/turf_decal/tile/red/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"oI" = ( +/obj/structure/table/glass, +/obj/item/grown/bananapeel/bluespace, +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"pl" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"ps" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/effect/turf_decal/tile/red/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"qM" = ( +/obj/structure/disposalpipe/segment{ + invisibility = 101 + }, +/obj/machinery/light/small/directional/north, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"rg" = ( +/obj/item/coin/bananium, +/obj/item/coin/bananium, +/obj/item/coin/bananium, +/obj/item/coin/bananium, +/obj/machinery/light/small/directional/west, +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"rh" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"rr" = ( +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"rH" = ( +/obj/structure/disposalpipe/junction/yjunction{ + dir = 1; + invisibility = 101 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"rT" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"sq" = ( +/obj/machinery/light/directional/north, +/obj/effect/turf_decal/tile/red/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"sT" = ( +/obj/structure/disposalpipe/sorting/mail/flip{ + dir = 1 + }, +/obj/effect/mapping_helpers/mail_sorting/supply/qm_office, +/turf/closed/wall/r_wall, +/area/virtual_domain/powered) +"tq" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"tt" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/turf/open/indestructible/light, +/area/virtual_domain/powered) +"tv" = ( +/obj/effect/mob_spawn/corpse/human/damaged, +/obj/effect/decal/cleanable/blood/old, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"tF" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"tI" = ( +/obj/item/coin/bananium, +/obj/item/coin/bananium, +/obj/item/coin/bananium, +/obj/item/coin/bananium, +/obj/machinery/light/small/directional/east, +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"uX" = ( +/obj/effect/mapping_helpers/no_lava, +/mob/living/basic/clown, +/turf/open/floor/noslip, +/area/virtual_domain/powered) +"uY" = ( +/turf/closed/mineral/bananium, +/area/virtual_domain/powered) +"uZ" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/obj/structure/table, +/obj/item/paper/crumpled/bloody/ruins/lavaland/clown_planet/escape, +/obj/item/pen/fourcolor, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"wz" = ( +/obj/machinery/light/small/directional/south, +/obj/effect/mapping_helpers/no_lava, +/mob/living/basic/clown, +/turf/open/floor/noslip, +/area/virtual_domain/powered) +"xt" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"yd" = ( +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"yz" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/closed/wall/r_wall, +/area/virtual_domain/powered) +"yS" = ( +/obj/structure/marker_beacon/yellow, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"yZ" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"zm" = ( +/obj/effect/decal/cleanable/cobweb, +/obj/effect/turf_decal/tile/red/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"zA" = ( +/obj/structure/statue/bananium/clown, +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"zF" = ( +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/obj/structure/disposaloutlet{ + dir = 8 + }, +/turf/open/floor/noslip, +/area/virtual_domain/powered) +"Aa" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/effect/turf_decal/tile/red/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"Bi" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/obj/effect/decal/cleanable/cobweb, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"Cp" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/obj/machinery/light/small/directional/west, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"Cs" = ( +/obj/item/bikehorn, +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"Dh" = ( +/turf/closed/wall/r_wall, +/area/virtual_domain/powered) +"Do" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"DL" = ( +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/item/bikehorn, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"Ex" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"FI" = ( +/obj/item/reagent_containers/cup/glass/trophy/gold_cup, +/obj/structure/table/glass, +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"Gg" = ( +/obj/structure/table/glass, +/obj/item/gun/magic/staff/honk, +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"Hq" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Hr" = ( +/obj/structure/table/glass, +/obj/item/clothing/shoes/clown_shoes/banana_shoes, +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"HQ" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/machinery/light/small/directional/east, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"Ie" = ( +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"Iz" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"IN" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/turf/closed/wall/r_wall, +/area/virtual_domain/powered) +"IY" = ( +/turf/open/indestructible/honk, +/area/virtual_domain/powered) +"Jv" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/indestructible/honk, +/area/virtual_domain/powered) +"JB" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/obj/machinery/light/small/directional/north, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"Ka" = ( +/obj/effect/decal/cleanable/food/pie_smudge, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"Kh" = ( +/obj/effect/mob_spawn/corpse/human/damaged, +/obj/effect/decal/cleanable/blood/old, +/turf/open/indestructible/honk, +/area/virtual_domain/powered) +"KG" = ( +/obj/item/pickaxe, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"KI" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/turf/closed/wall/r_wall, +/area/lavaland/surface/outdoors/virtual_domain) +"Lv" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/obj/machinery/light/small/directional/east, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"Nv" = ( +/obj/effect/decal/cleanable/cobweb, +/turf/open/indestructible/honk, +/area/virtual_domain/powered) +"NB" = ( +/obj/machinery/disposal/delivery_chute, +/obj/structure/disposalpipe/trunk{ + dir = 1 + }, +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"NL" = ( +/obj/machinery/disposal/delivery_chute{ + desc = "The following is engraved upon the chute: A FATE WORSE THAN DEATH LIES WITHIN"; + dir = 1; + name = "THE TRIAL OF HONKITUDE" + }, +/obj/structure/disposalpipe/trunk, +/obj/effect/mapping_helpers/no_lava, +/turf/open/floor/noslip, +/area/virtual_domain/powered) +"NW" = ( +/obj/structure/table/glass, +/obj/item/reagent_containers/spray/waterflower/superlube, +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"Ok" = ( +/obj/item/bikehorn, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"Ov" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"PJ" = ( +/obj/structure/disposalpipe/trunk, +/obj/structure/disposaloutlet{ + dir = 1 + }, +/obj/effect/mapping_helpers/no_lava, +/turf/open/floor/noslip, +/area/virtual_domain/powered) +"PM" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"PQ" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/obj/item/pickaxe, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"QP" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"QX" = ( +/obj/structure/closet/crate/secure/bitrunning/encrypted, +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"Rh" = ( +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"Rx" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/obj/structure/table, +/obj/item/flashlight/lamp/bananalamp, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"RU" = ( +/obj/structure/disposalpipe/segment{ + invisibility = 101 + }, +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"Sg" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/obj/effect/decal/cleanable/food/pie_smudge, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"Sm" = ( +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/closed/wall/r_wall, +/area/virtual_domain/powered) +"Tm" = ( +/obj/effect/decal/cleanable/food/pie_smudge, +/obj/structure/disposalpipe/segment{ + invisibility = 101 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"Tx" = ( +/obj/structure/disposalpipe/segment{ + invisibility = 101 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"TH" = ( +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/obj/structure/disposaloutlet{ + dir = 8 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"TK" = ( +/obj/structure/disposalpipe/segment{ + invisibility = 101 + }, +/turf/closed/wall/r_wall, +/area/virtual_domain/powered) +"Ug" = ( +/obj/machinery/light/small/directional/north, +/turf/open/floor/carpet, +/area/virtual_domain/powered) +"UL" = ( +/obj/effect/decal/cleanable/oil, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"UN" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"UQ" = ( +/obj/structure/disposalpipe/segment{ + invisibility = 101 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"UY" = ( +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"Vv" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/turf/closed/wall/r_wall, +/area/virtual_domain/powered) +"Vx" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"VI" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"VQ" = ( +/turf/open/floor/noslip, +/area/virtual_domain/powered) +"Ww" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/indestructible/permalube, +/area/virtual_domain/powered) +"WB" = ( +/obj/machinery/disposal/delivery_chute{ + dir = 1 + }, +/obj/structure/disposalpipe/trunk, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"WT" = ( +/obj/machinery/door/airlock/bananium, +/turf/open/indestructible/honk, +/area/virtual_domain/powered) +"WX" = ( +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"Xp" = ( +/obj/machinery/light/directional/south, +/turf/open/indestructible/honk, +/area/virtual_domain/powered) +"XB" = ( +/obj/machinery/light/directional/north, +/turf/open/indestructible/honk, +/area/virtual_domain/powered) +"Yb" = ( +/obj/effect/decal/cleanable/cobweb/cobweb2, +/turf/open/indestructible/honk, +/area/virtual_domain/powered) +"YP" = ( +/obj/structure/disposalpipe/segment{ + dir = 4; + invisibility = 101 + }, +/turf/open/indestructible/white, +/area/virtual_domain/powered) +"ZR" = ( +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/structure/disposaloutlet{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) + +(1,1,1) = {" +Ie +Ie +rT +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +rr +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(2,1,1) = {" +Ie +Ie +Vx +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(3,1,1) = {" +Ie +Ie +Vx +Ie +Ie +Ie +Ie +Ie +Dh +Dh +Dh +Dh +Dh +Dh +Dh +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Dh +Dh +Dh +Dh +Dh +Ie +Ie +Ie +Ie +Ie +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(4,1,1) = {" +Ie +Ie +Vx +Ie +Ie +Ie +Dh +Dh +Dh +ik +ik +ik +ik +ik +Dh +Dh +Ie +Ie +Ie +Ie +Ie +Dh +Dh +ik +ik +ik +Dh +Dh +Dh +Ie +Ie +Ie +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(5,1,1) = {" +Ie +Ie +Vx +Ie +Ie +Dh +Dh +ik +ik +ik +Hq +Sm +Hq +Sm +ik +Dh +Dh +Ie +Ie +Ie +Dh +Dh +ik +ik +tq +mD +ik +ik +Dh +Dh +Ie +Ie +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(6,1,1) = {" +Ie +Ie +Vx +Ie +Dh +Dh +ik +ik +IN +Tx +bU +ai +yZ +aP +Sm +ik +Dh +Dh +Dh +Dh +Dh +Nv +IY +tq +ik +ik +ik +ik +ik +Dh +Dh +Ie +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(7,1,1) = {" +Ie +Ie +Vx +Ie +Dh +ik +ik +Dh +Bi +cw +UQ +lr +UQ +UY +Vv +ik +Dh +IY +Jv +IY +Dh +IY +Jv +Kh +IY +tq +ik +tq +ik +ik +Dh +Ie +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(8,1,1) = {" +Ie +Ie +Vx +Dh +Dh +ik +IN +Tm +lx +Ww +cw +UQ +Sm +Vv +Vv +Dh +zm +oA +IY +Jv +Jv +IY +Jv +IY +IY +IY +Dh +ik +mD +ik +Dh +Dh +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(9,1,1) = {" +Ie +Ie +Vx +Dh +ik +ik +UN +UQ +UY +Ww +Vv +TH +Vv +YP +Cp +uY +Dh +sq +oA +IY +Dh +Dh +Jv +Dh +IY +IY +IY +tq +ik +ik +ik +Dh +Ie +Vx +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +tF +"} +(10,1,1) = {" +Ie +Ie +Vx +Dh +ik +IN +UQ +UQ +yZ +Do +Do +Vv +YP +YP +YP +KG +uY +Dh +Dh +oA +IY +IY +Jv +IY +IY +gH +Jv +Xp +Dh +ik +ik +Dh +by +KI +by +by +by +by +by +by +by +by +by +Ie +"} +(11,1,1) = {" +Ie +Ie +Vx +Dh +ik +yz +fh +UQ +UY +Vv +Ww +Vv +YP +YP +tt +bp +WX +oA +oA +oA +IY +Dh +IY +IY +Jv +Jv +IY +IY +ik +tq +ik +Dh +by +iR +PM +PM +PM +PM +PM +PM +PM +PM +by +Ie +"} +(12,1,1) = {" +Ie +Ie +Vx +Dh +ik +Hq +TK +qM +yZ +Ww +Ww +Vv +YP +PQ +tt +bp +uY +Dh +oA +oA +IY +IY +Dh +IY +IY +IY +IY +Jv +ik +tq +ik +ik +by +iR +yS +PM +PM +PM +PM +PM +yS +PM +by +Ie +"} +(13,1,1) = {" +Ie +Ie +Vx +Dh +ik +UN +UQ +UQ +DL +Ww +yz +lx +Vv +YP +Lv +WX +Dh +Dh +oA +IY +IY +Dh +Dh +IY +IY +Dh +IY +Jv +ik +mD +tq +ik +by +iR +PM +PM +PM +PM +PM +PM +PM +PM +by +Ie +"} +(14,1,1) = {" +Ie +Dh +Vv +nE +nE +mD +cw +UQ +lx +Ex +Tm +UQ +lx +Vv +Vv +ps +TK +Sm +Dh +Dh +Dh +zA +rg +Dh +XB +IY +Jv +gH +IY +ik +tq +ik +by +iR +PM +QP +QP +QP +QP +QP +xt +PM +by +Ie +"} +(15,1,1) = {" +Ie +Dh +ij +hK +nE +Dh +yz +UQ +UQ +UQ +UQ +bi +UQ +yZ +Do +Iz +kn +Ww +Dh +Dh +FI +mF +mF +mF +Dh +IY +Jv +Jv +IY +ik +tq +ik +by +ZR +PM +QP +QP +QP +QP +QP +QP +PM +by +Ie +"} +(16,1,1) = {" +Ie +Dh +VQ +uX +NL +TK +Tx +UQ +TK +UQ +cW +TK +Tm +UQ +yZ +pl +Do +Ex +UY +Dh +Ug +oI +NW +mF +Dh +Dh +Jv +IY +IY +ik +tq +ik +by +PM +PM +QP +QP +QP +QP +QP +QP +PM +by +Ie +"} +(17,1,1) = {" +Ie +Dh +VQ +bR +wz +Dh +Hq +UQ +Sm +cw +UY +cw +UQ +UQ +Tx +gy +Ex +UY +Iz +TK +NB +mF +aI +mF +WT +IY +Jv +IY +Dh +ik +tq +ik +by +PM +PM +QP +QP +QP +QP +QP +QP +PM +by +Ie +"} +(18,1,1) = {" +Ie +Dh +VQ +uX +PJ +TK +sT +kn +Do +Do +Vv +Do +Ov +UQ +UY +Ok +mE +rH +pl +Dh +mF +Hr +Gg +mF +Dh +IY +IY +IY +IY +ik +tq +ik +by +PM +PM +QP +QP +QP +QP +QP +QP +PM +by +Ie +"} +(19,1,1) = {" +Ie +Dh +zF +uX +nE +Dh +Dh +Ww +Ww +Ww +Do +Do +Do +lP +Ex +UY +Ka +Vv +tv +Dh +FI +mF +mF +QX +Dh +IY +IY +IY +IY +ik +tq +ik +by +lj +PM +QP +QP +QP +QP +QP +QP +PM +by +Ie +"} +(20,1,1) = {" +Ie +Dh +Vv +nE +nE +ik +Dh +Ww +Ww +Cs +Do +Do +Vv +Dh +Dh +bQ +Dh +ba +Dh +IY +Dh +zA +tI +Dh +XB +IY +Jv +Jv +IY +ik +tq +ik +by +iR +PM +QP +QP +QP +QP +QP +gr +PM +by +Ie +"} +(21,1,1) = {" +Ie +Ie +Vx +Dh +ik +Dh +Dh +Do +Do +Do +Ww +Do +Vv +rh +ed +gK +Dh +UL +Sm +IY +IY +Dh +Dh +Kh +IY +IY +Jv +IY +ik +tq +mD +ik +by +iR +PM +PM +PM +PM +PM +PM +PM +PM +by +Ie +"} +(22,1,1) = {" +Ie +Ie +Vx +Dh +ik +Dh +Dh +JB +Sg +Vv +Ww +Vv +uZ +YP +bp +bp +uY +Dh +bQ +oA +IY +IY +Dh +IY +Jv +IY +IY +IY +ik +tq +ik +ik +by +iR +PM +PM +yS +PM +PM +PM +PM +PM +by +Ie +"} +(23,1,1) = {" +Ie +Ie +Vx +Dh +ik +cM +eE +lx +Vv +ki +Ww +Vv +Rx +YP +bp +bp +WB +TK +Aa +Dh +IY +IY +Jv +Jv +Jv +IY +aM +Xp +Dh +tq +ik +Dh +by +iR +PM +PM +PM +PM +PM +PM +PM +PM +by +Ie +"} +(24,1,1) = {" +Ie +Ie +Vx +Dh +ik +Dh +Dh +lP +Do +Do +Cs +bQ +YP +bq +Rh +WX +uY +Dh +oA +oA +IY +IY +Jv +Jv +IY +IY +Dh +Dh +ik +mD +ik +Dh +by +KI +by +by +by +by +by +by +by +by +by +Ie +"} +(25,1,1) = {" +Ie +Ie +Vx +Dh +ik +Dh +Dh +pl +Do +Vv +Do +Vv +Vv +rh +lm +uY +Dh +sq +oA +IY +IY +IY +IY +IY +Dh +IY +IY +ik +mD +ik +ik +Dh +Ie +Vx +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +"} +(26,1,1) = {" +Ie +Ie +Vx +Dh +ik +ik +Dh +yd +Do +Do +Do +Ex +lx +Vv +Dh +Dh +oA +oA +IY +IY +IY +Jv +aM +IY +IY +IY +Dh +ik +tq +ik +Dh +Dh +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(27,1,1) = {" +Ie +Ie +Vx +Dh +Dh +ik +Dh +Dh +Ex +lx +HQ +UQ +UQ +bU +Dh +ik +Dh +Yb +IY +IY +Dh +IY +IY +Dh +IY +IY +ik +mD +ik +ik +Dh +Ie +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(28,1,1) = {" +Ie +Ie +Vx +Ie +Dh +Dh +ik +ik +Dh +mD +Dh +Ka +lP +mD +Dh +ik +Dh +Dh +Dh +Dh +Dh +IY +IY +IY +ik +ik +ik +ik +ik +Dh +Dh +Ie +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(29,1,1) = {" +Ie +Ie +Vx +Ie +Ie +Dh +Dh +ik +ik +ik +tq +tq +tq +Dh +ik +Dh +Dh +Ie +Ie +Ie +Dh +Dh +ik +ik +mD +tq +ik +ik +Dh +Dh +Ie +Ie +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(30,1,1) = {" +Ie +Ie +Vx +Ie +Ie +Ie +Dh +Dh +Dh +ik +ik +ik +ik +ik +Dh +Dh +Ie +Ie +Ie +Ie +Ie +Dh +Dh +ik +ik +ik +Dh +Dh +Dh +Ie +Ie +Ie +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(31,1,1) = {" +Ie +Ie +Vx +Ie +Ie +Ie +Ie +Ie +Dh +Dh +Dh +Dh +Dh +Dh +Dh +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Dh +Dh +Dh +Dh +Dh +Ie +Ie +Ie +Ie +Ie +Ie +Vx +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(32,1,1) = {" +Ie +Ie +VI +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +RU +ly +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} +(33,1,1) = {" +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +Ie +hY +hY +hY +hY +hY +hY +hY +hY +hY +hY +"} diff --git a/_maps/virtual_domains/colossus.dmm b/_maps/virtual_domains/colossus.dmm new file mode 100644 index 00000000000..a9c3c6e6d79 --- /dev/null +++ b/_maps/virtual_domains/colossus.dmm @@ -0,0 +1,2250 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"c" = ( +/obj/structure/marker_beacon/olive, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"e" = ( +/obj/structure/marker_beacon/bronze, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"j" = ( +/obj/structure/marker_beacon/cerulean, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"k" = ( +/turf/closed/mineral/volcanic/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"l" = ( +/obj/structure/marker_beacon/lime, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"m" = ( +/obj/structure/marker_beacon/violet, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"o" = ( +/obj/effect/mob_spawn/corpse/human/miner, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"p" = ( +/mob/living/simple_animal/hostile/megafauna/colossus/virtual_domain, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"q" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/open/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"r" = ( +/obj/machinery/light/small/blacklight/directional/south, +/obj/effect/baseturf_helper/virtual_domain, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/virtual_domain/powered) +"s" = ( +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"u" = ( +/obj/structure/marker_beacon/indigo, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"v" = ( +/turf/open/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"x" = ( +/obj/structure/marker_beacon/purple, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"z" = ( +/obj/structure/marker_beacon/jade, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"B" = ( +/obj/structure/marker_beacon/teal, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"D" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"L" = ( +/obj/structure/marker_beacon/yellow, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"N" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"T" = ( +/obj/structure/marker_beacon/burgundy, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"U" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"W" = ( +/obj/structure/marker_beacon/fuchsia, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) + +(1,1,1) = {" +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +q +"} +(2,1,1) = {" +v +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +v +"} +(3,1,1) = {" +v +k +a +a +k +k +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +k +k +a +a +a +a +a +a +a +a +k +k +a +a +a +a +a +a +k +k +k +v +"} +(4,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(5,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +s +k +v +"} +(6,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +m +a +a +a +a +a +a +a +a +a +a +a +a +s +s +k +v +"} +(7,1,1) = {" +v +k +a +a +a +a +o +a +a +a +a +a +a +a +a +a +c +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +a +a +a +a +s +k +v +"} +(8,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +k +a +a +a +k +k +v +"} +(9,1,1) = {" +v +k +a +a +a +a +a +a +s +s +s +s +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +k +v +"} +(10,1,1) = {" +v +k +k +a +a +a +a +a +k +k +k +s +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +k +v +"} +(11,1,1) = {" +v +k +k +a +a +a +a +a +k +k +k +s +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +k +a +a +a +a +a +a +a +a +s +s +a +a +a +a +a +k +v +"} +(12,1,1) = {" +v +k +k +a +a +a +a +a +s +k +s +s +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +k +a +a +a +a +a +a +a +s +a +a +a +a +a +k +v +"} +(13,1,1) = {" +v +k +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +k +k +a +a +a +a +a +u +a +a +a +a +a +a +a +k +v +"} +(14,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +k +k +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(15,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(16,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +e +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(17,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +j +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(18,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(19,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(20,1,1) = {" +v +k +a +a +a +a +a +x +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(21,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +r +U +U +U +U +U +N +a +k +v +"} +(22,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +U +U +U +U +U +U +a +k +v +"} +(23,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +p +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +U +U +U +U +U +U +a +k +v +"} +(24,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +l +a +a +U +U +U +U +U +U +a +k +v +"} +(25,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +U +U +U +U +U +U +a +k +v +"} +(26,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +U +U +U +U +U +U +a +k +v +"} +(27,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +o +a +r +U +U +U +U +U +D +a +k +v +"} +(28,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +T +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(29,1,1) = {" +v +k +a +a +a +a +a +a +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +W +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(30,1,1) = {" +v +k +a +a +a +a +a +a +k +k +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(31,1,1) = {" +v +k +a +a +a +a +a +a +k +k +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(32,1,1) = {" +v +k +a +a +a +a +a +a +a +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(33,1,1) = {" +v +k +a +a +a +a +a +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +z +a +a +a +a +a +a +a +k +v +"} +(34,1,1) = {" +v +k +k +a +a +a +a +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(35,1,1) = {" +v +k +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +l +a +a +a +a +a +a +a +a +k +k +k +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(36,1,1) = {" +v +k +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +k +k +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(37,1,1) = {" +v +k +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +k +v +"} +(38,1,1) = {" +v +k +a +a +a +s +s +a +a +a +a +a +B +a +a +a +a +k +a +a +a +a +a +a +s +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +k +v +"} +(39,1,1) = {" +v +k +a +a +a +s +s +a +a +a +a +a +a +a +a +a +k +k +k +a +a +a +a +a +s +s +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(40,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(41,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +L +a +a +a +a +a +a +a +k +v +"} +(42,1,1) = {" +v +k +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +k +v +"} +(43,1,1) = {" +v +k +a +k +k +k +k +a +a +a +a +a +k +k +k +k +a +a +a +k +k +k +k +k +a +a +a +a +a +a +k +k +k +k +a +a +a +a +a +a +k +k +a +a +k +v +"} +(44,1,1) = {" +v +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +k +v +"} +(45,1,1) = {" +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +v +"} diff --git a/_maps/virtual_domains/gondola_asteroid.dmm b/_maps/virtual_domains/gondola_asteroid.dmm new file mode 100644 index 00000000000..d6377a4a4c1 --- /dev/null +++ b/_maps/virtual_domains/gondola_asteroid.dmm @@ -0,0 +1,1784 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/indestructible/binary, +/area/ruin/space/has_grav/powered/virtual_domain) +"c" = ( +/turf/open/space/basic, +/area/space) +"e" = ( +/turf/open/misc/asteroid/airless, +/area/ruin/space/has_grav/powered/virtual_domain) +"g" = ( +/obj/structure/marker_beacon{ + light_color = "#FFE8AA"; + light_range = 20 + }, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"h" = ( +/turf/closed/mineral/random, +/area/ruin/space/has_grav/powered/virtual_domain) +"m" = ( +/obj/structure/closet/crate/secure/bitrunning/encrypted/gondola, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"n" = ( +/obj/structure/flora/bush/fullgrass/style_random, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"o" = ( +/turf/template_noop, +/area/template_noop) +"q" = ( +/obj/structure/flora/tree/palm, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"r" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"s" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"t" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"w" = ( +/obj/structure/water_source/puddle, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"y" = ( +/obj/structure/flora/bush/stalky/style_random, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"z" = ( +/mob/living/simple_animal/pet/gondola/virtual_domain, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"A" = ( +/obj/structure/chair/wood{ + dir = 8 + }, +/turf/template_noop, +/area/virtual_domain/safehouse) +"C" = ( +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"D" = ( +/obj/structure/flora/bush/flowers_br/style_random, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"F" = ( +/obj/structure/flora/bush/grassy/style_random, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"I" = ( +/obj/structure/flora/bush/reed/style_random, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"J" = ( +/obj/structure/flora/bush/flowers_yw/style_random, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"K" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/binary, +/area/ruin/space/has_grav/powered/virtual_domain) +"M" = ( +/obj/structure/table/wood, +/obj/item/storage/bag/tray, +/obj/item/kitchen/fork, +/obj/item/knife/kitchen, +/turf/template_noop, +/area/virtual_domain/safehouse) +"N" = ( +/obj/structure/flora/bush/large/style_random, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"O" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"Q" = ( +/obj/structure/flora/bush/lavendergrass/style_random, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"T" = ( +/obj/structure/flora/bush/sunny/style_random, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"V" = ( +/obj/structure/flora/coconuts, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) +"W" = ( +/obj/structure/flora/bush/ferny/style_random, +/turf/open/floor/grass, +/area/ruin/space/has_grav/powered/virtual_domain) + +(1,1,1) = {" +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +a +a +a +a +a +a +a +a +o +o +o +o +o +o +o +o +o +o +"} +(2,1,1) = {" +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +a +a +a +h +h +h +h +h +h +a +a +o +o +o +o +o +o +o +o +o +"} +(3,1,1) = {" +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +a +a +a +a +a +h +h +h +h +h +h +h +h +h +a +a +K +o +o +o +o +o +o +o +"} +(4,1,1) = {" +o +o +o +o +o +o +o +o +o +o +o +o +o +o +a +a +a +a +a +a +a +h +h +h +h +h +h +h +h +h +h +h +h +h +e +a +o +o +o +o +o +o +o +"} +(5,1,1) = {" +o +o +o +o +o +o +o +o +o +o +o +o +o +a +a +h +h +h +h +h +h +h +h +h +h +h +h +h +h +C +h +h +h +h +h +a +o +o +o +o +o +o +o +"} +(6,1,1) = {" +o +o +o +o +o +o +o +o +a +a +a +a +a +a +h +h +h +h +h +h +h +h +h +h +h +C +C +C +C +C +C +C +h +h +h +a +o +o +o +o +o +o +o +"} +(7,1,1) = {" +o +o +o +o +o +o +o +a +a +h +h +h +h +h +h +h +h +h +h +h +h +h +h +C +C +C +C +J +C +C +C +z +C +h +h +a +o +o +o +o +o +o +o +"} +(8,1,1) = {" +o +o +o +o +o +a +a +a +h +h +h +h +h +h +h +h +h +h +h +h +h +C +C +C +C +Q +C +q +C +h +h +h +h +h +e +a +a +a +a +a +a +a +a +"} +(9,1,1) = {" +o +o +o +o +a +a +h +h +h +h +h +h +h +h +h +h +C +h +C +C +C +C +C +C +C +C +V +C +C +C +C +h +h +h +e +c +c +c +c +c +c +c +a +"} +(10,1,1) = {" +o +o +a +a +a +h +h +h +h +h +h +h +h +C +q +C +C +W +C +C +V +C +C +q +C +C +C +C +F +C +C +h +h +h +e +c +c +c +c +c +c +c +a +"} +(11,1,1) = {" +o +a +a +h +h +h +h +h +h +h +h +h +h +h +h +C +C +C +C +C +N +C +C +C +C +C +C +s +C +C +C +h +h +h +e +c +c +c +c +c +c +c +a +"} +(12,1,1) = {" +o +a +h +h +h +h +h +h +h +h +h +h +h +h +C +s +I +J +C +C +g +C +C +V +C +z +C +y +C +g +C +h +h +h +e +c +c +c +c +c +c +c +a +"} +(13,1,1) = {" +a +a +h +h +h +h +h +h +h +h +h +h +C +C +C +C +Q +Q +C +z +C +C +C +C +C +C +C +s +Q +C +C +h +h +h +e +c +c +c +c +c +c +c +a +"} +(14,1,1) = {" +a +h +h +h +h +h +h +h +h +h +h +h +C +C +w +C +s +C +W +C +C +C +C +C +C +N +C +C +C +C +h +h +h +h +e +c +c +c +c +c +c +c +a +"} +(15,1,1) = {" +a +h +h +h +h +h +h +h +h +h +h +z +C +C +C +C +y +C +C +C +F +s +C +C +C +C +C +w +C +h +h +h +h +h +e +c +c +c +c +c +c +c +a +"} +(16,1,1) = {" +a +h +h +h +h +h +h +h +h +h +h +h +h +h +h +C +C +C +C +C +s +Q +C +C +C +C +C +C +C +C +h +h +h +h +e +c +c +c +c +c +c +c +a +"} +(17,1,1) = {" +a +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +C +C +C +Q +D +C +C +C +C +q +C +C +C +C +h +h +h +h +t +t +t +t +t +O +c +a +"} +(18,1,1) = {" +a +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +C +n +I +C +C +C +C +C +C +C +C +C +C +C +h +h +h +t +t +M +M +t +t +c +a +"} +(19,1,1) = {" +a +h +h +h +h +h +h +h +h +h +C +n +C +h +h +h +h +h +C +C +C +C +C +C +s +T +C +C +C +s +C +C +h +C +C +t +t +A +A +t +t +c +a +"} +(20,1,1) = {" +a +h +h +h +h +h +h +h +h +C +C +C +C +C +C +h +h +h +C +C +q +V +C +C +C +J +C +C +C +C +C +C +C +C +C +t +t +t +t +t +t +c +a +"} +(21,1,1) = {" +a +e +h +h +h +h +h +h +h +z +C +C +g +C +C +C +C +C +C +C +C +C +C +C +C +C +C +C +C +C +C +C +C +C +C +t +t +t +t +t +t +c +a +"} +(22,1,1) = {" +a +e +e +h +h +h +h +h +h +C +C +C +q +C +s +s +C +C +W +C +m +C +C +C +g +C +z +C +C +C +C +C +h +h +h +t +t +t +t +t +t +c +a +"} +(23,1,1) = {" +a +e +e +h +h +h +h +h +h +C +C +C +C +C +C +y +C +C +C +C +C +C +C +C +C +C +C +C +C +q +C +C +h +h +h +t +t +t +t +t +r +c +a +"} +(24,1,1) = {" +a +e +e +h +h +h +h +h +h +C +C +V +C +C +C +C +C +C +C +w +C +z +N +C +C +C +N +C +C +C +C +C +h +h +h +c +c +c +c +c +c +c +a +"} +(25,1,1) = {" +a +a +e +e +h +h +h +h +n +C +C +C +C +C +z +C +C +C +C +C +C +C +C +C +F +C +C +C +C +C +C +C +h +h +h +c +c +c +c +c +c +c +a +"} +(26,1,1) = {" +o +a +e +e +h +h +h +C +C +C +C +C +C +C +C +C +s +y +C +C +C +C +C +C +I +F +C +C +C +C +C +h +h +h +c +c +c +c +c +c +c +c +a +"} +(27,1,1) = {" +o +a +e +e +h +h +h +C +C +C +w +C +C +C +C +F +D +s +C +J +C +C +C +C +C +C +q +C +C +V +C +h +h +h +c +c +c +c +c +c +c +c +a +"} +(28,1,1) = {" +o +a +e +e +h +h +h +h +C +C +C +C +C +C +C +C +C +C +C +g +F +s +C +C +C +C +C +C +C +C +h +h +h +c +c +c +c +c +c +c +c +c +a +"} +(29,1,1) = {" +o +a +a +e +e +h +h +h +C +C +C +C +C +n +C +C +C +C +C +C +s +y +D +C +C +C +C +w +C +h +h +h +h +c +c +c +c +c +c +c +c +c +a +"} +(30,1,1) = {" +o +o +a +e +e +h +h +C +C +C +n +C +C +C +C +C +C +C +C +C +C +C +C +C +C +s +C +C +C +h +h +h +e +e +c +c +c +c +c +c +c +c +a +"} +(31,1,1) = {" +o +o +a +e +h +h +C +g +J +C +s +C +C +C +h +C +C +C +C +C +V +C +C +C +C +C +C +C +h +h +h +e +e +e +c +c +c +c +c +c +c +c +a +"} +(32,1,1) = {" +o +o +a +h +h +h +h +C +C +C +C +C +C +h +h +h +C +C +C +q +C +C +C +C +C +C +h +h +h +h +e +e +e +h +h +a +a +a +a +a +a +a +a +"} +(33,1,1) = {" +o +o +a +h +h +h +C +C +C +C +C +C +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +e +e +h +h +h +a +o +o +o +o +o +o +o +"} +(34,1,1) = {" +o +o +a +h +h +C +C +C +C +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +h +a +a +h +h +h +a +a +o +o +o +o +o +o +o +"} +(35,1,1) = {" +o +o +a +h +h +h +h +h +h +h +h +h +h +h +e +e +e +e +e +h +h +h +h +h +a +a +a +a +a +a +a +h +h +h +a +a +o +o +o +o +o +o +o +"} +(36,1,1) = {" +o +o +a +a +h +h +h +h +h +h +h +h +h +a +a +a +a +a +a +a +a +a +a +a +a +o +o +o +o +o +a +a +a +a +a +o +o +o +o +o +o +o +o +"} +(37,1,1) = {" +o +o +o +a +a +a +a +a +a +a +a +a +a +a +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +o +"} diff --git a/_maps/virtual_domains/hierophant.dmm b/_maps/virtual_domains/hierophant.dmm new file mode 100644 index 00000000000..02b11ad4e1e --- /dev/null +++ b/_maps/virtual_domains/hierophant.dmm @@ -0,0 +1,1066 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/open/indestructible/hierophant, +/area/lavaland/surface/outdoors/virtual_domain) +"c" = ( +/obj/effect/light_emitter{ + set_cap = 3; + set_luminosity = 5 + }, +/turf/open/indestructible/hierophant/two, +/area/lavaland/surface/outdoors/virtual_domain) +"h" = ( +/obj/effect/light_emitter{ + set_cap = 3; + set_luminosity = 5 + }, +/turf/open/indestructible/hierophant, +/area/lavaland/surface/outdoors/virtual_domain) +"n" = ( +/obj/structure/marker_beacon/indigo, +/turf/open/indestructible/hierophant, +/area/lavaland/surface/outdoors/virtual_domain) +"o" = ( +/turf/template_noop, +/area/template_noop) +"r" = ( +/turf/closed/indestructible/riveted/hierophant, +/area/lavaland/surface/outdoors/virtual_domain) +"u" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"w" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"y" = ( +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"E" = ( +/mob/living/simple_animal/hostile/megafauna/hierophant/virtual_domain, +/turf/open/indestructible/hierophant/two, +/area/lavaland/surface/outdoors/virtual_domain) +"H" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"K" = ( +/turf/open/indestructible/hierophant/two, +/area/lavaland/surface/outdoors/virtual_domain) +"N" = ( +/obj/machinery/light/small/blacklight/directional/south, +/obj/effect/baseturf_helper/virtual_domain, +/turf/open/indestructible/hierophant, +/area/virtual_domain/powered) +"S" = ( +/obj/effect/mob_spawn/corpse/human/miner, +/turf/open/indestructible/hierophant, +/area/lavaland/surface/outdoors/virtual_domain) +"W" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"Y" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) + +(1,1,1) = {" +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +o +o +y +y +y +y +y +y +y +y +y +y +W +"} +(2,1,1) = {" +y +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +y +o +o +y +Y +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(3,1,1) = {" +y +r +a +a +a +a +a +a +a +a +a +a +h +a +a +a +a +a +a +a +a +a +a +r +y +o +o +y +Y +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(4,1,1) = {" +y +r +a +a +a +h +h +a +a +a +r +a +a +a +r +a +a +a +h +h +a +a +a +r +y +y +y +y +Y +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(5,1,1) = {" +y +r +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +r +r +y +y +Y +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(6,1,1) = {" +y +r +a +h +a +r +r +a +h +n +a +a +h +a +a +a +h +a +r +r +a +h +a +a +a +a +r +y +Y +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(7,1,1) = {" +y +r +a +h +a +r +r +a +h +a +a +a +h +a +a +a +h +a +r +r +a +h +a +a +a +a +a +r +Y +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(8,1,1) = {" +y +r +a +a +a +a +a +K +K +K +K +K +K +K +K +K +K +K +a +a +a +n +a +a +r +a +a +a +r +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(9,1,1) = {" +y +r +a +a +a +h +h +K +K +K +r +K +K +K +r +K +K +K +h +h +a +a +a +r +y +r +S +a +a +r +Y +Y +Y +Y +Y +Y +Y +y +"} +(10,1,1) = {" +y +r +a +a +a +a +a +K +K +K +K +K +c +K +K +K +K +K +a +a +a +a +a +r +y +y +r +a +a +N +w +w +w +w +w +H +Y +y +"} +(11,1,1) = {" +y +r +a +r +a +a +a +K +r +K +K +K +K +K +K +K +r +K +a +a +a +r +a +r +y +y +y +r +a +a +w +w +w +w +w +w +Y +y +"} +(12,1,1) = {" +y +r +a +a +a +a +a +K +K +K +K +K +K +K +K +K +K +K +a +a +a +a +a +r +y +y +y +r +a +a +w +w +w +w +w +w +Y +y +"} +(13,1,1) = {" +y +r +h +a +a +h +h +K +K +c +K +K +E +K +K +c +K +K +h +h +a +a +h +r +y +y +y +r +a +a +w +w +w +w +w +w +Y +y +"} +(14,1,1) = {" +y +r +a +a +a +a +a +K +K +K +K +K +K +K +K +K +K +K +a +a +a +a +a +r +y +y +y +r +a +a +w +w +w +w +w +w +Y +y +"} +(15,1,1) = {" +y +r +a +r +a +a +a +K +r +K +K +K +K +K +K +K +r +K +a +a +a +r +a +r +y +y +y +r +a +a +w +w +w +w +w +w +Y +y +"} +(16,1,1) = {" +y +r +a +a +a +a +a +K +K +K +K +K +c +K +K +K +K +K +a +a +a +a +a +r +y +y +r +a +a +N +w +w +w +w +w +u +Y +y +"} +(17,1,1) = {" +y +r +a +a +a +h +h +K +K +K +r +K +K +K +r +K +K +K +h +h +a +a +a +r +y +r +a +a +a +r +Y +Y +Y +Y +Y +Y +Y +y +"} +(18,1,1) = {" +y +r +a +a +a +a +a +K +K +K +K +K +K +K +K +K +K +K +a +a +a +a +a +a +r +a +a +a +r +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(19,1,1) = {" +y +r +a +h +a +r +r +a +h +a +a +a +h +a +a +a +h +a +r +r +a +h +a +a +a +a +a +r +Y +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(20,1,1) = {" +y +r +a +h +a +r +r +S +h +a +a +a +h +a +n +a +h +a +r +r +a +h +a +a +a +a +r +y +Y +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(21,1,1) = {" +y +r +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +r +r +y +y +Y +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(22,1,1) = {" +y +r +a +a +a +h +h +a +a +a +r +a +a +a +r +a +a +a +h +h +a +a +a +r +y +y +y +y +Y +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(23,1,1) = {" +y +r +a +a +a +a +a +a +a +a +a +a +h +a +a +a +a +a +a +a +a +a +a +r +y +o +o +y +Y +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(24,1,1) = {" +y +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +r +y +o +o +y +Y +Y +Y +Y +Y +Y +Y +Y +Y +y +"} +(25,1,1) = {" +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +y +o +o +y +y +y +y +y +y +y +y +y +y +y +"} diff --git a/_maps/virtual_domains/legion.dmm b/_maps/virtual_domains/legion.dmm new file mode 100644 index 00000000000..55843177ad0 --- /dev/null +++ b/_maps/virtual_domains/legion.dmm @@ -0,0 +1,6370 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"ah" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"ak" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"aI" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"aR" = ( +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"bd" = ( +/obj/structure/stone_tile/block, +/obj/structure/stone_tile/block{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"be" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"bt" = ( +/obj/effect/decal/cleanable/blood, +/obj/effect/decal/cleanable/blood/drip, +/obj/effect/decal/cleanable/blood/footprints{ + dir = 1 + }, +/turf/open/floor/pod/dark, +/area/lavaland/surface/outdoors/virtual_domain) +"bu" = ( +/obj/structure/marker_beacon/bronze, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"ca" = ( +/obj/effect/mob_spawn/corpse/human/legioninfested, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"cf" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"cp" = ( +/turf/template_noop, +/area/template_noop) +"dm" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"dn" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/effect/mob_spawn/corpse/human/legioninfested, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"dr" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/obj/structure/stone_tile/block/cracked, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"dx" = ( +/obj/effect/decal/cleanable/blood/footprints{ + dir = 8 + }, +/obj/effect/decal/cleanable/blood/drip, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"dL" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"dQ" = ( +/turf/closed/wall/mineral/titanium/survival/pod, +/area/lavaland/surface/outdoors/virtual_domain) +"et" = ( +/obj/structure/stone_tile/block/cracked, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"ew" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"eJ" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"fA" = ( +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"fG" = ( +/obj/structure/marker_beacon/violet, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"gh" = ( +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"gk" = ( +/obj/structure/necropolis_gate/locked, +/obj/structure/stone_tile/slab, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"gK" = ( +/obj/effect/decal/cleanable/blood/footprints, +/obj/effect/decal/cleanable/blood/drip, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"gQ" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"hc" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"hw" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"hx" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"hU" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"ib" = ( +/turf/closed/mineral/volcanic/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"ie" = ( +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"iP" = ( +/obj/structure/fluff/drake_statue/falling, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"iR" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"iV" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"jk" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"jt" = ( +/obj/structure/stone_tile/slab/cracked, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"jw" = ( +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"jN" = ( +/obj/machinery/sleeper/survival_pod, +/turf/open/floor/pod/dark, +/area/lavaland/surface/outdoors/virtual_domain) +"ka" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"kg" = ( +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"kT" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"kZ" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"ll" = ( +/obj/structure/stone_tile/cracked, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"lz" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"lC" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"lO" = ( +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"lT" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"mz" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"mG" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"nm" = ( +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"nu" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"nv" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"ny" = ( +/obj/structure/stone_tile, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"nI" = ( +/obj/structure/stone_tile/block, +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"nO" = ( +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/obj/structure/stone_tile/center, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 8 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"ob" = ( +/obj/structure/necropolis_gate/legion_gate, +/obj/structure/necropolis_arch, +/obj/structure/stone_tile/slab, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"og" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"oo" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"ox" = ( +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"oS" = ( +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"pP" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"qo" = ( +/obj/structure/stone_tile/slab/cracked, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"qs" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"qW" = ( +/obj/effect/decal/cleanable/blood/footprints{ + dir = 1 + }, +/obj/machinery/door/airlock/survival_pod/glass, +/turf/open/floor/pod/dark, +/area/lavaland/surface/outdoors/virtual_domain) +"rt" = ( +/obj/effect/mob_spawn/corpse/human/miner, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"rU" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"sd" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/block{ + dir = 4 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"sk" = ( +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"sz" = ( +/obj/structure/stone_tile/center, +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"sA" = ( +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"tk" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"tF" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"uK" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/structure/stone_tile/block{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"vf" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"wq" = ( +/obj/structure/marker_beacon/teal, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"wy" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"xd" = ( +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"xm" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"xw" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"xD" = ( +/obj/structure/stone_tile/cracked, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"yu" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/block, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"yZ" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"zg" = ( +/obj/machinery/light/small/directional/south, +/obj/effect/baseturf_helper/virtual_domain, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/virtual_domain/powered) +"zo" = ( +/obj/effect/turf_decal/mining/survival, +/turf/closed/wall/mineral/titanium/survival/pod, +/area/lavaland/surface/outdoors/virtual_domain) +"zW" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/center/cracked, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Ah" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/binary, +/area/lavaland/surface/outdoors/virtual_domain) +"Aj" = ( +/obj/structure/marker_beacon/burgundy, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Ak" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/center/cracked, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 4 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"As" = ( +/obj/structure/marker_beacon/cerulean, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"AY" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Bo" = ( +/obj/structure/marker_beacon/indigo, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"BO" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"CX" = ( +/obj/effect/decal/cleanable/blood/drip, +/obj/effect/decal/cleanable/blood/footprints{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Dm" = ( +/turf/closed/mineral/random/volcanic, +/area/lavaland/surface/outdoors/virtual_domain) +"DP" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/center, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Ek" = ( +/obj/structure/stone_tile/block, +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Ep" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"Ez" = ( +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/cracked, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"EC" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Fg" = ( +/obj/structure/stone_tile/surrounding/cracked{ + dir = 6 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Fp" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"Fq" = ( +/obj/structure/marker_beacon/fuchsia, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"FV" = ( +/obj/structure/stone_tile/block, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Gj" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Gn" = ( +/turf/closed/indestructible/riveted/boss/see_through, +/area/lavaland/surface/outdoors/virtual_domain) +"Go" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 1 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"GH" = ( +/obj/structure/fans, +/turf/open/floor/pod/dark, +/area/lavaland/surface/outdoors/virtual_domain) +"GM" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Hi" = ( +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Hu" = ( +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"Hw" = ( +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/obj/structure/stone_tile/center/cracked, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 8 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"HK" = ( +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"HQ" = ( +/obj/structure/stone_tile/block/cracked, +/obj/structure/stone_tile/block{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"HZ" = ( +/obj/structure/stone_tile{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Ii" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Io" = ( +/obj/structure/marker_beacon/jade, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Ip" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"IB" = ( +/obj/structure/stone_tile, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"IG" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"IL" = ( +/obj/structure/stone_tile/surrounding, +/obj/structure/stone_tile/center/cracked, +/mob/living/simple_animal/hostile/megafauna/legion/virtual_domain, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"IQ" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Jc" = ( +/obj/structure/stone_tile/slab, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Jp" = ( +/obj/structure/stone_tile/block/cracked, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Jt" = ( +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Jw" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"JD" = ( +/obj/structure/fluff/drake_statue, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"KG" = ( +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Le" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Lx" = ( +/obj/effect/decal/cleanable/blood/footprints{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"LH" = ( +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Ml" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Mm" = ( +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/obj/structure/stone_tile/center/cracked, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 1 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Mo" = ( +/obj/structure/stone_tile/block/cracked, +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"MH" = ( +/obj/structure/stone_tile/cracked, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"MP" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"MW" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Nl" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/obj/structure/stone_tile/center, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"Ot" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/obj/structure/stone_tile/center, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Pv" = ( +/obj/effect/turf_decal/mining/survival{ + dir = 4 + }, +/turf/closed/wall/mineral/titanium/survival/pod, +/area/lavaland/surface/outdoors/virtual_domain) +"Px" = ( +/obj/structure/stone_tile{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"PO" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/structure/stone_tile/block{ + dir = 4 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"Qi" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Qx" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/marker_beacon/burgundy, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"QD" = ( +/obj/item/pickaxe, +/obj/effect/decal/cleanable/blood, +/turf/open/floor/pod/dark, +/area/lavaland/surface/outdoors/virtual_domain) +"RC" = ( +/obj/effect/turf_decal/mining/survival{ + dir = 1 + }, +/turf/closed/wall/mineral/titanium/survival/pod, +/area/lavaland/surface/outdoors/virtual_domain) +"RV" = ( +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"So" = ( +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Sw" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"SI" = ( +/obj/effect/turf_decal/mining, +/turf/closed/wall/mineral/titanium/survival/pod, +/area/lavaland/surface/outdoors/virtual_domain) +"SJ" = ( +/obj/structure/stone_tile/slab/cracked, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"SX" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Ti" = ( +/turf/closed/mineral/random/high_chance/volcanic, +/area/lavaland/surface/outdoors/virtual_domain) +"Tm" = ( +/obj/structure/bed/pod, +/obj/item/bedsheet/black, +/obj/structure/tubes, +/obj/machinery/light/small/broken/directional/east, +/turf/open/floor/pod/dark, +/area/lavaland/surface/outdoors/virtual_domain) +"TC" = ( +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"TJ" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Ud" = ( +/obj/machinery/light/small/directional/north, +/obj/effect/baseturf_helper/virtual_domain, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/virtual_domain/powered) +"UD" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/obj/structure/stone_tile/center/cracked, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"UM" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Vc" = ( +/obj/structure/tubes, +/obj/item/crowbar, +/obj/effect/decal/cleanable/blood/drip, +/turf/open/floor/pod/dark, +/area/lavaland/surface/outdoors/virtual_domain) +"VI" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/center, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"Wa" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/obj/structure/stone_tile/center/cracked, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Wm" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"WM" = ( +/obj/structure/stone_tile/block, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"WR" = ( +/obj/structure/stone_tile/block, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"WS" = ( +/obj/item/gps/computer, +/obj/structure/tubes, +/turf/open/floor/pod/dark, +/area/lavaland/surface/outdoors/virtual_domain) +"Xb" = ( +/obj/structure/marker_beacon/yellow, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Xn" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Xo" = ( +/obj/structure/stone_tile/block, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Xv" = ( +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile/cracked, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"XO" = ( +/obj/effect/turf_decal/mining/survival{ + dir = 8 + }, +/turf/closed/wall/mineral/titanium/survival/pod, +/area/lavaland/surface/outdoors/virtual_domain) +"Yu" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"YN" = ( +/obj/structure/stone_tile/block/cracked, +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"YV" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Zc" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"Zh" = ( +/obj/structure/marker_beacon/purple, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/lavaland/surface/outdoors/virtual_domain) +"Zj" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/block{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"Zq" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/indestructible/boss, +/area/lavaland/surface/outdoors/virtual_domain) +"Zu" = ( +/obj/machinery/smartfridge/survival_pod{ + desc = "A heated storage unit. This one's seen better days."; + name = "dusty survival pod storage" + }, +/turf/open/floor/pod/dark, +/area/lavaland/surface/outdoors/virtual_domain) +"ZM" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors/virtual_domain) +"ZN" = ( +/obj/structure/table/survival_pod, +/obj/item/knife/combat/survival, +/turf/open/floor/pod/dark, +/area/lavaland/surface/outdoors/virtual_domain) + +(1,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +Ah +"} +(2,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ox +"} +(3,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +ib +nu +nu +ib +ib +ib +ib +nu +nu +nu +nu +nu +nu +nu +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ib +nu +nu +nu +nu +nu +nu +ib +ib +nu +nu +ib +ox +"} +(4,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(5,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(6,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +wq +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(7,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ox +"} +(8,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +ib +nu +nu +nu +nu +nu +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +rt +nu +nu +ib +ib +ox +"} +(9,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +ib +nu +nu +nu +nu +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ox +"} +(10,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ib +ib +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ox +"} +(11,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ib +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(12,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +fA +fA +fA +nu +nu +nu +nu +ib +ox +"} +(13,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +ib +nu +fG +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +fA +fA +fA +nu +nu +nu +nu +ib +ox +"} +(14,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +fA +fA +nu +nu +nu +nu +ib +ox +"} +(15,1,1) = {" +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(16,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +nu +nu +nu +nu +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(17,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +Ti +Ti +Ti +Ti +GM +nu +nu +nu +nu +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +Io +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +Xb +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(18,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +et +Ti +GM +GM +GM +nu +nu +nu +nu +GM +GM +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(19,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +GM +nu +nu +nu +nu +nu +nu +nu +nu +GM +GM +GM +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +wq +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(20,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +Ti +nu +nu +nu +nu +nu +nu +nu +nu +GM +GM +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(21,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +Ti +nu +nu +nu +nu +GM +Ti +GM +GM +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +Zh +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(22,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +FV +nu +nu +nu +nu +Ti +Dm +Dm +GM +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(23,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +Ti +GM +GM +GM +Ti +Ti +Dm +Dm +Ti +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(24,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +FV +Ml +Ti +Dm +Dm +Ti +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ox +"} +(25,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +GM +GM +Ti +Dm +Dm +IB +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +GM +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ox +"} +(26,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +GM +GM +GM +GM +GM +GM +fA +fA +fA +fA +RV +fA +fA +fA +fA +fA +fA +Xn +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +As +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ox +"} +(27,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +Ek +Le +be +be +kT +GM +GM +GM +GM +fA +fA +xm +fA +fA +fA +GM +ZM +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(28,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +dr +KG +mz +KG +KG +jt +GM +GM +GM +GM +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +HZ +nu +bu +nu +nu +nu +MH +nu +nu +lz +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +nu +nu +ib +ox +"} +(29,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +bd +mG +Hw +hU +Mm +lO +et +GM +tk +fA +fA +fA +fA +ak +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +YV +nu +nu +So +nu +nu +nu +nu +nu +nu +bu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +nu +nu +ib +ox +"} +(30,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +Ez +WR +JD +rU +KG +dm +GM +GM +fA +Hi +fA +fA +fA +ll +fA +fA +Wm +fA +fA +YV +qs +MH +nu +nu +nu +ny +ca +oS +nu +nu +Qx +nu +nu +hx +nu +nu +nu +nu +nu +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +nu +nu +ib +ox +"} +(31,1,1) = {" +ox +kg +kg +kg +Hu +Zq +wy +Zq +lT +kg +kg +Gn +Gn +KG +Ak +nv +Ot +mG +hw +kg +kg +Wm +fA +fA +fA +fA +fA +fA +fA +fA +fA +ak +nu +nu +qs +nu +nu +TC +nu +YV +nu +ny +nu +oS +nu +nu +nu +SX +nu +nu +nu +zg +BO +BO +BO +BO +BO +og +Ud +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +nu +nu +ib +ox +"} +(32,1,1) = {" +ox +kg +kg +Gn +VI +xw +gQ +ka +iR +kg +kg +Gn +Gn +sz +KG +KG +KG +KG +mz +kg +kZ +kZ +sd +kZ +lC +kZ +TJ +UM +kZ +IQ +UM +UM +AY +nu +nI +nu +nu +nu +nu +oS +nu +nu +nu +nu +nu +qs +nu +nu +nu +nu +nu +nu +BO +BO +BO +BO +BO +BO +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +nu +nu +ib +ox +"} +(33,1,1) = {" +ox +PO +PO +gk +PO +Zc +IL +Yu +SJ +Yu +Yu +Yu +ob +dL +uK +MP +uK +uK +dL +Jc +Mo +eJ +Mo +hc +yu +eJ +Fg +eJ +YN +tF +Mo +Zj +HQ +qo +Jp +nu +aR +nu +TC +nu +YV +nu +nu +oS +nu +nu +ny +Sw +nu +nu +nu +nu +BO +BO +BO +BO +BO +BO +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +Io +ib +ib +nu +nu +ib +ox +"} +(34,1,1) = {" +ox +kg +kg +Gn +Nl +gh +jw +lT +oo +kg +kg +Gn +Gn +Wa +KG +xd +Ez +mz +HK +kg +ie +Jw +Jw +jk +Jw +jk +dn +Jw +Jw +LH +Ii +Qi +aI +nu +Xo +nu +nu +YV +Sw +nu +nu +nu +sA +nu +Gj +nu +nu +HZ +nu +YV +nu +nu +BO +BO +BO +BO +BO +BO +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +nu +nu +ib +ox +"} +(35,1,1) = {" +ox +kg +kg +kg +Hu +Ep +iV +Go +Ip +kg +kg +Gn +Gn +lO +nO +hU +UD +KG +dm +kg +kg +ll +fA +fA +fA +ak +fA +fA +fA +fA +ll +fA +nu +nu +ny +nu +nu +Aj +HZ +nu +ew +nu +nu +bu +nu +nu +nu +nu +nu +Aj +nu +nu +BO +BO +BO +BO +BO +BO +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +nu +nu +ib +ox +"} +(36,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +KG +WR +iP +rU +Ez +cf +GM +GM +fA +fA +yZ +vf +ll +fA +fA +fA +ak +fA +fA +oS +ny +qs +YV +qs +nu +nu +nu +nu +nu +nu +Sw +nu +qs +oS +nu +nu +Sw +nu +nu +BO +BO +BO +BO +BO +BO +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +nu +nu +ib +ox +"} +(37,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +bd +xd +zW +nv +DP +KG +FV +GM +GM +fA +fA +fA +GM +Px +fA +IG +GM +Hi +fA +fA +nu +nu +nu +nu +TC +nu +ah +nu +nu +nm +nu +nu +nu +nu +nu +nu +sk +nu +nu +zg +BO +BO +BO +BO +BO +Fp +Ud +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +nu +nu +ib +ox +"} +(38,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +bd +KG +KG +KG +lO +Jc +GM +GM +GM +fA +fA +fA +fA +fA +fA +GM +Jt +fA +fA +fA +nu +TC +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(39,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +Ek +KG +lO +MW +pP +GM +GM +GM +GM +fA +fA +fA +fA +fA +fA +fA +xD +fA +fA +fA +oS +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(40,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +IB +nu +nu +nu +nu +GM +RV +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(41,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +GM +nu +nu +Sw +Xv +GM +fA +fA +fA +fA +fA +fA +fA +fA +fA +GM +GM +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(42,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +GM +nu +nu +nu +ny +GM +fA +fA +fA +fA +fA +fA +fA +fA +fA +EC +GM +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +Bo +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ox +"} +(43,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +WM +GM +Px +ny +nu +nu +nu +nu +nu +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ox +"} +(44,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +GM +GM +GM +nu +nu +nu +nu +nu +nu +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(45,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +GM +GM +GM +nu +nu +nu +nu +nu +nu +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(46,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +Ti +GM +GM +nu +nu +nu +nu +nu +nu +fA +fA +ak +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +wq +nu +nu +nu +nu +nu +nu +nu +nu +nu +fA +ib +ox +"} +(47,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +Ti +GM +nu +nu +nu +nu +nu +nu +fA +fA +fA +xD +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +fA +fA +ib +ox +"} +(48,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +Ti +GM +nu +nu +nu +nu +nu +nu +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +fA +fA +ib +ox +"} +(49,1,1) = {" +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +Ti +GM +nu +nu +nu +nu +nu +nu +fA +fA +fA +GM +fA +fA +fA +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +Fq +nu +ib +ib +ib +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +fA +ib +ox +"} +(50,1,1) = {" +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +kg +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +rt +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(51,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +dQ +dQ +XO +dQ +dQ +GM +nu +nu +nu +ib +ox +"} +(52,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +Fq +nu +nu +nu +nu +nu +nu +nu +nu +nu +dQ +GH +jN +ZN +zo +GM +nu +nu +nu +ib +ox +"} +(53,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +RC +Zu +QD +bt +qW +CX +nu +nu +nu +ib +ox +"} +(54,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +dQ +WS +Tm +Vc +SI +Lx +nu +nu +nu +ib +ox +"} +(55,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +dQ +dQ +Pv +dQ +dQ +Lx +nu +nu +nu +ib +ox +"} +(56,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +ib +nu +nu +nu +fA +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +GM +GM +GM +GM +dx +gK +nu +nu +nu +ib +ox +"} +(57,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +Io +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(58,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ox +"} +(59,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +fA +fA +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +ox +"} +(60,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +fA +fA +fA +fA +nu +nu +nu +nu +nu +nu +Xb +nu +nu +nu +ib +ox +"} +(61,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +nu +nu +ib +ox +"} +(62,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +nu +ib +ox +"} +(63,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +ib +nu +nu +nu +ib +ib +ib +nu +nu +nu +nu +nu +ib +ib +nu +nu +nu +nu +ib +ib +ib +nu +nu +nu +nu +nu +nu +nu +nu +ib +ib +nu +nu +nu +nu +ib +ib +ox +"} +(64,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ib +ox +"} +(65,1,1) = {" +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +cp +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +ox +"} diff --git a/_maps/virtual_domains/pipedream.dmm b/_maps/virtual_domains/pipedream.dmm new file mode 100644 index 00000000000..44bd845477a --- /dev/null +++ b/_maps/virtual_domains/pipedream.dmm @@ -0,0 +1,3713 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"af" = ( +/obj/structure/chair/plastic{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"aw" = ( +/obj/structure/disposalpipe/sorting/mail/flip{ + dir = 1 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"ax" = ( +/obj/effect/turf_decal/tile/yellow/fourcorners, +/obj/structure/frame/computer{ + anchored = 1; + dir = 4 + }, +/obj/item/shard{ + icon_state = "medium" + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"aK" = ( +/turf/open/space/basic, +/area/space) +"aL" = ( +/obj/effect/turf_decal/tile/yellow/half/contrasted, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"bq" = ( +/obj/machinery/light/small/red/dim{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"bs" = ( +/turf/open/floor/carpet/orange, +/area/virtual_domain/powered) +"bw" = ( +/obj/structure/disposalpipe/broken{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/closet/crate/preopen, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"bx" = ( +/obj/structure/frame/computer, +/obj/item/shard, +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-12" + }, +/area/virtual_domain/powered) +"bA" = ( +/obj/structure/chair/plastic, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"bG" = ( +/obj/structure/lattice/catwalk{ + name = "industrial lift" + }, +/obj/structure/closet/crate/preopen, +/obj/structure/railing, +/turf/open/chasm, +/area/virtual_domain/powered) +"bS" = ( +/obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ + dir = 1 + }, +/obj/structure/table/reinforced, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/item/folder/yellow, +/obj/item/folder/blue{ + pixel_x = 2; + pixel_y = -2 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"cw" = ( +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 9 + }, +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"cB" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 10 + }, +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"cF" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 9 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"dx" = ( +/obj/effect/turf_decal/trimline/yellow/line, +/obj/item/shard, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"dz" = ( +/obj/machinery/light/broken, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/trimline/yellow/corner, +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 8 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"dA" = ( +/obj/machinery/light/dim{ + dir = 4 + }, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"dP" = ( +/obj/effect/turf_decal/tile/yellow/half/contrasted, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"eg" = ( +/turf/closed/wall, +/area/virtual_domain/powered) +"ei" = ( +/obj/machinery/conveyor/auto{ + dir = 6; + icon_state = "conveyor_map_inverted"; + inverted = 1 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"ev" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"eJ" = ( +/obj/structure/disposalpipe/sorting{ + dir = 2 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"eN" = ( +/obj/effect/turf_decal/trimline/yellow/arrow_cw{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/broken{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"eY" = ( +/turf/closed/wall/r_wall, +/area/virtual_domain/powered) +"fe" = ( +/obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ + dir = 8 + }, +/obj/structure/table/reinforced, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"fg" = ( +/turf/open/floor/iron/stairs/left{ + dir = 8 + }, +/area/virtual_domain/powered) +"fj" = ( +/obj/structure/closet/crate/preopen, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"fl" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"fw" = ( +/obj/structure/door_assembly/door_assembly_eng, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"fK" = ( +/obj/structure/chair/stool/bar/directional/west, +/turf/open/floor/iron/cafeteria, +/area/virtual_domain/powered) +"fR" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 5 + }, +/obj/structure/sign/poster/official/random/directional/west, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"fZ" = ( +/obj/effect/turf_decal/tile/yellow/fourcorners, +/obj/structure/chair/office{ + dir = 8 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"gc" = ( +/obj/structure/disposalpipe/broken, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"gj" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"gs" = ( +/obj/machinery/door/airlock/external/glass/ruin, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"gN" = ( +/obj/structure/disposalpipe/sorting{ + dir = 8 + }, +/turf/open/floor/catwalk_floor/iron, +/area/virtual_domain/powered) +"gV" = ( +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 8 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"hg" = ( +/obj/effect/turf_decal/caution{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"hi" = ( +/turf/open/floor/iron, +/area/virtual_domain/powered) +"hk" = ( +/obj/effect/turf_decal/tile/yellow/anticorner/contrasted, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/broken{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"ho" = ( +/obj/effect/turf_decal/siding/white{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"iw" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"iz" = ( +/obj/structure/broken_flooring/corner, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"iI" = ( +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/corner, +/obj/effect/decal/cleanable/blood/drip, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"jv" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 8 + }, +/obj/machinery/light/small/red/dim{ + dir = 8 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"jw" = ( +/obj/effect/turf_decal/delivery, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"jH" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/catwalk_floor/iron, +/area/virtual_domain/powered) +"jQ" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/light/small/red/dim{ + dir = 1 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"jS" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"jW" = ( +/obj/effect/decal/cleanable/generic, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"kh" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"ki" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/bitrunning/cache_spawn, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"kn" = ( +/obj/machinery/light/small/red/dim{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"kJ" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/door/poddoor/shutters/indestructible{ + dir = 4; + id = "factorylockdown" + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"kU" = ( +/turf/open/floor/plating, +/area/virtual_domain/powered) +"lp" = ( +/obj/machinery/door/airlock/maintenance, +/obj/effect/mapping_helpers/airlock/locked, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"lt" = ( +/obj/structure/disposalpipe/sorting{ + dir = 8 + }, +/mob/living/basic/hivebot/range, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"lx" = ( +/obj/machinery/door/poddoor/shutters/indestructible{ + dir = 4; + id = "factorylockdown" + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"lB" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 5 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"lC" = ( +/obj/machinery/door/airlock/glass, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"lI" = ( +/obj/effect/mapping_helpers/burnt_floor, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"lN" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"lW" = ( +/obj/structure/disposalpipe/sorting{ + dir = 8 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"mh" = ( +/obj/structure/broken_flooring/pile{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"mu" = ( +/obj/structure/disposalpipe/segment, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"mE" = ( +/obj/machinery/door/airlock/maintenance, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"mY" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 1 + }, +/obj/machinery/light/small/red/dim{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"nc" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/sign/poster/official/safety_internals/directional/south, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"nz" = ( +/obj/structure/broken_flooring/side/directional/north, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"nD" = ( +/obj/structure/disposalpipe/trunk/multiz, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"nL" = ( +/obj/effect/turf_decal/tile/dark/half, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"nS" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"op" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/dim{ + dir = 1 + }, +/obj/structure/sign/warning/doors/directional/north, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"oN" = ( +/obj/machinery/conveyor/auto, +/obj/structure/window/reinforced/spawner/directional/west, +/obj/structure/window/reinforced/spawner/directional/east, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"oX" = ( +/obj/structure/broken_flooring/corner/directional/north, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"pa" = ( +/obj/machinery/light/small/red/dim{ + dir = 1 + }, +/turf/open/floor/carpet/orange, +/area/virtual_domain/powered) +"pb" = ( +/obj/structure/broken_flooring/corner{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"pf" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/effect/mapping_helpers/damaged_window, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"pi" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"po" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/crate/maint, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"pv" = ( +/obj/structure/broken_flooring/side{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"pI" = ( +/obj/effect/turf_decal/tile/yellow/fourcorners, +/obj/machinery/light/small/red/dim{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"pJ" = ( +/obj/structure/broken_flooring/pile{ + dir = 1 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"qc" = ( +/obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ + dir = 8 + }, +/obj/structure/table/reinforced, +/obj/effect/spawner/random/bureaucracy/briefcase, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"qk" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"qK" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/sign/warning/secure_area/directional/north, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"qN" = ( +/obj/effect/turf_decal/siding/white{ + dir = 4 + }, +/obj/effect/mob_spawn/corpse/human/factory, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"qT" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/light/small/red/dim{ + dir = 1 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"qV" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"qW" = ( +/obj/machinery/light/dim{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"rc" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/sign/poster/contraband/random/directional/north, +/obj/effect/landmark/bitrunning/cache_spawn, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"rz" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 1 + }, +/obj/machinery/light/small/red/dim, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"rG" = ( +/obj/machinery/light/dim, +/obj/effect/turf_decal/trimline/yellow/line, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"rJ" = ( +/obj/structure/railing, +/obj/effect/decal/cleanable/oil, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"rM" = ( +/obj/structure/disposalpipe/broken{ + dir = 1 + }, +/mob/living/basic/hivebot/strong, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"rO" = ( +/turf/closed/mineral, +/area/space) +"sn" = ( +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-38" + }, +/area/virtual_domain/powered) +"sB" = ( +/obj/machinery/light/broken{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/stripes{ + dir = 8 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"sW" = ( +/obj/effect/decal/cleanable/oil/streak, +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 4 + }, +/obj/effect/decal/cleanable/blood/drip, +/obj/effect/decal/cleanable/blood/drip, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"tl" = ( +/obj/machinery/door/poddoor/shutters/indestructible{ + id = "factorylockdown" + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"tr" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"tE" = ( +/obj/structure/disposalpipe/segment, +/mob/living/basic/hivebot/range, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"ud" = ( +/obj/effect/decal/cleanable/blood/drip, +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-110" + }, +/area/virtual_domain/powered) +"uk" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/effect/decal/cleanable/blood/splatter/over_window, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"um" = ( +/obj/machinery/light/dim{ + dir = 1 + }, +/turf/open/floor/iron/cafeteria, +/area/virtual_domain/powered) +"uv" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/broken_flooring/pile{ + dir = 1 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"uz" = ( +/obj/effect/spawner/random/trash/mess, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"uC" = ( +/obj/structure/falsewall, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"uF" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"uP" = ( +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-55" + }, +/area/virtual_domain/powered) +"uU" = ( +/obj/structure/broken_flooring/side, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"vb" = ( +/obj/effect/turf_decal/trimline/yellow/line, +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 5 + }, +/obj/machinery/light/broken, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"ve" = ( +/obj/machinery/mass_driver/trash{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"vA" = ( +/obj/structure/closet/crate/maint, +/obj/effect/turf_decal/stripes{ + dir = 9 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"vL" = ( +/obj/effect/decal/cleanable/glass, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"vQ" = ( +/obj/structure/disposalpipe/segment, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"vU" = ( +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"wg" = ( +/obj/machinery/light/small/red/dim{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/crate/preopen, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"wh" = ( +/obj/structure/table/wood, +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-207" + }, +/area/virtual_domain/powered) +"wl" = ( +/obj/item/shard, +/turf/open/space/basic, +/area/space) +"wm" = ( +/obj/effect/turf_decal/tile/yellow/half/contrasted{ + dir = 1 + }, +/obj/structure/sign/clock/directional/north, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"wq" = ( +/obj/structure/table/wood, +/obj/machinery/button/door{ + name = "Cargo Bay Lockdown"; + id = "factorylockdown" + }, +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-63" + }, +/area/virtual_domain/powered) +"ws" = ( +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"ww" = ( +/obj/effect/turf_decal/stripes{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/mob/living/basic/hivebot, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"wU" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"wW" = ( +/obj/effect/turf_decal/tile/yellow/fourcorners, +/obj/structure/disposalpipe/segment, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"xa" = ( +/obj/machinery/door/poddoor/shutters/indestructible{ + dir = 8; + id = "factorylockdown" + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"xj" = ( +/obj/structure/railing/corner/end{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"xk" = ( +/obj/machinery/light/dim{ + dir = 4 + }, +/obj/effect/landmark/bitrunning/cache_spawn, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"xl" = ( +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"xA" = ( +/obj/effect/decal/cleanable/generic, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"xE" = ( +/obj/effect/turf_decal/trimline/yellow/line, +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 9 + }, +/obj/machinery/light/broken, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"xF" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/binary, +/area/virtual_domain/powered) +"xM" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/bed/dogbed{ + name = "cat bed" + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"xT" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"yB" = ( +/obj/machinery/door/airlock/maintenance, +/obj/effect/mapping_helpers/airlock/welded, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"yM" = ( +/turf/closed/indestructible/fakedoor{ + name = "Stairwell Access" + }, +/area/virtual_domain/powered) +"yQ" = ( +/turf/template_noop, +/area/template_noop) +"yX" = ( +/obj/structure/fans/tiny, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"zp" = ( +/obj/structure/chair/sofa/corp/right{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/broken, +/turf/open/floor/carpet/orange, +/area/virtual_domain/powered) +"zB" = ( +/obj/structure/closet/crate/bin, +/obj/item/trash/tray, +/obj/effect/spawner/random/trash/garbage, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"zE" = ( +/obj/structure/disposalpipe/broken{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"zO" = ( +/obj/effect/turf_decal/siding/white{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/broken, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Av" = ( +/obj/item/stack/rods/two, +/turf/open/space/basic, +/area/space) +"Aw" = ( +/obj/structure/lattice/catwalk{ + name = "industrial lift" + }, +/mob/living/basic/hivebot/rapid, +/turf/open/chasm, +/area/virtual_domain/powered) +"AJ" = ( +/obj/effect/decal/cleanable/generic, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"AP" = ( +/obj/structure/railing, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"AU" = ( +/turf/open/misc/asteroid/airless, +/area/space) +"Bd" = ( +/obj/structure/closet/secure_closet/tac{ + req_access = null + }, +/obj/item/ammo_casing/shotgun/buckshot, +/obj/item/ammo_casing/shotgun/buckshot, +/obj/item/ammo_casing/shotgun/buckshot, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Bh" = ( +/obj/structure/broken_flooring/corner/directional/east, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Bx" = ( +/obj/structure/table/reinforced, +/obj/machinery/microwave{ + broken = 1; + desc = "No longer cooks and boils stuff." + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"BA" = ( +/obj/structure/broken_flooring/corner/directional/south, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"BI" = ( +/obj/machinery/door/airlock/command/glass{ + name = "Quartermaster's Office" + }, +/obj/effect/mapping_helpers/airlock/access/any/away/command, +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"BN" = ( +/obj/structure/flora/rock/pile/style_random, +/turf/open/misc/asteroid/airless, +/area/space) +"BW" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"BX" = ( +/obj/effect/decal/cleanable/robot_debris/old, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Ci" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 8 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Ct" = ( +/obj/machinery/conveyor/auto{ + dir = 6 + }, +/obj/machinery/light/broken{ + dir = 1 + }, +/obj/structure/sign/warning/vacuum/directional/north, +/obj/structure/window/reinforced/spawner/directional/east, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Cv" = ( +/obj/structure/chair/office{ + dir = 8 + }, +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-157" + }, +/area/virtual_domain/powered) +"CA" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/broken_flooring/side{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"CQ" = ( +/obj/effect/spawner/random/trash/botanical_waste, +/obj/item/trash/chips, +/obj/structure/closet/secure_closet/freezer/empty/open, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"CR" = ( +/obj/structure/flora/rock/pile/style_random, +/turf/open/misc/asteroid/airless, +/area/virtual_domain/powered) +"CX" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Dr" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/machinery/light/dim{ + dir = 8 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"DA" = ( +/obj/structure/disposalpipe/segment, +/turf/open/floor/catwalk_floor/iron, +/area/virtual_domain/powered) +"DE" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"DP" = ( +/obj/structure/table/reinforced, +/obj/effect/spawner/random/food_or_drink/snack, +/turf/open/floor/iron/cafeteria, +/area/virtual_domain/powered) +"Ex" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-137" + }, +/area/virtual_domain/powered) +"Ez" = ( +/obj/structure/flora/rock/style_random, +/turf/open/misc/asteroid/airless, +/area/space) +"EI" = ( +/obj/effect/turf_decal/stripes{ + dir = 8 + }, +/obj/effect/decal/cleanable/oil, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"EJ" = ( +/obj/machinery/recycler/deathtrap{ + dir = 8 + }, +/obj/machinery/conveyor/auto{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Fa" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/closet/crate/maint, +/obj/effect/turf_decal/delivery, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Ff" = ( +/obj/structure/disposalpipe/trunk/multiz{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Fo" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/cafeteria, +/area/virtual_domain/powered) +"Fr" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/closet/crate/preopen, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Fw" = ( +/obj/structure/flora/bush/fullgrass/style_random, +/obj/structure/flora/rock/pile/style_random, +/obj/structure/flora/bush/flowers_yw/style_random, +/obj/structure/window/reinforced/spawner/directional/north, +/obj/structure/window/reinforced/spawner/directional/west, +/turf/open/floor/grass, +/area/virtual_domain/powered) +"FK" = ( +/obj/effect/mapping_helpers/burnt_floor, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"FO" = ( +/turf/open/misc/asteroid/airless, +/area/virtual_domain/powered) +"FP" = ( +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-110" + }, +/area/virtual_domain/powered) +"Gb" = ( +/obj/effect/turf_decal/stripes{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Ge" = ( +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-21" + }, +/area/virtual_domain/powered) +"Gh" = ( +/obj/machinery/door/airlock/maintenance, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Gi" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 9 + }, +/obj/effect/turf_decal/trimline/yellow/corner, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Gs" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 1 + }, +/obj/machinery/light/broken{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Gy" = ( +/obj/machinery/conveyor/auto{ + dir = 9; + inverted = 1; + icon_state = "conveyor_map_inverted" + }, +/obj/effect/turf_decal/stripes/line, +/obj/structure/window/reinforced/spawner/directional/west, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"GI" = ( +/obj/effect/turf_decal/trimline/yellow/arrow_ccw, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"GV" = ( +/obj/machinery/light/small/red/dim{ + dir = 8 + }, +/obj/effect/turf_decal/stripes{ + dir = 9 + }, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Hn" = ( +/turf/open/floor/iron/cafeteria, +/area/virtual_domain/powered) +"HI" = ( +/obj/structure/broken_flooring/pile/directional/north, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Ib" = ( +/obj/structure/chair/sofa/corp/left{ + dir = 1 + }, +/turf/open/floor/carpet/orange, +/area/virtual_domain/powered) +"Ip" = ( +/obj/machinery/door/airlock/engineering/glass, +/obj/effect/mapping_helpers/airlock/access/any/away/supply, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Is" = ( +/obj/machinery/door/airlock/engineering/glass, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"IF" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"IK" = ( +/obj/effect/turf_decal/trimline/yellow/line, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"IZ" = ( +/obj/structure/lattice/catwalk{ + name = "industrial lift" + }, +/obj/structure/closet/crate, +/turf/open/chasm, +/area/virtual_domain/powered) +"Jl" = ( +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Jm" = ( +/obj/structure/broken_flooring/pile/directional/north, +/obj/machinery/light/dim, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Jn" = ( +/obj/effect/turf_decal/stripes{ + dir = 4 + }, +/obj/structure/disposalpipe/segment, +/obj/structure/railing/corner/end/flip{ + dir = 8 + }, +/obj/structure/sign/warning/doors/directional/east, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Jq" = ( +/obj/structure/broken_flooring/pile{ + dir = 1 + }, +/obj/structure/sign/poster/contraband/random/directional/west, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"JE" = ( +/obj/machinery/light/small/red/dim{ + dir = 1 + }, +/obj/structure/sign/warning/chem_diamond/directional/west, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"JR" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"JT" = ( +/obj/structure/lattice/catwalk{ + name = "industrial lift" + }, +/obj/effect/spawner/random/trash/grime, +/turf/open/chasm, +/area/virtual_domain/powered) +"Kb" = ( +/obj/effect/mob_spawn/corpse/human/factory/guard, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Kt" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"KO" = ( +/obj/structure/broken_flooring/side/directional/north, +/obj/machinery/light/small/red/dim, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"KX" = ( +/obj/structure/lattice/catwalk{ + name = "industrial lift" + }, +/turf/open/chasm, +/area/virtual_domain/powered) +"Ln" = ( +/obj/structure/disposalpipe/broken{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Lp" = ( +/obj/effect/turf_decal/trimline/yellow/line, +/obj/machinery/light/broken, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"LN" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 10 + }, +/obj/machinery/light/dim{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"LU" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 6 + }, +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Mc" = ( +/obj/effect/turf_decal/trimline/yellow/warning, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Mh" = ( +/obj/machinery/conveyor/auto{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Mi" = ( +/obj/effect/mob_spawn/corpse/human/factory, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Mj" = ( +/turf/closed/mineral, +/area/virtual_domain/powered) +"Mu" = ( +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Mx" = ( +/obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ + dir = 1 + }, +/obj/structure/filingcabinet, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"My" = ( +/obj/machinery/conveyor/auto{ + dir = 1 + }, +/obj/machinery/light/small/red/dim{ + dir = 8 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"MI" = ( +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-74" + }, +/area/virtual_domain/powered) +"MN" = ( +/obj/effect/turf_decal/tile/dark, +/obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Nc" = ( +/obj/structure/chair/plastic{ + dir = 8 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Nu" = ( +/obj/effect/turf_decal/trimline/yellow/line, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"NW" = ( +/obj/effect/decal/cleanable/dirt, +/mob/living/basic/hivebot/strong, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Ok" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"On" = ( +/obj/structure/broken_flooring/side{ + dir = 4 + }, +/obj/machinery/light/broken{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"OJ" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/stripes{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"OL" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"OQ" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/sign/poster/ripped/directional/west, +/turf/open/floor/carpet/orange, +/area/virtual_domain/powered) +"OR" = ( +/obj/machinery/light/broken, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Po" = ( +/obj/machinery/light/small/red/dim{ + dir = 4 + }, +/obj/structure/disposalpipe/segment, +/obj/structure/broken_flooring/corner, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Pr" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 5 + }, +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 8 + }, +/obj/structure/sign/poster/official/random/directional/east, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"PH" = ( +/obj/structure/railing/corner/end/flip{ + dir = 8 + }, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Qd" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 6 + }, +/obj/machinery/light/dim{ + dir = 8 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Qh" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/light/broken{ + dir = 8 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Qj" = ( +/obj/machinery/light/dim{ + dir = 8 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Qo" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"Qr" = ( +/turf/closed/indestructible/fakedoor/maintenance{ + name = "maintenance access" + }, +/area/virtual_domain/powered) +"Qv" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 9 + }, +/obj/machinery/light/small/red/dim{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Qy" = ( +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/structure/disposaloutlet{ + dir = 1 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"QI" = ( +/obj/structure/sign/calendar/directional/north, +/obj/effect/spawner/random/trash/garbage, +/turf/open/floor/iron/cafeteria, +/area/virtual_domain/powered) +"QK" = ( +/obj/structure/table, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"QN" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"QP" = ( +/obj/structure/sign/poster/contraband/random/directional/east, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"QW" = ( +/obj/machinery/conveyor/auto{ + dir = 5 + }, +/obj/effect/decal/cleanable/cobweb, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Ru" = ( +/obj/machinery/door/airlock/external/glass/ruin, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Ry" = ( +/obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ + dir = 4 + }, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/machinery/disposal/bin, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"RJ" = ( +/turf/closed/indestructible/binary, +/area/virtual_domain/powered) +"RK" = ( +/obj/effect/decal/cleanable/blood/drip, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"RZ" = ( +/obj/effect/turf_decal/tile/yellow/half/contrasted{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Sg" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Sl" = ( +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 8 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"SC" = ( +/mob/living/basic/hivebot/strong, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"SR" = ( +/obj/effect/turf_decal/trimline/yellow/line, +/obj/effect/decal/cleanable/glass, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"SS" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/closed/mineral, +/area/virtual_domain/powered) +"SU" = ( +/obj/effect/spawner/structure/window, +/obj/item/stack/rods/two, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"SZ" = ( +/obj/structure/table/reinforced, +/obj/effect/spawner/random/food_or_drink/booze, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Te" = ( +/obj/effect/decal/cleanable/blood/tracks{ + dir = 5 + }, +/obj/effect/mob_spawn/corpse/human/factory/qm, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Tn" = ( +/obj/structure/broken_flooring/corner{ + dir = 4 + }, +/mob/living/basic/hivebot, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Tp" = ( +/obj/machinery/door/poddoor/shutters/indestructible{ + dir = 4; + id = "factorylockdown" + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Tt" = ( +/obj/machinery/conveyor/auto{ + dir = 9 + }, +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"TH" = ( +/obj/structure/broken_flooring/corner/directional/south, +/obj/item/ammo_casing/shotgun/buckshot/spent, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Ue" = ( +/obj/structure/table/reinforced, +/obj/machinery/light/small/red/dim{ + dir = 8 + }, +/obj/structure/sign/poster/official/cleanliness/directional/west, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Uw" = ( +/obj/machinery/light/dim{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"UO" = ( +/obj/structure/broken_flooring/side/directional/north, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"UV" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 6 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"UX" = ( +/obj/effect/turf_decal/trimline/yellow/line, +/obj/machinery/light/small/red/dim, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"UY" = ( +/obj/effect/decal/cleanable/blood/tracks{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Vb" = ( +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/light/broken, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Vg" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/machinery/light/small/red/dim, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Vh" = ( +/obj/structure/table/reinforced, +/turf/open/floor/iron/cafeteria, +/area/virtual_domain/powered) +"Vy" = ( +/obj/structure/broken_flooring/singular{ + dir = 4 + }, +/obj/effect/mob_spawn/corpse/human/factory/guard, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"VA" = ( +/obj/machinery/light/small/red/dim{ + dir = 1 + }, +/obj/structure/table, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"VJ" = ( +/obj/structure/broken_flooring/corner{ + dir = 1 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"VL" = ( +/obj/structure/sign/warning/secure_area/directional/south, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"VO" = ( +/obj/machinery/light/broken{ + dir = 1 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Wd" = ( +/obj/structure/lattice/catwalk{ + name = "industrial lift" + }, +/obj/structure/railing, +/turf/open/chasm, +/area/virtual_domain/powered) +"Wp" = ( +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"WT" = ( +/obj/effect/turf_decal/stripes{ + dir = 8 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"WV" = ( +/obj/machinery/conveyor/auto{ + dir = 10; + inverted = 1; + icon_state = "conveyor_map_inverted" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Xb" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/closed/wall, +/area/virtual_domain/powered) +"Xc" = ( +/obj/effect/turf_decal/trimline/yellow/line, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Xm" = ( +/obj/item/gun/ballistic/shotgun/lethal, +/obj/machinery/light/broken{ + dir = 1 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Xo" = ( +/obj/machinery/conveyor/auto{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Xw" = ( +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/yellow/line{ + dir = 10 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"XL" = ( +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 5 + }, +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 4 + }, +/obj/structure/sign/warning/vacuum/external/directional/south, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"XN" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"XO" = ( +/obj/effect/turf_decal/delivery, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"XP" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/railing/corner/end{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"XQ" = ( +/obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ + dir = 4 + }, +/obj/machinery/light/dim{ + dir = 4 + }, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"XR" = ( +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 1 + }, +/obj/structure/disposalpipe/segment, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Yc" = ( +/obj/item/gun/ballistic/revolver, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Yl" = ( +/obj/structure/broken_flooring/corner/directional/west, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Ym" = ( +/mob/living/simple_animal/pet/cat/space, +/obj/structure/bed/dogbed{ + name = "cat bed" + }, +/obj/item/toy/plush/moth{ + pixel_x = 3; + pixel_y = 4 + }, +/obj/machinery/light/small/dim/directional/south, +/obj/structure/sign/poster/official/moth_hardhat/directional/west, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Yt" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Yz" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/door/poddoor/shutters/indestructible{ + id = "factorylockdown" + }, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"YF" = ( +/obj/machinery/light/small/red/dim, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"YL" = ( +/obj/effect/turf_decal/tile/yellow/anticorner/contrasted, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"YP" = ( +/obj/effect/turf_decal/trimline/yellow/corner{ + dir = 1 + }, +/obj/machinery/light/dim, +/turf/open/floor/iron, +/area/virtual_domain/powered) +"Zb" = ( +/obj/effect/decal/cleanable/oil, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"Zg" = ( +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-157" + }, +/area/virtual_domain/powered) +"Zy" = ( +/obj/structure/table, +/obj/item/flashlight/lantern, +/turf/open/floor/plating, +/area/virtual_domain/powered) +"ZI" = ( +/turf/open/floor/carpet/royalblue{ + icon_state = "carpet_royalblue-203" + }, +/area/virtual_domain/powered) +"ZP" = ( +/obj/structure/railing, +/turf/open/floor/iron/stairs/right{ + dir = 8 + }, +/area/virtual_domain/powered) + +(1,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +"} +(2,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +Mj +Mj +eg +eg +SS +eg +eg +eg +Xb +Mj +Mj +RJ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +"} +(3,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +Mj +Bx +SZ +Ue +CQ +zB +eg +OQ +bs +Ib +Mj +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +yQ +yQ +"} +(4,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +eg +ho +ho +qN +ho +zO +eg +pa +bs +zp +eY +RJ +RJ +Mj +RJ +RJ +rO +rO +RJ +RJ +xF +"} +(5,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +eg +eg +eg +eg +eg +eg +eg +RJ +eg +um +DP +Vh +Vh +Hn +tr +fg +ZP +Fw +eY +Mj +Mj +Mj +AU +AU +AU +rO +rO +rO +RJ +"} +(6,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +eg +vA +Dr +bw +Jq +gc +eg +RJ +eg +Hn +fK +fK +fK +Hn +lC +hi +FK +eY +eY +Mj +Ez +AU +aK +aK +AU +AU +BN +rO +RJ +"} +(7,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +eg +jQ +lt +kU +vU +lN +eg +RJ +eg +QI +Fo +Hn +Hn +Hn +tr +hi +Ln +eY +Mj +Mj +AU +AU +BN +aK +aK +aK +AU +rO +RJ +"} +(8,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +eg +uU +gj +kU +Tn +OR +eg +RJ +eg +eg +uk +pf +pf +eg +eg +qV +Vb +eY +aK +aK +aK +aK +aK +aK +aK +aK +aK +aK +RJ +"} +(9,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +eg +ki +gj +kU +kU +kU +eg +RJ +eg +kU +kU +nD +nS +kU +Qj +FK +nc +eY +aK +aK +aK +aK +aK +aK +AU +aK +aK +aK +RJ +"} +(10,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +RJ +RJ +RJ +RJ +RJ +eg +eg +kJ +lx +lx +lp +eg +RJ +eg +mu +AJ +mu +eJ +MN +BW +hi +Sg +eY +aK +aK +aK +aK +aK +aK +aK +aK +aK +aK +RJ +"} +(11,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +eg +eg +eg +Qr +eg +eg +JE +gj +pi +kU +VL +eg +eg +eg +VO +kU +Fr +jw +qk +XR +vQ +Vg +eY +aK +aK +aK +JR +JR +JR +JR +JR +Qo +aK +RJ +"} +(12,1,1) = {" +yQ +yQ +yQ +yQ +RJ +RJ +RJ +eg +eg +eg +eg +eg +eg +yM +eg +GV +WT +xj +qk +Qh +XP +lW +ww +EI +Kt +Qh +mu +Yz +xl +HI +kU +Bh +Kb +kU +hi +CX +eY +eY +aK +aK +JR +JR +JR +JR +JR +JR +aK +RJ +"} +(13,1,1) = {" +yQ +yQ +yQ +yQ +RJ +RJ +RJ +eg +VA +bA +eg +kU +sB +WT +mh +kU +pv +AP +IZ +KX +Wd +uv +DE +Mi +gj +xT +hi +tl +IF +kU +hi +Yc +kU +kU +vU +lB +XL +eg +tr +eY +JR +JR +JR +JR +JR +JR +aK +RJ +"} +(14,1,1) = {" +yQ +yQ +yQ +yQ +RJ +RJ +kU +kU +Zy +kU +Gh +Kt +mu +mu +mu +uF +xl +AP +KX +JT +bG +qk +DA +DA +zE +gc +mu +Yz +lW +pi +kU +kU +nL +BW +hi +hg +Wp +Ru +hi +gs +JR +JR +JR +JR +JR +JR +aK +RJ +"} +(15,1,1) = {" +yQ +RJ +RJ +RJ +RJ +RJ +RJ +kU +QP +kU +eg +qT +Gb +Uw +iz +jS +gj +rJ +KX +Aw +Wd +Ff +lN +XO +gj +DE +SC +tl +qk +mu +mu +xl +kU +oX +hi +cF +cw +eY +tr +eY +JR +JR +JR +JR +JR +JR +aK +RJ +"} +(16,1,1) = {" +yQ +RJ +Mj +Mj +Mj +Mj +RJ +eg +eg +eg +eg +Xb +yB +eg +eg +kU +qk +PH +dA +Po +Jn +aw +OJ +CA +QN +kU +Uw +tl +kU +Mc +kU +kh +fj +kU +FK +CX +eY +eY +aK +aK +JR +JR +JR +JR +JR +JR +aK +RJ +"} +(17,1,1) = {" +yQ +RJ +Mj +BN +AU +Mj +Mj +Mj +eg +QW +My +Qy +kU +po +eg +tr +Is +tr +eg +eg +eg +kU +pi +kU +lI +YF +eg +eg +op +kU +BA +iw +kU +kU +FK +rz +eY +aK +aK +aK +JR +JR +JR +JR +JR +ev +aK +RJ +"} +(18,1,1) = {" +yQ +RJ +aK +AU +AU +AU +aK +aK +eg +Ct +oN +Gy +jW +xT +eg +Tp +Tp +Tp +eg +Ym +eg +eg +xa +xa +xa +eg +eg +eg +kU +Zb +kU +Yt +kU +UO +hi +CX +eY +aK +aK +aK +aK +aK +aK +aK +aK +aK +aK +RJ +"} +(19,1,1) = {" +RJ +RJ +aK +aK +aK +aK +wl +aK +yX +ve +Tt +Xo +DE +oX +eg +Sl +gV +dz +eg +uC +eg +qK +mh +kU +kU +Qj +VJ +eg +kU +kU +kU +gj +kU +kU +hi +Ok +eY +aK +aK +aK +aK +aK +aK +aK +aK +aK +aK +RJ +"} +(20,1,1) = {" +RJ +aK +aK +aK +aK +aK +aK +aK +tr +uz +Mh +EJ +kU +kU +mE +Mu +Yl +pJ +eg +kn +pb +kU +kU +kU +Fa +kU +YF +eg +eg +pf +tr +XN +eg +eg +Ci +YP +eY +eY +aK +aK +aK +aK +aK +aK +aK +aK +aK +RJ +"} +(21,1,1) = {" +RJ +aK +aK +aK +aK +aK +Av +CR +tr +kU +ei +WV +pi +Jm +eg +eN +gN +GI +eg +rc +mu +rM +gc +vQ +tE +mu +mu +eg +Mx +qc +ax +bS +fe +pf +hi +hi +af +eY +aK +aK +aK +aK +aK +aK +aK +aK +aK +RJ +"} +(22,1,1) = {" +RJ +aK +aK +aK +aK +aK +aK +FO +eg +eg +wg +uU +lN +uz +eg +mY +jH +rG +eg +xT +Uw +kU +kU +On +pi +kU +Mj +eg +wm +xA +fZ +OL +aL +Ip +hi +lN +QK +eY +aK +aK +aK +aK +BN +aK +aK +aK +aK +RJ +"} +(23,1,1) = {" +RJ +aK +aK +aK +aK +aK +AU +FO +Mj +eg +eg +Mj +Mj +eY +eY +UO +jH +Nu +eg +eg +eg +eg +eg +Mj +Mj +Mj +Mj +eg +RZ +vQ +wW +wU +dP +tr +hi +hi +Nc +eY +aK +BN +AU +aK +aK +aK +aK +aK +aK +RJ +"} +(24,1,1) = {" +RJ +RJ +aK +aK +aK +AU +Ez +Mj +Mj +RJ +Mj +Mj +Vy +hi +eY +CX +jH +Nu +eg +Gi +Qd +jv +fR +cB +Mj +RJ +RJ +eg +Ry +hk +pI +XQ +YL +eg +bq +hi +Mj +eY +Mj +Mj +AU +AU +aK +aK +aK +aK +rO +RJ +"} +(25,1,1) = {" +yQ +RJ +aK +AU +BN +AU +Mj +Mj +RJ +RJ +eY +Xm +TH +fw +eY +qW +hi +dx +pf +UV +sn +uP +Ge +vb +eg +RJ +RJ +eg +Mj +Mj +eg +eg +eg +eg +eg +Mj +Mj +RJ +RJ +Mj +Mj +Mj +RJ +RJ +Mj +Mj +Mj +RJ +"} +(26,1,1) = {" +yQ +RJ +RJ +RJ +RJ +rO +Mj +RJ +RJ +RJ +eY +Bd +vL +hi +vU +sW +hi +SR +SU +CX +FP +wh +Zg +Nu +eg +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +RJ +"} +(27,1,1) = {" +yQ +yQ +yQ +yQ +RJ +RJ +RJ +RJ +yQ +RJ +eY +Jl +RK +BX +eY +CX +RK +iI +BI +ws +ud +bx +Cv +Nu +eg +RJ +RJ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +"} +(28,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +eY +NW +UY +KO +eY +fl +jH +Nu +uk +CX +FP +wq +Zg +Nu +eg +RJ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +"} +(29,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +eY +xk +Te +xT +eY +CX +jH +Nu +pf +Xw +MI +ZI +Ex +xE +eg +RJ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +"} +(30,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +eY +eY +eY +eY +eY +CX +jH +Xc +eg +Pr +LN +xM +Qv +LU +Mj +RJ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +"} +(31,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +RJ +RJ +RJ +RJ +eg +Gs +jH +UX +eg +eg +eg +eg +Mj +Mj +Mj +RJ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +"} +(32,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +eg +Ok +nz +IK +eg +RJ +RJ +RJ +RJ +RJ +RJ +RJ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +"} +(33,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +Mj +CX +hi +Nu +RJ +RJ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +"} +(34,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +Mj +CX +RJ +Lp +eg +RJ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +"} +(35,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +RJ +fl +RJ +RJ +RJ +RJ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +"} +(36,1,1) = {" +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +RJ +RJ +RJ +RJ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +yQ +"} diff --git a/_maps/virtual_domains/pirates.dmm b/_maps/virtual_domains/pirates.dmm new file mode 100644 index 00000000000..9c970f78c37 --- /dev/null +++ b/_maps/virtual_domains/pirates.dmm @@ -0,0 +1,2601 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"ag" = ( +/obj/effect/mapping_helpers/burnt_floor, +/obj/effect/decal/cleanable/garbage, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"by" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"bz" = ( +/obj/structure/flora/bush/grassy{ + pixel_y = 8 + }, +/obj/structure/flora/bush/lavendergrass{ + pixel_y = -10 + }, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"bP" = ( +/obj/structure/flora/bush/flowers_br/style_random, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"cl" = ( +/obj/structure/flora/rock/style_3, +/turf/open/water/beach, +/area/virtual_domain/powered) +"ct" = ( +/obj/structure/closet/cabinet, +/obj/item/clothing/head/costume/pirate/armored, +/obj/item/clothing/suit/costume/pirate/captain/armored, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/wood/parquet, +/area/virtual_domain/powered) +"cx" = ( +/turf/closed/indestructible/binary, +/area/virtual_domain/powered) +"cJ" = ( +/obj/item/stack/cannonball/shellball{ + pixel_x = 13; + pixel_y = 11 + }, +/obj/item/stack/cannonball{ + pixel_x = 9; + pixel_y = 9 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"cQ" = ( +/obj/structure/flora/grass/jungle/b{ + pixel_x = -15; + pixel_y = 9 + }, +/obj/structure/flora/rock/pile/jungle/large/style_2{ + pixel_x = -3; + pixel_y = -1 + }, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"dp" = ( +/turf/closed/wall/mineral/wood/nonmetal, +/area/virtual_domain/powered) +"dA" = ( +/obj/structure/bonfire/prelit, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"dQ" = ( +/obj/structure/flora/rock/style_4, +/turf/open/water/beach, +/area/virtual_domain/powered) +"eb" = ( +/obj/structure/flora/bush/sparsegrass, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"eD" = ( +/obj/structure/flora/coconuts{ + pixel_x = 9; + pixel_y = -14 + }, +/obj/structure/flora/tree/palm/style_2, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"eQ" = ( +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"eW" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 6 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"fx" = ( +/obj/structure/fluff/beach_umbrella{ + pixel_x = -7; + pixel_y = -10 + }, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"gk" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/landmark/bitrunning/cache_spawn, +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"gw" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"ht" = ( +/obj/structure/bookcase/random/fiction, +/turf/open/floor/wood/parquet, +/area/virtual_domain/powered) +"hH" = ( +/obj/item/clothing/suit/armor/militia{ + pixel_x = -5; + pixel_y = 12 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/item/clothing/suit/armor/militia{ + pixel_x = -5; + pixel_y = 6 + }, +/obj/item/clothing/suit/armor/militia{ + pixel_x = -5; + pixel_y = -3 + }, +/obj/item/clothing/head/costume/fancy{ + pixel_x = 6; + pixel_y = 12 + }, +/obj/item/clothing/head/costume/fancy{ + pixel_x = 6; + pixel_y = 6 + }, +/obj/item/clothing/head/hats/coordinator{ + pixel_x = 8; + pixel_y = -5 + }, +/obj/structure/closet/cabinet, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"hM" = ( +/obj/structure/closet/crate/goldcrate, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"hW" = ( +/obj/structure/chair/comfy/carp{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"iM" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/mob/living/simple_animal/hostile/pirate/ranged/space, +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"iO" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"jl" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/structure/table/wood, +/obj/item/flashlight/flare/torch{ + pixel_y = 10; + pixel_x = 7 + }, +/obj/item/reagent_containers/cup/bucket/wooden{ + pixel_y = -16; + pixel_x = 12 + }, +/obj/machinery/recharger{ + pixel_y = 6; + pixel_x = -5 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"jz" = ( +/obj/effect/mapping_helpers/burnt_floor, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"jB" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/machinery/jukebox, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"jC" = ( +/obj/structure/table/wood, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/item/reagent_containers/cup/glass/bottle/rum{ + desc = "Rum with ghostly properties that can help the drinker enter the spirit realm. It has fermented under the sea of space for ages."; + name = "Ghost Pirate Rum"; + pixel_x = -4; + pixel_y = 12 + }, +/obj/item/reagent_containers/cup/glass/drinkingglass/shotglass{ + pixel_x = -7; + pixel_y = 5 + }, +/obj/item/reagent_containers/cup/glass/drinkingglass/shotglass{ + pixel_x = 3; + pixel_y = 7 + }, +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"jQ" = ( +/obj/item/gun/energy/laser/hellgun{ + pixel_y = 10 + }, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"kg" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"kl" = ( +/obj/structure/cannon, +/obj/effect/turf_decal/siding/wood, +/obj/effect/decal/cleanable/ash/large{ + pixel_y = -5; + pixel_x = 8 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"lC" = ( +/obj/item/stack/cannonball{ + pixel_x = 7; + pixel_y = 8 + }, +/obj/item/stack/cannonball{ + pixel_x = 11; + pixel_y = -4 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 1 + }, +/obj/effect/decal/cleanable/oil/streak, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"me" = ( +/obj/effect/turf_decal/siding/wood, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"mw" = ( +/obj/structure/flora/grass/jungle/b/style_random{ + pixel_x = -13; + pixel_y = 18 + }, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"mP" = ( +/obj/structure/flora/bush/fullgrass, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"nz" = ( +/obj/effect/mob_spawn/corpse/human/pirate, +/turf/open/misc/beach/coast{ + dir = 8 + }, +/area/virtual_domain/powered) +"nQ" = ( +/obj/machinery/loot_locator, +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"nS" = ( +/obj/structure/flora/rock/pile/jungle/large, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"nX" = ( +/obj/effect/decal/cleanable/dirt/dust, +/mob/living/simple_animal/hostile/pirate/melee/space, +/turf/open/floor/wood/parquet, +/area/virtual_domain/powered) +"oo" = ( +/obj/machinery/smartfridge/drying_rack, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"oU" = ( +/turf/open/misc/beach/coast{ + dir = 10 + }, +/area/virtual_domain/powered) +"pq" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"px" = ( +/obj/structure/headpike/bone{ + pixel_y = 24 + }, +/turf/open/misc/beach/coast, +/area/virtual_domain/powered) +"pP" = ( +/turf/open/misc/beach/coast, +/area/virtual_domain/powered) +"pU" = ( +/obj/effect/mob_spawn/corpse/human/pirate, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"qj" = ( +/obj/structure/barricade/wooden, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"qm" = ( +/obj/effect/turf_decal/siding/wood, +/obj/item/melee/sabre{ + pixel_y = 12; + pixel_x = -10 + }, +/obj/item/gun/energy/laser/retro, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"qx" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/mapping_helpers/burnt_floor, +/obj/effect/decal/cleanable/dirt/dust, +/mob/living/simple_animal/hostile/pirate/ranged, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"qN" = ( +/obj/structure/flora/bush/sunny/style_3{ + pixel_y = 22 + }, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"qX" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 9 + }, +/obj/structure/fermenting_barrel{ + pixel_x = 6; + pixel_y = 11 + }, +/obj/effect/mob_spawn/ghost_role/human/pirate/skeleton, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"sn" = ( +/obj/structure/table/wood, +/obj/item/book/manual/wiki/ordnance, +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"so" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"th" = ( +/obj/effect/turf_decal/weather/sand, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"tk" = ( +/obj/structure/flora/bush/flowers_pp, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"to" = ( +/mob/living/simple_animal/hostile/pirate/melee, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"ub" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"uw" = ( +/obj/structure/barricade/sandbags, +/obj/effect/turf_decal/weather/sand{ + dir = 4 + }, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"uM" = ( +/obj/structure/flora/bush/stalky{ + pixel_y = 13; + pixel_x = -8 + }, +/turf/open/water/beach, +/area/virtual_domain/powered) +"uT" = ( +/obj/structure/closet/crate/grave, +/obj/structure/flora/grass/jungle/b, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"wb" = ( +/obj/structure/flora/rock, +/turf/open/water/beach, +/area/virtual_domain/powered) +"we" = ( +/obj/effect/mine/explosive/light, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"xc" = ( +/turf/open/misc/beach/coast{ + dir = 4 + }, +/area/virtual_domain/powered) +"xg" = ( +/turf/template_noop, +/area/template_noop) +"xm" = ( +/obj/structure/barricade/wooden/crude, +/turf/closed/wall/mineral/wood/nonmetal, +/area/virtual_domain/powered) +"xB" = ( +/obj/structure/fermenting_barrel/gunpowder{ + pixel_x = -4; + pixel_y = 17 + }, +/obj/structure/fermenting_barrel/gunpowder{ + pixel_x = 4 + }, +/obj/item/stack/cannonball/four{ + pixel_x = -9; + pixel_y = -10 + }, +/obj/item/stack/cannonball{ + pixel_x = 3; + pixel_y = 8 + }, +/obj/item/reagent_containers/cup/bucket/wooden{ + pixel_y = -10 + }, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"xC" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/obj/effect/turf_decal/weather/dirt, +/turf/open/water/beach, +/area/virtual_domain/powered) +"xI" = ( +/obj/structure/flora/rock/pile/style_2, +/turf/open/water/beach, +/area/virtual_domain/powered) +"yc" = ( +/obj/effect/turf_decal/weather/dirt, +/turf/open/water/beach, +/area/virtual_domain/powered) +"ye" = ( +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"yi" = ( +/mob/living/simple_animal/hostile/pirate/melee, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"yq" = ( +/obj/structure/barricade/sandbags, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"yw" = ( +/obj/effect/mapping_helpers/burnt_floor, +/mob/living/simple_animal/hostile/pirate/ranged, +/obj/structure/chair/wood, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"yA" = ( +/obj/item/bedsheet/rainbow/double, +/obj/structure/bed/double, +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"zf" = ( +/obj/structure/flora/bush/flowers_br/style_random, +/obj/structure/flora/bush/ferny, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"zg" = ( +/obj/structure/flora/rock/pile/style_3, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"zR" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"Ax" = ( +/obj/effect/turf_decal/weather/dirt, +/obj/effect/turf_decal/weather/dirt, +/turf/open/water/beach, +/area/virtual_domain/powered) +"AU" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/turf/open/water/beach, +/area/virtual_domain/powered) +"BC" = ( +/obj/effect/turf_decal/siding/wood, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"BO" = ( +/obj/structure/bookcase/random/adult, +/obj/effect/decal/cleanable/cobweb, +/turf/open/floor/wood/parquet, +/area/virtual_domain/powered) +"Cc" = ( +/obj/structure/flora/tree/palm, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Ct" = ( +/turf/open/misc/beach/coast/corner, +/area/virtual_domain/powered) +"Dm" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/table/wood, +/obj/item/flashlight/flare/torch{ + pixel_y = 10 + }, +/obj/item/flashlight/flare/torch{ + pixel_x = 8; + pixel_y = 6 + }, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"DJ" = ( +/obj/effect/mapping_helpers/burnt_floor, +/obj/structure/bed/maint{ + pixel_x = -10; + pixel_y = 9 + }, +/obj/effect/decal/cleanable/wrapping, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"DL" = ( +/obj/structure/flora/bush/sunny, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"ED" = ( +/obj/effect/turf_decal/siding/wood, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 9 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"EZ" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 9 + }, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"FG" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/claymore/cutlass, +/obj/item/clothing/head/costume/pirate/bandana/armored{ + pixel_x = -9; + pixel_y = 7 + }, +/obj/structure/table/wood, +/obj/item/gun/energy/laser{ + pixel_y = -3 + }, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"FT" = ( +/turf/closed/mineral/random/jungle, +/area/virtual_domain/powered) +"GF" = ( +/obj/effect/turf_decal/weather/dirt, +/obj/structure/flora/rock/pile, +/turf/open/water/beach, +/area/virtual_domain/powered) +"GG" = ( +/obj/structure/barricade/sandbags, +/obj/effect/turf_decal/weather/sand{ + dir = 6 + }, +/obj/item/binoculars{ + pixel_x = -1; + pixel_y = 1 + }, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"Hp" = ( +/obj/effect/turf_decal/siding/wood, +/mob/living/simple_animal/hostile/pirate/ranged, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"HY" = ( +/turf/open/misc/beach/coast{ + dir = 6 + }, +/area/virtual_domain/powered) +"It" = ( +/obj/structure/flora/bush/sparsegrass, +/obj/structure/flora/bush/lavendergrass, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"Iz" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/bed/maint, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"IF" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 4 + }, +/turf/open/water/beach, +/area/virtual_domain/powered) +"IG" = ( +/obj/effect/mob_spawn/corpse/human/pirate, +/obj/effect/decal/cleanable/blood/gibs/old, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"IM" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"Jo" = ( +/obj/effect/landmark/bitrunning/cache_spawn, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"Jr" = ( +/obj/structure/headpike/bone, +/turf/open/misc/beach/coast, +/area/virtual_domain/powered) +"Jv" = ( +/obj/effect/turf_decal/siding/wood, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"JT" = ( +/obj/effect/decal/cleanable/ants, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"Kb" = ( +/obj/structure/railing{ + color = "#4C3117"; + name = "wooden railing" + }, +/obj/effect/decal/cleanable/vomit/old, +/obj/effect/turf_decal/weather/sand{ + dir = 1 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Kl" = ( +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Kw" = ( +/obj/machinery/door/airlock/vault{ + color = "#825427"; + name = "Ye Olde Strong Door" + }, +/turf/open/floor/wood/parquet, +/area/virtual_domain/powered) +"KC" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 5 + }, +/turf/open/water/beach, +/area/virtual_domain/powered) +"KG" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/structure/table/wood, +/obj/item/gun/energy/laser/musket{ + pixel_y = 7 + }, +/obj/item/gun/energy/laser/musket{ + pixel_y = 2 + }, +/obj/item/gun/energy/laser/musket{ + pixel_y = -3 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"KQ" = ( +/obj/structure/flora/rock/style_2, +/turf/open/water/beach, +/area/virtual_domain/powered) +"Ld" = ( +/obj/structure/flora/rock/pile, +/turf/open/water/beach, +/area/virtual_domain/powered) +"Ma" = ( +/obj/structure/flora/bush/sparsegrass/style_random, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"Mi" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/oil, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"MW" = ( +/obj/effect/turf_decal/weather/sand{ + dir = 5 + }, +/obj/effect/decal/cleanable/glass, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Nh" = ( +/obj/structure/flora/rock/pile/jungle/style_3{ + pixel_x = -15; + pixel_y = -4 + }, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"Nk" = ( +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Nz" = ( +/obj/structure/flora/bush/jungle, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"NI" = ( +/obj/structure/railing{ + color = "#4C3117"; + name = "wooden railing" + }, +/obj/effect/turf_decal/weather/sand{ + dir = 9 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"ON" = ( +/obj/item/kirbyplants/organic/plant21{ + pixel_x = -8 + }, +/obj/structure/filingcabinet{ + pixel_x = 11 + }, +/turf/open/floor/wood/parquet, +/area/virtual_domain/powered) +"OP" = ( +/obj/structure/flora/bush/stalky, +/turf/open/misc/beach/coast, +/area/virtual_domain/powered) +"Pq" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/effect/mapping_helpers/burnt_floor, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/bed/maint{ + pixel_x = 2; + pixel_y = 13 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Pz" = ( +/obj/structure/table/wood, +/mob/living/simple_animal/parrot{ + name = "pepper" + }, +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"PQ" = ( +/obj/structure/flora/grass/jungle/b, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"Qb" = ( +/obj/structure/flora/rock{ + pixel_x = 7 + }, +/turf/open/water/beach, +/area/virtual_domain/powered) +"Rr" = ( +/obj/structure/bed/maint{ + pixel_x = -5; + pixel_y = 9 + }, +/obj/effect/turf_decal/weather/sand{ + dir = 6 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"RR" = ( +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"Sm" = ( +/obj/structure/flora/tree/jungle, +/obj/structure/flora/bush/fullgrass/style_random, +/turf/open/misc/grass, +/area/virtual_domain/powered) +"St" = ( +/obj/structure/table/wood, +/obj/item/melee/energy/sword/pirate{ + pixel_y = 10 + }, +/obj/item/clothing/mask/cigarette/cigar{ + pixel_x = 4 + }, +/obj/item/lighter{ + pixel_x = 10; + pixel_y = -8 + }, +/obj/machinery/light/small/directional/north, +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"Tp" = ( +/turf/open/misc/beach/coast/corner{ + dir = 1 + }, +/area/virtual_domain/powered) +"Tt" = ( +/obj/structure/cannon{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"TO" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/machinery/light/small/directional/south, +/obj/effect/landmark/bitrunning/cache_spawn, +/turf/open/floor/carpet/blue, +/area/virtual_domain/powered) +"TP" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 4 + }, +/turf/open/misc/beach/coast{ + dir = 6 + }, +/area/virtual_domain/powered) +"TQ" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/bed/maint{ + pixel_x = 2; + pixel_y = 1 + }, +/obj/effect/decal/cleanable/cobweb, +/obj/item/toy/plush/beeplushie, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Uy" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/binary, +/area/virtual_domain/powered) +"UE" = ( +/obj/structure/barricade/sandbags, +/obj/effect/turf_decal/weather/sand{ + dir = 10 + }, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"Vg" = ( +/obj/effect/mob_spawn/corpse/human/pirate/melee, +/turf/open/water/beach, +/area/virtual_domain/powered) +"Vk" = ( +/obj/structure/barricade/sandbags, +/obj/effect/turf_decal/weather/sand, +/turf/open/floor/wood{ + icon_state = "wood_large" + }, +/area/virtual_domain/powered) +"VC" = ( +/obj/effect/mob_spawn/corpse/human/damaged, +/turf/open/water/beach, +/area/virtual_domain/powered) +"VF" = ( +/turf/open/water/beach, +/area/virtual_domain/powered) +"VX" = ( +/obj/effect/mapping_helpers/burnt_floor, +/obj/structure/rack{ + icon = 'icons/obj/fluff/general.dmi'; + icon_state = "minibar"; + name = "skeletal minibar" + }, +/obj/item/storage/bag/money/dutchmen{ + pixel_y = 13 + }, +/turf/open/floor/wood/parquet, +/area/virtual_domain/powered) +"WM" = ( +/obj/structure/flora/rock/pile/jungle/style_2, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) +"WP" = ( +/turf/open/floor/wood/parquet, +/area/virtual_domain/powered) +"Xn" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"XG" = ( +/obj/structure/fermenting_barrel/gunpowder{ + pixel_x = -4; + pixel_y = 17 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Yj" = ( +/obj/effect/landmark/bitrunning/cache_spawn, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"Yk" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/wood/parquet, +/area/virtual_domain/powered) +"Yq" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 10 + }, +/turf/open/floor/wood, +/area/virtual_domain/powered) +"Zk" = ( +/obj/structure/flora/coconuts{ + pixel_x = 12 + }, +/obj/structure/flora/tree/palm, +/turf/open/misc/beach/sand, +/area/virtual_domain/powered) +"ZZ" = ( +/obj/structure/flora/grass/jungle, +/turf/open/misc/dirt/jungle, +/area/virtual_domain/powered) + +(1,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +cx +cx +cx +cx +cx +cx +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(2,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +cx +FT +FT +FT +FT +FT +FT +cx +cx +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(3,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +cx +cx +FT +FT +FT +FT +FT +FT +FT +FT +FT +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(4,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +cx +FT +FT +FT +FT +FT +FT +FT +FT +FT +FT +FT +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(5,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +FT +FT +FT +FT +FT +FT +zf +eb +we +FT +FT +FT +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(6,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +cx +cx +cx +FT +FT +FT +Sm +Ma +bz +JT +Kl +Kl +Kl +FT +FT +cx +cx +cx +cx +cx +cx +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(7,1,1) = {" +xg +xg +xg +xg +xg +cx +cx +cx +cx +FT +FT +FT +FT +It +tk +DL +Kl +Kl +Kl +Cc +Kl +IG +FT +cx +cx +FT +FT +FT +FT +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(8,1,1) = {" +xg +xg +xg +xg +cx +cx +FT +FT +FT +FT +FT +Nz +bP +mP +to +Kl +Kl +we +Kl +Kl +Kl +Kl +we +cx +cx +FT +FT +FT +FT +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(9,1,1) = {" +xg +xg +xg +cx +cx +FT +dp +dp +dp +dp +xB +yq +yq +Kl +Kl +Ct +xc +xc +xc +xc +xc +xc +xc +HY +VF +VF +VF +VF +VF +cx +cx +cx +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(10,1,1) = {" +xg +xg +xg +cx +FT +dp +dp +Pq +qx +Mi +th +Kl +yq +Kl +IG +OP +uM +VF +VF +VF +VF +VF +VF +VF +VF +VC +VF +VF +VF +VF +VF +dp +cx +cx +cx +xg +xg +xg +xg +xg +xg +xg +"} +(11,1,1) = {" +xg +xg +cx +cx +FT +dp +TQ +Iz +DJ +ag +eW +Kl +Kl +ED +Kl +Jr +VF +VF +VF +VF +VF +VF +VF +VF +VF +KQ +VF +VF +VF +VF +VF +dp +KG +pq +cx +cx +cx +cx +cx +cx +cx +Uy +"} +(12,1,1) = {" +xg +xg +cx +FT +FT +dp +Yj +MW +iO +Rr +qj +Kl +NI +xm +Ct +HY +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +wb +dp +jl +pq +BC +ub +ub +ub +ub +ub +Xn +cx +"} +(13,1,1) = {" +cx +cx +cx +FT +FT +FT +qj +Kl +Kl +Kl +Kl +Kl +lC +kl +pP +VF +VF +VF +VF +VF +VF +Vg +VF +VF +VF +VF +VF +VF +VF +VF +cl +dp +hH +Nk +qm +ub +ub +ub +ub +ub +ub +cx +"} +(14,1,1) = {" +cx +dp +dp +dp +dp +dp +dp +oo +Kl +Kl +Kl +Kl +Kb +dp +px +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +dp +dp +Nk +Jv +ub +ub +ub +ub +ub +ub +cx +"} +(15,1,1) = {" +cx +dp +BO +ht +VX +ct +dp +yi +Kl +dA +Kl +Kl +by +Hp +pP +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +me +ub +ub +ub +ub +ub +ub +cx +"} +(16,1,1) = {" +cx +dp +ON +WP +nX +Yk +Kw +Kl +Kl +Kl +Kl +Kl +Kl +dp +px +VF +VF +VF +VF +Qb +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +ub +ub +ub +ub +ub +ub +cx +"} +(17,1,1) = {" +cx +dp +jC +iM +so +TO +dp +Kl +Kl +EZ +IM +Kl +Kl +Kl +pP +VF +VF +VF +VF +cl +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +ub +ub +ub +ub +ub +ub +cx +"} +(18,1,1) = {" +cx +dp +sn +hW +eQ +gk +dp +dp +qX +gw +jz +UE +Kl +Zk +pP +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +me +VF +ub +ub +ub +ub +ub +zR +cx +"} +(19,1,1) = {" +cx +dp +St +Pz +nQ +yA +dp +dp +Dm +jz +jz +Vk +Kl +Kl +pP +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +dp +BC +VF +VF +VF +VF +VF +VF +cx +cx +"} +(20,1,1) = {" +cx +dp +dp +dp +dp +dp +dp +xm +FG +RR +yw +Vk +Kl +Kl +pP +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +Tt +cJ +Yq +VF +VF +VF +VF +VF +cx +xg +"} +(21,1,1) = {" +cx +cx +cx +FT +FT +Kl +Kl +dp +dp +jB +uw +GG +Kl +Kl +pP +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +xI +dp +XG +BC +VF +VF +VF +VF +VF +cx +xg +"} +(22,1,1) = {" +xg +xg +cx +FT +FT +fx +Kl +Kl +dp +dp +Kl +Kl +Kl +Kl +pP +VF +VF +VF +VF +VF +VF +dQ +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +kg +pq +Ld +VF +VF +VF +VF +VF +cx +xg +"} +(23,1,1) = {" +xg +xg +cx +FT +FT +FT +Kl +Kl +Kl +Kl +Kl +Kl +Kl +Kl +Tp +oU +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +FT +FT +cx +xg +"} +(24,1,1) = {" +xg +xg +cx +FT +FT +FT +FT +dp +Kl +eD +Kl +Kl +Kl +Kl +Kl +Tp +nz +oU +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +FT +FT +cx +xg +"} +(25,1,1) = {" +xg +xg +cx +cx +FT +FT +FT +FT +Kl +Kl +Kl +Kl +Kl +Kl +yi +Kl +Kl +pP +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +FT +FT +FT +cx +xg +"} +(26,1,1) = {" +xg +xg +xg +cx +cx +cx +FT +FT +FT +FT +FT +FT +FT +FT +FT +FT +FT +TP +VF +FT +FT +cx +cx +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +cx +FT +FT +FT +FT +cx +xg +"} +(27,1,1) = {" +xg +xg +xg +xg +xg +cx +FT +FT +FT +FT +FT +FT +FT +FT +FT +FT +FT +PQ +AU +FT +FT +FT +cx +cx +VF +VF +VF +VF +VF +VF +VF +VF +VF +VF +cx +cx +FT +FT +FT +cx +cx +xg +"} +(28,1,1) = {" +xg +xg +xg +xg +xg +cx +cx +FT +FT +FT +FT +FT +FT +FT +FT +FT +FT +Nh +AU +FT +FT +FT +FT +cx +cx +cx +cx +VF +VF +VF +VF +VF +VF +cx +cx +cx +cx +cx +cx +cx +xg +xg +"} +(29,1,1) = {" +xg +xg +xg +xg +xg +xg +cx +cx +cx +cx +cx +cx +FT +FT +FT +FT +FT +ye +KC +VF +FT +FT +FT +FT +FT +FT +cx +cx +cx +cx +cx +cx +cx +cx +xg +xg +xg +xg +xg +xg +xg +xg +"} +(30,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +cx +FT +FT +FT +FT +FT +zg +ye +KC +IF +VF +FT +FT +FT +FT +FT +cx +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(31,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +cx +FT +FT +FT +FT +FT +ye +ye +pU +AU +VF +GF +WM +FT +FT +FT +cx +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(32,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +cx +FT +FT +FT +FT +FT +ye +nS +KC +VF +Ax +ye +hM +FT +FT +FT +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(33,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +cx +FT +FT +FT +FT +ZZ +ye +cQ +KC +yc +qN +ye +hM +FT +FT +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(34,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +cx +FT +FT +FT +FT +ye +ye +mw +xC +uT +jQ +Jo +FT +FT +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(35,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +cx +cx +FT +FT +FT +FT +FT +FT +FT +FT +FT +FT +FT +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(36,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +FT +FT +FT +FT +FT +FT +FT +FT +FT +FT +FT +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} +(37,1,1) = {" +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +cx +cx +cx +cx +cx +cx +cx +cx +cx +cx +cx +cx +cx +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +xg +"} diff --git a/_maps/virtual_domains/stairs_and_cliffs.dmm b/_maps/virtual_domains/stairs_and_cliffs.dmm new file mode 100644 index 00000000000..82e15fcc090 --- /dev/null +++ b/_maps/virtual_domains/stairs_and_cliffs.dmm @@ -0,0 +1,6056 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"be" = ( +/obj/structure/railing/corner{ + dir = 1 + }, +/turf/open/cliff/snowrock/virtual_domain, +/area/icemoon/underground/explored/virtual_domain) +"cu" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/obj/structure/railing, +/obj/structure/railing{ + dir = 1 + }, +/turf/open/floor/wood, +/area/icemoon/underground/explored/virtual_domain) +"cJ" = ( +/obj/structure/chair/sofa/bench, +/turf/open/floor/plating/snowed/smoothed, +/area/icemoon/underground/explored/virtual_domain) +"dR" = ( +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"en" = ( +/obj/item/clothing/under/color/grey, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"eB" = ( +/obj/structure/flora/rock/icy/style_random, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"gB" = ( +/obj/structure/railing/corner, +/turf/open/cliff/snowrock/virtual_domain, +/area/icemoon/underground/explored/virtual_domain) +"hc" = ( +/obj/structure/railing/corner/end{ + dir = 8 + }, +/obj/structure/railing/corner/end/flip{ + dir = 8 + }, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"hE" = ( +/turf/open/floor/wood, +/area/icemoon/underground/explored/virtual_domain) +"jK" = ( +/obj/structure/railing/corner{ + dir = 8 + }, +/turf/open/cliff/snowrock/virtual_domain, +/area/icemoon/underground/explored/virtual_domain) +"kc" = ( +/obj/effect/decal/cleanable/blood/old, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"km" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/ash/large, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"kK" = ( +/obj/structure/flora/tree/pine/style_random, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"mx" = ( +/obj/structure/railing, +/obj/structure/railing{ + dir = 1 + }, +/turf/open/floor/wood, +/area/icemoon/underground/explored/virtual_domain) +"nj" = ( +/obj/structure/chair/sofa/bench/left, +/turf/open/floor/plating/snowed/smoothed, +/area/icemoon/underground/explored/virtual_domain) +"no" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 8 + }, +/obj/structure/railing, +/obj/structure/railing{ + dir = 1 + }, +/turf/open/floor/wood, +/area/icemoon/underground/explored/virtual_domain) +"pl" = ( +/obj/structure/bonfire/prelit, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"pL" = ( +/turf/open/lava/plasma/virtual_domain, +/area/icemoon/underground/explored/virtual_domain) +"qc" = ( +/turf/open/misc/ice, +/area/icemoon/underground/explored/virtual_domain) +"sa" = ( +/obj/structure/flora/grass/green/style_random, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"sw" = ( +/obj/structure/flora/rock/pile/icy/style_random, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"sM" = ( +/turf/open/cliff/snowrock/virtual_domain, +/area/icemoon/underground/explored/virtual_domain) +"uJ" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"vz" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"xB" = ( +/obj/structure/railing/corner{ + dir = 4 + }, +/turf/open/floor/wood, +/area/icemoon/underground/explored/virtual_domain) +"yo" = ( +/turf/open/floor/plating/snowed/smoothed, +/area/icemoon/underground/explored/virtual_domain) +"yJ" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 8 + }, +/obj/structure/railing, +/obj/structure/railing/corner{ + dir = 1 + }, +/turf/open/floor/wood, +/area/icemoon/underground/explored/virtual_domain) +"yL" = ( +/obj/structure/chair/sofa/bench/right, +/turf/open/floor/plating/snowed/smoothed, +/area/icemoon/underground/explored/virtual_domain) +"zn" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 8 + }, +/turf/open/floor/wood, +/area/icemoon/underground/explored/virtual_domain) +"Am" = ( +/turf/closed/indestructible/binary, +/area/icemoon/underground/explored/virtual_domain) +"AI" = ( +/obj/structure/flora/grass/green/style_random, +/turf/open/floor/plating/snowed/smoothed, +/area/icemoon/underground/explored/virtual_domain) +"BV" = ( +/obj/effect/decal/remains/plasma, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"Dz" = ( +/obj/structure/railing/corner/end{ + dir = 4 + }, +/obj/structure/railing/corner/end/flip{ + dir = 4 + }, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"DB" = ( +/obj/structure/flora/rock/icy/style_random, +/obj/structure/flora/rock/pile/icy/style_random, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"DY" = ( +/obj/structure/flora/rock/icy/style_random, +/obj/structure/flora/grass/green/style_random, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"Eh" = ( +/obj/structure/railing/corner{ + dir = 4 + }, +/turf/open/cliff/snowrock/virtual_domain, +/area/icemoon/underground/explored/virtual_domain) +"Gn" = ( +/obj/structure/flora/rock/pile/icy/style_random, +/obj/effect/decal/cleanable/blood/old, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"GX" = ( +/obj/effect/decal/cleanable/ash/large, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"HU" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/turf/open/floor/wood, +/area/icemoon/underground/explored/virtual_domain) +"Kl" = ( +/obj/effect/decal/remains/plasma, +/obj/effect/decal/cleanable/ash/large, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"KA" = ( +/obj/structure/statue/snow/snowman{ + name = "Norm"; + desc = "Norm has seen many a man roll down these cliffs, some more stubborn than others. Its usually the stubborn ones who stop getting back up." + }, +/obj/item/pickaxe/mini, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"Lw" = ( +/obj/structure/flora/rock/pile/icy/style_random, +/obj/structure/flora/grass/green/style_random, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"MP" = ( +/obj/structure/railing/corner/end/flip{ + dir = 4 + }, +/obj/structure/railing/corner/end{ + dir = 4 + }, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"MT" = ( +/obj/structure/railing/corner{ + dir = 8 + }, +/turf/open/floor/wood, +/area/icemoon/underground/explored/virtual_domain) +"Nv" = ( +/turf/open/floor/iron/stairs, +/area/icemoon/underground/explored/virtual_domain) +"NM" = ( +/obj/structure/railing/corner/end/flip{ + dir = 8 + }, +/obj/structure/railing/corner/end{ + dir = 8 + }, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"Pl" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/obj/structure/railing{ + dir = 1 + }, +/obj/structure/railing/corner, +/turf/open/floor/wood, +/area/icemoon/underground/explored/virtual_domain) +"Qv" = ( +/turf/closed/indestructible/rock/snow/ice, +/area/icemoon/underground/explored/virtual_domain) +"RD" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/binary, +/area/icemoon/underground/explored/virtual_domain) +"Tz" = ( +/obj/item/pickaxe/mini, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"Ug" = ( +/obj/structure/flora/rock/icy/style_random, +/obj/effect/decal/cleanable/blood/old, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"VW" = ( +/obj/structure/closet/crate/secure/bitrunning/encrypted, +/turf/open/floor/plating/snowed/smoothed, +/area/icemoon/underground/explored/virtual_domain) +"YR" = ( +/obj/structure/flora/tree/pine/style_random, +/obj/structure/flora/grass/green/style_random, +/turf/open/misc/asteroid/snow, +/area/icemoon/underground/explored/virtual_domain) +"YT" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +RD +"} +(2,1,1) = {" +Am +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(3,1,1) = {" +Am +Qv +Qv +Qv +Qv +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(4,1,1) = {" +Am +Qv +Qv +Qv +dR +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(5,1,1) = {" +Am +Qv +Qv +dR +dR +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(6,1,1) = {" +Am +Qv +Qv +kK +sw +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(7,1,1) = {" +Am +Qv +Qv +dR +dR +sa +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(8,1,1) = {" +Am +Qv +Qv +eB +sw +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +Qv +Qv +Qv +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(9,1,1) = {" +Am +Qv +Qv +dR +eB +dR +sw +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(10,1,1) = {" +Am +Qv +dR +sw +eB +eB +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(11,1,1) = {" +Am +Qv +dR +eB +sw +sa +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pl +dR +sw +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(12,1,1) = {" +Am +Qv +dR +dR +sw +sa +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sw +dR +Nv +Nv +Nv +sM +sM +Nv +Nv +Nv +Nv +Nv +Nv +sM +sM +sM +sM +Nv +Nv +Nv +Nv +dR +qc +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(13,1,1) = {" +Am +Qv +dR +sa +sw +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sw +dR +dR +sM +Nv +Nv +Nv +Nv +sM +sM +sM +sM +Nv +Nv +Nv +Nv +Nv +Nv +Nv +Nv +Nv +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(14,1,1) = {" +Am +Qv +dR +dR +dR +dR +kK +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sw +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sa +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(15,1,1) = {" +Am +Qv +sw +sa +dR +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(16,1,1) = {" +Am +Qv +dR +sa +sa +sa +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +pl +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +GX +pL +pL +pL +pL +Qv +Qv +Qv +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(17,1,1) = {" +Am +Qv +dR +sa +sa +dR +yo +Nv +Nv +Nv +Nv +sM +sM +Nv +Nv +Nv +dR +dR +sM +sM +sM +sM +sM +dR +qc +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +sw +dR +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +dR +dR +pL +pL +pL +Qv +Qv +Qv +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(18,1,1) = {" +Am +Qv +Qv +dR +dR +yo +yo +sM +sM +sM +Nv +Nv +Nv +Nv +sM +sM +sa +qc +sM +sM +sM +sM +sM +dR +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +pL +dR +sa +pL +pL +sM +sM +sM +sM +sM +sM +sw +dR +sM +sM +sM +sM +sM +sM +sM +sM +pL +dR +en +dR +dR +pL +pL +Qv +Qv +Qv +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(19,1,1) = {" +Am +Qv +Qv +kK +sa +yo +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sw +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sw +BV +pL +sM +sM +sM +sM +sM +sM +eB +dR +sM +sM +sM +sM +sM +sM +sM +sM +pL +GX +sw +dR +dR +pL +pL +pL +pL +Qv +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(20,1,1) = {" +Am +Qv +Qv +dR +dR +yo +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +qc +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +kK +GX +pL +pL +sM +sM +sM +sM +sM +sM +sM +dR +qc +dR +sM +sM +sM +sM +sM +sM +pL +dR +dR +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(21,1,1) = {" +Am +Qv +Qv +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +pL +pL +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +sM +dR +dR +dR +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(22,1,1) = {" +Am +Qv +Qv +dR +sa +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sw +dR +dR +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Am +"} +(23,1,1) = {" +Am +Qv +Qv +Qv +sa +qc +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +qc +sM +sM +sM +sM +sM +sM +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +qc +sM +sM +sM +sM +sM +sM +DB +kc +dR +dR +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Am +"} +(24,1,1) = {" +Am +Qv +Qv +sw +eB +qc +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +qc +sM +sM +sM +sM +sM +sM +qc +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sa +dR +sM +sM +sM +sM +sM +sM +Ug +eB +dR +dR +dR +pL +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Am +"} +(25,1,1) = {" +Am +Qv +Qv +dR +dR +sa +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +qc +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +dR +Nv +Nv +Nv +Nv +Nv +Nv +Nv +Nv +Nv +Nv +Nv +Nv +sM +Nv +Nv +dR +dR +sM +sM +sM +sM +sM +sM +Ug +sw +dR +dR +dR +dR +dR +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Am +"} +(26,1,1) = {" +Am +Qv +Qv +dR +yo +dR +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +qc +dR +sM +sM +sM +sM +sM +dR +Nv +Nv +Nv +Nv +Nv +sM +sM +sM +sM +Nv +Nv +Nv +Nv +Nv +Nv +qc +qc +sM +sM +sM +sM +sM +sM +Ug +sw +dR +dR +dR +sa +dR +dR +dR +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Am +"} +(27,1,1) = {" +Am +Qv +Qv +dR +yo +sa +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sa +dR +sM +sM +sM +sM +dR +sM +sM +sM +sM +eB +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +dR +dR +kK +dR +dR +dR +sw +dR +dR +pL +pL +pL +pL +pL +Qv +Qv +Qv +Am +"} +(28,1,1) = {" +Am +Qv +Qv +sa +yo +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sa +dR +sM +sM +sM +sM +dR +sM +sM +sM +sM +dR +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +kK +sa +dR +qc +qc +sa +sa +dR +kK +dR +pL +pL +pL +pL +pL +pL +Qv +Qv +Am +"} +(29,1,1) = {" +Am +Qv +Qv +sa +yo +yo +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +dR +sM +sM +sM +sM +MP +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +dR +qc +qc +qc +sa +sa +dR +dR +dR +pL +pL +pL +pL +pL +Qv +Qv +Qv +Am +"} +(30,1,1) = {" +Am +Qv +Qv +qc +dR +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +dR +sM +sM +sM +sM +no +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +yL +dR +dR +dR +kK +dR +dR +dR +dR +dR +dR +dR +dR +pL +pL +pL +Qv +Qv +Qv +Am +"} +(31,1,1) = {" +Am +Qv +pl +qc +dR +yo +sM +sM +sM +sM +sM +sM +sM +dR +dR +Nv +Nv +Nv +Nv +qc +sM +sM +sM +sM +dR +dR +sM +sM +sM +mx +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +cJ +yo +dR +dR +dR +dR +dR +kK +sa +sa +dR +dR +dR +dR +dR +dR +dR +dR +Qv +Am +"} +(32,1,1) = {" +Am +Qv +sM +sM +zn +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sw +dR +sM +sM +sM +cu +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +nj +yo +dR +kK +dR +dR +dR +kK +sa +sa +dR +dR +dR +dR +kK +dR +dR +Qv +Qv +Am +"} +(33,1,1) = {" +Am +Qv +sM +sM +hE +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +NM +sM +sM +sM +sM +sM +sM +sM +qc +dR +Nv +Nv +Nv +Nv +Nv +dR +dR +sw +sM +sM +sM +sM +sM +sM +sM +sM +yo +yo +dR +dR +sa +dR +sw +dR +dR +dR +dR +sa +sa +dR +dR +dR +dR +Qv +Qv +Am +"} +(34,1,1) = {" +Am +Qv +sM +sM +hE +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sa +dR +sM +sM +sM +sM +sM +sM +sM +sM +qc +sM +sM +sM +dR +qc +sM +sM +sM +sM +sM +sM +qc +yo +Nv +Nv +Nv +Nv +Nv +yo +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +yo +dR +dR +sa +dR +dR +dR +dR +kK +qc +dR +dR +dR +dR +dR +dR +dR +Qv +Am +"} +(35,1,1) = {" +Am +Qv +sM +sM +hE +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +qc +sM +sM +sM +qc +sa +sM +sM +sM +sM +sM +sM +qc +dR +sM +sM +sM +sM +sM +eB +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +dR +yo +yo +dR +dR +dR +qc +qc +qc +qc +qc +dR +YT +YT +YT +YT +YT +vz +Qv +Am +"} +(36,1,1) = {" +Am +Qv +dR +sM +HU +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +qc +sM +sM +sM +sM +sM +sM +sM +sM +dR +qc +sM +sM +sw +dR +sM +sM +sM +sM +sM +sM +qc +dR +sM +sM +sM +sM +sM +kK +dR +qc +sM +sM +sM +sM +sM +sM +sM +sM +pl +dR +yo +dR +dR +dR +dR +dR +qc +qc +qc +dR +YT +YT +YT +YT +YT +YT +Qv +Am +"} +(37,1,1) = {" +Am +Qv +Qv +dR +dR +dR +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +dR +dR +sM +sM +sM +sM +eB +dR +sa +sM +sM +sM +sM +sM +sM +sa +yo +dR +sM +sM +sM +sM +sM +sM +sM +yo +dR +yo +dR +dR +dR +dR +sw +qc +qc +dR +dR +YT +YT +YT +YT +YT +YT +Qv +Am +"} +(38,1,1) = {" +Am +Qv +Qv +dR +yo +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +qc +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +dR +dR +sM +sM +sM +sM +dR +dR +qc +sM +sM +sM +sM +sM +sM +sM +yo +AI +Nv +Nv +Nv +Nv +Nv +Nv +Nv +yo +yo +yo +yo +yo +yo +dR +dR +yo +dR +yo +yo +YT +YT +YT +YT +YT +YT +Qv +Am +"} +(39,1,1) = {" +Am +Qv +Qv +dR +dR +dR +kK +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +qc +sM +sM +sM +sM +sM +sM +sM +dR +qc +sM +sM +sM +pl +dR +dR +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +yo +AI +Nv +Nv +Nv +Nv +Nv +Nv +Nv +yo +yo +yo +yo +dR +yo +yo +yo +yo +yo +yo +yo +YT +YT +YT +YT +YT +YT +Qv +Am +"} +(40,1,1) = {" +Am +Qv +Qv +dR +yo +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +qc +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +dR +dR +Nv +Nv +Nv +dR +kK +sM +sM +sM +sM +sM +sM +sM +sM +sw +dR +Nv +Nv +Nv +Nv +Nv +Nv +Nv +yo +yo +dR +dR +dR +yo +dR +yo +yo +yo +dR +yo +YT +YT +YT +YT +YT +YT +Qv +Am +"} +(41,1,1) = {" +Am +Qv +dR +sa +yo +dR +sa +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +dR +qc +sM +sM +sM +qc +Tz +Nv +Nv +Nv +qc +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +dR +sw +dR +dR +dR +dR +dR +dR +dR +dR +YT +YT +YT +YT +YT +uJ +Qv +Am +"} +(42,1,1) = {" +Am +Qv +dR +AI +yo +yo +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pl +KA +dR +dR +dR +sa +sa +dR +qc +qc +qc +dR +dR +dR +dR +dR +dR +dR +Qv +Am +"} +(43,1,1) = {" +Am +Qv +yo +yo +VW +yo +yo +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sa +dR +dR +kK +sa +sa +dR +dR +qc +qc +qc +dR +sa +sa +dR +dR +dR +Qv +Am +"} +(44,1,1) = {" +Am +Qv +dR +yo +yo +yo +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +qc +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sa +dR +sa +dR +dR +dR +dR +kK +qc +qc +qc +dR +sa +sa +dR +dR +dR +Qv +Am +"} +(45,1,1) = {" +Am +Qv +dR +dR +yo +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +dR +dR +dR +dR +kK +dR +dR +dR +dR +Qv +dR +Qv +dR +kK +dR +Qv +Qv +Am +"} +(46,1,1) = {" +Am +Qv +Qv +sa +dR +dR +sa +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +qc +dR +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +kK +dR +dR +dR +dR +dR +dR +dR +dR +dR +dR +Qv +Qv +Qv +dR +dR +dR +Qv +Qv +Am +"} +(47,1,1) = {" +Am +Qv +Qv +dR +dR +YR +sa +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +dR +dR +qc +Nv +Nv +Nv +sM +sM +sM +sM +Nv +Nv +Nv +Nv +sM +sM +sM +Nv +Nv +Nv +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +dR +pL +dR +dR +dR +dR +dR +dR +Qv +Qv +Qv +Qv +Qv +dR +dR +dR +Qv +Qv +Am +"} +(48,1,1) = {" +Am +Qv +Qv +dR +kK +sa +YR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +dR +dR +dR +sw +sM +Nv +Nv +Nv +Nv +Nv +Nv +sM +sM +Nv +Nv +Nv +Nv +Nv +sM +Nv +Nv +Nv +qc +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +dR +dR +dR +dR +Qv +Qv +Qv +Qv +dR +sw +dR +dR +dR +Qv +Am +"} +(49,1,1) = {" +Am +Qv +Qv +dR +dR +YR +sa +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +qc +sM +sM +sM +sM +sM +eB +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +dR +dR +dR +dR +dR +pL +pL +Qv +Qv +Qv +Qv +dR +sw +dR +dR +Qv +Am +"} +(50,1,1) = {" +Am +Qv +Qv +sa +dR +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sa +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +pl +sM +sM +sM +sM +sM +sM +dR +pL +pL +dR +dR +sa +dR +pL +pL +pL +pL +Qv +Qv +Qv +sw +eB +dR +dR +Qv +Am +"} +(51,1,1) = {" +Am +Qv +Qv +Qv +dR +sa +kK +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sa +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sa +sM +sM +sM +sM +sM +sM +dR +pL +dR +dR +kK +dR +dR +pL +pL +pL +pL +Qv +Qv +Qv +Qv +dR +dR +sa +Qv +Am +"} +(52,1,1) = {" +Am +Qv +Qv +Qv +dR +sa +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +pL +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sa +sM +sM +sM +sM +sM +sM +dR +pL +dR +dR +dR +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +dR +dR +dR +Qv +Am +"} +(53,1,1) = {" +Am +Qv +Qv +Qv +dR +YR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sw +Dz +sM +sM +sM +sM +sM +pL +pL +pL +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +dR +dR +dR +sa +dR +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +dR +dR +Qv +Am +"} +(54,1,1) = {" +Am +Qv +Qv +Qv +dR +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +jK +yJ +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +sM +sM +GX +dR +dR +pL +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sa +dR +sw +sa +dR +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +dR +Qv +Qv +Am +"} +(55,1,1) = {" +Am +Qv +Qv +dR +dR +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +MT +be +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +pL +dR +kK +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +qc +sM +sM +sM +sM +sM +dR +sw +eB +dR +dR +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +dR +dR +dR +Qv +Am +"} +(56,1,1) = {" +Am +Qv +Qv +dR +eB +sw +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +gB +xB +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +qc +sM +sM +sM +sM +sM +km +sw +eB +eB +sw +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +dR +dR +dR +Qv +Am +"} +(57,1,1) = {" +Am +Qv +Qv +dR +Lw +sa +sa +kK +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +Pl +Eh +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +dR +sw +dR +sM +sM +sM +sM +sM +sM +sM +sM +sa +eB +sM +sM +sM +sM +sM +pL +dR +eB +eB +dR +dR +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +dR +dR +dR +Qv +Am +"} +(58,1,1) = {" +Am +Qv +Qv +dR +sa +sa +YR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +hc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +Gn +eB +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +dR +sw +sM +sM +sM +sM +sM +pL +GX +dR +pL +dR +dR +pL +pL +pL +pL +Qv +Qv +Qv +Qv +dR +sa +dR +dR +Qv +Am +"} +(59,1,1) = {" +Am +Qv +Qv +sa +YR +sa +sa +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +qc +sM +sM +sM +dR +sM +sM +Nv +Nv +Nv +dR +sM +sM +sM +sM +sM +kK +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +pL +dR +dR +pL +dR +pL +pL +pL +pL +pL +pL +Qv +Qv +dR +dR +dR +Qv +Qv +Qv +Am +"} +(60,1,1) = {" +Am +Qv +Qv +dR +dR +sw +kK +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +dR +dR +Nv +Nv +Nv +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +kK +dR +qc +sM +sM +sM +sM +sM +pL +GX +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +dR +dR +dR +Qv +Qv +Qv +Am +"} +(61,1,1) = {" +Am +Qv +dR +kK +sw +eB +eB +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +dR +sM +sM +sM +sM +sM +dR +sa +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +dR +dR +dR +Qv +Qv +Qv +Qv +Am +"} +(62,1,1) = {" +Am +Qv +dR +sa +DY +eB +eB +dR +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sa +dR +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sa +dR +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +dR +dR +Qv +Qv +Qv +Qv +Qv +Am +"} +(63,1,1) = {" +Am +Qv +dR +Lw +Lw +dR +sa +dR +sM +sM +sM +sM +sM +sM +sM +sM +eB +dR +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sa +dR +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +dR +Qv +Qv +dR +dR +dR +dR +Qv +Qv +Qv +Qv +Am +"} +(64,1,1) = {" +Am +Qv +dR +sa +sa +sw +kK +dR +sM +sM +sM +sM +sM +sM +sM +sM +sw +dR +sM +sM +sM +sM +sM +qc +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +eB +dR +dR +dR +sa +dR +sw +Qv +Qv +Qv +Qv +Qv +Am +"} +(65,1,1) = {" +Am +Qv +dR +dR +kK +dR +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +qc +sM +sM +sM +sM +qc +sM +sM +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +Nv +Nv +Nv +Nv +Nv +Nv +dR +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +sw +sa +sa +dR +sw +sw +eB +Qv +Qv +Qv +Qv +Qv +Am +"} +(66,1,1) = {" +Am +Qv +dR +kK +sa +sa +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +sa +dR +sM +sM +sM +sM +qc +sM +sM +sM +sM +sa +dR +sM +sM +sM +sM +sM +sw +dR +Nv +Nv +Nv +Nv +Nv +sM +sM +sM +Nv +Nv +dR +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +dR +sa +sa +dR +dR +dR +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(67,1,1) = {" +Am +Qv +dR +dR +YR +DY +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sa +dR +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +dR +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +sa +dR +dR +dR +Qv +Qv +Qv +Qv +Qv +Am +"} +(68,1,1) = {" +Am +Qv +dR +dR +Lw +sa +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +sM +sM +sM +dR +dR +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +sa +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +dR +dR +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(69,1,1) = {" +Am +Qv +Qv +dR +eB +sw +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +dR +Nv +Nv +Nv +dR +dR +sM +sM +sM +sM +sM +dR +sM +sM +sM +sM +sM +dR +qc +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(70,1,1) = {" +Am +Qv +Qv +Qv +dR +eB +sw +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +kK +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +Nv +dR +dR +dR +dR +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(71,1,1) = {" +Am +Qv +Qv +dR +sa +sa +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +dR +qc +dR +pl +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +Kl +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(72,1,1) = {" +Am +Qv +Qv +sa +sa +Lw +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(73,1,1) = {" +Am +Qv +Qv +Qv +dR +sw +dR +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +sM +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +pL +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(74,1,1) = {" +Am +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Qv +Am +"} +(75,1,1) = {" +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +Am +"} diff --git a/_maps/virtual_domains/syndicate_assault.dmm b/_maps/virtual_domains/syndicate_assault.dmm new file mode 100644 index 00000000000..770f0967404 --- /dev/null +++ b/_maps/virtual_domains/syndicate_assault.dmm @@ -0,0 +1,4265 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aq" = ( +/obj/item/storage/backpack/duffelbag/syndie/surgery, +/obj/structure/table/reinforced, +/turf/open/floor/plastic, +/area/ruin/space/has_grav/powered/virtual_domain) +"aw" = ( +/obj/structure/table/reinforced, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"aN" = ( +/obj/structure/closet/crate/secure/gear{ + req_access = list("syndicate") + }, +/obj/item/stack/sheet/iron/fifty, +/obj/item/stack/sheet/iron/fifty, +/obj/item/stack/sheet/iron/fifty, +/obj/item/stack/sheet/plasteel/twenty, +/obj/item/stack/sheet/mineral/plastitanium{ + amount = 50 + }, +/obj/item/stack/sheet/glass/fifty, +/obj/item/stack/rods/fifty, +/turf/open/floor/pod/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"aO" = ( +/obj/machinery/recharge_station, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"aZ" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/mob/living/basic/syndicate/ranged/shotgun/space/stormtrooper, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"bh" = ( +/turf/open/floor/carpet/royalblack, +/area/ruin/space/has_grav/powered/virtual_domain) +"bo" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 1 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"bD" = ( +/obj/structure/table/reinforced, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"bG" = ( +/turf/open/floor/pod/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"cc" = ( +/obj/structure/closet/crate/secure/gear{ + req_access = list("syndicate") + }, +/obj/effect/spawner/random/clothing/costume, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"cj" = ( +/obj/structure/transit_tube/crossing, +/turf/closed/wall/r_wall/syndicate, +/area/ruin/space/has_grav/powered/virtual_domain) +"ct" = ( +/obj/structure/closet/syndicate{ + anchored = 1; + desc = "A basic closet for all your villainous needs."; + locked = 1; + name = "Closet"; + req_access = list("syndicate"); + secure = 1 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"cw" = ( +/obj/structure/closet/syndicate{ + anchored = 1; + desc = "A basic closet for all your villainous needs."; + locked = 1; + name = "Closet"; + req_access = list("syndicate"); + secure = 1 + }, +/obj/item/clothing/under/syndicate/combat, +/obj/item/clothing/gloves/combat, +/obj/item/clothing/shoes/combat, +/obj/item/clothing/mask/gas/syndicate, +/obj/item/clothing/under/syndicate/skirt, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"cy" = ( +/obj/machinery/door/airlock/grunge{ + name = "Syndicate Ship Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"cB" = ( +/obj/machinery/camera/xray{ + c_tag = "Medbay"; + dir = 6; + network = list("fsci"); + screen_loc = "" + }, +/turf/open/floor/plastic, +/area/ruin/space/has_grav/powered/virtual_domain) +"cR" = ( +/obj/machinery/light/small/directional/south, +/turf/open/floor/carpet/royalblack, +/area/ruin/space/has_grav/powered/virtual_domain) +"cZ" = ( +/obj/structure/table/reinforced, +/obj/item/gun/ballistic/automatic/l6_saw/unrestricted, +/obj/item/ammo_box/magazine/m7mm, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"da" = ( +/obj/machinery/stasis, +/turf/open/floor/plastic, +/area/ruin/space/has_grav/powered/virtual_domain) +"dd" = ( +/obj/structure/sign/warning/vacuum/external, +/turf/closed/wall/r_wall/syndicate, +/area/ruin/space/has_grav/powered/virtual_domain) +"di" = ( +/obj/machinery/power/terminal{ + dir = 1 + }, +/obj/structure/cable, +/obj/item/paper/fluff/ruins/forgottenship/powerissues, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"dw" = ( +/obj/machinery/light/small/directional/south, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"dz" = ( +/obj/effect/landmark/bitrunning/cache_spawn, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"dU" = ( +/obj/structure/cable, +/obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/ruin{ + name = "Syndicate Ship Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"eB" = ( +/obj/machinery/camera/xray{ + c_tag = "Cargo pod"; + dir = 9; + network = list("fsci"); + screen_loc = "" + }, +/obj/structure/closet, +/obj/item/clothing/under/syndicate/tacticool, +/obj/item/clothing/under/syndicate/tacticool, +/obj/item/clothing/under/syndicate/tacticool, +/obj/item/card/id/advanced/black/syndicate_command/crew_id, +/obj/item/card/id/advanced/black/syndicate_command/crew_id, +/obj/item/card/id/advanced/black/syndicate_command/crew_id, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"fd" = ( +/obj/structure/transit_tube/crossing, +/turf/open/space/basic, +/area/space) +"fG" = ( +/obj/structure/toilet{ + dir = 1 + }, +/obj/machinery/light/directional/south, +/turf/open/floor/iron, +/area/ruin/space/has_grav/powered/virtual_domain) +"fJ" = ( +/obj/machinery/light/small/directional/north, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"fM" = ( +/obj/machinery/computer/crew/syndie{ + dir = 8 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"fV" = ( +/obj/machinery/atmospherics/components/unary/vent_pump, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"gD" = ( +/obj/effect/mob_spawn/ghost_role/human/syndicatespace, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"hg" = ( +/obj/structure/window/reinforced/plasma/plastitanium, +/obj/machinery/door/poddoor{ + id = "fslockdown"; + name = "Ship Blast Door"; + state_open = 1 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"hy" = ( +/obj/structure/table/reinforced, +/obj/item/paper/fluff/ruins/forgottenship/missionobj, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"hA" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/wall/r_wall/syndicate, +/area/ruin/space/has_grav/powered/virtual_domain) +"hD" = ( +/obj/structure/table/reinforced, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"ip" = ( +/mob/living/basic/syndicate/melee/sword/space/stormtrooper, +/turf/open/floor/plastic, +/area/ruin/space/has_grav/powered/virtual_domain) +"iB" = ( +/obj/machinery/light/directional/north, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"iL" = ( +/obj/structure/sign/departments/cargo, +/turf/closed/wall/r_wall/syndicate, +/area/ruin/space/has_grav/powered/virtual_domain) +"iU" = ( +/obj/structure/closet/crate/secure/gear{ + req_access = list("syndicate") + }, +/obj/item/melee/energy/sword/saber/red, +/obj/machinery/light/small/directional/north, +/turf/open/floor/pod/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"iW" = ( +/obj/structure/table/reinforced, +/obj/machinery/button/door{ + id = "fslockdown"; + name = "Window shutters"; + req_access = list("syndicate") + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"iX" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/mob/living/basic/syndicate/ranged/smg/space/stormtrooper, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"ja" = ( +/obj/machinery/door/window{ + dir = 1; + name = "Spare Equipment"; + req_access = list("syndicate") + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"jl" = ( +/obj/structure/bodycontainer/crematorium{ + id = "fscremate" + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"jA" = ( +/obj/structure/cable, +/mob/living/basic/syndicate/melee/space/stormtrooper, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"jJ" = ( +/obj/machinery/door/airlock/grunge{ + name = "Syndicate Ship Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/turf/open/floor/iron/dark/side{ + dir = 1 + }, +/area/ruin/space/has_grav/powered/virtual_domain) +"kh" = ( +/obj/machinery/door/airlock/grunge{ + name = "Syndicate Ship Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"ki" = ( +/obj/structure/table/reinforced, +/obj/machinery/computer/security/telescreen/interrogation{ + name = "Cameras monitor"; + network = list("fsci"); + req_access = list("syndicate"); + screen_loc = "" + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"kI" = ( +/obj/machinery/computer/atmos_alert{ + dir = 8 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"kJ" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"li" = ( +/obj/structure/transit_tube/station/dispenser/reverse{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"ln" = ( +/obj/machinery/turretid{ + control_area = "/area/ruin/space/has_grav/syndicate_forgotten_ship"; + enabled = 0; + icon_state = "control_kill"; + lethal = 1; + name = "Ship turret control panel"; + pixel_y = 32; + req_access = list("syndicate") + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"lo" = ( +/obj/structure/fans/tiny, +/obj/machinery/door/airlock/external/ruin{ + name = "Syndicate Ship Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"lN" = ( +/obj/machinery/light/small/directional/east, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"mo" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/layer2{ + dir = 8 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"mD" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 10 + }, +/obj/item/wrench, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"nk" = ( +/obj/machinery/power/apc/auto_name/directional/north, +/obj/effect/mapping_helpers/apc/syndicate_access, +/obj/structure/cable, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"nB" = ( +/turf/closed/mineral/random, +/area/space) +"nG" = ( +/obj/machinery/light/directional/south, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"nO" = ( +/obj/machinery/mineral/ore_redemption{ + name = "Syndicate ore redemption machine"; + ore_multiplier = 4; + req_access = list("syndicate") + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"nU" = ( +/obj/structure/sign/poster/contraband/syndicate_pistol, +/turf/closed/wall/r_wall/syndicate, +/area/ruin/space/has_grav/powered/virtual_domain) +"oM" = ( +/obj/structure/cable, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"oZ" = ( +/mob/living/basic/syndicate/melee/sword/space/stormtrooper, +/turf/open/floor/carpet/royalblack, +/area/ruin/space/has_grav/powered/virtual_domain) +"pl" = ( +/obj/machinery/atmospherics/components/tank/air{ + dir = 8 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"pz" = ( +/obj/machinery/computer/security{ + desc = "Used to access interrogation room camera."; + dir = 8; + name = "Ship cameras console"; + network = list("fsc","fsci"); + screen_loc = "" + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"pH" = ( +/obj/structure/table/reinforced, +/obj/item/toy/plush/nukeplushie, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"pM" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"pS" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 6 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"pU" = ( +/obj/machinery/shower/directional/north, +/obj/machinery/light/directional/south, +/turf/open/floor/iron, +/area/ruin/space/has_grav/powered/virtual_domain) +"qf" = ( +/obj/structure/table/optable, +/obj/machinery/light/small/directional/north, +/turf/open/floor/plastic, +/area/ruin/space/has_grav/powered/virtual_domain) +"qx" = ( +/turf/open/space/basic, +/area/space) +"qU" = ( +/obj/structure/sign/poster/contraband/c20r, +/turf/closed/wall/r_wall/syndicate, +/area/ruin/space/has_grav/powered/virtual_domain) +"qY" = ( +/obj/machinery/light/small/directional/south, +/turf/open/floor/iron/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"rm" = ( +/obj/machinery/button/crematorium{ + id = "fscremate"; + pixel_x = -32 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"ru" = ( +/turf/closed/wall/r_wall/syndicate, +/area/ruin/space/has_grav/powered/virtual_domain) +"rH" = ( +/obj/machinery/airalarm/directional/north, +/obj/effect/mapping_helpers/airalarm/syndicate_access, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"rM" = ( +/obj/structure/closet/syndicate{ + anchored = 1; + desc = "A basic closet for all your villainous needs."; + locked = 1; + name = "Closet"; + req_access = list("syndicate"); + secure = 1 + }, +/obj/effect/spawner/random/contraband/armory, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"rP" = ( +/obj/effect/mob_spawn/ghost_role/human/syndicatespace, +/obj/machinery/light/small/directional/south, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"sg" = ( +/obj/machinery/ore_silo, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"sq" = ( +/obj/machinery/door/window{ + name = "Control Room"; + req_access = list("syndicate") + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"sz" = ( +/obj/machinery/atmospherics/components/unary/vent_pump{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"sH" = ( +/obj/structure/displaycase{ + req_access = list("syndicate"); + start_showpiece_type = /obj/item/gun/ballistic/automatic/pistol/deagle/camo + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"sK" = ( +/obj/structure/closet/crate/secure/gear{ + req_access = list("syndicate") + }, +/obj/item/stack/sheet/mineral/titanium{ + amount = 40 + }, +/obj/item/stack/sheet/mineral/uranium{ + amount = 15 + }, +/turf/open/floor/pod/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"sL" = ( +/obj/structure/chair/comfy, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"sM" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"tv" = ( +/obj/structure/table/reinforced, +/obj/machinery/button/door{ + id = "fscaproom"; + name = "Room shutters control"; + req_access = list("syndicate") + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"tI" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"uP" = ( +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"vp" = ( +/obj/structure/table/reinforced, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"vD" = ( +/obj/machinery/portable_atmospherics/canister/oxygen, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"vK" = ( +/obj/machinery/door/airlock/grunge{ + name = "Syndicate Ship Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"vU" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"wb" = ( +/obj/machinery/atmospherics/components/unary/portables_connector/visible/layer2, +/obj/machinery/portable_atmospherics/scrubber{ + anchored = 1 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"we" = ( +/turf/closed/mineral/random/high_chance, +/area/space) +"wK" = ( +/obj/machinery/door/airlock/grunge{ + name = "Syndicate Ship Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/turf/open/floor/iron/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"wL" = ( +/obj/structure/table/reinforced, +/obj/item/storage/medkit/regular, +/obj/machinery/light/small/directional/north, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"xJ" = ( +/obj/structure/closet/syndicate{ + anchored = 1; + desc = "A basic closet for all your villainous needs."; + locked = 1; + name = "Closet"; + req_access = list("syndicate"); + secure = 1 + }, +/obj/item/ammo_box/c9mm, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"xZ" = ( +/obj/machinery/computer/camera_advanced/syndie{ + dir = 8 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"yl" = ( +/obj/machinery/door/airlock/grunge{ + name = "Captain's Room" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/machinery/door/poddoor{ + id = "fscaproom"; + name = "Captain's Blast Door"; + state_open = 1 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"yD" = ( +/mob/living/basic/syndicate/ranged/smg/space/stormtrooper, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"yJ" = ( +/obj/structure/table/reinforced, +/obj/machinery/atmospherics/components/unary/vent_scrubber/layer2, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"yR" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"yT" = ( +/obj/item/ai_module/core/full/cybersun, +/obj/structure/table/reinforced, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"yV" = ( +/obj/structure/table/reinforced, +/obj/item/assembly/prox_sensor, +/obj/item/assembly/prox_sensor, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"yZ" = ( +/turf/closed/mineral, +/area/space) +"zi" = ( +/obj/machinery/vending/cigarette/syndicate, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"zt" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_scrubber/layer2{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"Aa" = ( +/obj/structure/chair/comfy/shuttle, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"AN" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/mob/living/basic/syndicate/ranged/smg/space/stormtrooper, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Bm" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/syndicate, +/area/ruin/space/has_grav/powered/virtual_domain) +"BK" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable, +/turf/open/space/basic, +/area/space) +"BN" = ( +/obj/structure/transit_tube/crossing, +/turf/template_noop, +/area/virtual_domain/safehouse) +"Cf" = ( +/obj/machinery/light/directional/south, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Ci" = ( +/obj/structure/closet/syndicate{ + anchored = 1; + desc = "A basic closet for all your villainous needs."; + locked = 1; + name = "Closet"; + req_access = list("syndicate"); + secure = 1 + }, +/obj/item/crowbar/red, +/obj/item/ammo_box/magazine/m9mm_aps, +/obj/item/ammo_box/magazine/m9mm_aps, +/turf/open/floor/carpet/royalblack, +/area/ruin/space/has_grav/powered/virtual_domain) +"Cn" = ( +/obj/machinery/camera/xray/directional/east{ + c_tag = "Conference room"; + network = list("fsc"); + screen_loc = "" + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"CK" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/mob/living/basic/syndicate/ranged/smg/pilot, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"CR" = ( +/obj/structure/closet/syndicate{ + anchored = 1; + desc = "A basic closet for all your villainous needs."; + locked = 1; + name = "Closet"; + req_access = list("syndicate"); + secure = 1 + }, +/obj/item/coin/antagtoken, +/obj/item/dnainjector/thermal, +/obj/item/storage/box/firingpins/syndicate, +/obj/item/storage/box/firingpins/syndicate, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"De" = ( +/obj/machinery/door/airlock/grunge{ + name = "Syndicate Ship Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"Dj" = ( +/obj/structure/table/reinforced, +/obj/item/ammo_box/magazine/smgm45, +/obj/item/ammo_box/magazine/smgm45, +/obj/item/ammo_box/magazine/smgm45, +/obj/item/gun/ballistic/automatic/c20r/unrestricted, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"DA" = ( +/obj/structure/closet/crate/secure/gear{ + req_access = list("syndicate") + }, +/obj/effect/spawner/random/maintenance, +/obj/effect/spawner/random/maintenance, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"EB" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"EX" = ( +/mob/living/basic/syndicate/ranged/shotgun/space/stormtrooper, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Fp" = ( +/obj/structure/tank_dispenser/oxygen, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"FN" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Gn" = ( +/obj/structure/chair/comfy{ + dir = 1 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Gs" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"GB" = ( +/obj/structure/cable, +/obj/machinery/door/airlock/external/ruin{ + name = "Syndicate Ship Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"GZ" = ( +/obj/machinery/door/airlock/external/ruin{ + name = "Syndicate Ship Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Hq" = ( +/turf/closed/indestructible/binary, +/area/space) +"HU" = ( +/obj/machinery/door/airlock/grunge{ + name = "Bridge" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"Ia" = ( +/obj/effect/mob_spawn/ghost_role/human/syndicatespace/captain, +/turf/open/floor/carpet/royalblack, +/area/ruin/space/has_grav/powered/virtual_domain) +"Id" = ( +/obj/machinery/power/shuttle_engine/huge{ + dir = 8 + }, +/turf/open/space/basic, +/area/ruin/space/has_grav/powered/virtual_domain) +"If" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 9 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"Ig" = ( +/obj/machinery/porta_turret/syndicate/energy{ + dir = 4; + name = "Syndicate Ship Turret"; + on = 0; + shot_delay = 10 + }, +/turf/closed/wall/r_wall/syndicate/nodiagonal, +/area/ruin/space/has_grav/powered/virtual_domain) +"Im" = ( +/obj/structure/table/reinforced, +/obj/item/ammo_box/c9mm, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Io" = ( +/obj/effect/landmark/bitrunning/cache_spawn, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"IC" = ( +/obj/structure/table/reinforced, +/obj/item/paper, +/obj/item/pen, +/turf/open/floor/carpet/royalblack, +/area/ruin/space/has_grav/powered/virtual_domain) +"IH" = ( +/obj/machinery/door/airlock/external/ruin{ + name = "Syndicate Ship Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/structure/cable, +/obj/structure/fans/tiny, +/turf/open/floor/plating, +/area/ruin/space/has_grav/powered/virtual_domain) +"IV" = ( +/obj/machinery/door/airlock/grunge{ + name = "Syndicate Ship Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/turf/open/floor/plating, +/area/ruin/space/has_grav/powered/virtual_domain) +"Jg" = ( +/obj/machinery/light/small/directional/south, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"Jz" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 5 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"JA" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"JN" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 5 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"JP" = ( +/obj/structure/sink/directional/south, +/turf/open/floor/iron/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"Kz" = ( +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"Lk" = ( +/obj/structure/transit_tube/crossing, +/turf/closed/mineral/random, +/area/space) +"Lo" = ( +/obj/structure/filingcabinet, +/obj/machinery/door/window{ + dir = 8; + name = "Syndicate Interior Door"; + req_access = list("syndicate") + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"Mc" = ( +/obj/structure/closet/syndicate{ + anchored = 1; + desc = "A basic closet for all your villainous needs."; + locked = 1; + name = "Closet"; + req_access = list("syndicate"); + secure = 1 + }, +/obj/item/crowbar/red, +/obj/item/ammo_box/magazine/m9mm, +/obj/item/ammo_box/magazine/m9mm, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Mm" = ( +/obj/structure/closet/syndicate{ + anchored = 1; + desc = "A basic closet for all your villainous needs."; + locked = 1; + name = "Closet"; + req_access = list("syndicate"); + secure = 1 + }, +/obj/item/clothing/head/hats/hos/beret/syndicate, +/obj/item/clothing/suit/armor/vest/capcarapace/syndicate, +/obj/item/clothing/mask/gas/syndicate, +/obj/item/clothing/under/syndicate, +/obj/item/clothing/under/syndicate/skirt, +/obj/item/clothing/gloves/combat, +/obj/item/clothing/shoes/combat, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"MR" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/obj/machinery/light/small/directional/south, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"Nm" = ( +/obj/structure/closet/crate/secure/gear{ + req_access = list("syndicate") + }, +/turf/open/floor/pod/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"Nr" = ( +/obj/structure/closet/crate/secure/gear{ + req_access = list("syndicate") + }, +/obj/item/stack/sheet/mineral/gold{ + amount = 30 + }, +/obj/item/stack/sheet/mineral/silver{ + amount = 30 + }, +/obj/machinery/light/small/directional/south, +/turf/open/floor/pod/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"Nt" = ( +/obj/structure/table/reinforced, +/obj/machinery/atmospherics/components/unary/vent_pump, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Of" = ( +/obj/structure/closet/crate/secure/gear{ + req_access = list("syndicate") + }, +/obj/item/disk/surgery/forgottenship, +/turf/open/floor/pod/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"Ox" = ( +/obj/machinery/atmospherics/components/unary/vent_pump, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"OH" = ( +/obj/structure/cable, +/obj/structure/table/reinforced, +/obj/item/storage/toolbox/syndicate, +/obj/item/storage/toolbox/syndicate, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"OI" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 1 + }, +/obj/structure/cable, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"PR" = ( +/obj/machinery/door/password/voice/sfc{ + password = null + }, +/obj/structure/fans/tiny, +/obj/machinery/door/airlock/grunge{ + desc = "Vault airlock preventing air from going out."; + name = "Syndicate Vault Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/turf/open/floor/pod/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"Qg" = ( +/obj/machinery/suit_storage_unit/syndicate{ + helmet_type = /obj/item/clothing/head/helmet/space/syndicate/black; + suit_type = /obj/item/clothing/suit/space/syndicate/black + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Qi" = ( +/obj/item/stack/sheet/mineral/uranium{ + amount = 15 + }, +/obj/structure/cable, +/obj/machinery/light/small/directional/north, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"QF" = ( +/obj/structure/table/reinforced, +/obj/item/dualsaber/green, +/obj/machinery/light/small/directional/east, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"QG" = ( +/obj/structure/tank_dispenser/oxygen, +/turf/closed/mineral/random, +/area/space) +"QX" = ( +/mob/living/basic/syndicate/ranged/space/stormtrooper, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Ra" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/layer2, +/obj/machinery/light/small/directional/north, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"RQ" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"RU" = ( +/obj/machinery/suit_storage_unit/syndicate, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Sc" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Sd" = ( +/obj/structure/closet/syndicate{ + anchored = 1; + desc = "A basic closet for all your villainous needs."; + locked = 1; + name = "Closet"; + req_access = list("syndicate"); + secure = 1 + }, +/obj/item/crowbar/red, +/obj/item/ammo_box/magazine/m9mm, +/obj/item/ammo_box/magazine/m9mm, +/obj/machinery/light/small/directional/north, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Sq" = ( +/obj/machinery/power/smes, +/obj/structure/cable, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"Sv" = ( +/obj/structure/closet/crate/secure/gear{ + req_access = list("syndicate") + }, +/obj/effect/spawner/random/food_or_drink/donkpockets, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Sz" = ( +/turf/open/floor/iron/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"SX" = ( +/obj/machinery/vending/medical/syndicate_access/cybersun, +/turf/open/floor/plastic, +/area/ruin/space/has_grav/powered/virtual_domain) +"TB" = ( +/turf/closed/indestructible/syndicate, +/area/ruin/space/has_grav/powered/virtual_domain) +"UQ" = ( +/obj/structure/sign/poster/contraband/syndicate_recruitment, +/turf/closed/wall/r_wall/syndicate, +/area/ruin/space/has_grav/powered/virtual_domain) +"Vk" = ( +/obj/machinery/porta_turret/syndicate/energy{ + dir = 4; + name = "Syndicate Ship Turret"; + on = 0; + shot_delay = 10 + }, +/turf/closed/wall/r_wall/syndicate, +/area/ruin/space/has_grav/powered/virtual_domain) +"Vq" = ( +/obj/structure/transit_tube/station/dispenser/reverse{ + dir = 8 + }, +/turf/template_noop, +/area/virtual_domain/safehouse) +"Wd" = ( +/obj/structure/sign/poster/contraband/tools, +/turf/closed/wall/r_wall/syndicate, +/area/ruin/space/has_grav/powered/virtual_domain) +"Wy" = ( +/obj/structure/closet/crate/secure/gear{ + req_access = list("syndicate") + }, +/obj/item/stack/ore/plasma{ + amount = 19 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"WR" = ( +/obj/machinery/power/port_gen/pacman/super{ + anchored = 1 + }, +/obj/structure/cable, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/space/has_grav/powered/virtual_domain) +"Xp" = ( +/turf/open/space/basic, +/area/ruin/space/has_grav/powered/virtual_domain) +"XS" = ( +/obj/machinery/light/directional/north, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Yb" = ( +/obj/structure/closet/crate/secure/gear{ + req_access = list("syndicate") + }, +/obj/item/clothing/head/helmet/space/syndicate/black/engie, +/obj/item/clothing/suit/space/syndicate/black/engie, +/turf/open/floor/pod/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"Yi" = ( +/obj/effect/landmark/bitrunning/cache_spawn, +/turf/open/floor/plastic, +/area/ruin/space/has_grav/powered/virtual_domain) +"Yj" = ( +/obj/structure/closet/crate/secure/gear{ + req_access = list("syndicate") + }, +/obj/item/stack/ore/diamond{ + amount = 3 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/space/has_grav/powered/virtual_domain) +"Yk" = ( +/obj/machinery/door/airlock/grunge{ + name = "Captain's Room" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/machinery/door/poddoor{ + id = "fscaproom"; + name = "Captain's Blast Door"; + state_open = 1 + }, +/turf/open/floor/carpet/royalblack, +/area/ruin/space/has_grav/powered/virtual_domain) +"Yr" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"Yu" = ( +/obj/structure/chair/comfy/black, +/turf/open/floor/carpet/royalblack, +/area/ruin/space/has_grav/powered/virtual_domain) +"YV" = ( +/obj/structure/sink/directional/south, +/obj/structure/mirror/directional/west, +/turf/open/floor/iron/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"Za" = ( +/obj/machinery/computer/operating, +/turf/open/floor/plastic, +/area/ruin/space/has_grav/powered/virtual_domain) +"Zb" = ( +/turf/open/floor/plastic, +/area/ruin/space/has_grav/powered/virtual_domain) +"ZA" = ( +/obj/machinery/power/shuttle_engine/propulsion{ + dir = 8 + }, +/turf/open/space/basic, +/area/ruin/space/has_grav/powered/virtual_domain) + +(1,1,1) = {" +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +"} +(2,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(3,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(4,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(5,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(6,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(7,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(8,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +we +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(9,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(10,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Xp +Xp +Id +qx +qx +Xp +Xp +Id +qx +qx +Xp +Xp +Id +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(11,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Xp +Xp +Xp +qx +qx +Xp +Xp +Xp +qx +qx +Xp +Xp +Xp +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(12,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +ZA +Xp +Xp +Xp +ZA +ZA +Xp +Xp +Xp +ZA +ZA +Xp +Xp +Xp +ZA +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +we +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(13,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +ru +ru +ru +ru +ru +ru +ru +ru +ru +ru +ru +ru +ru +ru +ru +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +we +we +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(14,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +Vk +ru +Sv +vD +uP +uP +Yj +vD +uP +Wy +DA +uP +QX +vD +cc +ru +Vk +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(15,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +Io +uP +uP +QX +lN +uP +uP +uP +uP +uP +lN +uP +uP +uP +uP +hA +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(16,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +ru +ru +ru +ru +ru +ru +ru +IV +ru +ru +ru +IV +ru +ru +ru +ru +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(17,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +ru +vp +ru +Ia +Ci +ru +Sq +di +WR +ru +yV +Gn +uP +Mc +uP +ru +qx +qx +qx +qx +qx +qx +qx +qx +qx +nB +we +nB +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(18,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +vp +Jg +ru +bh +cR +ru +Qi +sz +Kz +ru +Mc +gD +yD +uP +rP +ru +qx +qx +qx +qx +qx +qx +qx +nB +nB +nB +nB +nB +nB +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(19,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +sH +Kz +yl +oZ +bh +Yk +pS +RQ +Jz +vK +uP +uP +uP +sL +hy +ru +qx +qx +qx +qx +qx +qx +nB +nB +TB +TB +TB +TB +nB +nB +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(20,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +CR +Kz +ru +bh +bh +Yk +pM +zt +pM +vK +uP +uP +EX +sL +Im +ru +qx +qx +qx +qx +qx +nB +nB +TB +TB +Yb +Yb +TB +Bm +nB +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(21,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +yT +Kz +ru +Yu +IC +ru +mD +JN +MR +ru +Sd +gD +uP +uP +gD +ru +qx +qx +qx +qx +nB +QG +nB +TB +aN +bG +bG +sK +TB +nB +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(22,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +Ig +ru +Lo +ru +tv +ki +nU +wb +EB +pl +ru +hD +Gn +uP +Mc +ru +Ig +qx +qx +qx +qx +nB +we +nB +TB +iU +bG +bG +Nr +TB +nB +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(23,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +ru +ru +ru +ru +ru +ru +ru +cy +ru +ru +ru +ru +ru +ru +ru +qx +qx +qx +qx +qx +qx +nB +nB +TB +Nm +bG +bG +Of +TB +nB +nB +qx +qx +qx +qx +qx +qx +qx +sM +sM +sM +sM +sM +kJ +qx +Hq +"} +(24,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +ru +Za +Yi +Zb +SX +ru +uP +yR +uP +ru +YV +Sz +jJ +fG +ru +qx +qx +qx +qx +qx +nB +nB +nB +TB +TB +PR +TB +TB +TB +nB +nB +nB +qx +qx +qx +qx +qx +qx +sM +sM +sM +sM +sM +sM +qx +Hq +"} +(25,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +ru +qf +Zb +ip +da +ru +Ra +Sc +uP +ru +JP +qY +ru +ru +ru +qx +qx +qx +qx +qx +nB +nB +we +ru +ru +uP +sg +ru +ru +nB +nB +nB +nB +qx +qx +qx +qx +qx +sM +sM +sM +sM +sM +sM +qx +Hq +"} +(26,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +ru +aq +cB +Zb +Zb +De +Ox +Gs +uP +wK +Sz +Sz +jJ +pU +ru +qx +qx +qx +qx +qx +qx +nB +nB +qU +Fp +uP +uP +li +cj +Lk +Lk +fd +fd +fd +fd +fd +fd +fd +BN +Vq +sM +sM +sM +sM +qx +Hq +"} +(27,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +Vk +ru +ru +ru +ru +ru +ru +ru +kh +ru +ru +ru +ru +ru +ru +ru +Vk +qx +qx +qx +qx +qx +nB +nB +ru +eB +uP +nO +uP +ru +nB +qx +qx +qx +qx +qx +qx +qx +qx +sM +sM +sM +sM +sM +sM +qx +Hq +"} +(28,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +jl +rm +ru +nk +oM +oM +oM +yR +oM +oM +oM +uP +ru +uP +Qg +ru +qx +qx +qx +qx +qx +qx +nB +ru +wL +oM +uP +dw +ru +yZ +nB +nB +nB +qx +qx +qx +qx +qx +sM +sM +sM +sM +sM +sM +qx +Hq +"} +(29,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +uP +dw +ru +rH +uP +AN +JA +iX +JA +JA +oM +uP +ru +fJ +Qg +ru +qx +qx +qx +qx +qx +qx +qx +Wd +OH +oM +uP +RU +ru +we +nB +nB +qx +qx +qx +qx +qx +qx +sM +sM +sM +sM +sM +Yr +qx +Hq +"} +(30,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +lo +uP +uP +GZ +uP +Aa +hD +yJ +bD +hD +hD +OI +oM +GB +jA +oM +dU +BK +BK +BK +BK +BK +BK +BK +IH +oM +oM +uP +RU +ru +nB +nB +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(31,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +uP +uP +dd +uP +Aa +hD +Nt +aw +hD +hD +bo +uP +dd +uP +Qg +ru +qx +qx +qx +qx +qx +qx +qx +iL +cZ +uP +uP +RU +ru +nB +nB +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(32,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +aO +uP +ru +XS +uP +uP +hD +aZ +hD +uP +uP +Cf +ru +uP +Fp +ru +qx +qx +qx +qx +qx +qx +nB +ru +ru +Dj +QF +ru +ru +nB +nB +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(33,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +Ig +ru +hD +ru +zi +uP +uP +uP +FN +Cn +uP +uP +uP +ru +hD +ru +Ig +qx +qx +qx +qx +qx +nB +nB +nB +ru +ru +ru +ru +nB +nB +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(34,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +ru +ru +ru +ru +ru +ru +ru +HU +ru +ru +ru +ru +ru +ru +ru +qx +qx +qx +qx +qx +qx +qx +nB +nB +nB +nB +we +nB +nB +nB +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(35,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +UQ +rM +xJ +Kz +Kz +tI +Kz +Kz +ct +xJ +ru +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +nB +nB +nB +nB +nB +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(36,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +ru +ru +ru +Kz +Kz +Kz +Kz +tI +Kz +Kz +Kz +Kz +ru +ru +ru +ru +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(37,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +ln +Kz +ru +iB +Kz +Kz +fV +If +Kz +Kz +Kz +nG +ru +cw +cw +ru +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(38,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +ru +Kz +dz +sq +Kz +CK +Kz +vU +mo +vU +Kz +CK +Kz +ja +Kz +Jg +ru +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(39,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +Ig +ru +Kz +ru +Kz +pz +Kz +xZ +Kz +fM +Kz +kI +Kz +ru +Mm +ru +Ig +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(40,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +ru +ru +ru +Kz +Kz +Kz +Kz +Kz +Kz +Kz +Kz +Kz +ru +ru +ru +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(41,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +ru +ru +vp +vp +pH +vp +iW +vp +vp +vp +vp +ru +ru +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(42,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Ig +hg +hg +hg +hg +hg +hg +hg +hg +hg +Ig +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +we +we +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(43,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +we +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(44,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(45,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +we +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(46,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +we +we +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(47,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +we +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(48,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(49,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(50,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(51,1,1) = {" +Hq +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +qx +Hq +"} +(52,1,1) = {" +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +Hq +"} diff --git a/_maps/virtual_domains/test_only.dmm b/_maps/virtual_domains/test_only.dmm new file mode 100644 index 00000000000..22b647188b6 --- /dev/null +++ b/_maps/virtual_domains/test_only.dmm @@ -0,0 +1,52 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/open/floor, +/area/virtual_domain/powered) +"D" = ( +/obj/effect/mob_spawn/corpse/human/miner, +/turf/open/floor, +/area/virtual_domain/powered) +"I" = ( +/mob/living/basic/pet/dog/corgi, +/turf/open/floor, +/area/virtual_domain/powered) +"U" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/open/floor, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +I +a +a +a +U +"} +(2,1,1) = {" +D +a +a +a +a +"} +(3,1,1) = {" +a +a +a +a +a +"} +(4,1,1) = {" +a +a +a +a +a +"} +(5,1,1) = {" +a +a +a +a +a +"} diff --git a/_maps/virtual_domains/vaporwave.dmm b/_maps/virtual_domains/vaporwave.dmm new file mode 100644 index 00000000000..984bbbe2914 --- /dev/null +++ b/_maps/virtual_domains/vaporwave.dmm @@ -0,0 +1,1017 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aA" = ( +/obj/machinery/light/small/directional/north, +/obj/effect/turf_decal/sand/plating, +/turf/open/floor/plating{ + initial_gas_mix = "TEMP=2.7" + }, +/area/ruin/space/has_grav/powered/virtual_domain) +"bs" = ( +/obj/effect/turf_decal/sand, +/turf/open/floor/iron/airless, +/area/ruin/space/has_grav/powered/virtual_domain) +"bF" = ( +/obj/effect/turf_decal/sand/plating, +/turf/open/floor/plating{ + initial_gas_mix = "TEMP=2.7" + }, +/area/ruin/space/has_grav/powered/virtual_domain) +"cz" = ( +/turf/open/misc/asteroid/airless, +/area/ruin/space/has_grav/powered/virtual_domain) +"cL" = ( +/obj/structure/table/reinforced, +/obj/item/reagent_containers/cup/glass/drinkingglass{ + pixel_x = 6; + pixel_y = 4 + }, +/obj/item/reagent_containers/cup/glass/drinkingglass, +/obj/item/reagent_containers/cup/glass/drinkingglass{ + pixel_x = -6; + pixel_y = 8 + }, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"df" = ( +/obj/effect/turf_decal/sand, +/turf/open/floor/iron/airless{ + icon_state = "stairs-l" + }, +/area/ruin/space/has_grav/powered/virtual_domain) +"eF" = ( +/turf/closed/indestructible/binary, +/area/space) +"fx" = ( +/obj/item/statuebust, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"fQ" = ( +/obj/structure/flora/tree/palm, +/turf/open/floor/holofloor/beach, +/area/ruin/space/has_grav/powered/virtual_domain) +"gM" = ( +/obj/structure/table/reinforced, +/obj/item/clothing/glasses/sunglasses/big{ + name = "aesthetic sunglasses" + }, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"hN" = ( +/turf/open/floor/holofloor/beach, +/area/ruin/space/has_grav/powered/virtual_domain) +"il" = ( +/obj/effect/turf_decal/sand, +/obj/effect/turf_decal/sand, +/turf/open/floor/iron/airless, +/area/ruin/space/has_grav/powered/virtual_domain) +"iP" = ( +/obj/machinery/suit_storage_unit/standard_unit, +/turf/template_noop, +/area/virtual_domain/safehouse) +"kj" = ( +/obj/structure/window/spawner/directional/east, +/obj/structure/closet/crate/secure/bitrunning/encrypted, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"ku" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"kF" = ( +/obj/effect/turf_decal/sand, +/turf/open/floor/iron/airless{ + icon_state = "stairs-r" + }, +/area/ruin/space/has_grav/powered/virtual_domain) +"ll" = ( +/obj/structure/sign/poster/contraband/clown/directional/north, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"lu" = ( +/turf/closed/wall/rust, +/area/ruin/space/has_grav/powered/virtual_domain) +"lB" = ( +/obj/item/tank/internals/emergency_oxygen, +/obj/item/tank/internals/emergency_oxygen, +/obj/item/tank/internals/emergency_oxygen, +/turf/template_noop, +/area/virtual_domain/safehouse) +"lI" = ( +/obj/structure/table/reinforced, +/obj/machinery/chem_dispenser/drinks/beer/fullupgrade, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"qm" = ( +/obj/structure/flora/tree/palm, +/obj/machinery/light/directional/west, +/turf/open/floor/holofloor/beach, +/area/ruin/space/has_grav/powered/virtual_domain) +"qu" = ( +/turf/open/floor/holofloor/beach/water, +/area/ruin/space/has_grav/powered/virtual_domain) +"rn" = ( +/obj/structure/statue/sandstone/venus{ + anchored = 1; + dir = 4 + }, +/obj/effect/turf_decal/sand/plating, +/turf/open/floor/plating{ + initial_gas_mix = "TEMP=2.7" + }, +/area/ruin/space/has_grav/powered/virtual_domain) +"xb" = ( +/obj/structure/chair/stool/directional/west, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"xp" = ( +/obj/structure/table/reinforced, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"xK" = ( +/turf/closed/wall, +/area/ruin/space/has_grav/powered/virtual_domain) +"ym" = ( +/obj/structure/lattice, +/turf/open/space/basic, +/area/space) +"AX" = ( +/obj/effect/turf_decal/stripes/asteroid/line, +/obj/effect/turf_decal/sand/plating, +/turf/open/floor/plating{ + initial_gas_mix = "TEMP=2.7" + }, +/area/ruin/space/has_grav/powered/virtual_domain) +"Cq" = ( +/obj/item/instrument/eguitar, +/turf/open/floor/holofloor/beach, +/area/ruin/space/has_grav/powered/virtual_domain) +"CR" = ( +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"Dk" = ( +/obj/structure/window/spawner/directional/east, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"Es" = ( +/obj/structure/chair/comfy/black{ + dir = 4 + }, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"Fd" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/wall/rust, +/area/ruin/space/has_grav/powered/virtual_domain) +"Hf" = ( +/obj/effect/turf_decal/sand, +/turf/open/floor/iron/airless{ + icon_state = "recharge_floor_asteroid" + }, +/area/ruin/space/has_grav/powered/virtual_domain) +"HA" = ( +/turf/open/floor/holofloor/beach/coast, +/area/ruin/space/has_grav/powered/virtual_domain) +"HV" = ( +/obj/structure/chair/comfy/black{ + dir = 4 + }, +/obj/machinery/light/small/directional/north, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"Jr" = ( +/obj/structure/window/spawner/directional/west, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"KO" = ( +/obj/structure/chair/comfy/black{ + dir = 8 + }, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"KY" = ( +/obj/effect/turf_decal/sand, +/turf/open/floor/iron/airless{ + icon_state = "stairs-m" + }, +/area/ruin/space/has_grav/powered/virtual_domain) +"LG" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"LJ" = ( +/obj/structure/lattice, +/turf/open/misc/asteroid/airless, +/area/ruin/space/has_grav/powered/virtual_domain) +"LP" = ( +/obj/structure/flora/tree/palm, +/obj/machinery/light/directional/east, +/turf/open/floor/holofloor/beach, +/area/ruin/space/has_grav/powered/virtual_domain) +"Nz" = ( +/obj/structure/window/spawner/directional/east, +/obj/structure/table/reinforced, +/obj/item/storage/fancy/cigarettes/cigars/havana, +/obj/effect/spawner/random/entertainment/lighter, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"NT" = ( +/turf/open/space/basic, +/area/space) +"Qh" = ( +/obj/structure/closet/crate/bin, +/turf/open/misc/asteroid/airless, +/area/ruin/space/has_grav/powered/virtual_domain) +"Uy" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"UE" = ( +/obj/effect/turf_decal/sand, +/obj/effect/turf_decal/sand/plating, +/turf/open/floor/plating{ + initial_gas_mix = "TEMP=2.7" + }, +/area/ruin/space/has_grav/powered/virtual_domain) +"UV" = ( +/obj/structure/lattice, +/turf/open/floor/plating/airless, +/area/ruin/space/has_grav/powered/virtual_domain) +"Vc" = ( +/obj/structure/flora/tree/palm, +/turf/open/misc/asteroid/airless, +/area/ruin/space/has_grav/powered/virtual_domain) +"XJ" = ( +/obj/structure/fans/tiny, +/obj/machinery/door/airlock/hatch, +/turf/open/floor/pod/dark, +/area/ruin/space/has_grav/powered/virtual_domain) +"Yo" = ( +/obj/structure/statue/sandstone/venus{ + anchored = 1; + desc = "Ugh, this is merely an ugly amateurish replica of the other statue! The letters RIPGOAT are scribbled onto the base."; + dir = 8 + }, +/obj/effect/turf_decal/sand/plating, +/turf/open/floor/plating{ + initial_gas_mix = "TEMP=2.7" + }, +/area/ruin/space/has_grav/powered/virtual_domain) +"YE" = ( +/mob/living/basic/butterfly, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) +"ZI" = ( +/obj/effect/spawner/random/structure/musician/piano/random_piano, +/obj/structure/window/spawner/directional/west, +/turf/open/floor/iron/vaporwave, +/area/ruin/space/has_grav/powered/virtual_domain) + +(1,1,1) = {" +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +"} +(2,1,1) = {" +eF +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(3,1,1) = {" +eF +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(4,1,1) = {" +eF +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(5,1,1) = {" +eF +NT +NT +NT +NT +NT +NT +cz +LJ +cz +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(6,1,1) = {" +eF +NT +NT +NT +NT +NT +cz +cz +LJ +cz +cz +LJ +cz +cz +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(7,1,1) = {" +eF +NT +NT +NT +NT +cz +cz +cz +UV +LJ +cz +UV +cz +cz +cz +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(8,1,1) = {" +eF +NT +NT +NT +NT +cz +xK +xK +lu +lu +lu +xK +lu +UE +cz +cz +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(9,1,1) = {" +eF +NT +NT +NT +LJ +Qh +xK +fQ +hN +qm +HA +qu +xK +aA +cz +cz +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(10,1,1) = {" +eF +NT +NT +NT +LJ +UV +lu +ZI +Jr +Jr +Jr +Jr +xK +bF +Vc +cz +cz +NT +NT +NT +ku +ku +ku +ku +ku +Uy +NT +eF +"} +(11,1,1) = {" +eF +NT +NT +NT +cz +cz +xK +xb +CR +CR +fx +CR +xK +Yo +il +UE +cz +NT +NT +NT +ku +iP +iP +iP +ku +ku +NT +eF +"} +(12,1,1) = {" +eF +NT +NT +NT +cz +cz +xK +ll +CR +CR +CR +CR +xK +Hf +df +il +cz +NT +NT +NT +ku +ku +ku +ku +ku +ku +NT +eF +"} +(13,1,1) = {" +eF +NT +NT +NT +cz +LJ +xK +HV +Es +CR +CR +CR +XJ +bs +KY +bs +il +NT +NT +NT +ku +ku +ku +ku +ku +ku +NT +eF +"} +(14,1,1) = {" +eF +NT +NT +NT +cz +LJ +lu +xp +gM +CR +CR +cL +xK +Hf +kF +bs +il +NT +NT +NT +ku +ku +ku +ku +ku +ku +NT +eF +"} +(15,1,1) = {" +eF +NT +NT +NT +cz +LJ +lu +KO +KO +CR +YE +lI +lu +rn +il +UE +UE +NT +NT +NT +ku +ku +ku +ku +lB +ku +NT +eF +"} +(16,1,1) = {" +eF +NT +NT +NT +LJ +UV +xK +kj +Dk +Dk +Dk +Nz +xK +AX +Vc +cz +cz +NT +NT +NT +ku +ku +ku +ku +ku +LG +NT +eF +"} +(17,1,1) = {" +eF +NT +NT +NT +cz +cz +lu +fQ +Cq +LP +HA +qu +lu +aA +cz +cz +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(18,1,1) = {" +eF +NT +NT +NT +cz +cz +xK +xK +lu +xK +lu +lu +Fd +UE +cz +cz +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(19,1,1) = {" +eF +NT +NT +NT +NT +cz +cz +cz +UV +LJ +Qh +UV +cz +cz +cz +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(20,1,1) = {" +eF +NT +NT +NT +NT +NT +NT +cz +LJ +cz +cz +LJ +cz +cz +cz +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(21,1,1) = {" +eF +NT +NT +NT +NT +NT +NT +NT +ym +cz +cz +cz +cz +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(22,1,1) = {" +eF +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(23,1,1) = {" +eF +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(24,1,1) = {" +eF +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +NT +eF +"} +(25,1,1) = {" +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +eF +"} diff --git a/_maps/virtual_domains/wendigo.dmm b/_maps/virtual_domains/wendigo.dmm new file mode 100644 index 00000000000..17bcb48d688 --- /dev/null +++ b/_maps/virtual_domains/wendigo.dmm @@ -0,0 +1,1373 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/open/indestructible/necropolis{ + initial_gas_mix = "ICEMOON_ATMOS" + }, +/area/icemoon/underground/explored/virtual_domain) +"b" = ( +/turf/closed/indestructible/rock/snow/ice/ore, +/area/icemoon/underground/explored/virtual_domain) +"e" = ( +/turf/open/misc/asteroid/snow/ice/icemoon, +/area/icemoon/underground/explored/virtual_domain) +"f" = ( +/obj/structure/marker_beacon/olive, +/turf/open/indestructible/necropolis{ + initial_gas_mix = "ICEMOON_ATMOS" + }, +/area/icemoon/underground/explored/virtual_domain) +"i" = ( +/turf/closed/indestructible/binary, +/area/icemoon/underground/explored/virtual_domain) +"o" = ( +/obj/structure/marker_beacon/indigo, +/turf/open/indestructible/necropolis{ + initial_gas_mix = "ICEMOON_ATMOS" + }, +/area/icemoon/underground/explored/virtual_domain) +"p" = ( +/obj/structure/marker_beacon/bronze, +/turf/open/indestructible/necropolis{ + initial_gas_mix = "ICEMOON_ATMOS" + }, +/area/icemoon/underground/explored/virtual_domain) +"q" = ( +/obj/structure/marker_beacon/yellow, +/turf/open/indestructible/necropolis{ + initial_gas_mix = "ICEMOON_ATMOS" + }, +/area/icemoon/underground/explored/virtual_domain) +"t" = ( +/obj/structure/marker_beacon/teal, +/turf/open/indestructible/necropolis{ + initial_gas_mix = "ICEMOON_ATMOS" + }, +/area/icemoon/underground/explored/virtual_domain) +"x" = ( +/obj/structure/marker_beacon/burgundy, +/turf/open/indestructible/necropolis{ + initial_gas_mix = "ICEMOON_ATMOS" + }, +/area/icemoon/underground/explored/virtual_domain) +"A" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"E" = ( +/obj/effect/mob_spawn/corpse/human/miner, +/turf/open/misc/asteroid/snow/ice/icemoon, +/area/icemoon/underground/explored/virtual_domain) +"H" = ( +/mob/living/simple_animal/hostile/megafauna/wendigo/virtual_domain, +/turf/open/indestructible/necropolis{ + initial_gas_mix = "ICEMOON_ATMOS" + }, +/area/icemoon/underground/explored/virtual_domain) +"L" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/binary, +/area/icemoon/underground/explored/virtual_domain) +"R" = ( +/obj/item/paper/crumpled/bloody{ + default_raw_text = "for your own sake, do not enter" + }, +/turf/open/misc/asteroid/snow/ice/icemoon, +/area/icemoon/underground/explored/virtual_domain) +"S" = ( +/turf/template_noop, +/area/template_noop) +"V" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"Z" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) + +(1,1,1) = {" +S +S +S +S +S +S +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +S +S +S +S +S +S +S +S +S +S +S +S +S +S +"} +(2,1,1) = {" +S +S +S +S +S +i +i +e +e +e +e +e +e +e +e +e +e +e +e +e +e +e +i +i +S +S +S +S +S +S +S +S +S +S +S +S +S +"} +(3,1,1) = {" +S +S +S +S +i +i +e +e +e +e +e +e +e +e +e +e +e +e +e +e +e +e +e +i +i +S +S +S +S +S +S +S +S +S +S +S +S +"} +(4,1,1) = {" +S +S +S +i +i +e +e +e +b +b +b +b +b +e +e +e +b +b +b +b +b +e +e +e +i +i +S +S +S +S +S +S +S +S +S +S +S +"} +(5,1,1) = {" +S +S +i +i +e +e +e +b +b +b +b +b +b +b +e +b +b +b +b +b +b +b +e +e +e +i +i +i +i +i +i +i +i +i +i +i +L +"} +(6,1,1) = {" +S +i +i +e +e +e +b +b +b +b +b +b +b +b +e +b +b +b +b +b +b +b +b +e +e +e +i +i +e +e +e +e +e +e +e +e +i +"} +(7,1,1) = {" +i +i +e +e +e +b +b +b +b +b +b +b +b +b +e +b +b +b +b +b +b +b +b +b +e +e +e +i +e +e +e +e +e +e +e +e +i +"} +(8,1,1) = {" +i +e +e +e +b +b +b +b +b +b +a +a +a +a +a +a +a +a +a +b +b +b +b +b +b +e +e +e +e +e +e +e +e +e +e +e +i +"} +(9,1,1) = {" +i +e +e +b +b +b +b +b +b +a +a +a +a +a +a +a +a +a +a +a +b +b +b +b +b +b +e +e +e +e +e +e +e +e +e +e +i +"} +(10,1,1) = {" +i +e +e +b +b +b +b +b +a +a +a +a +a +a +a +a +a +a +a +a +a +b +b +b +b +b +e +e +e +e +e +e +e +e +e +e +i +"} +(11,1,1) = {" +i +e +E +b +b +b +b +a +a +a +a +a +a +a +a +a +a +a +a +o +a +a +b +b +b +b +e +e +e +e +e +e +e +e +e +e +i +"} +(12,1,1) = {" +i +e +e +b +b +b +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +b +b +b +e +e +e +e +e +e +e +e +e +e +i +"} +(13,1,1) = {" +i +e +e +b +b +b +a +a +a +a +q +a +a +a +a +a +a +a +a +a +a +a +a +b +b +b +e +e +e +e +e +e +e +e +e +e +i +"} +(14,1,1) = {" +i +e +e +b +b +b +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +b +b +b +e +e +e +V +V +V +V +V +Z +e +i +"} +(15,1,1) = {" +i +e +e +b +b +b +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +b +b +b +E +e +e +V +V +V +V +V +V +e +i +"} +(16,1,1) = {" +i +e +e +e +b +b +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +b +b +e +e +e +e +V +V +V +V +V +V +e +i +"} +(17,1,1) = {" +i +e +e +e +e +e +a +a +a +a +a +a +a +a +H +a +a +a +a +x +a +a +a +e +e +e +e +R +e +V +V +V +V +V +V +e +i +"} +(18,1,1) = {" +i +e +e +e +b +b +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +b +b +e +e +e +e +V +V +V +V +V +V +e +i +"} +(19,1,1) = {" +i +e +e +b +b +b +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +b +b +b +e +e +e +V +V +V +V +V +V +e +i +"} +(20,1,1) = {" +i +e +e +b +b +b +a +a +a +a +a +a +a +a +p +a +a +a +a +a +a +a +a +b +b +b +e +e +e +V +V +V +V +V +A +e +i +"} +(21,1,1) = {" +i +e +e +b +b +b +a +a +a +a +f +a +a +a +a +a +a +a +a +a +a +a +a +b +b +b +e +e +e +e +e +e +e +e +e +e +i +"} +(22,1,1) = {" +i +e +e +b +b +b +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +b +b +b +e +e +e +e +e +e +e +e +e +e +i +"} +(23,1,1) = {" +i +e +e +b +b +b +b +a +a +a +a +a +a +a +a +a +a +a +a +a +t +a +b +b +b +b +e +e +e +e +e +e +e +e +e +e +i +"} +(24,1,1) = {" +i +e +e +b +b +b +b +b +a +a +a +a +a +a +a +a +a +a +a +a +a +b +b +b +b +b +e +e +e +e +e +e +e +e +e +e +i +"} +(25,1,1) = {" +i +e +e +b +b +b +b +b +b +a +a +a +a +a +a +a +a +a +a +a +b +b +b +b +b +b +e +e +e +e +e +e +e +e +e +e +i +"} +(26,1,1) = {" +i +e +e +e +b +b +b +b +b +b +a +a +a +a +a +a +a +a +a +b +b +b +b +b +b +e +e +e +e +e +e +e +e +e +e +e +i +"} +(27,1,1) = {" +i +i +e +e +e +b +b +b +b +b +b +b +b +b +e +b +b +b +b +b +b +b +b +b +e +e +e +i +e +e +e +e +e +e +e +e +i +"} +(28,1,1) = {" +S +i +i +e +e +e +b +b +b +b +b +b +b +b +e +b +b +b +b +b +b +b +b +e +e +e +i +i +e +e +e +e +e +e +e +e +i +"} +(29,1,1) = {" +S +S +i +i +e +e +e +b +b +b +b +b +b +b +e +b +b +b +b +b +b +b +e +e +e +i +i +i +i +i +i +i +i +i +i +i +i +"} +(30,1,1) = {" +S +S +S +i +i +e +e +e +b +b +b +b +b +e +e +e +b +b +b +b +b +e +e +e +i +i +S +S +S +S +S +S +S +S +S +S +S +"} +(31,1,1) = {" +S +S +S +S +i +i +e +e +e +e +e +e +e +e +e +e +e +e +e +e +e +e +e +i +i +S +S +S +S +S +S +S +S +S +S +S +S +"} +(32,1,1) = {" +S +S +S +S +S +i +i +e +e +e +e +e +e +e +e +e +e +e +e +e +e +e +i +i +S +S +S +S +S +S +S +S +S +S +S +S +S +"} +(33,1,1) = {" +S +S +S +S +S +S +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +S +S +S +S +S +S +S +S +S +S +S +S +S +S +"} diff --git a/_maps/virtual_domains/xeno_nest.dmm b/_maps/virtual_domains/xeno_nest.dmm new file mode 100644 index 00000000000..fcbd7cc116c --- /dev/null +++ b/_maps/virtual_domains/xeno_nest.dmm @@ -0,0 +1,2071 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"c" = ( +/obj/structure/alien/weeds, +/obj/structure/alien/resin/wall, +/obj/structure/alien/resin/wall, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"d" = ( +/obj/structure/alien/resin/wall, +/turf/closed/indestructible/binary, +/area/ruin/space/has_grav/powered/virtual_domain) +"e" = ( +/obj/structure/alien/weeds, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"f" = ( +/obj/structure/alien/weeds, +/obj/structure/alien/egg/burst, +/obj/effect/decal/cleanable/blood, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"h" = ( +/obj/structure/alien/weeds, +/mob/living/simple_animal/hostile/alien/sentinel, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"i" = ( +/obj/structure/alien/weeds, +/obj/structure/bed/nest, +/obj/effect/decal/cleanable/blood/gibs, +/obj/effect/decal/cleanable/blood, +/obj/item/clothing/under/syndicate, +/obj/item/clothing/glasses/night, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"j" = ( +/obj/machinery/suit_storage_unit/spaceruin, +/turf/template_noop, +/area/virtual_domain/safehouse) +"k" = ( +/obj/structure/alien/weeds/node, +/obj/structure/alien/resin/wall, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"l" = ( +/obj/structure/alien/weeds, +/obj/structure/alien/resin/wall, +/turf/closed/indestructible/binary, +/area/ruin/space/has_grav/powered/virtual_domain) +"m" = ( +/obj/structure/alien/weeds, +/obj/structure/bed/nest, +/obj/structure/alien/resin/wall, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"n" = ( +/turf/template_noop, +/area/virtual_domain/safehouse) +"o" = ( +/obj/structure/alien/weeds, +/obj/effect/decal/cleanable/blood/gibs, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"p" = ( +/obj/structure/alien/weeds, +/mob/living/simple_animal/hostile/alien/drone{ + plants_off = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"q" = ( +/obj/structure/alien/resin/wall, +/turf/open/space/basic, +/area/ruin/space/has_grav/powered/virtual_domain) +"r" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/template_noop, +/area/virtual_domain/safehouse) +"s" = ( +/obj/structure/alien/weeds/node, +/mob/living/simple_animal/hostile/alien/drone{ + plants_off = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"t" = ( +/obj/structure/alien/weeds, +/obj/structure/alien/weeds, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"u" = ( +/obj/structure/alien/weeds/node, +/obj/effect/decal/cleanable/blood, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"v" = ( +/obj/effect/landmark/bitrunning/safehouse_spawn, +/turf/template_noop, +/area/virtual_domain/safehouse) +"x" = ( +/obj/structure/alien/weeds, +/obj/structure/bed/nest, +/obj/effect/landmark/bitrunning/cache_spawn, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"z" = ( +/obj/structure/alien/weeds, +/obj/structure/alien/resin/wall, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"A" = ( +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/ruin/space/has_grav/powered/virtual_domain) +"B" = ( +/obj/structure/alien/weeds, +/obj/effect/decal/cleanable/blood, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"C" = ( +/obj/structure/alien/weeds, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/ruin/space/has_grav/powered/virtual_domain) +"D" = ( +/obj/structure/alien/weeds, +/obj/structure/alien/weeds, +/turf/open/misc/asteroid/basalt/lava_land_surface/no_ruins, +/area/ruin/space/has_grav/powered/virtual_domain) +"E" = ( +/turf/closed/indestructible/binary, +/area/ruin/space/has_grav/powered/virtual_domain) +"F" = ( +/obj/structure/table/greyscale, +/obj/item/gun/energy/beam_rifle, +/obj/item/gun/energy/laser{ + pixel_x = 4; + pixel_y = -6 + }, +/obj/item/gun/energy/laser{ + pixel_x = -8; + pixel_y = 6 + }, +/turf/template_noop, +/area/virtual_domain/safehouse) +"G" = ( +/obj/structure/alien/resin/wall, +/obj/structure/alien/weeds, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"H" = ( +/obj/structure/table/greyscale, +/obj/machinery/recharger{ + pixel_x = 8; + pixel_y = 4 + }, +/obj/machinery/recharger{ + pixel_x = -8; + pixel_y = 4 + }, +/turf/template_noop, +/area/virtual_domain/safehouse) +"I" = ( +/obj/structure/alien/weeds, +/obj/structure/bed/nest, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"J" = ( +/obj/structure/alien/weeds, +/mob/living/simple_animal/hostile/alien/queen/large{ + desc = "A gigantic alien who is in charge of the hive and all of its loyal servants."; + name = "alien queen"; + pixel_x = -16; + plants_off = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"K" = ( +/obj/structure/alien/weeds, +/obj/effect/landmark/bitrunning/cache_spawn, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"L" = ( +/obj/item/storage/medkit/regular, +/obj/item/storage/medkit/regular, +/turf/template_noop, +/area/virtual_domain/safehouse) +"M" = ( +/obj/structure/alien/weeds, +/obj/structure/alien/resin/wall{ + move_force = 1000; + move_resist = 3000; + pull_force = 1000 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"N" = ( +/obj/structure/alien/weeds, +/obj/structure/bed/nest, +/obj/effect/decal/cleanable/blood/gibs, +/obj/item/clothing/under/rank/security/officer, +/obj/item/clothing/suit/armor/vest, +/obj/item/melee/baton/security/loaded, +/obj/item/clothing/head/helmet, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"O" = ( +/obj/effect/baseturf_helper/virtual_domain, +/turf/closed/indestructible/binary, +/area/ruin/space/has_grav/powered/virtual_domain) +"P" = ( +/obj/structure/alien/weeds/node, +/mob/living/simple_animal/hostile/alien, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"Q" = ( +/obj/structure/alien/resin/wall, +/obj/structure/alien/resin/wall, +/turf/closed/indestructible/binary, +/area/ruin/space/has_grav/powered/virtual_domain) +"S" = ( +/obj/structure/alien/weeds, +/mob/living/simple_animal/hostile/alien, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"T" = ( +/obj/structure/alien/weeds, +/obj/structure/alien/egg/burst, +/obj/effect/decal/cleanable/blood/gibs, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"U" = ( +/obj/structure/alien/weeds, +/obj/structure/bed/nest, +/obj/effect/decal/cleanable/blood/gibs, +/obj/item/gun/ballistic/automatic/pistol, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"V" = ( +/obj/structure/alien/weeds/node, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"W" = ( +/obj/structure/alien/weeds, +/obj/structure/alien/egg/burst, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"Y" = ( +/obj/structure/alien/weeds, +/obj/effect/decal/cleanable/blood, +/mob/living/simple_animal/hostile/alien/drone{ + plants_off = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) +"Z" = ( +/obj/structure/alien/weeds, +/obj/structure/bed/nest, +/obj/effect/decal/cleanable/blood/gibs, +/obj/item/tank/internals/oxygen, +/obj/item/clothing/suit/space/syndicate/orange, +/obj/item/clothing/mask/gas, +/obj/item/clothing/head/helmet/space/syndicate/orange, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/ruin/space/has_grav/powered/virtual_domain) + +(1,1,1) = {" +a +a +a +E +E +E +E +E +E +E +E +E +E +E +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +a +a +E +E +z +z +z +z +z +z +z +z +E +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(3,1,1) = {" +a +a +a +E +E +z +e +W +W +z +e +e +z +M +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(4,1,1) = {" +a +a +a +E +z +z +e +e +e +e +p +e +W +z +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(5,1,1) = {" +a +a +a +E +z +e +e +k +z +z +z +k +z +z +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(6,1,1) = {" +a +a +a +E +z +e +e +m +K +J +o +i +z +z +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(7,1,1) = {" +a +a +a +E +z +W +h +e +e +e +B +o +e +z +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(8,1,1) = {" +a +a +a +E +z +I +o +z +e +V +e +h +W +z +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(9,1,1) = {" +a +a +a +E +z +U +u +e +z +e +e +W +z +z +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(10,1,1) = {" +a +a +a +E +z +e +o +z +e +e +e +k +W +z +E +a +a +a +a +a +a +a +E +E +E +E +E +E +E +E +E +E +a +a +a +a +a +a +a +"} +(11,1,1) = {" +a +a +a +E +z +z +e +h +e +e +h +e +e +z +E +a +a +a +a +a +a +a +E +E +E +E +z +z +z +z +E +E +a +a +a +a +a +a +a +"} +(12,1,1) = {" +a +a +a +E +E +z +W +e +e +e +e +e +e +z +E +a +a +a +a +a +a +a +E +E +E +z +z +Z +I +z +z +E +a +a +a +a +a +a +a +"} +(13,1,1) = {" +a +a +a +E +E +z +z +e +e +V +e +e +z +z +E +a +a +a +a +a +a +a +E +E +z +z +W +o +Y +e +z +E +a +a +a +a +a +a +a +"} +(14,1,1) = {" +a +a +a +E +E +E +z +z +e +e +e +z +z +E +E +a +a +a +a +E +E +E +E +E +z +I +e +V +e +W +z +E +a +a +a +a +a +a +a +"} +(15,1,1) = {" +a +a +a +a +a +E +E +z +z +z +z +z +E +E +E +E +E +E +E +E +E +E +z +z +z +e +e +e +I +z +z +E +a +a +a +a +a +a +a +"} +(16,1,1) = {" +a +a +a +a +a +a +E +z +V +V +z +E +E +E +E +E +E +E +E +E +E +z +z +e +S +e +W +z +z +z +E +E +a +a +a +a +a +a +a +"} +(17,1,1) = {" +a +a +a +a +a +a +E +z +p +e +z +z +E +z +z +z +z +z +z +z +z +z +e +e +z +z +z +z +E +E +E +E +a +a +a +a +a +a +a +"} +(18,1,1) = {" +a +a +a +a +a +a +E +z +e +e +p +z +z +z +e +e +e +e +e +e +z +z +e +z +z +E +E +E +E +E +E +E +E +E +E +E +E +E +O +"} +(19,1,1) = {" +E +E +E +E +E +E +E +z +z +e +e +e +z +e +e +e +e +e +e +V +e +e +e +z +E +E +E +E +E +E +Q +d +q +q +q +q +q +q +E +"} +(20,1,1) = {" +E +z +z +z +z +E +E +E +z +z +e +V +e +e +e +z +z +z +z +e +e +t +z +z +E +E +a +a +a +E +q +A +A +A +A +A +A +A +E +"} +(21,1,1) = {" +E +z +W +I +z +z +z +z +z +z +e +e +e +e +z +z +E +E +z +z +e +e +z +E +E +E +a +a +a +E +q +A +A +A +A +A +A +A +E +"} +(22,1,1) = {" +E +G +t +S +e +z +z +e +e +e +e +e +e +z +z +E +E +E +z +e +e +e +z +E +E +E +a +a +a +E +q +A +C +A +A +A +A +A +E +"} +(23,1,1) = {" +E +G +K +W +V +e +e +e +z +z +e +z +z +z +E +E +E +E +z +e +e +z +z +E +E +a +a +a +a +E +q +C +C +C +A +A +A +A +E +"} +(24,1,1) = {" +E +z +z +I +I +z +z +z +z +z +e +z +E +E +E +E +E +E +z +e +e +z +E +E +E +E +E +E +E +E +d +C +C +A +A +C +A +A +E +"} +(25,1,1) = {" +E +E +z +z +z +z +E +E +E +z +p +z +z +E +E +E +E +E +z +e +s +z +z +z +E +E +E +E +E +E +z +C +C +C +A +C +C +A +E +"} +(26,1,1) = {" +a +E +E +E +E +E +E +E +E +z +e +e +z +E +E +E +E +E +z +e +e +e +e +z +z +z +E +E +E +z +z +n +n +n +n +n +v +A +E +"} +(27,1,1) = {" +a +a +a +a +a +E +E +z +z +z +e +e +z +z +E +E +E +E +z +z +e +e +e +e +e +z +z +z +z +k +e +n +j +j +j +n +n +A +E +"} +(28,1,1) = {" +a +a +a +a +a +E +z +z +T +e +e +V +W +z +E +E +E +z +z +e +e +z +z +e +e +e +z +V +e +e +e +n +n +n +n +n +n +A +E +"} +(29,1,1) = {" +a +a +a +a +a +E +z +N +f +S +e +W +I +z +E +E +E +z +e +e +z +z +z +z +e +V +z +V +t +e +e +n +n +F +H +n +n +A +E +"} +(30,1,1) = {" +a +a +a +a +a +E +z +x +o +e +I +I +z +z +E +E +E +z +e +z +z +E +E +z +z +z +z +z +k +e +e +n +n +n +n +n +n +A +E +"} +(31,1,1) = {" +a +a +a +a +a +E +z +z +z +e +z +z +z +E +E +E +E +z +e +z +z +E +E +E +E +E +E +E +z +e +e +n +L +n +n +n +n +A +E +"} +(32,1,1) = {" +a +a +a +a +a +E +E +E +z +e +z +E +E +E +E +E +E +z +e +e +z +E +a +a +a +a +E +E +z +e +e +n +n +n +n +n +r +A +E +"} +(33,1,1) = {" +a +a +a +a +a +a +a +E +z +e +z +E +E +a +a +a +E +l +z +V +z +E +a +a +a +a +E +z +z +z +q +C +A +A +C +A +A +A +E +"} +(34,1,1) = {" +a +a +a +a +a +a +a +E +z +V +z +E +E +a +a +a +E +E +z +e +z +E +a +a +a +a +E +z +E +d +q +C +C +C +A +A +A +A +E +"} +(35,1,1) = {" +a +a +a +a +a +a +a +E +z +e +z +E +E +a +a +a +E +E +z +e +z +E +a +a +a +a +E +E +E +d +q +A +A +A +A +A +A +A +E +"} +(36,1,1) = {" +a +a +a +a +a +a +a +E +z +e +z +E +E +E +E +E +E +z +z +e +z +E +a +a +a +a +a +a +E +d +q +A +C +D +A +A +A +A +E +"} +(37,1,1) = {" +a +a +a +a +E +E +E +E +z +e +z +E +E +E +E +E +z +z +e +e +z +E +a +a +a +a +a +a +E +d +q +A +A +A +A +A +A +A +E +"} +(38,1,1) = {" +a +a +a +a +E +E +E +z +z +e +z +z +z +z +z +z +z +e +e +z +z +E +a +a +a +a +a +a +E +d +q +A +A +A +A +A +A +A +E +"} +(39,1,1) = {" +a +a +a +a +E +E +z +z +e +e +W +z +z +e +e +P +e +e +z +z +E +E +a +a +a +a +a +a +E +Q +q +q +q +q +q +q +q +q +E +"} +(40,1,1) = {" +a +a +a +a +E +E +z +I +p +e +e +e +e +e +z +z +z +z +z +E +E +a +a +a +a +a +a +a +E +E +E +E +E +E +E +E +E +E +E +"} +(41,1,1) = {" +a +a +a +a +E +z +z +W +e +V +e +W +z +z +z +E +E +E +E +E +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(42,1,1) = {" +a +a +a +a +E +z +W +K +e +I +I +z +z +E +E +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(43,1,1) = {" +a +a +a +a +E +c +z +z +z +z +z +z +E +E +E +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(44,1,1) = {" +a +a +a +a +E +E +E +E +E +E +E +E +E +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/code/__DEFINES/access.dm b/code/__DEFINES/access.dm index 41a26faffdc..7a1e91cd408 100644 --- a/code/__DEFINES/access.dm +++ b/code/__DEFINES/access.dm @@ -104,6 +104,8 @@ #define ACCESS_VAULT "vault" /// Access for the Quartermaster's personal quarters in mapping, as well as some other QM-related things. #define ACCESS_QM "qm" +/// Access for the bitrunning den +#define ACCESS_BIT_DEN "bit_den" /// General access for Science, allows for entry to the general hallways of Science, as well as the main lathe room. #define ACCESS_SCIENCE "science" @@ -281,6 +283,7 @@ ACCESS_ATMOSPHERICS, \ ACCESS_AUX_BASE, \ ACCESS_BAR, \ + ACCESS_BIT_DEN, \ ACCESS_BRIG, \ ACCESS_BRIG_ENTRANCE, \ ACCESS_CARGO, \ @@ -492,6 +495,7 @@ #define REGION_SUPPLY "Supply" /// Used to seed the accesses_by_region list in SSid_access. A list of all cargo regional accesses that are overseen by the HoP. #define REGION_ACCESS_SUPPLY list( \ + ACCESS_BIT_DEN, \ ACCESS_CARGO, \ ACCESS_MECH_MINING, \ ACCESS_MINERAL_STOREROOM, \ @@ -550,6 +554,7 @@ /obj/item/modular_computer/pda/heads/rd = list(REGION_COMMAND), \ /obj/item/modular_computer/pda/heads/captain = list(REGION_COMMAND), \ /obj/item/modular_computer/pda/cargo = list(REGION_SUPPLY), \ + /obj/item/modular_computer/pda/bitrunner = list(REGION_SUPPLY), \ /obj/item/modular_computer/pda/shaftminer = list(REGION_SUPPLY), \ /obj/item/modular_computer/pda/chaplain = list(REGION_GENERAL), \ /obj/item/modular_computer/pda/lawyer = list(REGION_GENERAL), \ diff --git a/code/__DEFINES/actions.dm b/code/__DEFINES/actions.dm index 066d2d60c1e..5bc2b161781 100644 --- a/code/__DEFINES/actions.dm +++ b/code/__DEFINES/actions.dm @@ -8,6 +8,8 @@ #define AB_CHECK_CONSCIOUS (1<<3) ///Action button checks if user is incapacitated #define AB_CHECK_INCAPACITATED (1<<4) +///Action button checks if user is jaunting +#define AB_CHECK_PHASED (1<<5) DEFINE_BITFIELD(check_flags, list( "CHECK IF HANDS BLOCKED" = AB_CHECK_HANDS_BLOCKED, @@ -15,6 +17,7 @@ DEFINE_BITFIELD(check_flags, list( "CHECK IF LYING DOWN" = AB_CHECK_LYING, "CHECK IF CONSCIOUS" = AB_CHECK_CONSCIOUS, "CHECK IF INCAPACITATED" = AB_CHECK_INCAPACITATED, + "CHECK IF TEMPORARILY INCORPOREAL" = AB_CHECK_PHASED, )) ///Action button triggered with right click diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index 443a51a7eb7..24ecf0a19f6 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -8,6 +8,11 @@ #define BB_FOOD_TARGET "bb_food_target" ///Path we should use next time we use the JPS movement datum #define BB_PATH_TO_USE "BB_path_to_use" +///How close a mob must be for us to select it as a target, if that is less than how far we can maintain it as a target +#define BB_AGGRO_RANGE "BB_aggro_range" + +///Turf we want a mob to move to +#define BB_TRAVEL_DESTINATION "BB_travel_destination" ///song instrument blackboard, set by instrument subtrees #define BB_SONG_INSTRUMENT "BB_SONG_INSTRUMENT" @@ -41,6 +46,8 @@ #define BB_BASIC_MOB_FLEE_TARGET "BB_basic_flee_target" #define BB_BASIC_MOB_FLEE_TARGET_HIDING_LOCATION "BB_basic_flee_target_hiding_location" #define BB_FLEE_TARGETTING_DATUM "flee_targetting_datum" +#define BB_BASIC_MOB_FLEE_DISTANCE "BB_basic_flee_distance" +#define DEFAULT_BASIC_FLEE_DISTANCE 9 /// Generic key for a non-specific targetted action #define BB_TARGETTED_ACTION "BB_targetted_action" diff --git a/code/__DEFINES/ai/monsters.dm b/code/__DEFINES/ai/monsters.dm index 927f3736832..be9a4be34cd 100644 --- a/code/__DEFINES/ai/monsters.dm +++ b/code/__DEFINES/ai/monsters.dm @@ -146,3 +146,10 @@ #define BB_RAPIDSEEDS_ABILITY "rapidseeds_ability" /// key holds the tray we will beam #define BB_BEAMABLE_HYDROPLANT_TARGET "beamable_hydroplant_target" + +/// Corpse we have consumed +#define BB_LEGION_CORPSE "legion_corpse" +/// Things our target recently said +#define BB_LEGION_RECENT_LINES "legion_recent_lines" +/// The creator of our legion skull +#define BB_LEGION_BROOD_CREATOR "legion_brood_creator" diff --git a/code/__DEFINES/alerts.dm b/code/__DEFINES/alerts.dm index 43ec8199d0f..6f25e61e7c5 100644 --- a/code/__DEFINES/alerts.dm +++ b/code/__DEFINES/alerts.dm @@ -61,3 +61,12 @@ #define ALERT_TEMPERATURE "temp" #define ALERT_TEMPERATURE_HOT "temphot" #define ALERT_TEMPERATURE_COLD "tempcold" + +/** Bitrunning */ +#define ALERT_BITRUNNER_CROWBAR "bitrunning_crowbar" +#define ALERT_BITRUNNER_COMPLETED "bitrunning_complete" +#define ALERT_BITRUNNER_INTEGRITY "bitrunning_integrity" +#define ALERT_BITRUNNER_SHUTDOWN "bitrunning_shutdown" +#define ALERT_BITRUNNER_RESET "bitrunning_reset" +#define ALERT_BITRUNNER_SPAWN_CYBERCOP "bitrunning_spawn_cybercop" +#define ALERT_BITRUNNER_THREAT "bitrunning_threat" diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index e74cd6a58bd..8ac421f8b0a 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -317,6 +317,7 @@ GLOBAL_LIST_INIT(human_invader_antagonists, list( #define ANTAG_GROUP_ASHWALKERS "Ash Walkers" #define ANTAG_GROUP_BIOHAZARDS "Biohazards" #define ANTAG_GROUP_CLOWNOPS "Clown Operatives" +#define ANTAG_GROUP_CYBERAUTH "Cyber Authority" #define ANTAG_GROUP_ERT "Emergency Response Team" #define ANTAG_GROUP_HORRORS "Eldritch Horrors" #define ANTAG_GROUP_LEVIATHANS "Spaceborne Leviathans" @@ -331,8 +332,8 @@ GLOBAL_LIST_INIT(human_invader_antagonists, list( #define ANTAG_GROUP_PARADOX "Spacetime Aberrations" -// If this flag is enabled the antagonist datum allows the antagonist to be inducted into a nuclear operative team. -#define FLAG_ANTAG_CAN_BE_INDUCTED (1 << 0) +// This flag disables certain checks that presume antagonist datums mean 'baddie'. +#define FLAG_FAKE_ANTAG (1 << 0) #define HUNTER_PACK_COPS "Spacepol Fugitive Hunters" #define HUNTER_PACK_RUSSIAN "Russian Fugitive Hunters" @@ -365,3 +366,5 @@ GLOBAL_LIST_INIT(human_invader_antagonists, list( #define BATON_CUFF 2 #define BATON_PROBE 3 #define BATON_MODES 4 + +#define FREEDOM_IMPLANT_CHARGES 4 diff --git a/code/__DEFINES/aquarium.dm b/code/__DEFINES/aquarium.dm deleted file mode 100644 index 6e0a39f5040..00000000000 --- a/code/__DEFINES/aquarium.dm +++ /dev/null @@ -1,44 +0,0 @@ -#define AQUARIUM_ANIMATION_FISH_SWIM "fish" -#define AQUARIUM_ANIMATION_FISH_DEAD "dead" - -#define AQUARIUM_PROPERTIES_PX_MIN "px_min" -#define AQUARIUM_PROPERTIES_PX_MAX "px_max" -#define AQUARIUM_PROPERTIES_PY_MIN "py_min" -#define AQUARIUM_PROPERTIES_PY_MAX "py_max" - -#define AQUARIUM_LAYER_MODE_BOTTOM "bottom" -#define AQUARIUM_LAYER_MODE_TOP "top" -#define AQUARIUM_LAYER_MODE_AUTO "auto" - -#define FISH_ALIVE "alive" -#define FISH_DEAD "dead" - -#define FISH_SIZE_TINY_MAX 30 -#define FISH_SIZE_SMALL_MAX 50 -#define FISH_SIZE_NORMAL_MAX 90 -#define FISH_SIZE_BULKY_MAX 130 - -#define FISH_GRIND_RESULTS_WEIGHT_DIVISOR 500 -#define FISH_FILLET_NUMBER_SIZE_DIVISOR 30 - -#define NEW_FISH_BREEDING_TIMEOUT_MULT 2 -#define NEW_FISH_LAST_FEEDING_MULT 0.5 - -#define MIN_AQUARIUM_TEMP T0C -#define MAX_AQUARIUM_TEMP (T0C + 100) -#define DEFAULT_AQUARIUM_TEMP (T0C + 24) - -#define FISH_RARITY_BASIC 1000 -#define FISH_RARITY_RARE 400 -#define FISH_RARITY_VERY_RARE 200 -#define FISH_RARITY_GOOD_LUCK_FINDING_THIS 1 -#define FISH_RARITY_NOPE 0 - -#define AQUARIUM_FLUID_FRESHWATER "Freshwater" -#define AQUARIUM_FLUID_SALTWATER "Saltwater" -#define AQUARIUM_FLUID_SULPHWATEVER "Sulfuric Water" -#define AQUARIUM_FLUID_AIR "Air" -#define AQUARIUM_FLUID_ANADROMOUS "Adaptive to both Freshwater and Saltwater" -#define AQUARIUM_FLUID_ANY_WATER "Adaptive to all kind of water" - -#define AQUARIUM_COMPANY "Aquatech Ltd." diff --git a/code/__DEFINES/atom_hud.dm b/code/__DEFINES/atom_hud.dm index b2623ecd988..b1ca16dc23c 100644 --- a/code/__DEFINES/atom_hud.dm +++ b/code/__DEFINES/atom_hud.dm @@ -92,6 +92,7 @@ #define SECHUD_ASSISTANT "hudassistant" #define SECHUD_ATMOSPHERIC_TECHNICIAN "hudatmospherictechnician" #define SECHUD_BARTENDER "hudbartender" +#define SECHUD_BITRUNNER "hudbitrunner" #define SECHUD_BOTANIST "hudbotanist" #define SECHUD_CAPTAIN "hudcaptain" #define SECHUD_CARGO_TECHNICIAN "hudcargotechnician" diff --git a/code/__DEFINES/bitrunning.dm b/code/__DEFINES/bitrunning.dm new file mode 100644 index 00000000000..343801c477e --- /dev/null +++ b/code/__DEFINES/bitrunning.dm @@ -0,0 +1,20 @@ +#define BITRUNNER_COST_NONE 0 +#define BITRUNNER_COST_LOW 1 +#define BITRUNNER_COST_MEDIUM 2 +#define BITRUNNER_COST_HIGH 3 +#define BITRUNNER_COST_EXTREME 20 + +#define BITRUNNER_REWARD_MIN 1 +#define BITRUNNER_REWARD_LOW 3 +#define BITRUNNER_REWARD_MEDIUM 4 +#define BITRUNNER_REWARD_HIGH 5 +#define BITRUNNER_REWARD_EXTREME 6 + +/// Blue in ui +#define BITRUNNER_DIFFICULTY_NONE 0 +/// Yellow +#define BITRUNNER_DIFFICULTY_LOW 1 +/// Orange +#define BITRUNNER_DIFFICULTY_MEDIUM 2 +/// Red with skull +#define BITRUNNER_DIFFICULTY_HIGH 3 diff --git a/code/__DEFINES/cargo.dm b/code/__DEFINES/cargo.dm index 747e48559f7..56d3896f0dc 100644 --- a/code/__DEFINES/cargo.dm +++ b/code/__DEFINES/cargo.dm @@ -40,6 +40,12 @@ /// The baseline unit for cargo crates. Adjusting this will change the cost of all in-game shuttles, crate export values, bounty rewards, and all supply pack import values, as they use this as their unit of measurement. #define CARGO_CRATE_VALUE 200 +/// The highest amount of orders you can have of one thing at any one time +#define CARGO_MAX_ORDER 50 + +/// Returned by /obj/docking_port/mobile/supply/proc/get_order_count to signify us going over the order limit +#define OVER_ORDER_LIMIT "GO AWAY" + /// Universal Scanner mode for export scanning. #define SCAN_EXPORTS 1 /// Universal Scanner mode for using the sales tagger. diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 25bd59bc8b5..b14fd514b85 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -93,6 +93,7 @@ #define COLOR_STRONG_MAGENTA "#B800B8" #define COLOR_PURPLE "#800080" #define COLOR_VIOLET "#B900F7" +#define COLOR_VOID_PURPLE "#53277E" #define COLOR_STRONG_VIOLET "#6927C5" #define COLOR_DARK_PURPLE "#551A8B" diff --git a/code/__DEFINES/computers.dm b/code/__DEFINES/computers.dm index 1349913c183..ba3294ae683 100644 --- a/code/__DEFINES/computers.dm +++ b/code/__DEFINES/computers.dm @@ -8,3 +8,6 @@ #define CATEGORY_CONSUMABLES "Consumables" #define CATEGORY_TOYS_DRONE "Toys & Drones" #define CATEGORY_PKA "PKAs" +#define CATEGORY_BEPIS "Bepis Tech" +#define CATEGORY_BITRUNNING_FLAIR "Misc" +#define CATEGORY_BITRUNNING_TECH "Tech" diff --git a/code/__DEFINES/cooldowns.dm b/code/__DEFINES/cooldowns.dm index f486e6a943b..63c1f2fd713 100644 --- a/code/__DEFINES/cooldowns.dm +++ b/code/__DEFINES/cooldowns.dm @@ -108,4 +108,6 @@ #define COOLDOWN_RESET(cd_source, cd_index) cd_source.cd_index = 0 +#define COOLDOWN_STARTED(cd_source, cd_index) (cd_source.cd_index != 0) + #define COOLDOWN_TIMELEFT(cd_source, cd_index) (max(0, cd_source.cd_index - world.time)) diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm index dc0293fb274..cd123e2e0b1 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm @@ -11,17 +11,19 @@ #define COMSIG_ATOM_EXAMINE "atom_examine" ///from base of atom/get_examine_name(): (/mob, list/overrides) #define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" -///from base of atom/examine(): (/mob, list/examine_text, can_see_inside) -#define COMSIG_ATOM_REAGENT_EXAMINE "atom_reagent_examine" - /// Stop the generic reagent examine text - #define STOP_GENERIC_REAGENT_EXAMINE (1<<0) -///from base of atom/examine_more(): (/mob) -#define COMSIG_ATOM_EXAMINE_MORE "atom_examine_more" //Positions for overrides list #define EXAMINE_POSITION_ARTICLE (1<<0) #define EXAMINE_POSITION_BEFORE (1<<1) //End positions #define COMPONENT_EXNAME_CHANGED (1<<0) +///from base of atom/examine(): (/mob, list/examine_text, can_see_inside) +#define COMSIG_ATOM_REAGENT_EXAMINE "atom_reagent_examine" + /// Stop the generic reagent examine text + #define STOP_GENERIC_REAGENT_EXAMINE (1<<0) +///from base of atom/examine_more(): (/mob, examine_list) +#define COMSIG_ATOM_EXAMINE_MORE "atom_examine_more" +/// from atom/examine_more(): (/atom/examining, examine_list) +#define COMSIG_MOB_EXAMINING_MORE "mob_examining_more" ///from base of [/atom/proc/update_appearance]: (updates) #define COMSIG_ATOM_UPDATE_APPEARANCE "atom_update_appearance" /// If returned from [COMSIG_ATOM_UPDATE_APPEARANCE] it prevents the atom from updating its name. diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm index d7063b0df5f..0c9523b9c20 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm @@ -17,6 +17,9 @@ #define COMSIG_ATOM_AFTER_SHUTTLE_MOVE "movable_after_shuttle_move" ///called on a movable (NOT living) when it starts pulling (atom/movable/pulled, state, force) #define COMSIG_ATOM_START_PULL "movable_start_pull" +/// called on /atom when something attempts to pass through it (atom/movable/source, atom/movable/passing, dir) +#define COMSIG_ATOM_TRIED_PASS "atom_tried_pass" + #define COMSIG_COMPONENT_PERMIT_PASSAGE (1 << 0) ///called on /living when someone starts pulling (atom/movable/pulled, state, force) #define COMSIG_LIVING_START_PULL "living_start_pull" ///called on /living when someone is pulled (mob/living/puller) diff --git a/code/__DEFINES/dcs/signals/signals_bitrunning.dm b/code/__DEFINES/dcs/signals/signals_bitrunning.dm new file mode 100644 index 00000000000..3d008449ee7 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_bitrunning.dm @@ -0,0 +1,31 @@ +/// from /obj/machinery/netpod/default_pry_open() : (mob/living/intruder) +#define COMSIG_BITRUNNER_CROWBAR_ALERT "bitrunner_crowbar" + +/// from /obj/effect/bitrunning/loot_signal: (points) +#define COMSIG_BITRUNNER_GOAL_POINT "bitrunner_goal_point" + +/// from /obj/machinery/quantum_server/on_goal_turf_entered(): (atom/entered, reward_points) +#define COMSIG_BITRUNNER_DOMAIN_COMPLETE "bitrunner_complete" + +/// from /obj/machinery/netpod/on_take_damage() +#define COMSIG_BITRUNNER_NETPOD_INTEGRITY "bitrunner_netpod_damage" + +/// from /obj/structure/hololadder and complete alert +#define COMSIG_BITRUNNER_SAFE_DISCONNECT "bitrunner_disconnect" + +/// from /obj/machinery/netpod/open_machine(), /obj/machinery/quantum_server, etc (obj/machinery/netpod) +#define COMSIG_BITRUNNER_SEVER_AVATAR "bitrunner_sever" + +/// from /obj/machinery/quantum_server/shutdown() : (mob/living) +#define COMSIG_BITRUNNER_SHUTDOWN_ALERT "bitrunner_shutdown" + +// Notifies the bitrunners +/// from /datum/antagonist/cyber_police/proc/notify() : +#define COMSIG_BITRUNNER_THREAT_CREATED "bitrunner_threat" + +// Informs the server to up the threat count +/// from event spawns: (mob/living) +#define COMSIG_BITRUNNER_SPAWN_GLITCH "bitrunner_spawn_glitch" + +/// from /obj/machinery/quantum_server/refreshParts(): (servo rating) +#define COMSIG_BITRUNNER_SERVER_UPGRADED "bitrunner_server_upgraded" diff --git a/code/__DEFINES/dcs/signals/signals_blob.dm b/code/__DEFINES/dcs/signals/signals_blob.dm new file mode 100644 index 00000000000..afd4737bdd9 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_blob.dm @@ -0,0 +1,4 @@ +/// Signal sent when a blob overmind picked a new strain (/mob/camera/blob/overmind, /datum/blobstrain/new_strain) +#define COMSIG_BLOB_SELECTED_STRAIN "blob_selected_strain" +/// Signal sent by a blob spore when it creates a zombie (/mob/living/basic/blob_minion/spore/spore, //mob/living/basic/blob_minion/zombie/zombie) +#define COMSIG_BLOB_ZOMBIFIED "blob_zombified" diff --git a/code/__DEFINES/dcs/signals/signals_fish.dm b/code/__DEFINES/dcs/signals/signals_fish.dm index 281c73adb52..90e580e9166 100644 --- a/code/__DEFINES/dcs/signals/signals_fish.dm +++ b/code/__DEFINES/dcs/signals/signals_fish.dm @@ -24,8 +24,10 @@ #define COMSIG_FISHING_ROD_CAST "fishing_rod_cast" #define FISHING_ROD_CAST_HANDLED (1 << 0) -/// Sent when fishing line is snapped -#define COMSIG_FISHING_LINE_SNAPPED "fishing_line_interrupted" +/// From /datum/fish_source/proc/dispense_reward(), not set if the reward is a dud: (reward, user) +#define COMSIG_FISHING_ROD_CAUGHT_FISH "fishing_rod_caught_fish" +/// From /obj/item/fishing_rod/proc/hook_item(): (reward, user) +#define COMSIG_FISHING_ROD_HOOKED_ITEM "fishing_rod_hooked_item" /// Sent when the challenge is to be interrupted: (reason) #define COMSIG_FISHING_SOURCE_INTERRUPT_CHALLENGE "fishing_spot_interrupt_challenge" 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 677a65a7be1..c96d21b7163 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -36,8 +36,10 @@ #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" -#define COMSIG_BODYPART_GAUZED "bodypart_gauzed" // from /obj/item/bodypart/proc/apply_gauze(/obj/item/stack/gauze) -#define COMSIG_BODYPART_GAUZE_DESTROYED "bodypart_degauzed" // from [/obj/item/bodypart/proc/seep_gauze] when it runs out of absorption +/// 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) +#define COMSIG_BODYPART_UNGAUZED "bodypart_ungauzed" /// Called from bodypart changing owner, which could be on attach or detachment. Either argument can be null. (mob/living/carbon/new_owner, mob/living/carbon/old_owner) #define COMSIG_BODYPART_CHANGED_OWNER "bodypart_changed_owner" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index d4c3c659c68..7dffe24331a 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -7,6 +7,8 @@ #define COMSIG_MOB_LOGIN "mob_login" ///from base of /mob/Logout(): () #define COMSIG_MOB_LOGOUT "mob_logout" +///from base of /mob/mind_initialize +#define COMSIG_MOB_MIND_INITIALIZED "mob_mind_inited" ///from base of mob/set_stat(): (new_stat, old_stat) #define COMSIG_MOB_STATCHANGE "mob_statchange" ///from base of mob/reagent_check(): (datum/reagent/chem, seconds_per_tick, times_fired) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_spawner.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_spawner.dm index a5f66788b86..6ff8b1e8d61 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_spawner.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_spawner.dm @@ -1,3 +1,6 @@ // signals for use by mob spawners /// called when a spawner spawns a mob #define COMSIG_SPAWNER_SPAWNED "spawner_spawned" + +/// called when a ghost clicks a spawner role: (mob/living) +#define COMSIG_GHOSTROLE_SPAWNED "ghostrole_spawned" diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index 19286859e9e..4521360d039 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -33,6 +33,8 @@ #define COMSIG_MACHINERY_STOP_PROCESSING_AIR "stop_processing_air" ///from /obj/machinery/RefreshParts: () #define COMSIG_MACHINERY_REFRESH_PARTS "machine_refresh_parts" +///from /obj/machinery/default_change_direction_wrench: (mob/user, obj/item/wrench) +#define COMSIG_MACHINERY_DEFAULT_ROTATE_WRENCH "machinery_default_rotate_wrench" ///from /obj/machinery/can_interact(mob/user): Called on user when attempting to interact with a machine (obj/machinery/machine) #define COMSIG_TRY_USE_MACHINE "try_use_machine" @@ -58,9 +60,9 @@ #define COMSIG_SUPERMATTER_DELAM_ALARM "sm_delam_alarm" -// /obj/machinery/atmospherics/components/unary/cryo_cell signals +// /obj/machinery/cryo_cell signals -/// from /obj/machinery/atmospherics/components/unary/cryo_cell/set_on(bool): (on) +/// from /obj/machinery/cryo_cell/set_on(bool): (on) #define COMSIG_CRYO_SET_ON "cryo_set_on" /// from /obj/proc/unfreeze() diff --git a/code/__DEFINES/economy.dm b/code/__DEFINES/economy.dm index 7e12f3904b6..9d6841b56fd 100644 --- a/code/__DEFINES/economy.dm +++ b/code/__DEFINES/economy.dm @@ -73,3 +73,30 @@ #define PAYMENT_CLINICAL "clinical" #define PAYMENT_FRIENDLY "friendly" #define PAYMENT_ANGRY "angry" + +#define MARKET_TREND_UPWARD 1 +#define MARKET_TREND_DOWNWARD -1 +#define MARKET_TREND_STABLE 0 + +#define MARKET_EVENT_PROBABILITY 1 //Probability of a market event firing, in percent. Fires once per material, every 20 seconds. + +#define MARKET_PROFIT_MODIFIER 0.8 //We don't make every sale a 1-1 of the actual buy price value, like with real life taxes and to encourage more smart trades + +/// Create quantity subtypes for stock market datums. +#define MARKET_QUANTITY_HELPERS(path) ##path/one {\ + amount = 1; \ +} \ +##path/five {\ + amount = 5; \ +} \ +##path/ten {\ + amount = 10; \ +} \ +##path/twenty_five {\ + amount = 25; \ +} \ +##path/fifty {\ + amount = 50; \ +} + + diff --git a/code/__DEFINES/experisci.dm b/code/__DEFINES/experisci.dm index 9130e0ae565..c74290ff5f7 100644 --- a/code/__DEFINES/experisci.dm +++ b/code/__DEFINES/experisci.dm @@ -26,6 +26,8 @@ /// Destructive experiments which will destroy the sample #define EXPERIMENT_TRAIT_DESTRUCTIVE (1 << 0) +/// Used by scanning experiments: instead of storing refs or be a number, the list for scanned atoms is used as typecache +#define EXPERIMENT_TRAIT_TYPECACHE (1 << 1) /// Will always attempt to action every experiment eligible with a single input, /// no experiment selection required @@ -33,3 +35,7 @@ /// Experiment handlers with this flag will not automatically connect to the first techweb they find /// on initialization #define EXPERIMENT_CONFIG_NO_AUTOCONNECT (1 << 1) +/// Experiment handlers with this flag won't pester the user of objects not pertinent to the test or if no experiment is selected +#define EXPERIMENT_CONFIG_SILENT_FAIL (1 << 2) +/// Experiment handlers with this flag will bypass any delay when trying to scan something +#define EXPERIMENT_CONFIG_IMMEDIATE_ACTION (1 << 3) diff --git a/code/__DEFINES/fish.dm b/code/__DEFINES/fish.dm new file mode 100644 index 00000000000..89b7963d91d --- /dev/null +++ b/code/__DEFINES/fish.dm @@ -0,0 +1,136 @@ +/// Use in fish tables to denote miss chance. +#define FISHING_DUD "dud" + +// Baseline fishing difficulty levels +#define FISHING_DEFAULT_DIFFICULTY 15 + +/// Difficulty modifier when bait is fish's favorite +#define FAV_BAIT_DIFFICULTY_MOD -5 +/// Difficulty modifier when bait is fish's disliked +#define DISLIKED_BAIT_DIFFICULTY_MOD 15 +/// Difficulty modifier when our fisherman has the trait TRAIT_SETTLER +#define SETTLER_DIFFICULTY_MOD -5 + +#define FISH_TRAIT_MINOR_DIFFICULTY_BOOST 5 + +// These define how the fish will behave in the minigame +#define FISH_AI_DUMB "dumb" +#define FISH_AI_ZIPPY "zippy" +#define FISH_AI_SLOW "slow" + +#define ADDITIVE_FISHING_MOD "additive" +#define MULTIPLICATIVE_FISHING_MOD "multiplicative" + +// These defines are intended for use to interact with fishing hooks when going +// through the fishing rod, and not the hook itself. They could probably be +// handled differently, but for now that's how they work. It's grounds for +// a future refactor, however. +/// Fishing hook trait that signifies that it's shiny. Useful for fishes +/// that care about shiner hooks more. +#define FISHING_HOOK_SHINY (1 << 0) +/// Fishing hook trait that lessens the bounce from hitting the edges of the minigame bar. +#define FISHING_HOOK_WEIGHTED (1 << 1) +///See FISHING_MINIGAME_RULE_BIDIRECTIONAL +#define FISHING_HOOK_BIDIRECTIONAL (1 << 2) +///Prevents the user from losing the game by letting the fish get away. +#define FISHING_HOOK_NO_ESCAPE (1 << 3) +///Limits the completion loss of the minigame when the fsh is not on the bait area. +#define FISHING_HOOK_ENSNARE (1 << 4) +///Automatically kills the fish after a while, at the cost of killing it. +#define FISHING_HOOK_KILL (1 << 5) + +///Reduces the difficulty of the minigame +#define FISHING_LINE_CLOAKED (1 << 0) +///Required to cast a line on lava. +#define FISHING_LINE_REINFORCED (1 << 1) +/// Much like FISHING_HOOK_ENSNARE but for the fishing line. +#define FISHING_LINE_BOUNCY (1 << 2) + +///Keeps the bait from falling from gravity, instead allowing the player to move the bait down with right click. +#define FISHING_MINIGAME_RULE_BIDIRECTIONAL (1 << 2) +///Prevents the player from losing the minigame when the completion reaches 0 +#define FISHING_MINIGAME_RULE_NO_ESCAPE (1 << 3) +///Automatically kills the fish after a while, at the cost of killing it +#define FISHING_MINIGAME_RULE_KILL (1 << 4) +///Prevents the fishing skill from having an effect on the minigame and experience from being awarded +#define FISHING_MINIGAME_RULE_NO_EXP (1 << 5) +///If enabled, the minigame will occasionally screw around and invert the velocity of the bait +#define FISHING_MINIGAME_RULE_ANTIGRAV (1 << 6) +///Will filp the minigame hud for the duration of the effect +#define FISHING_MINIGAME_RULE_FLIP (1 << 7) + +///all the effects that are active and will last for a few seconds before triggering a cooldown +#define FISHING_MINIGAME_ACTIVE_EFFECTS (FISHING_MINIGAME_RULE_ANTIGRAV|FISHING_MINIGAME_RULE_FLIP) + +/// The default additive value for fishing hook catch weight modifiers. +#define FISHING_DEFAULT_HOOK_BONUS_ADDITIVE 0 +/// The default multiplicative value for fishing hook catch weight modifiers. +#define FISHING_DEFAULT_HOOK_BONUS_MULTIPLICATIVE 1 + +//Fish icon defines, used by fishing minigame +#define FISH_ICON_DEF "fish" +#define FISH_ICON_HOSTILE "hostile" +#define FISH_ICON_STAR "star" +#define FISH_ICON_CHUNKY "chunky" +#define FISH_ICON_SLIME "slime" +#define FISH_ICON_COIN "coin" +#define FISH_ICON_GEM "gem" +#define FISH_ICON_CRAB "crab" +#define FISH_ICON_JELLYFISH "jellyfish" +#define FISH_ICON_BONE "bone" + +#define AQUARIUM_ANIMATION_FISH_SWIM "fish" +#define AQUARIUM_ANIMATION_FISH_DEAD "dead" + +#define AQUARIUM_PROPERTIES_PX_MIN "px_min" +#define AQUARIUM_PROPERTIES_PX_MAX "px_max" +#define AQUARIUM_PROPERTIES_PY_MIN "py_min" +#define AQUARIUM_PROPERTIES_PY_MAX "py_max" + +#define AQUARIUM_LAYER_MODE_BOTTOM "bottom" +#define AQUARIUM_LAYER_MODE_TOP "top" +#define AQUARIUM_LAYER_MODE_AUTO "auto" + +#define FISH_ALIVE "alive" +#define FISH_DEAD "dead" + +///Fish size thresholds for w_class. +#define FISH_SIZE_TINY_MAX 30 +#define FISH_SIZE_SMALL_MAX 50 +#define FISH_SIZE_NORMAL_MAX 90 +#define FISH_SIZE_BULKY_MAX 130 + +///The coefficient for maximum weight/size divergence relative to the averages. +#define MAX_FISH_DEVIATION_COEFF 2.5 + +///The volume of the grind results is multiplied by the fish' weight and divided by this. +#define FISH_GRIND_RESULTS_WEIGHT_DIVISOR 500 +///The number of fillets is multiplied by the fish' size and divided by this. +#define FISH_FILLET_NUMBER_SIZE_DIVISOR 30 + +///The breeding timeout for newly instantiated fish is multiplied by this. +#define NEW_FISH_BREEDING_TIMEOUT_MULT 2 +///The last feeding timestamp of newly instantiated fish is multiplied by this: ergo, they spawn 50% hungry. +#define NEW_FISH_LAST_FEEDING_MULT 0.5 + +#define MIN_AQUARIUM_TEMP T0C +#define MAX_AQUARIUM_TEMP (T0C + 100) +#define DEFAULT_AQUARIUM_TEMP (T0C + 24) + +///How likely one's to find a given fish from random fish cases. +#define FISH_RARITY_BASIC 1000 +#define FISH_RARITY_RARE 400 +#define FISH_RARITY_VERY_RARE 200 +#define FISH_RARITY_GOOD_LUCK_FINDING_THIS 5 +#define FISH_RARITY_NOPE 0 + +///Aquarium fluid variables. The fish' required fluid has to match this, or it'll slowly die. +#define AQUARIUM_FLUID_FRESHWATER "Freshwater" +#define AQUARIUM_FLUID_SALTWATER "Saltwater" +#define AQUARIUM_FLUID_SULPHWATEVER "Sulfuric Water" +#define AQUARIUM_FLUID_AIR "Air" +#define AQUARIUM_FLUID_ANADROMOUS "Adaptive to both Freshwater and Saltwater" +#define AQUARIUM_FLUID_ANY_WATER "Adaptive to all kind of water" + +///Fluff. The name of the aquarium company shown in the fish catalog +#define AQUARIUM_COMPANY "Aquatech Ltd." diff --git a/code/__DEFINES/fishing.dm b/code/__DEFINES/fishing.dm deleted file mode 100644 index dc73623f27c..00000000000 --- a/code/__DEFINES/fishing.dm +++ /dev/null @@ -1,62 +0,0 @@ -/// Use in fish tables to denote miss chance. -#define FISHING_DUD "dud" - -// Baseline fishing difficulty levels -#define FISHING_DEFAULT_DIFFICULTY 15 - -/// Difficulty modifier when bait is fish's favorite -#define FAV_BAIT_DIFFICULTY_MOD -5 -/// Difficulty modifier when bait is fish's disliked -#define DISLIKED_BAIT_DIFFICULTY_MOD 15 -/// Difficulty modifier when our fisherman has the trait TRAIT_SETTLER -#define SETTLER_DIFFICULTY_MOD -5 - - -#define FISH_TRAIT_MINOR_DIFFICULTY_BOOST 5 - -// These define how the fish will behave in the minigame -#define FISH_AI_DUMB "dumb" -#define FISH_AI_ZIPPY "zippy" -#define FISH_AI_SLOW "slow" - -#define ADDITIVE_FISHING_MOD "additive" -#define MULTIPLICATIVE_FISHING_MOD "multiplicative" - -// These defines are intended for use to interact with fishing hooks when going -// through the fishing rod, and not the hook itself. They could probably be -// handled differently, but for now that's how they work. It's grounds for -// a future refactor, however. -/// Fishing hook trait that signifies that it's shiny. Useful for fishes -/// that care about shiner hooks more. -#define FISHING_HOOK_SHINY (1 << 0) -/// Fishing hook trait that's used to make the bait more weighted, for the -/// fishing minigame itself. -#define FISHING_HOOK_WEIGHTED (1 << 1) -/** - * During the fishing minigame, it stops the bait from being pulled down by gravity, - * while also allowing the player to move it down with right-click. - */ -#define FISHING_HOOK_BIDIRECTIONAL (1 << 2) -///Prevents the user from losing the game by letting the fish get away. -#define FISHING_HOOK_NO_ESCAPE (1 << 3) -///Limits the completion loss of the minigame when the fsh is not on the bait area. -#define FISHING_HOOK_ENSNARE (1 << 4) -///Slowly damages the fish, until it dies, then it's victory. -#define FISHING_HOOK_KILL (1 << 5) - -///Reduces the difficulty of the minigame -#define FISHING_LINE_CLOAKED (1 << 0) -///Required to cast a line on lava. -#define FISHING_LINE_REINFORCED (1 << 1) -/// Much like FISHING_HOOK_ENSNARE but for the reel. -#define FISHING_LINE_BOUNCY (1 << 2) - -#define FISHING_MINIGAME_RULE_BIDIRECTIONAL (1 << 2) -#define FISHING_MINIGAME_RULE_NO_ESCAPE (1 << 3) -#define FISHING_MINIGAME_RULE_KILL (1 << 4) -#define FISHING_MINIGAME_RULE_NO_EXP (1 << 5) - -/// The default additive value for fishing hook catch weight modifiers. -#define FISHING_DEFAULT_HOOK_BONUS_ADDITIVE 0 -/// The default multiplicative value for fishing hook catch weight modifiers. -#define FISHING_DEFAULT_HOOK_BONUS_MULTIPLICATIVE 1 diff --git a/code/__DEFINES/icon_smoothing.dm b/code/__DEFINES/icon_smoothing.dm index bc3c2011ae2..830daef563d 100644 --- a/code/__DEFINES/icon_smoothing.dm +++ b/code/__DEFINES/icon_smoothing.dm @@ -27,6 +27,27 @@ DEFINE_BITFIELD(smoothing_flags, list( "SMOOTH_BORDER_OBJECT" = SMOOTH_BORDER_OBJECT, )) +/// Components of a smoothing junction +/// Redefinitions of the diagonal directions so they can be stored in one var without conflicts +#define NORTH_JUNCTION NORTH //(1<<0) +#define SOUTH_JUNCTION SOUTH //(1<<1) +#define EAST_JUNCTION EAST //(1<<2) +#define WEST_JUNCTION WEST //(1<<3) +#define NORTHEAST_JUNCTION (1<<4) +#define SOUTHEAST_JUNCTION (1<<5) +#define SOUTHWEST_JUNCTION (1<<6) +#define NORTHWEST_JUNCTION (1<<7) + +DEFINE_BITFIELD(smoothing_junction, list( + "NORTH_JUNCTION" = NORTH_JUNCTION, + "SOUTH_JUNCTION" = SOUTH_JUNCTION, + "EAST_JUNCTION" = EAST_JUNCTION, + "WEST_JUNCTION" = WEST_JUNCTION, + "NORTHEAST_JUNCTION" = NORTHEAST_JUNCTION, + "SOUTHEAST_JUNCTION" = SOUTHEAST_JUNCTION, + "SOUTHWEST_JUNCTION" = SOUTHWEST_JUNCTION, + "NORTHWEST_JUNCTION" = NORTHWEST_JUNCTION, +)) /*smoothing macros*/ diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index c76276c019d..f2f511c791b 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -170,6 +170,7 @@ #define MASKCOVERSMOUTH (1<<3) // on other items, these are just for mask/head #define HEADCOVERSMOUTH (1<<4) #define PEPPERPROOF (1<<5) //protects against pepperspray +#define EARS_COVERED (1<<6) #define TINT_DARKENED 2 //Threshold of tint level to apply weld mask overlay #define TINT_BLIND 3 //Threshold of tint level to obscure vision fully diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index a52d2d809e6..e909c23bb90 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -278,8 +278,6 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list( #define isholoeffect(O) (istype(O, /obj/effect/holodeck_effect)) -#define isblobmonster(O) (istype(O, /mob/living/simple_animal/hostile/blob)) - #define isshuttleturf(T) (!isnull(T.depth_to_find_baseturf(/turf/baseturf_skipover/shuttle))) #define isProbablyWallMounted(O) (O.pixel_x > 20 || O.pixel_x < -20 || O.pixel_y > 20 || O.pixel_y < -20) diff --git a/code/__DEFINES/jobs.dm b/code/__DEFINES/jobs.dm index 44e67226604..7feca0782dc 100644 --- a/code/__DEFINES/jobs.dm +++ b/code/__DEFINES/jobs.dm @@ -81,6 +81,7 @@ #define JOB_QUARTERMASTER "Quartermaster" #define JOB_CARGO_TECHNICIAN "Cargo Technician" #define JOB_SHAFT_MINER "Shaft Miner" +#define JOB_BITRUNNER "Bitrunner" #define JOB_CUSTOMS_AGENT "Customs Agent" // SKYRAT EDIT ADDITION //Service #define JOB_BARTENDER "Bartender" @@ -162,23 +163,23 @@ #define JOB_DISPLAY_ORDER_QUARTERMASTER 19 #define JOB_DISPLAY_ORDER_CARGO_TECHNICIAN 20 #define JOB_DISPLAY_ORDER_SHAFT_MINER 21 -#define JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER 22 -#define JOB_DISPLAY_ORDER_MEDICAL_DOCTOR 23 -#define JOB_DISPLAY_ORDER_PARAMEDIC 24 -#define JOB_DISPLAY_ORDER_CHEMIST 25 -#define JOB_DISPLAY_ORDER_VIROLOGIST 26 -#define JOB_DISPLAY_ORDER_CORONER 27 -#define JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR 28 -#define JOB_DISPLAY_ORDER_SCIENTIST 29 -#define JOB_DISPLAY_ORDER_ROBOTICIST 30 -#define JOB_DISPLAY_ORDER_GENETICIST 31 -#define JOB_DISPLAY_ORDER_EXP_CORPS 32 //SKYRAT EDIT ADDITON +#define JOB_DISPLAY_ORDER_BITRUNNER 22 +#define JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER 23 +#define JOB_DISPLAY_ORDER_MEDICAL_DOCTOR 24 +#define JOB_DISPLAY_ORDER_PARAMEDIC 25 +#define JOB_DISPLAY_ORDER_CHEMIST 26 +#define JOB_DISPLAY_ORDER_VIROLOGIST 27 +#define JOB_DISPLAY_ORDER_CORONER 28 +#define JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR 29 +#define JOB_DISPLAY_ORDER_SCIENTIST 30 +#define JOB_DISPLAY_ORDER_ROBOTICIST 31 +#define JOB_DISPLAY_ORDER_GENETICIST 32 #define JOB_DISPLAY_ORDER_HEAD_OF_SECURITY 33 #define JOB_DISPLAY_ORDER_WARDEN 34 #define JOB_DISPLAY_ORDER_DETECTIVE 35 #define JOB_DISPLAY_ORDER_SECURITY_OFFICER 36 -#define JOB_DISPLAY_ORDER_SECURITY_MEDIC 37 //SKYRAT EDIT ADDITON -#define JOB_DISPLAY_ORDER_PRISONER 38 +#define JOB_DISPLAY_ORDER_PRISONER 37 +#define JOB_DISPLAY_ORDER_SECURITY_MEDIC 38 //SKYRAT EDIT ADDITON #define JOB_DISPLAY_ORDER_CORRECTIONS_OFFICER 39 //SKYRAT EDIT ADDITON #define JOB_DISPLAY_ORDER_NANOTRASEN_CONSULTANT 40 //SKYRAT EDIT ADDITON #define JOB_DISPLAY_ORDER_BLUESHIELD 41 //SKYRAT EDIT ADDITON @@ -187,6 +188,7 @@ #define JOB_DISPLAY_ORDER_BOUNCER 44 //SKYRAT EDIT ADDITION #define JOB_DISPLAY_ORDER_ENGINEER_GUARD 45 //SKYRAT EDIT ADDITION #define JOB_DISPLAY_ORDER_CUSTOMS_AGENT 46 //SKYRAT EDIT ADDITION +#define JOB_DISPLAY_ORDER_EXP_CORPS 47 //SKYRAT EDIT ADDITON #define DEPARTMENT_UNASSIGNED "No Department" diff --git a/code/__DEFINES/magic.dm b/code/__DEFINES/magic.dm index 34ec4b6659b..ecc470c04e9 100644 --- a/code/__DEFINES/magic.dm +++ b/code/__DEFINES/magic.dm @@ -50,8 +50,7 @@ /// Whether the spell can be cast by mobs who are brains / mmis. /// When applying, bear in mind most spells will not function for brains out of the box. #define SPELL_CASTABLE_AS_BRAIN (1 << 2) -/// Whether the spell can be cast while phased, such as blood crawling, ethereal jaunting or using rod form. -#define SPELL_CASTABLE_WHILE_PHASED (1 << 3) + /// Whether the spell can be cast while the user has antimagic on them that corresponds to the spell's own antimagic flags. #define SPELL_REQUIRES_NO_ANTIMAGIC (1 << 4) /// Whether the spell requires being on the station z-level to be cast. @@ -66,7 +65,6 @@ DEFINE_BITFIELD(spell_requirements, list( "SPELL_CASTABLE_AS_BRAIN" = SPELL_CASTABLE_AS_BRAIN, - "SPELL_CASTABLE_WHILE_PHASED" = SPELL_CASTABLE_WHILE_PHASED, "SPELL_CASTABLE_WITHOUT_INVOCATION" = SPELL_CASTABLE_WITHOUT_INVOCATION, "SPELL_REQUIRES_HUMAN" = SPELL_REQUIRES_HUMAN, "SPELL_REQUIRES_MIME_VOW" = SPELL_REQUIRES_MIME_VOW, diff --git a/code/__DEFINES/materials.dm b/code/__DEFINES/materials.dm index 08b88324826..5fc5cc08ea2 100644 --- a/code/__DEFINES/materials.dm +++ b/code/__DEFINES/materials.dm @@ -75,3 +75,13 @@ #define MATERIAL_SLOWDOWN_PLASTEEL (0.05) /// The slowdown value of one [SHEET_MATERIAL_AMOUNT] of alien alloy. #define MATERIAL_SLOWDOWN_ALIEN_ALLOY (0.1) + +//Stock market stock values. +/// How much quantity of a material stock exists for common materials like iron & glass. +#define MATERIAL_QUANTITY_COMMON 25000 +/// How much quantity of a material stock exists for uncommon materials like silver & titanium. +#define MATERIAL_QUANTITY_UNCOMMON 10000 +/// How much quantity of a material stock exists for rare materials like gold, uranium, & diamond. +#define MATERIAL_QUANTITY_RARE 2500 +/// How much quantity of a material stock exists for exotic materials like diamond & bluespace crystals. +#define MATERIAL_QUANTITY_EXOTIC 500 diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm index eb1b2ecce51..1260e3daf03 100644 --- a/code/__DEFINES/maths.dm +++ b/code/__DEFINES/maths.dm @@ -254,3 +254,6 @@ /// Returns a random decimal between x and y. #define RANDOM_DECIMAL(x, y) LERP((x), (y), rand()) + +#define SI_COEFFICIENT "coefficient" +#define SI_UNIT "unit" diff --git a/code/__DEFINES/mood.dm b/code/__DEFINES/mood.dm new file mode 100644 index 00000000000..161f253b04c --- /dev/null +++ b/code/__DEFINES/mood.dm @@ -0,0 +1 @@ +#define MOOD_CATEGORY_LEGION_CORE "regenerative core" diff --git a/code/__DEFINES/robots.dm b/code/__DEFINES/robots.dm index 7f7961e05be..4d32c136331 100644 --- a/code/__DEFINES/robots.dm +++ b/code/__DEFINES/robots.dm @@ -1,4 +1,4 @@ -/** AI defines */ +// AI defines #define DEFAULT_AI_LAWID "default" #define LAW_ZEROTH "zeroth" @@ -27,7 +27,10 @@ ///Malfunctioning AI hijacking mecha #define AI_MECH_HACK 3 -/** Cyborg defines */ +// Cyborg defines + +/// If an item does this or more throwing damage it will slow a borg down on hit +#define CYBORG_THROW_SLOWDOWN_THRESHOLD 10 /// Special value to reset cyborg's lamp_cooldown #define BORG_LAMP_CD_RESET -1 diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 32a5e3b8fda..cd76af78f6c 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -27,6 +27,7 @@ #define ROLE_BLOB "Blob" #define ROLE_BLOB_INFECTION "Blob Infection" #define ROLE_CHANGELING_MIDROUND "Changeling (Midround)" +#define ROLE_CYBER_POLICE "Cyber Police" #define ROLE_FUGITIVE "Fugitive" #define ROLE_LONE_OPERATIVE "Lone Operative" #define ROLE_MALF_MIDROUND "Malf AI (Midround)" @@ -52,69 +53,69 @@ // Latejoin roles #define ROLE_HERETIC_SMUGGLER "Heretic Smuggler" #define ROLE_PROVOCATEUR "Provocateur" -#define ROLE_SYNDICATE_INFILTRATOR "Syndicate Infiltrator" #define ROLE_STOWAWAY_CHANGELING "Stowaway Changeling" +#define ROLE_SYNDICATE_INFILTRATOR "Syndicate Infiltrator" // Other roles -#define ROLE_SYNDICATE "Syndicate" -#define ROLE_REV "Revolutionary" -#define ROLE_PAI "pAI" -#define ROLE_MONKEY_HELMET "Monkey Mind Magnification Helmet" -#define ROLE_REVENANT "Revenant" -#define ROLE_BRAINWASHED "Brainwashed Victim" -#define ROLE_HYPNOTIZED "Hypnotized Victim" -#define ROLE_OVERTHROW "Syndicate Mutineer" //Role removed, left here for safety. -#define ROLE_HIVE "Hivemind Host" //Role removed, left here for safety. -#define ROLE_SENTIENCE "Sentience Potion Spawn" -#define ROLE_PYROCLASTIC_SLIME "Pyroclastic Anomaly Slime" #define ROLE_ANOMALY_GHOST "Ectoplasmic Anomaly Ghost" -#define ROLE_MIND_TRANSFER "Mind Transfer Potion" -#define ROLE_LAZARUS_GOOD "Friendly Revived Mob" -#define ROLE_LAZARUS_BAD "Slaved Revived Mob" -#define ROLE_POSIBRAIN "Posibrain" +#define ROLE_BRAINWASHED "Brainwashed Victim" +#define ROLE_DEATHSQUAD "Deathsquad" #define ROLE_DRONE "Drone" #define ROLE_EMAGGED_BOT "Malfunctioning Bot" -#define ROLE_DEATHSQUAD "Deathsquad" +#define ROLE_HIVE "Hivemind Host" //Role removed, left here for safety. +#define ROLE_HYPNOTIZED "Hypnotized Victim" #define ROLE_LAVALAND "Lavaland" +#define ROLE_LAZARUS_BAD "Slaved Revived Mob" +#define ROLE_LAZARUS_GOOD "Friendly Revived Mob" +#define ROLE_MIND_TRANSFER "Mind Transfer Potion" +#define ROLE_MONKEY_HELMET "Monkey Mind Magnification Helmet" +#define ROLE_OVERTHROW "Syndicate Mutineer" //Role removed, left here for safety. +#define ROLE_PAI "pAI" +#define ROLE_POSIBRAIN "Posibrain" +#define ROLE_PYROCLASTIC_SLIME "Pyroclastic Anomaly Slime" +#define ROLE_REV "Revolutionary" +#define ROLE_REVENANT "Revenant" +#define ROLE_SENTIENCE "Sentience Potion Spawn" +#define ROLE_SYNDICATE "Syndicate" -#define ROLE_POSITRONIC_BRAIN "Positronic Brain" -#define ROLE_FREE_GOLEM "Free Golem" -#define ROLE_SERVANT_GOLEM "Servant Golem" -#define ROLE_NUCLEAR_OPERATIVE "Nuclear Operative" #define ROLE_CLOWN_OPERATIVE "Clown Operative" -#define ROLE_WIZARD_APPRENTICE "apprentice" -#define ROLE_SLAUGHTER_DEMON "Slaughter Demon" +#define ROLE_FREE_GOLEM "Free Golem" #define ROLE_MORPH "Morph" +#define ROLE_NUCLEAR_OPERATIVE "Nuclear Operative" +#define ROLE_POSITRONIC_BRAIN "Positronic Brain" #define ROLE_SANTA "Santa" +#define ROLE_SERVANT_GOLEM "Servant Golem" +#define ROLE_SLAUGHTER_DEMON "Slaughter Demon" +#define ROLE_WIZARD_APPRENTICE "apprentice" //Spawner roles -#define ROLE_GHOST_ROLE "Ghost Role" +#define ROLE_ANCIENT_CREW "Ancient Crew" +#define ROLE_ASHWALKER "Ash Walker" +#define ROLE_BATTLECRUISER_CAPTAIN "Battlecruiser Captain" +#define ROLE_BATTLECRUISER_CREW "Battlecruiser Crew" +#define ROLE_BEACH_BUM "Beach Bum" +#define ROLE_BOT "Bot" +#define ROLE_DERELICT_DRONE "Derelict Drone" +#define ROLE_ESCAPED_PRISONER "Escaped Prisoner" #define ROLE_EXILE "Exile" #define ROLE_FUGITIVE_HUNTER "Fugitive Hunter" -#define ROLE_ESCAPED_PRISONER "Escaped Prisoner" -#define ROLE_LIFEBRINGER "Lifebringer" -#define ROLE_ASHWALKER "Ash Walker" -#define ROLE_LAVALAND_SYNDICATE "Lavaland Syndicate" +#define ROLE_GHOST_ROLE "Ghost Role" #define ROLE_HERMIT "Hermit" -#define ROLE_BEACH_BUM "Beach Bum" #define ROLE_HOTEL_STAFF "Hotel Staff" +#define ROLE_LAVALAND_SYNDICATE "Lavaland Syndicate" +#define ROLE_LIFEBRINGER "Lifebringer" +#define ROLE_MAINTENANCE_DRONE "Maintenance Drone" +#define ROLE_SKELETON "Skeleton" +#define ROLE_SPACE_BAR_PATRON "Space Bar Patron" +#define ROLE_SPACE_BARTENDER "Space Bartender" +#define ROLE_SPACE_DOCTOR "Space Doctor" +#define ROLE_SPACE_PIRATE "Space Pirate" #define ROLE_SPACE_SYNDICATE "Space Syndicate" #define ROLE_SYNDICATE_CYBERSUN "Cybersun Space Syndicate" //Ghost role syndi from Forgottenship ruin #define ROLE_SYNDICATE_CYBERSUN_CAPTAIN "Cybersun Space Syndicate Captain" //Forgottenship captain syndie -#define ROLE_SPACE_PIRATE "Space Pirate" -#define ROLE_ANCIENT_CREW "Ancient Crew" -#define ROLE_SPACE_DOCTOR "Space Doctor" -#define ROLE_SPACE_BARTENDER "Space Bartender" -#define ROLE_SPACE_BAR_PATRON "Space Bar Patron" -#define ROLE_SKELETON "Skeleton" -#define ROLE_ZOMBIE "Zombie" -#define ROLE_MAINTENANCE_DRONE "Maintenance Drone" -#define ROLE_DERELICT_DRONE "Derelict Drone" #define ROLE_SYNDICATE_DRONE "Syndicate Drone" -#define ROLE_BATTLECRUISER_CREW "Battlecruiser Crew" -#define ROLE_BATTLECRUISER_CAPTAIN "Battlecruiser Captain" #define ROLE_VENUSHUMANTRAP "Venus Human Trap" -#define ROLE_BOT "Bot" +#define ROLE_ZOMBIE "Zombie" //SKYRAT EDIT START #define ROLE_BLACK_MARKET_DEALER "Black Market Dealer" #define ROLE_DS2 "DS2 Syndicate" @@ -123,7 +124,6 @@ #define ROLE_PORT_TARKON "Port Tarkon Survivor" //SKYRAT EDIT END - /// This defines the antagonists you can operate with in the settings. /// Keys are the antagonist, values are the number of days since the player's /// first connection in order to play. @@ -149,6 +149,7 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_BLOB = 0, ROLE_BLOB_INFECTION = 0, ROLE_CHANGELING_MIDROUND = 0, + ROLE_CYBER_POLICE = 0, ROLE_FUGITIVE = 0, ROLE_LONE_OPERATIVE = 14, ROLE_MALF_MIDROUND = 0, diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index 3caed7a0622..d95973e3fdb 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -150,7 +150,6 @@ #define ANNOUNCER_ICARUS "announcer_icarus" #define ANNOUNCER_NRI_RAIDERS "announcer_nri_raiders" #define ANNOUNCER_OUTBREAK6 "announcer_outbreak6" -#define ANNOUNCER_FUNGI "announcer_fungi" #define ANNOUNCER_DEPARTMENTAL "announcer_departmental" #define ANNOUNCER_SHUTTLE "announcer_shuttle" //SKYRAT EDIT END @@ -199,7 +198,6 @@ GLOBAL_LIST_INIT(announcer_keys, list( ANNOUNCER_ICARUS, ANNOUNCER_NRI_RAIDERS, ANNOUNCER_OUTBREAK6, - ANNOUNCER_FUNGI, //SKYRAT EDIT END )) diff --git a/code/__DEFINES/span.dm b/code/__DEFINES/span.dm index 22cf26e19a5..7b23869988b 100644 --- a/code/__DEFINES/span.dm +++ b/code/__DEFINES/span.dm @@ -17,6 +17,7 @@ #define span_bigicon(str) ("" + str + "") #define span_binarysay(str) ("" + str + "") #define span_blob(str) ("" + str + "") +#define span_blobannounce(str) ("" + str + "") #define span_blue(str) ("" + str + "") #define span_blueteamradio(str) ("" + str + "") #define span_bold(str) ("" + str + "") diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 50b33eb4c75..03a3bf49ebb 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -37,6 +37,9 @@ #define STASIS_CHEMICAL_EFFECT "stasis_chemical" #define STASIS_SHAPECHANGE_EFFECT "stasis_shapechange" #define STASIS_ADMIN "stasis_admin" +#define STASIS_LEGION_EATEN "stasis_eaten" + +#define STASIS_NETPOD_EFFECT "stasis_netpod" /// Causes the mob to become blind via the passed source #define become_blind(source) apply_status_effect(/datum/status_effect/grouped/blindness, source) @@ -153,3 +156,8 @@ #define adjust_temp_blindness_up_to(duration, up_to) adjust_timed_status_effect(duration, /datum/status_effect/temporary_blindness, up_to) #define set_temp_blindness(duration) set_timed_status_effect(duration, /datum/status_effect/temporary_blindness) #define set_temp_blindness_if_lower(duration) set_timed_status_effect(duration, /datum/status_effect/temporary_blindness, TRUE) + +#define adjust_static_vision(duration) adjust_timed_status_effect(duration, /datum/status_effect/static_vision) +#define adjust_static_vision_up_to(duration, up_to) adjust_timed_status_effect(duration, /datum/status_effect/static_vision, up_to) +#define set_static_vision(duration) set_timed_status_effect(duration, /datum/status_effect/static_vision) +#define set_static_vision_if_lower(duration) set_timed_status_effect(duration, /datum/status_effect/static_vision, TRUE) diff --git a/code/__DEFINES/supermatter.dm b/code/__DEFINES/supermatter.dm index bac35207fb5..5eab41fcdf9 100644 --- a/code/__DEFINES/supermatter.dm +++ b/code/__DEFINES/supermatter.dm @@ -28,6 +28,12 @@ #define MATTER_POWER_CONVERSION 10 //Crystal converts 1/this value of stored matter into energy. +/// The internal energy gain coefficient. +#define GAS_HEAT_POWER_SCALING_COEFFICIENT (1/6) + +/// The base zap power transmission of the supermatter crystal in W/MeV. +#define BASE_POWER_TRANSMISSION_RATE 1040 + //These would be what you would get at point blank, decreases with distance #define DETONATION_HALLUCINATION (20 MINUTES) @@ -165,9 +171,9 @@ #define SM_TEMP_LIMIT_LOW_MOLES "Low Moles Heat Resistance" /// How much we are multiplying our zap energy. -#define SM_ZAP_BASE "Base Zap Multiplier" +#define SM_ZAP_BASE "Base Zap Transmission" /// How much we are multiplying our zap energy because of gas factors. -#define SM_ZAP_GAS "Gas Zap Multiplier" +#define SM_ZAP_GAS "Gas Zap Transmission Modifier" /// Delamination types. #define CASCADE_DELAMINATION "cascade" #define SINGULARITY_DELAMINATION "singularity" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index a416a081cb8..2d05f29a012 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -318,6 +318,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_BLOOD_DEFICIENCY "blood_deficiency" #define TRAIT_JOLLY "jolly" #define TRAIT_NOCRITDAMAGE "no_crit" +///Added to mob or mind, changes the icons of the fish shown in the minigame UI depending on the possible reward. +#define TRAIT_REVEAL_FISH "reveal_fish" /// Stops the mob from slipping on water, or banana peels, or pretty much anything that doesn't have [GALOSHES_DONT_HELP] set #define TRAIT_NO_SLIP_WATER "noslip_water" @@ -889,9 +891,15 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// For clarity, this trait should always be associated/tied to a reference to the mob that suicided- not anything else. #define TRAIT_SUICIDED "committed_suicide" +/// Trait given to a living mob to prevent wizards from making it immortal +#define TRAIT_PERMANENTLY_MORTAL "permanently_mortal" + ///Trait given to a mob with a ckey currently in a temporary body, allowing people to know someone will re-enter the round later. #define TRAIT_MIND_TEMPORARILY_GONE "temporarily_gone" +/// Similar trait given to temporary bodies inhabited by players +#define TRAIT_TEMPORARY_BODY "temporary_body" + /// Trait given to mechs that can have orebox functionality on movement #define TRAIT_OREBOX_FUNCTIONAL "orebox_functional" @@ -905,6 +913,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_FISH_AMPHIBIOUS "fish_amphibious" ///Trait needed for the lubefish evolution #define TRAIT_FISH_FED_LUBE "fish_fed_lube" +#define TRAIT_FISH_NO_HUNGER "fish_no_hunger" // common trait sources #define TRAIT_GENERIC "generic" @@ -986,6 +995,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define MOTOR_LACK_TRAIT "motor-lack" /// Trait associated with mafia #define MAFIA_TRAIT "mafia" +/// Trait associated with ctf +#define CTF_TRAIT "ctf" /// Trait associated with highlander #define HIGHLANDER_TRAIT "highlander" /// Trait given from playing pretend with baguettes @@ -1078,6 +1089,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// sticky nodrop sounds like a bad soundcloud rapper's name #define STICKY_NODROP "sticky-nodrop" #define SKILLCHIP_TRAIT "skillchip" +#define SKILL_TRAIT "skill" #define BUSY_FLOORBOT_TRAIT "busy-floorbot" #define PULLED_WHILE_SOFTCRIT_TRAIT "pulled-while-softcrit" #define LOCKED_BORG_TRAIT "locked-borg" @@ -1141,6 +1153,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define AUTOPSY_TRAIT "autopsy_trait" /// Trait given by [/datum/status_effect/blessing_of_insanity] #define MAD_WIZARD_TRAIT "mad_wizard_trait" +/// Isn't attacked harmfully by blob structures +#define TRAIT_BLOB_ALLY "blob_ally" /** * Trait granted by [/mob/living/carbon/Initialize] and diff --git a/code/__DEFINES/tts.dm b/code/__DEFINES/tts.dm index cca1b5db000..fd88016408c 100644 --- a/code/__DEFINES/tts.dm +++ b/code/__DEFINES/tts.dm @@ -4,3 +4,7 @@ #define TTS_SOUND_ENABLED "Enabled" ///TTS preference is set to only play blips of a sound, rather than speech. #define TTS_SOUND_BLIPS "Blips Only" +///TTS filter to activate start/stop radio clicks on speech. +#define TTS_FILTER_RADIO "radio" +///TTS filter to activate a silicon effect on speech. +#define TTS_FILTER_SILICON "silicon" diff --git a/code/__DEFINES/visual_helpers.dm b/code/__DEFINES/visual_helpers.dm index 204cc8ba03a..bb54c5d6b0b 100644 --- a/code/__DEFINES/visual_helpers.dm +++ b/code/__DEFINES/visual_helpers.dm @@ -11,5 +11,15 @@ base_pixel_x = x; \ base_pixel_y = y; +#define SET_BASE_VISUAL_PIXEL(w, z) \ + pixel_w = w; \ + base_pixel_w = w; \ + pixel_z = z; \ + base_pixel_z = z; + +#define _SET_BASE_PIXEL_VISUAL_NO_OFFSET(w, z) \ + base_pixel_z = w; \ + base_pixel_z = z; + /// Much like [SET_BASE_PIXEL], except it will not effect pixel offsets in mapping programs #define SET_BASE_PIXEL_NOMAP(x, y) MAP_SWITCH(SET_BASE_PIXEL(x, y), _SET_BASE_PIXEL_NO_OFFSET(x, y)) diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm index 07239ca07c5..1cc9025b821 100644 --- a/code/__DEFINES/vv.dm +++ b/code/__DEFINES/vv.dm @@ -114,6 +114,8 @@ // /mob #define VV_HK_GIB "gib" +#define VV_HK_GIVE_MOB_ACTION "give_mob_action" +#define VV_HK_REMOVE_MOB_ACTION "remove_mob_action" #define VV_HK_GIVE_SPELL "give_spell" #define VV_HK_REMOVE_SPELL "remove_spell" #define VV_HK_GIVE_DISEASE "give_disease" @@ -149,6 +151,7 @@ #define VV_HK_MOD_QUIRKS "quirkmod" #define VV_HK_SET_SPECIES "setspecies" #define VV_HK_PURRBATION "purrbation" +#define VV_HK_APPLY_DNA_INFUSION "apply_dna_infusion" // misc #define VV_HK_SPACEVINE_PURGE "spacevine_purge" diff --git a/code/__DEFINES/~skyrat_defines/nifsofts.dm b/code/__DEFINES/~skyrat_defines/nifsofts.dm index ebf138343c0..f3852414f60 100644 --- a/code/__DEFINES/~skyrat_defines/nifsofts.dm +++ b/code/__DEFINES/~skyrat_defines/nifsofts.dm @@ -4,3 +4,4 @@ #define NIFSOFT_CATEGORY_COSMETIC "Cosmetic" #define NIFSOFT_CATEGORY_UTILITY "Utility" #define NIFSOFT_CATEGORY_FUN "Fun" +#define NIFSOFT_CATEGORY_INFORMATION "Information" diff --git a/code/__DEFINES/~skyrat_defines/traits.dm b/code/__DEFINES/~skyrat_defines/traits.dm index 920b58a082f..49f025e4ab0 100644 --- a/code/__DEFINES/~skyrat_defines/traits.dm +++ b/code/__DEFINES/~skyrat_defines/traits.dm @@ -90,3 +90,6 @@ /// Trait given to a piece of eyewear that allows the user to use NIFSoft HUDs #define TRAIT_NIFSOFT_HUD_GRANTER "nifsoft_hud_granter" + +/// Trait given to a brain that is able to accept souls from a RSD +#define TRAIT_RSD_COMPATIBLE "rsd_compatible" diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 34512b95952..fb1603d650d 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -408,6 +408,17 @@ list_to_clear -= new_list return list_to_clear.len < start_len +/** + * Removes any empty weakrefs from the list + * Returns TRUE if the list had empty refs, FALSE otherwise +**/ +/proc/list_clear_empty_weakrefs(list/list_to_clear) + var/start_len = list_to_clear.len + for(var/datum/weakref/entry in list_to_clear) + if(!entry.resolve()) + list_to_clear -= entry + return list_to_clear.len < start_len + /* * Returns list containing all the entries from first list that are not present in second. * If skiprep = 1, repeated elements are treated as one. diff --git a/code/__HELPERS/chat.dm b/code/__HELPERS/chat.dm index e853547ec73..31f9ad271d3 100644 --- a/code/__HELPERS/chat.dm +++ b/code/__HELPERS/chat.dm @@ -81,3 +81,19 @@ it will be sent to all connected chats. /// Handles text formatting for item use hints in examine text #define EXAMINE_HINT(text) ("" + text + "") + +/// Sends a message to all dead and observing players, if a source is provided a follow link will be attached. +/proc/send_to_observers(message, source) + var/list/all_observers = GLOB.dead_player_list + GLOB.current_observers_list + for(var/mob/observer as anything in all_observers) + if (isnull(source)) + to_chat(observer, "[message]") + continue + var/link = FOLLOW_LINK(observer, source) + to_chat(observer, "[link] [message]") + +/// Sends a message to everyone with blob telepathy, and all observers +/proc/blob_telepathy(message, source) + for(var/mob/creature as anything in GLOB.blob_telepathy_mobs) + to_chat(creature, message) + send_to_observers(message, source) diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm index 5f92c67a6fc..6a1cfd6191a 100644 --- a/code/__HELPERS/icon_smoothing.dm +++ b/code/__HELPERS/icon_smoothing.dm @@ -24,27 +24,6 @@ To see an example of a diagonal wall, see '/turf/closed/wall/mineral/titanium' and its subtypes. */ -//Redefinitions of the diagonal directions so they can be stored in one var without conflicts -#define NORTH_JUNCTION NORTH //(1<<0) -#define SOUTH_JUNCTION SOUTH //(1<<1) -#define EAST_JUNCTION EAST //(1<<2) -#define WEST_JUNCTION WEST //(1<<3) -#define NORTHEAST_JUNCTION (1<<4) -#define SOUTHEAST_JUNCTION (1<<5) -#define SOUTHWEST_JUNCTION (1<<6) -#define NORTHWEST_JUNCTION (1<<7) - -DEFINE_BITFIELD(smoothing_junction, list( - "NORTH_JUNCTION" = NORTH_JUNCTION, - "SOUTH_JUNCTION" = SOUTH_JUNCTION, - "EAST_JUNCTION" = EAST_JUNCTION, - "WEST_JUNCTION" = WEST_JUNCTION, - "NORTHEAST_JUNCTION" = NORTHEAST_JUNCTION, - "SOUTHEAST_JUNCTION" = SOUTHEAST_JUNCTION, - "SOUTHWEST_JUNCTION" = SOUTHWEST_JUNCTION, - "NORTHWEST_JUNCTION" = NORTHWEST_JUNCTION, -)) - #define NO_ADJ_FOUND 0 #define ADJ_FOUND 1 #define NULLTURF_BORDER 2 @@ -55,13 +34,13 @@ GLOBAL_LIST_INIT(adjacent_direction_lookup, generate_adjacent_directions()) * Each 3x3 grid is a tile, with each X representing a direction a border object could be in IN said grid * Directions marked with A are acceptable smoothing targets, M is the example direction * The example given here is of a northfacing border object -xxx xxx xxx xxx AxA xxx -xxx xAx xxx +xxx AxA xxx +xxx AxA xxx -xAx xMx xAx +AAA MMM AAA +xxx AxA xxx xxx AxA xxx -xxx xxx xxx xxx xxx xxx xxx xxx xxx @@ -96,21 +75,20 @@ xxx xxx xxx // We'll do the two dirs to our left and right // They connect.. "below" us and on their side if(connectable_dir == NONE) - smoothable_dirs[left] = opposite | left - smoothable_dirs[right] = opposite | right + smoothable_dirs[left] = dir_to_junction(opposite | left) + smoothable_dirs[right] = dir_to_junction(opposite | right) // If it's to our right or left we'll include just the dir matching ours // Left edge touches only our left side, and so on else if (connectable_dir == left) smoothable_dirs[dir] = left else if (connectable_dir == right) smoothable_dirs[dir] = right - // If it's straight on we'll include all cardinals but us, since all 3 bits would touch us - // Turf opposite gets just our dir as the connection, the other two get our dir + theirs - // Since they touch the edges + // If it's straight on we'll include our direction as a link + // Then include the two edges on the other side as diagonals else if(connectable_dir == dir) smoothable_dirs[opposite] = dir - smoothable_dirs[left] = dir | left - smoothable_dirs[right] = dir | right + smoothable_dirs[left] = dir_to_junction(dir | left) + smoothable_dirs[right] = dir_to_junction(dir | right) // otherwise, go HOME, I don't want to encode anything for you else continue @@ -594,6 +572,39 @@ xxx xxx xxx add_overlay(new_overlays) +/// Takes a direction, turns it into all the junctions that contain it +/proc/dir_to_all_junctions(dir) + var/handback = NONE + if(dir & NORTH) + handback |= NORTH_JUNCTION | NORTHEAST_JUNCTION | NORTHWEST_JUNCTION + if(dir & SOUTH) + handback |= SOUTH_JUNCTION | SOUTHEAST_JUNCTION | SOUTHWEST_JUNCTION + if(dir & EAST) + handback |= EAST_JUNCTION | SOUTHEAST_JUNCTION | NORTHEAST_JUNCTION + if(dir & WEST) + handback |= WEST_JUNCTION | NORTHWEST_JUNCTION | SOUTHWEST_JUNCTION + return handback + +/proc/dir_to_junction(dir) + switch(dir) + if(NORTH) + return NORTH_JUNCTION + if(SOUTH) + return SOUTH_JUNCTION + if(WEST) + return WEST_JUNCTION + if(EAST) + return EAST_JUNCTION + if(NORTHWEST) + return NORTHWEST_JUNCTION + if(NORTHEAST) + return NORTHEAST_JUNCTION + if(SOUTHEAST) + return SOUTHEAST_JUNCTION + if(SOUTHWEST) + return SOUTHWEST_JUNCTION + else + return NONE /proc/reverse_ndir(ndir) switch(ndir) diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm index 6cda3466949..116fb34fad5 100644 --- a/code/__HELPERS/maths.dm +++ b/code/__HELPERS/maths.dm @@ -119,25 +119,48 @@ dx -= 1 return perimeter -///Format a power value in W, kW, MW, or GW. +/** + * Formats a number into a list representing the si unit. + * Access the coefficient with [SI_COEFFICIENT], and access the unit with [SI_UNIT]. + * + * Supports SI exponents between 1e-15 to 1e15, but properly handles numbers outside that range as well. + * Arguments: + * * value - The number to convert to text. Can be positive or negative. + * * unit - The base unit of the number, such as "Pa" or "W". + * * maxdecimals - Maximum amount of decimals to display for the final number. Defaults to 1. + * Returns: [SI_COEFFICIENT = si unit coefficient, SI_UNIT = prefixed si unit.] + */ +/proc/siunit_isolated(value, unit, maxdecimals=1) + var/static/list/prefixes = list("f","p","n","μ","m","","k","M","G","T","P") + + // We don't have prefixes beyond this point + // and this also captures value = 0 which you can't compute the logarithm for + // and also byond numbers are floats and doesn't have much precision beyond this point anyway + if(abs(value) <= 1e-18) + . = list(SI_COEFFICIENT = 0, SI_UNIT = " [unit]") + return + + var/exponent = clamp(log(10, abs(value)), -15, 15) // Calculate the exponent and clamp it so we don't go outside the prefix list bounds + var/divider = 10 ** (round(exponent / 3) * 3) // Rounds the exponent to nearest SI unit and power it back to the full form + var/coefficient = round(value / divider, 10 ** -maxdecimals) // Calculate the coefficient and round it to desired decimals + var/prefix_index = round(exponent / 3) + 6 // Calculate the index in the prefixes list for this exponent + + // An edge case which happens if we round 999.9 to 0 decimals for example, which gets rounded to 1000 + // In that case, we manually swap up to the next prefix if there is one available + if(coefficient >= 1000 && prefix_index < 11) + coefficient /= 1e3 + prefix_index++ + + var/prefix = prefixes[prefix_index] + . = list(SI_COEFFICIENT = coefficient, SI_UNIT = " [prefix][unit]") + +///Format a power value in prefixed watts. /proc/display_power(powerused) - if(powerused < 1000) //Less than a kW - return "[powerused] W" - else if(powerused < 1000000) //Less than a MW - return "[round((powerused * 0.001),0.01)] kW" - else if(powerused < 1000000000) //Less than a GW - return "[round((powerused * 0.000001),0.001)] MW" - return "[round((powerused * 0.000000001),0.0001)] GW" - -///Format an energy value in J, kJ, MJ, or GJ. 1W = 1J/s. + return siunit(powerused, "W", 3) + +///Format an energy value in prefixed joules. /proc/display_joules(units) - if (units < 1000) // Less than a kJ - return "[round(units, 0.1)] J" - else if (units < 1000000) // Less than a MJ - return "[round(units * 0.001, 0.01)] kJ" - else if (units < 1000000000) // Less than a GJ - return "[round(units * 0.000001, 0.001)] MJ" - return "[round(units * 0.000000001, 0.0001)] GJ" + return siunit(units, "J", 3) /proc/joules_to_energy(joules) return joules * (1 SECONDS) / SSmachines.wait diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index de9ed493b62..aa161690ceb 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -589,7 +589,7 @@ GLOBAL_LIST_EMPTY(species_list) #define ISADVANCEDTOOLUSER(mob) (HAS_TRAIT(mob, TRAIT_ADVANCEDTOOLUSER) && !HAS_TRAIT(mob, TRAIT_DISCOORDINATED_TOOL_USER)) -#define IS_IN_STASIS(mob) (mob.has_status_effect(/datum/status_effect/grouped/stasis)) +#define IS_IN_STASIS(mob) (mob.has_status_effect(/datum/status_effect/grouped/stasis) || mob.has_status_effect(/datum/status_effect/embryonic)) /// Gets the client of the mob, allowing for mocking of the client. /// You only need to use this if you know you're going to be mocking clients somewhere else. diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index f75e6770207..91406650d20 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -191,7 +191,7 @@ // 0 .. 9 if(48 to 57) //Numbers - if(last_char_group == NO_CHARS_DETECTED || !allow_numbers) //suppress at start of string + if(!allow_numbers) //allow name to start with number if AI/Borg if(strict) return continue @@ -1048,27 +1048,8 @@ GLOBAL_LIST_INIT(binary, list("0","1")) * * For pressure conversion, use proc/siunit_pressure() below */ /proc/siunit(value, unit, maxdecimals=1) - var/static/list/prefixes = list("f","p","n","μ","m","","k","M","G","T","P") - - // We don't have prefixes beyond this point - // and this also captures value = 0 which you can't compute the logarithm for - // and also byond numbers are floats and doesn't have much precision beyond this point anyway - if(abs(value) <= 1e-18) - return "0 [unit]" - - var/exponent = clamp(log(10, abs(value)), -15, 15) // Calculate the exponent and clamp it so we don't go outside the prefix list bounds - var/divider = 10 ** (round(exponent / 3) * 3) // Rounds the exponent to nearest SI unit and power it back to the full form - var/coefficient = round(value / divider, 10 ** -maxdecimals) // Calculate the coefficient and round it to desired decimals - var/prefix_index = round(exponent / 3) + 6 // Calculate the index in the prefixes list for this exponent - - // An edge case which happens if we round 999.9 to 0 decimals for example, which gets rounded to 1000 - // In that case, we manually swap up to the next prefix if there is one available - if(coefficient >= 1000 && prefix_index < 11) - coefficient /= 1e3 - prefix_index++ - - var/prefix = prefixes[prefix_index] - return "[coefficient] [prefix][unit]" + var/si_isolated = siunit_isolated(value, unit, maxdecimals) + return "[si_isolated[SI_COEFFICIENT]][si_isolated[SI_UNIT]]" /** The game code never uses Pa, but kPa, since 1 Pa is too small to reasonably handle diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm index d16c466f9dc..50575d24b5b 100644 --- a/code/_globalvars/lists/maintenance_loot.dm +++ b/code/_globalvars/lists/maintenance_loot.dm @@ -216,6 +216,7 @@ GLOBAL_LIST_INIT(uncommon_loot, list(//uncommon: useful items /obj/item/stack/medical/gauze = 1, /obj/item/stack/medical/mesh = 1, /obj/item/stack/medical/suture = 1, + /obj/item/stack/medical/bandage = 1, ) = 1, list(//medical chems /obj/item/reagent_containers/cup/bottle/multiver = 1, @@ -333,6 +334,7 @@ GLOBAL_LIST_INIT(rarity_loot, list(//rare: really good items /obj/item/storage/box/hug/medical = 1, /obj/item/storage/medkit/emergency = 1, /obj/item/storage/medkit/regular = 1, + /obj/item/storage/box/bandages = 1, ) = 1, list(//medical chems /obj/item/reagent_containers/hypospray/medipen/oxandrolone = 1, @@ -347,6 +349,7 @@ GLOBAL_LIST_INIT(rarity_loot, list(//rare: really good items /obj/item/book/granter/crafting_recipe/dusting/laser_musket_prime = 1, /obj/item/book/granter/sign_language = 1, /obj/item/disk/nuclear/fake = 1, + /obj/item/disk/surgery/advanced_plastic_surgery = 1, /obj/item/skillchip/brainwashing = 1, /obj/item/tattoo_kit = 1, /obj/item/folder/ancient_paperwork = 1, diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 6f7d9c987f7..5fc93a2494e 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -52,6 +52,9 @@ GLOBAL_LIST_EMPTY(current_living_antags) /// All observers with clients that joined as observers. GLOBAL_LIST_EMPTY(current_observers_list) +/// All living mobs which can hear blob telepathy +GLOBAL_LIST_EMPTY(blob_telepathy_mobs) + ///underages who have been reported to security for trying to buy things they shouldn't, so they can't spam GLOBAL_LIST_EMPTY(narcd_underages) @@ -113,7 +116,7 @@ GLOBAL_LIST_INIT(construct_radial_images, list( /proc/get_crewmember_minds() var/list/minds = list() for(var/datum/record/locked/target in GLOB.manifest.locked) - var/datum/mind/mind = target.mind_ref + var/datum/mind/mind = target.mind_ref.resolve() if(mind) minds += mind return minds diff --git a/code/_globalvars/lists/names.dm b/code/_globalvars/lists/names.dm index 018164e2c78..01e6f3b59dc 100644 --- a/code/_globalvars/lists/names.dm +++ b/code/_globalvars/lists/names.dm @@ -23,6 +23,7 @@ GLOBAL_LIST_INIT(posibrain_names, world.file2list("strings/names/posibrain.txt") GLOBAL_LIST_INIT(nightmare_names, world.file2list("strings/names/nightmare.txt")) GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1.txt")) GLOBAL_LIST_INIT(megacarp_last_names, world.file2list("strings/names/megacarp2.txt")) +GLOBAL_LIST_INIT(cyberauth_names, world.file2list("strings/names/cyberauth.txt")) GLOBAL_LIST_INIT(verbs, world.file2list("strings/names/verbs.txt")) GLOBAL_LIST_INIT(ing_verbs, world.file2list("strings/names/ing_verbs.txt")) diff --git a/code/_globalvars/lists/poll_ignore.dm b/code/_globalvars/lists/poll_ignore.dm index 4d4f10ddc8a..1a56a44f5e5 100644 --- a/code/_globalvars/lists/poll_ignore.dm +++ b/code/_globalvars/lists/poll_ignore.dm @@ -5,6 +5,7 @@ #define POLL_IGNORE_ALIEN_LARVA "alien_larva" #define POLL_IGNORE_ASH_SPIRIT "ash_spirit" #define POLL_IGNORE_ASHWALKER "ashwalker" +#define POLL_IGNORE_BLOB "blob" #define POLL_IGNORE_BOTS "bots" #define POLL_IGNORE_CARGORILLA "cargorilla" #define POLL_IGNORE_CONTRACTOR_SUPPORT "contractor_support" @@ -43,6 +44,7 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list( POLL_IGNORE_ALIEN_LARVA = "Xenomorph larva", POLL_IGNORE_ASH_SPIRIT = "Ash Spirit", POLL_IGNORE_ASHWALKER = "Ashwalker eggs", + POLL_IGNORE_BLOB = "Blob spores", POLL_IGNORE_BOTS = "Bots", POLL_IGNORE_CARGORILLA = "Cargorilla", POLL_IGNORE_CONTRACTOR_SUPPORT = "Contractor Support Unit", diff --git a/code/_globalvars/lists/quirks.dm b/code/_globalvars/lists/quirks.dm index 9d936c18e56..f907206a30c 100644 --- a/code/_globalvars/lists/quirks.dm +++ b/code/_globalvars/lists/quirks.dm @@ -11,3 +11,11 @@ GLOBAL_LIST_INIT(nearsighted_glasses, list( "Modern" = /obj/item/clothing/glasses/betterunshit, // SKYRAT ADD )) + +///Options for the prothetic limb quirk to choose from +GLOBAL_LIST_INIT(limb_choice, list( + "Left Arm" = /obj/item/bodypart/arm/left/robot/surplus, + "Right Arm" = /obj/item/bodypart/arm/right/robot/surplus, + "Left Leg" = /obj/item/bodypart/leg/left/robot/surplus, + "Right Leg" = /obj/item/bodypart/leg/right/robot/surplus, +)) diff --git a/code/_globalvars/phobias.dm b/code/_globalvars/phobias.dm index a6cb2dedb32..a913410214d 100644 --- a/code/_globalvars/phobias.dm +++ b/code/_globalvars/phobias.dm @@ -88,7 +88,7 @@ GLOBAL_LIST_INIT(phobia_mobs, list( "security" = typecacheof(list(/mob/living/simple_animal/bot/secbot)), "spiders" = typecacheof(list(/mob/living/basic/spider/giant)), "skeletons" = typecacheof(list(/mob/living/simple_animal/hostile/skeleton)), - "snakes" = typecacheof(list(/mob/living/simple_animal/hostile/retaliate/snake)), + "snakes" = typecacheof(list(/mob/living/basic/snake)), "the supernatural" = typecacheof(list( /mob/dead/observer, /mob/living/basic/bat, @@ -331,7 +331,7 @@ GLOBAL_LIST_INIT(phobia_objs, list( /obj/item/storage/pill_bottle, /obj/item/surgical_drapes, /obj/item/surgicaldrill, - /obj/machinery/atmospherics/components/unary/cryo_cell, + /obj/machinery/cryo_cell, /obj/machinery/dna_scannernew, /obj/machinery/door/airlock/medical, /obj/machinery/sleeper, diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index d35c97ef68a..a4a79763865 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -272,6 +272,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_FISH_TOXIN_IMMUNE" = TRAIT_FISH_TOXIN_IMMUNE, "TRAIT_FISH_CROSSBREEDER" = TRAIT_FISH_CROSSBREEDER, "TRAIT_FISH_FED_LUBE" = TRAIT_FISH_FED_LUBE, + "TRAIT_FISH_NO_HUNGER" = TRAIT_FISH_NO_HUNGER, ), )) diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index afedfa5befe..ef184e18b1d 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -216,3 +216,10 @@ layer = LIGHTING_ABOVE_ALL blend_mode = BLEND_ADD show_when_dead = TRUE + +/atom/movable/screen/fullscreen/static_vision + icon = 'icons/hud/screen_gen.dmi' + screen_loc = "WEST,SOUTH to EAST,NORTH" + icon_state = "noise" + color = "#04a8d1" + alpha = 80 diff --git a/code/controllers/configuration/entries/jobs.dm b/code/controllers/configuration/entries/jobs.dm index 99a3ab7a701..06563e01a8e 100644 --- a/code/controllers/configuration/entries/jobs.dm +++ b/code/controllers/configuration/entries/jobs.dm @@ -9,7 +9,7 @@ return returnable_list /// Sets all of the job datum configurable values to what they've been set to in the config file, jobconfig.toml. -/datum/controller/subsystem/job/proc/load_jobs_from_config() +/datum/controller/subsystem/job/proc/load_jobs_from_config(silent = FALSE) if(!length(job_config_datum_singletons)) stack_trace("SSjob tried to load jobs from config, but the config singletons were not initialized! Likely tried to load jobs before SSjob was initialized.") return @@ -25,7 +25,8 @@ var/job_key = occupation.config_tag if(!job_config[job_key]) // Job isn't listed, skip it. // List both job_title and job_key in case they de-sync over time. - message_admins(span_notice("[occupation.title] (with config key [job_key]) is missing from jobconfig.toml! Using codebase defaults.")) + if(!silent) + message_admins(span_notice("[occupation.title] (with config key [job_key]) is missing from jobconfig.toml! Using codebase defaults.")) continue for(var/config_datum_key in job_config_datum_singletons) diff --git a/code/controllers/subsystem/economy.dm b/code/controllers/subsystem/economy.dm index b8e1ab9e772..511a438bf9a 100644 --- a/code/controllers/subsystem/economy.dm +++ b/code/controllers/subsystem/economy.dm @@ -123,6 +123,8 @@ SUBSYSTEM_DEF(economy) var/effective_mailcount = round(living_player_count()/(inflation_value - 0.5)) //More mail at low inflation, and vis versa. mail_waiting += clamp(effective_mailcount, 1, MAX_MAIL_PER_MINUTE * seconds_per_tick) + SSstock_market.news_string = "" + /** * Handy proc for obtaining a department's bank account, given the department ID, AKA the define assigned for what department they're under. */ @@ -173,7 +175,7 @@ SUBSYSTEM_DEF(economy) fluff_string = ", but company countermeasures protect YOU from being affected!" else fluff_string = ", and company countermeasures are failing to protect YOU from being affected. We're all doomed!" - earning_report = "Sector Economic Report

Sector vendor prices is currently at [SSeconomy.inflation_value()*100]%[fluff_string]

The station spending power is currently [station_total] Credits, and the crew's targeted allowance is at [station_target] Credits.

That's all from the Nanotrasen Economist Division." + earning_report = "Sector Economic Report

Sector vendor prices is currently at [SSeconomy.inflation_value()*100]%[fluff_string]

The station spending power is currently [station_total] Credits, and the crew's targeted allowance is at [station_target] Credits.

[SSstock_market.news_string] That's all from the Nanotrasen Economist Division." GLOB.news_network.submit_article(earning_report, "Station Earnings Report", "Station Announcements", null, update_alert = FALSE) return TRUE @@ -204,9 +206,9 @@ SUBSYSTEM_DEF(economy) CRASH("Track purchases was missing an argument! (Account, Price, or Vendor.)") audit_log += list(list( - "account" = account.account_holder, + "account" = "[account.account_holder]", "cost" = price_to_use, - "vendor" = vendor, + "vendor" = "[vendor]", )) /** diff --git a/code/controllers/subsystem/id_access.dm b/code/controllers/subsystem/id_access.dm index 963957741f2..86f2e124a8f 100644 --- a/code/controllers/subsystem/id_access.dm +++ b/code/controllers/subsystem/id_access.dm @@ -329,6 +329,7 @@ SUBSYSTEM_DEF(id_access) desc_by_access["[ACCESS_CENT_SPECOPS]"] = "Code Black" desc_by_access["[ACCESS_CENT_CAPTAIN]"] = "Code Gold" desc_by_access["[ACCESS_CENT_BAR]"] = "Code Scotch" + desc_by_access["[ACCESS_BIT_DEN]"] = "Bitrunner Den" desc_by_access["[ACCESS_BARBER]"] = "Barber" // SKYRAT EDIT ADD - BARBER UPDATE /** diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 5c957445526..8376059e910 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -1,5 +1,3 @@ -#define VERY_LATE_ARRIVAL_TOAST_PROB 20 - SUBSYSTEM_DEF(job) name = "Jobs" init_order = INIT_ORDER_JOBS @@ -305,6 +303,10 @@ SUBSYSTEM_DEF(job) player.mind.special_role = null SetupOccupations() unassigned = list() + if(CONFIG_GET(flag/load_jobs_from_txt)) + // Any errors with the configs has already been said, we don't need to repeat them here. + load_jobs_from_config(silent = TRUE) + set_overflow_role(overflow_role) return @@ -542,21 +544,16 @@ SUBSYSTEM_DEF(job) /datum/controller/subsystem/job/proc/EquipRank(mob/living/equipping, datum/job/job, client/player_client) // SKYRAT EDIT ADDITION BEGIN - ALTERNATIVE_JOB_TITLES // The alt job title, if user picked one, or the default - var/chosen_title = player_client?.prefs.alt_job_titles[job.title] || job.title - var/default_title = job.title - // SKYRAT EDIT ADDITION END - job.title + var/alt_title = player_client?.prefs.alt_job_titles[job.title] + // SKYRAT EDIT ADDITION END equipping.job = job.title SEND_SIGNAL(equipping, COMSIG_JOB_RECEIVED, job) - equipping.mind?.set_assigned_role_with_greeting(job, player_client) - if(player_client) - to_chat(player_client, span_infoplain("You are the [chosen_title].")) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - Original: to_chat(player_client, span_infoplain("You are the [job.title].")) - - equipping.on_job_equipping(job, player_client?.prefs) //SKYRAT EDIT CHANGE - - job.announce_job(equipping, chosen_title) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - Original: job.announce_job(equipping) + equipping.mind?.set_assigned_role_with_greeting(job, player_client, alt_title) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - ORIGINAL: equipping.mind?.set_assigned_role_with_greeting(job, player_client) + equipping.on_job_equipping(job, player_client?.prefs, player_client) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - ORIGINAL: equipping.on_job_equipping(job) + job.announce_job(equipping, alt_title) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - ORIGINAL: job.announce_job(equipping) if(player_client?.holder) if(CONFIG_GET(flag/auto_deadmin_players) || (player_client.prefs?.toggles & DEADMIN_ALWAYS)) @@ -564,46 +561,7 @@ SUBSYSTEM_DEF(job) else handle_auto_deadmin_roles(player_client, job.title) - - if(player_client) - to_chat(player_client, span_infoplain("As the [chosen_title == job.title ? chosen_title : "[chosen_title] ([job.title])"] you answer directly to [job.supervisors]. Special circumstances may change this.")) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - Original: to_chat(player_client, span_infoplain("As the [job.title] you answer directly to [job.supervisors]. Special circumstances may change this.")) - - job.radio_help_message(equipping) - - if(player_client) - if(job.req_admin_notify) - to_chat(player_client, span_infoplain("You are playing a job that is important for Game Progression. \ - If you have to disconnect, please notify the admins via adminhelp.")) - if(CONFIG_GET(number/minimal_access_threshold)) - to_chat(player_client, span_boldnotice("As this station was initially staffed with a \ - [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] \ - have been added to your ID card.")) - //SKYRAT EDIT START - ALTERNATIVE_JOB_TITLES - if(chosen_title != default_title) - to_chat(player_client, span_infoplain(span_warning("Remember that alternate titles are purely for flavor and roleplay."))) - to_chat(player_client, span_infoplain(span_doyourjobidiot("Do not use your \"[chosen_title]\" alt title as an excuse to forego your duties as a [job.title]."))) - //SKYRAT EDIT END - var/related_policy = get_policy(job.title) - if(related_policy) - to_chat(player_client, related_policy) - to_chat(player_client, span_boldnotice("As this station was initially staffed with a \ - [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] \ - have been added to your ID card.")) - - if(ishuman(equipping)) - var/mob/living/carbon/human/wageslave = equipping - wageslave.add_mob_memory(/datum/memory/key/account, remembered_id = wageslave.account_id) - - setup_alt_job_items(wageslave, job, player_client) // SKYRAT EDIT ADDITION - ALTERNATIVE_JOB_TITLES - - if(EMERGENCY_PAST_POINT_OF_NO_RETURN && prob(VERY_LATE_ARRIVAL_TOAST_PROB)) - // SKYRAT EDIT CHANGE START - Lizards - if(islizard(equipping)) - equipping.equip_to_slot_or_del(new /obj/item/food/breadslice/root(equipping), ITEM_SLOT_MASK) - else - equipping.equip_to_slot_or_del(new /obj/item/food/griddle_toast(equipping), ITEM_SLOT_MASK) - // SKYRAT EDIT CHANGE END - Lizards - + setup_alt_job_items(equipping, job, player_client) // SKYRAT EDIT ADDITION - ALTERNATIVE_JOB_TITLES job.after_spawn(equipping, player_client) /datum/controller/subsystem/job/proc/handle_auto_deadmin_roles(client/C, rank) @@ -1006,5 +964,3 @@ SUBSYSTEM_DEF(job) return TRUE return FALSE - -#undef VERY_LATE_ARRIVAL_TOAST_PROB diff --git a/code/controllers/subsystem/movement/movement_types.dm b/code/controllers/subsystem/movement/movement_types.dm index 7067b3abbfc..6ff9d39d531 100644 --- a/code/controllers/subsystem/movement/movement_types.dm +++ b/code/controllers/subsystem/movement/movement_types.dm @@ -384,7 +384,7 @@ src.simulated_only = simulated_only src.avoid = avoid src.skip_first = skip_first - movement_path = initial_path.Copy() + movement_path = initial_path?.Copy() if(isidcard(id)) RegisterSignal(id, COMSIG_QDELETING, PROC_REF(handle_no_id)) //I prefer erroring to harddels. If this breaks anything consider making id info into a datum or something diff --git a/code/controllers/subsystem/radiation.dm b/code/controllers/subsystem/radiation.dm index b2b3d1926dd..d52fe83856a 100644 --- a/code/controllers/subsystem/radiation.dm +++ b/code/controllers/subsystem/radiation.dm @@ -135,7 +135,7 @@ SUBSYSTEM_DEF(radiation) for (var/obj/item/bodypart/limb as anything in human.bodyparts) var/protected = FALSE - for (var/obj/item/clothing as anything in human.clothingonpart(limb)) + for (var/obj/item/clothing as anything in human.get_clothing_on_part(limb)) if (HAS_TRAIT(clothing, TRAIT_RADIATION_PROTECTED_CLOTHING)) protected = TRUE break diff --git a/code/controllers/subsystem/stock_market.dm b/code/controllers/subsystem/stock_market.dm new file mode 100644 index 00000000000..7c2cb71dc49 --- /dev/null +++ b/code/controllers/subsystem/stock_market.dm @@ -0,0 +1,154 @@ + +SUBSYSTEM_DEF(stock_market) + name = "Stock Market" + wait = 20 SECONDS + init_order = INIT_ORDER_DEFAULT + runlevels = RUNLEVEL_GAME + + /// Associated list of materials and their prices at the given time. + var/list/materials_prices = list() + /// Associated list of materials alongside their market trends. 1 is up, 0 is stable, -1 is down. + var/list/materials_trends = list() + /// Associated list of materials alongside the life of it's current trend. After it's life is up, it will change to a new trend. + var/list/materials_trend_life = list() + /// Associated list of materials alongside their available quantity. This is used to determine how much of a material is available to buy, and how much buying and selling affects the price. + var/list/materials_quantity = list() + /// HTML string that is used to display the market events to the player. + var/news_string = "" + +/datum/controller/subsystem/stock_market/Initialize() + for(var/datum/material/possible_market as anything in subtypesof(/datum/material)) // I need to make this work like this, but lets hardcode it for now + if(initial(possible_market.tradable)) + materials_prices += possible_market + materials_prices[possible_market] = initial(possible_market.value_per_unit) * SHEET_MATERIAL_AMOUNT + + materials_trends += possible_market + materials_trends[possible_market] = rand(MARKET_TREND_DOWNWARD,MARKET_TREND_UPWARD) //aka -1 to 1 + + materials_trend_life += possible_market + materials_trend_life[possible_market] = rand(1,10) + + materials_quantity += possible_market + materials_quantity[possible_market] = initial(possible_market.tradable_base_quantity) + (rand(-initial(possible_market.tradable_base_quantity) * 0.5, initial(possible_market.tradable_base_quantity) * 0.5)) + return SS_INIT_SUCCESS +/datum/controller/subsystem/stock_market/fire(resumed) + for(var/datum/material/market as anything in materials_prices) + handle_trends_and_price(market) + +/** + * Handles shifts in the cost of materials, and in what direction the material is most likely to move. + */ +/datum/controller/subsystem/stock_market/proc/handle_trends_and_price(datum/material/mat) + if(prob(MARKET_EVENT_PROBABILITY)) + handle_market_event(mat) + return + var/trend = materials_trends[mat] + var/trend_life = materials_trend_life[mat] + + var/price_units = materials_prices[mat] + var/price_minimum = round(initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 0.5) + if(!isnull(initial(mat.minimum_value_override))) + price_minimum = round(initial(mat.minimum_value_override) * SHEET_MATERIAL_AMOUNT) + var/price_maximum = round(initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 3) + var/price_baseline = initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT + + var/stock_quantity = materials_quantity[mat] + + if(HAS_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING)) //We hardset to the worst possible price and lowest possible impact if sold + materials_prices[mat] = price_minimum + materials_quantity[mat] = stock_quantity * 2 + materials_trends[mat] = MARKET_TREND_DOWNWARD + trend_life = materials_trend_life[mat] = 1 + return + + if(trend_life == 0) + ///We want to scale our trend so that if we're closer to our minimum or maximum price, we're more likely to trend the other way. + if((price_units < price_baseline)) + var/chance_swap = 100 - ((clamp((price_units - price_minimum), 1, 1000) / (price_baseline - price_minimum))*100) + if(prob(chance_swap)) + materials_trends[mat] = MARKET_TREND_UPWARD + else + materials_trends[mat] = MARKET_TREND_STABLE + else if((price_units > price_baseline)) + var/chance_swap = 100 - ((clamp((price_units - price_maximum), 1, 1000) / (price_maximum - price_baseline))*100) + if(prob(chance_swap)) + materials_trends[mat] = MARKET_TREND_DOWNWARD + else + materials_trends[mat] = MARKET_TREND_STABLE + materials_trend_life[mat] = rand(3,10) // Change our trend life for x number of cycles + else + materials_trend_life[mat] -= 1 + + var/price_change = 0 + var/quantity_change = 0 + switch(trend) + if(MARKET_TREND_UPWARD) + price_change = ROUND_UP(gaussian(price_units * 0.1, price_baseline * 0.05)) //If we don't ceil, small numbers will get trapped at low values + quantity_change = -round(gaussian(stock_quantity * 0.1, stock_quantity * 0.05)) + if(MARKET_TREND_STABLE) + price_change = round(gaussian(0, price_baseline * 0.01)) + quantity_change = round(gaussian(0, stock_quantity * 0.01)) + if(MARKET_TREND_DOWNWARD) + price_change = -ROUND_UP(gaussian(price_units * 0.1, price_baseline * 0.05)) + quantity_change = round(gaussian(stock_quantity * 0.1, stock_quantity * 0.05)) + materials_prices[mat] = round(clamp(price_units + price_change, price_minimum, price_maximum)) + materials_quantity[mat] = round(clamp(stock_quantity + quantity_change, 0, initial(mat.tradable_base_quantity) * 2)) + +/** + * Market events are a way to spice up the market and make it more interesting. + * Randomly one will occur to a random material, and it will change the price of that material more drastically, or reset it to a stable price. + * Events are also broadcast to the newscaster as a fun little fluff piece. Good way to tell some lore as well, or just make a joke. + */ +/datum/controller/subsystem/stock_market/proc/handle_market_event(datum/material/mat) + + var/company_name = list( // Pick a random company name from the list, I let copilot make a few up for me which is why some suck + "Nakamura Engineering", + "Robust Industries, LLC", + "MODular Solutions", + "SolGov", + "Australicus Industrial Mining", + "Vey-Medical", + "Aussec Armory", + "Dreamland Robotics" + ) + var/circumstance + var/event = rand(1,3) + + var/price_units = materials_prices[mat] + var/price_minimum = round(initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 0.5) + if(!isnull(initial(mat.minimum_value_override))) + price_minimum = round(initial(mat.minimum_value_override) * SHEET_MATERIAL_AMOUNT) + var/price_maximum = round(initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 3) + var/price_baseline = initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT + + switch(event) + if(1) //Reset to stable + materials_prices[mat] = price_baseline + materials_trends[mat] = MARKET_TREND_STABLE + materials_trend_life[mat] = 1 + circumstance = pick(list( + "[pick(company_name)] has been bought out by a private investment firm. As a result, [initial(mat.name)] is now stable at [materials_prices[mat]] cr.", + "Due to a corporate restructuring, the largest supplier of [initial(mat.name)] has had the price changed to [materials_prices[mat]] cr.", + "[initial(mat.name)] is now under a monopoly by [pick(company_name)]. The price has been changed to [materials_prices[mat]] cr accordingly." + )) + if(2) //Big boost + materials_prices[mat] += round(gaussian(price_units * 0.5, price_units * 0.1)) + materials_prices[mat] = clamp(materials_prices[mat], price_minimum, price_maximum) + materials_trends[mat] = MARKET_TREND_UPWARD + materials_trend_life[mat] = rand(1,5) + circumstance = pick(list( + "[pick(company_name)] has just released a new product that uses [initial(mat.name)]! As a result, the price has been raised to [materials_prices[mat]] cr.", + "Due to [pick(company_name)] finding a new property of [initial(mat.name)], its price has been raised to [materials_prices[mat]] cr.", + "A study has found that [initial(mat.name)] may run out within the next 100 years. The price has raised to [materials_prices[mat]] cr due to panic." + )) + if(3) //Big drop + materials_prices[mat] -= round(gaussian(price_units * 1.5, price_units * 0.1)) + materials_prices[mat] = clamp(materials_prices[mat], price_minimum, price_maximum) + materials_trends[mat] = MARKET_TREND_DOWNWARD + materials_trend_life[mat] = rand(1,5) + circumstance = pick(list( + "[pick(company_name)]'s latest product has seen major controversy, and as a result, the price of [initial(mat.name)] has dropped to [materials_prices[mat]] cr.", + "Due to a new competitor, the price of [initial(mat.name)] has dropped to [materials_prices[mat]] cr.", + "[initial(mat.name)] has been found to be a carcinogen. The price has dropped to [materials_prices[mat]] cr due to panic." + )) + news_string += circumstance + "
" // Add the event to the news_string, formatted for newscasters. diff --git a/code/controllers/subsystem/tts.dm b/code/controllers/subsystem/tts.dm index 712168b5027..b9cb85ea78a 100644 --- a/code/controllers/subsystem/tts.dm +++ b/code/controllers/subsystem/tts.dm @@ -261,7 +261,7 @@ SUBSYSTEM_DEF(tts) #undef TTS_ARBRITRARY_DELAY -/datum/controller/subsystem/tts/proc/queue_tts_message(datum/target, message, datum/language/language, speaker, filter, list/listeners, local = FALSE, message_range = 7, volume_offset = 0, pitch = 0, silicon = "") +/datum/controller/subsystem/tts/proc/queue_tts_message(datum/target, message, datum/language/language, speaker, filter, list/listeners, local = FALSE, message_range = 7, volume_offset = 0, pitch = 0, special_filters = "") if(!tts_enabled) return @@ -277,7 +277,7 @@ SUBSYSTEM_DEF(tts) var/shell_scrubbed_input = tts_speech_filter(message) shell_scrubbed_input = copytext(shell_scrubbed_input, 1, 300) - var/identifier = "[sha1(speaker + filter + num2text(pitch) + num2text(silicon) + shell_scrubbed_input)].[world.time]" + var/identifier = "[sha1(speaker + filter + num2text(pitch) + special_filters + shell_scrubbed_input)].[world.time]" if(!(speaker in available_speakers)) return @@ -288,9 +288,9 @@ SUBSYSTEM_DEF(tts) var/datum/http_request/request_blips = new() var/file_name = "tmp/tts/[identifier].ogg" var/file_name_blips = "tmp/tts/[identifier]_blips.ogg" - request.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts?voice=[speaker]&identifier=[identifier]&filter=[url_encode(filter)]&pitch=[pitch]&silicon=[silicon]", json_encode(list("text" = shell_scrubbed_input)), headers, file_name) - request_blips.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts-blips?voice=[speaker]&identifier=[identifier]&filter=[url_encode(filter)]&pitch=[pitch]&silicon=[silicon]", json_encode(list("text" = shell_scrubbed_input)), headers, file_name_blips) - var/datum/tts_request/current_request = new /datum/tts_request(identifier, request, request_blips, shell_scrubbed_input, target, local, language, message_range, volume_offset, listeners, pitch, silicon) + request.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts?voice=[speaker]&identifier=[identifier]&filter=[url_encode(filter)]&pitch=[pitch]&special_filters=[url_encode(special_filters)]", json_encode(list("text" = shell_scrubbed_input)), headers, file_name) + request_blips.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/tts_http_url)]/tts-blips?voice=[speaker]&identifier=[identifier]&filter=[url_encode(filter)]&pitch=[pitch]&special_filters=[url_encode(special_filters)]", json_encode(list("text" = shell_scrubbed_input)), headers, file_name_blips) + var/datum/tts_request/current_request = new /datum/tts_request(identifier, request, request_blips, shell_scrubbed_input, target, local, language, message_range, volume_offset, listeners, pitch) var/list/player_queued_tts_messages = queued_tts_messages[target] if(!player_queued_tts_messages) player_queued_tts_messages = list() @@ -342,8 +342,6 @@ SUBSYSTEM_DEF(tts) var/use_blips = FALSE /// What's the pitch adjustment? var/pitch = 0 - /// Are we using the silicon vocal effect on this? - var/silicon = "" /datum/tts_request/New(identifier, datum/http_request/request, datum/http_request/request_blips, message, target, local, datum/language/language, message_range, volume_offset, list/listeners, pitch) diff --git a/code/datums/actions/action.dm b/code/datums/actions/action.dm index b43220fb7d4..d81c72cc920 100644 --- a/code/datums/actions/action.dm +++ b/code/datums/actions/action.dm @@ -96,13 +96,15 @@ if(check_flags & AB_CHECK_CONSCIOUS) RegisterSignal(owner, COMSIG_MOB_STATCHANGE, PROC_REF(update_status_on_signal)) if(check_flags & AB_CHECK_INCAPACITATED) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_INCAPACITATED), PROC_REF(update_status_on_signal)) + RegisterSignals(owner, list(SIGNAL_ADDTRAIT(TRAIT_INCAPACITATED), SIGNAL_REMOVETRAIT(TRAIT_INCAPACITATED)), PROC_REF(update_status_on_signal)) if(check_flags & AB_CHECK_IMMOBILE) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_IMMOBILIZED), PROC_REF(update_status_on_signal)) + RegisterSignals(owner, list(SIGNAL_ADDTRAIT(TRAIT_IMMOBILIZED), SIGNAL_REMOVETRAIT(TRAIT_IMMOBILIZED)), PROC_REF(update_status_on_signal)) if(check_flags & AB_CHECK_HANDS_BLOCKED) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_HANDS_BLOCKED), PROC_REF(update_status_on_signal)) + RegisterSignals(owner, list(SIGNAL_ADDTRAIT(TRAIT_HANDS_BLOCKED), SIGNAL_REMOVETRAIT(TRAIT_HANDS_BLOCKED)), PROC_REF(update_status_on_signal)) if(check_flags & AB_CHECK_LYING) RegisterSignal(owner, COMSIG_LIVING_SET_BODY_POSITION, PROC_REF(update_status_on_signal)) + if(check_flags & AB_CHECK_PHASED) + RegisterSignals(owner, list(SIGNAL_ADDTRAIT(TRAIT_MAGICALLY_PHASED), SIGNAL_REMOVETRAIT(TRAIT_MAGICALLY_PHASED)), PROC_REF(update_status_on_signal)) if(owner_has_control) GiveAction(grant_to) @@ -115,7 +117,7 @@ if(!hud.mymob) continue HideFrom(hud.mymob) - LAZYREMOVE(remove_from.actions, src) // We aren't always properly inserted into the viewers list, gotta make sure that action's cleared + LAZYREMOVE(remove_from?.actions, src) // We aren't always properly inserted into the viewers list, gotta make sure that action's cleared viewers = list() if(owner) @@ -130,6 +132,11 @@ SIGNAL_ADDTRAIT(TRAIT_HANDS_BLOCKED), SIGNAL_ADDTRAIT(TRAIT_IMMOBILIZED), SIGNAL_ADDTRAIT(TRAIT_INCAPACITATED), + SIGNAL_ADDTRAIT(TRAIT_MAGICALLY_PHASED), + SIGNAL_REMOVETRAIT(TRAIT_HANDS_BLOCKED), + SIGNAL_REMOVETRAIT(TRAIT_IMMOBILIZED), + SIGNAL_REMOVETRAIT(TRAIT_INCAPACITATED), + SIGNAL_REMOVETRAIT(TRAIT_MAGICALLY_PHASED), )) if(target == owner) @@ -174,6 +181,10 @@ if (feedback) owner.balloon_alert(owner, "unconscious!") return FALSE + if((check_flags & AB_CHECK_PHASED) && HAS_TRAIT(owner, TRAIT_MAGICALLY_PHASED)) + if (feedback) + owner.balloon_alert(owner, "incorporeal!") + return FALSE return TRUE /// Builds / updates all buttons we have shared or given out diff --git a/code/datums/actions/mobs/charge.dm b/code/datums/actions/mobs/charge.dm index 2ae576f5e61..7fb56209777 100644 --- a/code/datums/actions/mobs/charge.dm +++ b/code/datums/actions/mobs/charge.dm @@ -51,6 +51,7 @@ RegisterSignal(charger, COMSIG_MOVABLE_BUMP, PROC_REF(on_bump), TRUE) RegisterSignal(charger, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(on_move), TRUE) RegisterSignal(charger, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved), TRUE) + RegisterSignal(charger, COMSIG_LIVING_DEATH, PROC_REF(charge_end)) charger.setDir(dir) do_charge_indicator(charger, target) @@ -80,10 +81,13 @@ SIGNAL_HANDLER actively_moving = FALSE -/datum/action/cooldown/mob_cooldown/charge/proc/charge_end(datum/move_loop/source) +/datum/action/cooldown/mob_cooldown/charge/proc/charge_end(datum/source) SIGNAL_HANDLER - var/atom/movable/charger = source.moving - UnregisterSignal(charger, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_PRE_MOVE, COMSIG_MOVABLE_MOVED)) + var/atom/movable/charger = source + if(istype(source, /datum/move_loop)) + var/datum/move_loop/move_loop_source = source + charger = move_loop_source.moving + UnregisterSignal(charger, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_PRE_MOVE, COMSIG_MOVABLE_MOVED, COMSIG_LIVING_DEATH)) SEND_SIGNAL(owner, COMSIG_FINISHED_CHARGE) actively_moving = FALSE charging -= charger diff --git a/code/datums/actions/mobs/lava_swoop.dm b/code/datums/actions/mobs/lava_swoop.dm index 9c305ceb13b..7532ccfda08 100644 --- a/code/datums/actions/mobs/lava_swoop.dm +++ b/code/datums/actions/mobs/lava_swoop.dm @@ -147,7 +147,7 @@ if(isindestructiblefloor(T)) continue if(!isindestructiblewall(T)) - T.ChangeTurf(/turf/open/misc/asteroid/basalt/lava_land_surface, flags = CHANGETURF_INHERIT_AIR) + T.TerraformTurf(/turf/open/misc/asteroid/basalt/lava_land_surface, flags = CHANGETURF_INHERIT_AIR) else indestructible_turfs += T SLEEP_CHECK_DEATH(1 SECONDS, owner) // give them a bit of time to realize what attack is actually happening diff --git a/code/datums/actions/mobs/open_mob_commands.dm b/code/datums/actions/mobs/open_mob_commands.dm index 008e7c4dc1b..e7ffd104eff 100644 --- a/code/datums/actions/mobs/open_mob_commands.dm +++ b/code/datums/actions/mobs/open_mob_commands.dm @@ -5,6 +5,7 @@ overlay_icon_state = "bg_heretic_border" button_icon = 'icons/mob/actions/actions_ecult.dmi' button_icon_state = "stargazer_menu" + check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED | AB_CHECK_PHASED /// Weakref for storing our stargazer var/datum/weakref/our_mob diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm index 6683fb02f93..91ba7ec4894 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm @@ -51,6 +51,8 @@ required_distance = 3 /// range we will try chasing the target before giving up var/chase_range = 9 + ///do we care about avoiding friendly fire? + var/avoid_friendly_fire = FALSE /datum/ai_behavior/basic_ranged_attack/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) . = ..() @@ -75,6 +77,10 @@ if(!can_see(basic_mob, final_target, required_distance)) return + if(avoid_friendly_fire && check_friendly_in_path(basic_mob, target, targetting_datum)) + adjust_position(basic_mob, target) + return ..() + controller.set_blackboard_key(hiding_location_key, hiding_target) basic_mob.RangedAttack(final_target) return ..() //only start the cooldown when the shot is shot @@ -83,3 +89,52 @@ . = ..() if(!succeeded) controller.clear_blackboard_key(target_key) + +/datum/ai_behavior/basic_ranged_attack/proc/check_friendly_in_path(mob/living/source, atom/target, datum/targetting_datum/targetting_datum) + var/list/turfs_list = calculate_trajectory(source, target) + for(var/turf/possible_turf as anything in turfs_list) + + for(var/mob/living/potential_friend in possible_turf) + if(!targetting_datum.can_attack(source, potential_friend)) + return TRUE + + return FALSE + +/datum/ai_behavior/basic_ranged_attack/proc/adjust_position(mob/living/living_pawn, atom/target) + var/turf/our_turf = get_turf(living_pawn) + var/list/possible_turfs = list() + + for(var/direction in GLOB.alldirs) + var/turf/target_turf = get_step(our_turf, direction) + if(isnull(target_turf)) + continue + if(target_turf.is_blocked_turf() || get_dist(target_turf, target) > get_dist(living_pawn, target)) + continue + possible_turfs += target_turf + + if(!length(possible_turfs)) + return + var/turf/picked_turf = get_closest_atom(/turf, possible_turfs, target) + step(living_pawn, get_dir(living_pawn, picked_turf)) + +/datum/ai_behavior/basic_ranged_attack/proc/calculate_trajectory(mob/living/source , atom/target) + var/list/turf_list = get_line(source, target) + var/list_length = length(turf_list) - 1 + for(var/i in 1 to list_length) + var/turf/current_turf = turf_list[i] + var/turf/next_turf = turf_list[i+1] + var/direction_to_turf = get_dir(current_turf, next_turf) + if(!ISDIAGONALDIR(direction_to_turf)) + continue + + for(var/cardinal_direction in GLOB.cardinals) + if(cardinal_direction & direction_to_turf) + turf_list += get_step(current_turf, cardinal_direction) + + turf_list -= get_turf(source) + turf_list -= get_turf(target) + + return turf_list + +/datum/ai_behavior/basic_ranged_attack/avoid_friendly_fire + avoid_friendly_fire = TRUE 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 486f9a0fdb2..bd86260ee89 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 @@ -4,7 +4,7 @@ action_cooldown = 0 behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION /// How far do we try to run? Further makes for smoother running, but potentially weirder pathfinding - var/run_distance = 9 + var/run_distance = DEFAULT_BASIC_FLEE_DISTANCE /// Clear target if we finish the action unsuccessfully var/clear_failed_targets = TRUE @@ -12,6 +12,7 @@ var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] if(QDELETED(target)) return FALSE + run_distance = controller.blackboard[BB_BASIC_MOB_FLEE_DISTANCE] || initial(run_distance) if(!plot_path_away_from(controller, target)) return FALSE return ..() @@ -21,13 +22,12 @@ if (!controller.blackboard[BB_BASIC_MOB_FLEEING]) return var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] - var/escaped = QDELETED(target) || !can_see(controller.pawn, target, run_distance) // If we can't see it we got away - if (escaped) + 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) - return - if(plot_path_away_from(controller, target)) + if (get_dist(controller.pawn, controller.current_movement_target) >= required_distance) + return // Still heading over + if (plot_path_away_from(controller, target)) return finish_action(controller, succeeded = FALSE, target_key = target_key, hiding_location_key = hiding_location_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 9d7587c712b..0b9e31db667 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm @@ -2,6 +2,8 @@ action_cooldown = 2 SECONDS /// How far can we see stuff? var/vision_range = 9 + /// Blackboard key for aggro range, uses vision range if not specified + var/aggro_range_key = BB_AGGRO_RANGE /// Static typecache list of potentially dangerous objs var/static/list/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/vehicle/sealed/mecha)) @@ -18,11 +20,13 @@ finish_action(controller, succeeded = FALSE) return + var/aggro_range = controller.blackboard[aggro_range_key] || vision_range + controller.clear_blackboard_key(target_key) - var/list/potential_targets = hearers(vision_range, controller.pawn) - living_mob //Remove self, so we don't suicide + var/list/potential_targets = hearers(aggro_range, controller.pawn) - living_mob //Remove self, so we don't suicide - for(var/HM in typecache_filter_list(range(vision_range, living_mob), hostile_machines)) //Can we see any hostile machines? - if(can_see(living_mob, HM, vision_range)) + 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)) potential_targets += HM if(!potential_targets.len) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm index bbc1a43e322..55f6ef4c4c0 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm @@ -6,6 +6,8 @@ /datum/ai_behavior/travel_towards required_distance = 0 behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + /// If true we will get rid of our target on completion + var/clear_target = FALSE /datum/ai_behavior/travel_towards/setup(datum/ai_controller/controller, target_key) . = ..() @@ -16,7 +18,15 @@ /datum/ai_behavior/travel_towards/perform(seconds_per_tick, datum/ai_controller/controller, target_key) . = ..() - finish_action(controller, TRUE) + finish_action(controller, TRUE, target_key) + +/datum/ai_behavior/travel_towards/finish_action(datum/ai_controller/controller, succeeded, target_key) + . = ..() + if (clear_target) + controller.clear_blackboard_key(target_key) + +/datum/ai_behavior/travel_towards/stop_on_arrival + clear_target = TRUE /** * # Travel Towards Atom 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 a4982fa660e..8d1391f7c7d 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm @@ -9,8 +9,13 @@ /datum/ai_planning_subtree/flee_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() - if (!controller.blackboard[BB_BASIC_MOB_FLEEING] || !controller.blackboard_key_exists(target_key)) + var/atom/flee_from = controller.blackboard[target_key] + if (!controller.blackboard[BB_BASIC_MOB_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) + return + controller.queue_behavior(flee_behaviour, target_key, hiding_place_key) return SUBTREE_RETURN_FINISH_PLANNING //we gotta get out of here. 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 b80a28836a0..c09e7cdbf75 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm @@ -3,7 +3,7 @@ /// Blackboard key holding atom we want to stay away from var/target_key = BB_BASIC_MOB_CURRENT_TARGET /// How close will we allow our target to get? - var/minimum_distance = 3 + var/minimum_distance = 4 /// How far away will we allow our target to get? var/maximum_distance = 6 /// How far do we look for our target? diff --git a/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm b/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm index 005a9ee835d..52f4a3459bf 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm @@ -22,24 +22,31 @@ emote_see = string_list(emote_see) /datum/ai_planning_subtree/random_speech/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - if(SPT_PROB(speech_chance, seconds_per_tick)) - var/audible_emotes_length = emote_hear?.len - var/non_audible_emotes_length = emote_see?.len - var/speak_lines_length = speak?.len + if(!SPT_PROB(speech_chance, seconds_per_tick)) + return + speak(controller) + +/// Actually perform an action +/datum/ai_planning_subtree/random_speech/proc/speak(datum/ai_controller/controller) + var/audible_emotes_length = emote_hear?.len + var/non_audible_emotes_length = emote_see?.len + var/speak_lines_length = speak?.len - var/total_choices_length = audible_emotes_length + non_audible_emotes_length + speak_lines_length + var/total_choices_length = audible_emotes_length + non_audible_emotes_length + speak_lines_length - var/random_number_in_range = rand(1, total_choices_length) + var/random_number_in_range = rand(1, total_choices_length) + var/sound_to_play = length(sound) > 0 ? pick(sound) : null - if(random_number_in_range <= audible_emotes_length) - controller.queue_behavior(/datum/ai_behavior/perform_emote, pick(emote_hear)) - else if(random_number_in_range <= (audible_emotes_length + non_audible_emotes_length)) - controller.queue_behavior(/datum/ai_behavior/perform_emote, pick(emote_see)) - else - controller.queue_behavior(/datum/ai_behavior/perform_speech, pick(speak), length(sound) > 0 ? pick(sound) : null) + if(random_number_in_range <= audible_emotes_length) + controller.queue_behavior(/datum/ai_behavior/perform_emote, pick(emote_hear), sound_to_play) + else if(random_number_in_range <= (audible_emotes_length + non_audible_emotes_length)) + controller.queue_behavior(/datum/ai_behavior/perform_emote, pick(emote_see)) + else + controller.queue_behavior(/datum/ai_behavior/perform_speech, pick(speak), sound_to_play) /datum/ai_planning_subtree/random_speech/insect speech_chance = 5 + sound = list('sound/creatures/chitter.ogg') emote_hear = list("chitters.") /datum/ai_planning_subtree/random_speech/mothroach @@ -49,6 +56,7 @@ /datum/ai_planning_subtree/random_speech/mouse speech_chance = 1 speak = list("Squeak!", "SQUEAK!", "Squeak?") + sound = list('sound/creatures/mousesqueek.ogg') emote_hear = list("squeaks.") emote_see = list("runs in a circle.", "shakes.") @@ -93,12 +101,14 @@ /datum/ai_planning_subtree/random_speech/chicken speech_chance = 15 // really talkative ladies speak = list("Cluck!", "BWAAAAARK BWAK BWAK BWAK!", "Bwaak bwak.") + sound = list('sound/creatures/clucks.ogg', 'sound/creatures/bagawk.ogg') emote_hear = list("clucks.", "croons.") emote_see = list("pecks at the ground.","flaps her wings viciously.") /datum/ai_planning_subtree/random_speech/chick speech_chance = 4 speak = list("Cherp.", "Cherp?", "Chirrup.", "Cheep!") + sound = list('sound/creatures/chick_peep.ogg') emote_hear = list("cheeps.") emote_see = list("pecks at the ground.","flaps her tiny wings.") @@ -160,33 +170,37 @@ /datum/ai_planning_subtree/random_speech/pony speech_chance = 3 + sound = list('sound/creatures/pony/whinny01.ogg', 'sound/creatures/pony/whinny02.ogg', 'sound/creatures/pony/whinny03.ogg') emote_hear = list("whinnies!") emote_see = list("horses around.") /datum/ai_planning_subtree/random_speech/pony/tamed speech_chance = 3 + sound = list('sound/creatures/pony/snort.ogg') + emote_hear = list("snorts.") emote_see = list("snorts.") /datum/ai_planning_subtree/random_speech/killer_tomato speech_chance = 3 - speak = list("gnashes.", "growls lowly.", "snarls.") - emote_hear = list("gnashes.") + emote_hear = list("gnashes.", "growls lowly.", "snarls.") emote_see = list("salivates.") /datum/ai_planning_subtree/random_speech/ant speech_chance = 1 + speak = list("BZZZZT!", "CHTCHTCHT!", "Bzzz", "ChtChtCht") + sound = list('sound/creatures/chitter.ogg') emote_hear = list("buzzes.", "clacks.") emote_see = list("shakes their head.", "twitches their antennae.") - speak = list("BZZZZT!", "CHTCHTCHT!", "Bzzz", "ChtChtCht") /datum/ai_planning_subtree/random_speech/fox speech_chance = 1 + speak = list("Ack-Ack", "Ack-Ack-Ack-Ackawoooo", "Geckers", "Awoo", "Tchoff") emote_hear = list("howls.", "barks.", "screams.") emote_see = list("shakes their head.", "shivers.") - speak = list("Ack-Ack", "Ack-Ack-Ack-Ackawoooo", "Geckers", "Awoo", "Tchoff") /datum/ai_planning_subtree/random_speech/crab speech_chance = 1 + sound = list('sound/creatures/claw_click.ogg') emote_hear = list("clicks.") emote_see = list("clacks.") @@ -207,11 +221,13 @@ var/list/speech_lines = controller.blackboard[BB_BASIC_MOB_SPEAK_LINES] if(isnull(speech_lines)) return ..() - - speak = speech_lines[BB_EMOTE_SAY] ? speech_lines[BB_EMOTE_SAY] : initial(speak) - emote_see = speech_lines[BB_EMOTE_SEE] ? speech_lines[BB_EMOTE_SEE] : initial(emote_see) - emote_hear = speech_lines[BB_EMOTE_HEAR] ? speech_lines[BB_EMOTE_HEAR] : initial(emote_hear) - sound = speech_lines[BB_EMOTE_SOUND] ? speech_lines[BB_EMOTE_SOUND] : initial(sound) + + // Note to future developers: this behaviour a singleton so this probably doesn't work as you would expect + // The whole speech tree really needs to be refactored because this isn't how we use AI data these days + speak = speech_lines[BB_EMOTE_SAY] || list() + emote_see = speech_lines[BB_EMOTE_SEE] || list() + emote_hear = speech_lines[BB_EMOTE_HEAR] || list() + sound = speech_lines[BB_EMOTE_SOUND] || list() speech_chance = speech_lines[BB_EMOTE_CHANCE] ? speech_lines[BB_EMOTE_CHANCE] : initial(speech_chance) return ..() diff --git a/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm b/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm index 8d75f797163..d9ee3ef0918 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm @@ -23,3 +23,6 @@ controller.queue_behavior(use_ability_behaviour, ability_key, target_key) if (finish_planning) return SUBTREE_RETURN_FINISH_PLANNING + +/datum/ai_planning_subtree/targeted_mob_ability/continue_planning + finish_planning = FALSE diff --git a/code/datums/ai/basic_mobs/basic_subtrees/travel_to_point.dm b/code/datums/ai/basic_mobs/basic_subtrees/travel_to_point.dm new file mode 100644 index 00000000000..9ce7cc95c07 --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/travel_to_point.dm @@ -0,0 +1,18 @@ +/// Simply walk to a location +/datum/ai_planning_subtree/travel_to_point + /// Blackboard key where we travel a place we walk to + var/location_key = BB_TRAVEL_DESTINATION + /// What do we do in order to travel + var/travel_behaviour = /datum/ai_behavior/travel_towards + +/datum/ai_planning_subtree/travel_to_point/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + . = ..() + var/atom/target = controller.blackboard[location_key] + if (QDELETED(target)) + return + controller.queue_behavior(travel_behaviour, location_key) + return SUBTREE_RETURN_FINISH_PLANNING + + +/datum/ai_planning_subtree/travel_to_point/and_clear_target + travel_behaviour = /datum/ai_behavior/travel_towards/stop_on_arrival diff --git a/code/datums/ai/basic_mobs/generic_controllers.dm b/code/datums/ai/basic_mobs/generic_controllers.dm new file mode 100644 index 00000000000..208c1833add --- /dev/null +++ b/code/datums/ai/basic_mobs/generic_controllers.dm @@ -0,0 +1,26 @@ +/// The most basic AI tree which just finds a guy and then runs at them to click them +/datum/ai_controller/basic_controller/simple_hostile + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + ) + + 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/basic_melee_attack_subtree, + ) + +/// Find a target, walk at target, attack intervening obstacles +/datum/ai_controller/basic_controller/simple_hostile_obstacles + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + ) + + 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/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) diff --git a/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm b/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm index 8e6c79fda3f..3556e11900f 100644 --- a/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm +++ b/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm @@ -39,3 +39,12 @@ /datum/targetting_datum/not_friends/attack_closed_turfs attack_closed_turf = TRUE + +/// Subtype that allows us to target items while deftly avoiding attacking our allies. Be careful when it comes to targetting items as an AI could get trapped targetting something it can't destroy. +/datum/targetting_datum/basic/not_friends/allow_items + +/datum/targetting_datum/basic/not_friends/allow_items/can_attack(mob/living/living_mob, atom/the_target) + . = ..() + if(isitem(the_target)) + // trust fall exercise + return TRUE diff --git a/code/datums/ai/generic/generic_behaviors.dm b/code/datums/ai/generic/generic_behaviors.dm index e7bfe7a7c60..4f816de4be3 100644 --- a/code/datums/ai/generic/generic_behaviors.dm +++ b/code/datums/ai/generic/generic_behaviors.dm @@ -287,11 +287,13 @@ /datum/ai_behavior/perform_emote -/datum/ai_behavior/perform_emote/perform(seconds_per_tick, datum/ai_controller/controller, emote) +/datum/ai_behavior/perform_emote/perform(seconds_per_tick, datum/ai_controller/controller, emote, speech_sound) var/mob/living/living_pawn = controller.pawn if(!istype(living_pawn)) return living_pawn.manual_emote(emote) + if(speech_sound) // Only audible emotes will pass in a sound + playsound(living_pawn, speech_sound, 80, vary = TRUE) finish_action(controller, TRUE) /datum/ai_behavior/perform_speech @@ -305,6 +307,16 @@ playsound(living_pawn, speech_sound, 80, vary = TRUE) finish_action(controller, TRUE) +/datum/ai_behavior/perform_speech_radio + +/datum/ai_behavior/perform_speech_radio/perform(seconds_per_tick, datum/ai_controller/controller, speech, obj/item/radio/speech_radio, list/try_channels = list(RADIO_CHANNEL_COMMON)) + var/mob/living/living_pawn = controller.pawn + if(!istype(living_pawn) || !istype(speech_radio) || QDELETED(speech_radio) || !length(try_channels)) + finish_action(controller, FALSE) + return + speech_radio.talk_into(living_pawn, speech, pick(try_channels)) + finish_action(controller, TRUE) + //song behaviors /datum/ai_behavior/setup_instrument diff --git a/code/datums/ai/hunting_behavior/hunting_behaviors.dm b/code/datums/ai/hunting_behavior/hunting_behaviors.dm index 036176dc85e..ba7c7f2ffba 100644 --- a/code/datums/ai/hunting_behavior/hunting_behaviors.dm +++ b/code/datums/ai/hunting_behavior/hunting_behaviors.dm @@ -93,7 +93,7 @@ var/mob/living/hunter = controller.pawn var/atom/hunted = controller.blackboard[hunting_target_key] - if(isnull(hunted)) + 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) diff --git a/code/datums/ai/hunting_behavior/hunting_corpses.dm b/code/datums/ai/hunting_behavior/hunting_corpses.dm new file mode 100644 index 00000000000..e720e4da947 --- /dev/null +++ b/code/datums/ai/hunting_behavior/hunting_corpses.dm @@ -0,0 +1,17 @@ +/// Find and attack corpses +/datum/ai_planning_subtree/find_and_hunt_target/corpses + finding_behavior = /datum/ai_behavior/find_hunt_target/corpses + hunting_behavior = /datum/ai_behavior/hunt_target/unarmed_attack_target + hunt_targets = list(/mob/living) + +/// Find nearby dead mobs +/datum/ai_behavior/find_hunt_target/corpses + +/datum/ai_behavior/find_hunt_target/corpses/valid_dinner(mob/living/source, mob/living/dinner, radius) + if (!isliving(dinner) || dinner.stat != DEAD) + return FALSE + return can_see(source, dinner, radius) + +/// Find and attack specifically human corpses +/datum/ai_planning_subtree/find_and_hunt_target/corpses/human + hunt_targets = list(/mob/living/carbon/human) diff --git a/code/datums/ai/movement/ai_movement_jps.dm b/code/datums/ai/movement/ai_movement_jps.dm index 3523da7ecec..da46735ec36 100644 --- a/code/datums/ai/movement/ai_movement_jps.dm +++ b/code/datums/ai/movement/ai_movement_jps.dm @@ -2,7 +2,7 @@ * This movement datum represents smart-pathing */ /datum/ai_movement/jps - max_pathing_attempts = 4 + max_pathing_attempts = 20 /datum/ai_movement/jps/start_moving_towards(datum/ai_controller/controller, atom/current_movement_target, min_distance) . = ..() @@ -12,13 +12,13 @@ var/datum/move_loop/loop = SSmove_manager.jps_move(moving, current_movement_target, delay, - repath_delay = 2 SECONDS, + repath_delay = 0.5 SECONDS, max_path_length = AI_MAX_PATH_LENGTH, minimum_distance = controller.get_minimum_distance(), id = controller.get_access(), subsystem = SSai_movement, extra_info = controller, - initial_path = controller.blackboard[BB_PATH_TO_USE]) + ) RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move)) diff --git a/code/datums/ai/robot_customer/robot_customer_behaviors.dm b/code/datums/ai/robot_customer/robot_customer_behaviors.dm index ff9e59c3931..95260b8e68d 100644 --- a/code/datums/ai/robot_customer/robot_customer_behaviors.dm +++ b/code/datums/ai/robot_customer/robot_customer_behaviors.dm @@ -3,7 +3,7 @@ /datum/ai_behavior/find_seat/perform(seconds_per_tick, datum/ai_controller/controller) . = ..() - var/mob/living/simple_animal/robot_customer/customer_pawn = controller.pawn + var/mob/living/basic/robot_customer/customer_pawn = controller.pawn var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] var/datum/venue/attending_venue = controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] @@ -44,7 +44,7 @@ /datum/ai_behavior/order_food/perform(seconds_per_tick, datum/ai_controller/controller) . = ..() - var/mob/living/simple_animal/robot_customer/customer_pawn = controller.pawn + var/mob/living/basic/robot_customer/customer_pawn = controller.pawn var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] var/obj/structure/holosign/robot_seat/seat_marker = controller.blackboard[BB_CUSTOMER_MY_SEAT] if(get_turf(seat_marker) == get_turf(customer_pawn)) @@ -75,7 +75,7 @@ // SPT_PROB 1.5 is about a 40% chance that the tourist will have vocalised at least once every minute. if(SPT_PROB(0.85, seconds_per_tick)) - var/mob/living/simple_animal/robot_customer/customer_pawn = controller.pawn + var/mob/living/basic/robot_customer/customer_pawn = controller.pawn var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] customer_pawn.say(pick(customer_data.wait_for_food_lines)) @@ -98,7 +98,7 @@ /datum/ai_behavior/wait_for_food/finish_action(datum/ai_controller/controller, succeeded) . = ..() - var/mob/living/simple_animal/robot_customer/customer_pawn = controller.pawn + var/mob/living/basic/robot_customer/customer_pawn = controller.pawn var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] var/mob/living/greytider = controller.blackboard[BB_CUSTOMER_CURRENT_TARGET] //usually if we stop waiting, it's because we're done with the venue. but here we're either beating some dude up diff --git a/code/datums/ai/robot_customer/robot_customer_controller.dm b/code/datums/ai/robot_customer/robot_customer_controller.dm index 2a633590f68..0fc9d27eb43 100644 --- a/code/datums/ai/robot_customer/robot_customer_controller.dm +++ b/code/datums/ai/robot_customer/robot_customer_controller.dm @@ -1,14 +1,16 @@ /datum/ai_controller/robot_customer ai_movement = /datum/ai_movement/basic_avoidance movement_delay = 0.8 SECONDS - blackboard = list(BB_CUSTOMER_CURRENT_ORDER = null, - BB_CUSTOMER_MY_SEAT = null, - BB_CUSTOMER_PATIENCE = 999, - BB_CUSTOMER_CUSTOMERINFO = null, - BB_CUSTOMER_EATING = FALSE, - BB_CUSTOMER_LEAVING = FALSE, - BB_CUSTOMER_ATTENDING_VENUE = null, - BB_CUSTOMER_SAID_CANT_FIND_SEAT_LINE = FALSE) + blackboard = list( + BB_CUSTOMER_ATTENDING_VENUE = null, + BB_CUSTOMER_CURRENT_ORDER = null, + BB_CUSTOMER_CUSTOMERINFO = null, + BB_CUSTOMER_EATING = FALSE, + BB_CUSTOMER_LEAVING = FALSE, + BB_CUSTOMER_MY_SEAT = null, + BB_CUSTOMER_PATIENCE = 999 SECONDS, + BB_CUSTOMER_SAID_CANT_FIND_SEAT_LINE = FALSE, + ) planning_subtrees = list(/datum/ai_planning_subtree/robot_customer) /datum/ai_controller/robot_customer/Destroy() @@ -18,7 +20,7 @@ return ..() /datum/ai_controller/robot_customer/TryPossessPawn(atom/new_pawn) - if(!istype(new_pawn, /mob/living/simple_animal/robot_customer)) + if(!istype(new_pawn, /mob/living/basic/robot_customer)) return AI_CONTROLLER_INCOMPATIBLE new_pawn.AddElement(/datum/element/relay_attackers) RegisterSignal(new_pawn, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) @@ -28,6 +30,12 @@ return ..() //Run parent at end /datum/ai_controller/robot_customer/UnpossessPawn(destroy) + if(isnull(pawn)) +#ifndef UNIT_TESTS + stack_trace("Robot Customer AI Controller UnpossessPawn called with null pawn! This shouldn't happen in normal circumstances.") // and unit tests are abnormal circumstances +#endif + return + UnregisterSignal(pawn, list(COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_WAS_ATTACKED, COMSIG_LIVING_GET_PULLED, COMSIG_ATOM_ATTACK_HAND)) return ..() //Run parent at end @@ -67,7 +75,7 @@ INVOKE_ASYNC(src, PROC_REF(async_on_get_pulled), source, puller) /datum/ai_controller/robot_customer/proc/async_on_get_pulled(datum/source, mob/living/puller) - var/mob/living/simple_animal/robot_customer/customer = pawn + var/mob/living/basic/robot_customer/customer = pawn var/datum/customer_data/customer_data = blackboard[BB_CUSTOMER_CUSTOMERINFO] var/datum/venue/attending_venue = blackboard[BB_CUSTOMER_ATTENDING_VENUE] @@ -81,12 +89,12 @@ /datum/ai_controller/robot_customer/proc/dont_want_that(mob/living/chef, obj/item/thing) - var/mob/living/simple_animal/robot_customer/customer = pawn + var/mob/living/basic/robot_customer/customer = pawn var/datum/customer_data/customer_data = blackboard[BB_CUSTOMER_CUSTOMERINFO] customer.say(customer_data.wrong_item_line) /datum/ai_controller/robot_customer/proc/warn_greytider(mob/living/greytider) - var/mob/living/simple_animal/robot_customer/customer = pawn + var/mob/living/basic/robot_customer/customer = pawn var/datum/venue/attending_venue = blackboard[BB_CUSTOMER_ATTENDING_VENUE] var/datum/customer_data/customer_data = blackboard[BB_CUSTOMER_CUSTOMERINFO] //Living mobs are tagged, so these will always be valid diff --git a/code/datums/atmosphere/_atmosphere.dm b/code/datums/atmosphere/_atmosphere.dm index 1dace1dd1b2..702a42e7ab0 100644 --- a/code/datums/atmosphere/_atmosphere.dm +++ b/code/datums/atmosphere/_atmosphere.dm @@ -52,6 +52,9 @@ ASSERT_GAS_IN_LIST(gastype, gaslist) gaslist[gastype][MOLES] += amount + // Ensure that minimum_pressure is actually a hard lower limit + target_pressure = clamp(target_pressure, minimum_pressure + (gaslist[gastype][MOLES] * 0.1), maximum_pressure) + // That last one put us over the limit, remove some of it while(gasmix.return_pressure() > target_pressure) gaslist[gastype][MOLES] -= gaslist[gastype][MOLES] * 0.1 diff --git a/code/datums/components/acid.dm b/code/datums/components/acid.dm index 9758cd0c1b6..1d9cf9e87d6 100644 --- a/code/datums/components/acid.dm +++ b/code/datums/components/acid.dm @@ -78,8 +78,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e QDEL_NULL(sizzle) if(particle_effect) QDEL_NULL(particle_effect) - if(process_effect) - process_effect = null + process_effect = null return ..() /datum/component/acid/RegisterWithParent() diff --git a/code/datums/components/appearance_on_aggro.dm b/code/datums/components/appearance_on_aggro.dm index affb926d28d..33a3d7c2e90 100644 --- a/code/datums/components/appearance_on_aggro.dm +++ b/code/datums/components/appearance_on_aggro.dm @@ -1,11 +1,14 @@ /** - * component gave to basic creatures to allow them to change appearance when find a target + * Changes visuals of the attached mob while it has a target */ /datum/component/appearance_on_aggro + /// Blackboardey to search for a target var/target_key = BB_BASIC_MOB_CURRENT_TARGET + /// Icon state to use when we have a target + var/aggro_state /// path of the overlay to apply - var/mutable_appearance/overlay_path + var/mutable_appearance/aggro_overlay /// visibility of our icon when aggroed var/alpha_on_aggro /// visibility of our icon when deaggroed @@ -13,20 +16,22 @@ /// do we currently have a target var/atom/current_target -/datum/component/appearance_on_aggro/Initialize(overlay_icon, overlay_state, alpha_on_aggro, alpha_on_deaggro) - if(!isliving(parent)) +/datum/component/appearance_on_aggro/Initialize(aggro_state, overlay_icon, overlay_state, alpha_on_aggro, alpha_on_deaggro) + if (!isliving(parent)) return COMPONENT_INCOMPATIBLE - if(overlay_icon && overlay_state) - src.overlay_path = mutable_appearance(overlay_icon, overlay_state) - if(!alpha_on_aggro || !alpha_on_deaggro) - return + src.aggro_state = aggro_state src.alpha_on_aggro = alpha_on_aggro src.alpha_on_deaggro = alpha_on_deaggro + if (!isnull(overlay_icon) && !isnull(overlay_state)) + aggro_overlay = mutable_appearance(overlay_icon, overlay_state) /datum/component/appearance_on_aggro/RegisterWithParent() - RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(change_overlays)) RegisterSignal(parent, COMSIG_AI_BLACKBOARD_KEY_SET(target_key), PROC_REF(on_set_target)) RegisterSignal(parent, COMSIG_AI_BLACKBOARD_KEY_CLEARED(target_key), PROC_REF(on_clear_target)) + if (!isnull(aggro_state)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_ICON_STATE, PROC_REF(on_icon_state_updated)) + if (!isnull(aggro_overlay)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_overlays_updated)) /datum/component/appearance_on_aggro/UnregisterFromParent() . = ..() @@ -36,37 +41,42 @@ SIGNAL_HANDLER var/atom/target = source.ai_controller.blackboard[target_key] - if(isnull(target)) + if (QDELETED(target)) return + current_target = target RegisterSignal(target, COMSIG_QDELETING, PROC_REF(on_clear_target)) - if(overlay_path) - source.update_appearance(UPDATE_OVERLAYS) - if(alpha_on_aggro) + if (!isnull(aggro_overlay) || !isnull(aggro_state)) + source.update_appearance(UPDATE_ICON) + if (!isnull(alpha_on_aggro)) animate(source, alpha = alpha_on_aggro, time = 2 SECONDS) /datum/component/appearance_on_aggro/Destroy() - if(current_target) + if (!isnull(current_target)) revert_appearance(parent) return ..() /datum/component/appearance_on_aggro/proc/on_clear_target(atom/source) SIGNAL_HANDLER - revert_appearance(parent) /datum/component/appearance_on_aggro/proc/revert_appearance(mob/living/source) UnregisterSignal(current_target, COMSIG_QDELETING) current_target = null - if(overlay_path) - source.update_appearance(UPDATE_OVERLAYS) - if(alpha_on_deaggro) + if (!isnull(aggro_overlay) || !isnull(aggro_state)) + source.update_appearance(UPDATE_ICON) + if (!isnull(alpha_on_deaggro)) animate(source, alpha = alpha_on_deaggro, time = 2 SECONDS) -/datum/component/appearance_on_aggro/proc/change_overlays(atom/source, list/overlays) +/datum/component/appearance_on_aggro/proc/on_icon_state_updated(mob/living/source) SIGNAL_HANDLER - - if(isnull(current_target)) + if (source.stat == DEAD) return + source.icon_state = isnull(current_target) ? initial(source.icon_state) : aggro_state - overlays += overlay_path +/datum/component/appearance_on_aggro/proc/on_overlays_updated(atom/source, list/overlays) + SIGNAL_HANDLER + + if (isnull(current_target)) + return + overlays += aggro_overlay diff --git a/code/datums/components/bakeable.dm b/code/datums/components/bakeable.dm index 5aa60cd89a7..537ae62ddbe 100644 --- a/code/datums/components/bakeable.dm +++ b/code/datums/components/bakeable.dm @@ -67,8 +67,9 @@ 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) - baked_result.reagents.clear_reagents() - original_object.reagents?.trans_to(baked_result, original_object.reagents.total_volume) + if(baked_result.reagents) //make space and tranfer reagents if it has any + baked_result.reagents.clear_reagents() + original_object.reagents.trans_to(baked_result, original_object.reagents.total_volume) if(who_baked_us) ADD_TRAIT(baked_result, TRAIT_FOOD_CHEF_MADE, who_baked_us) diff --git a/code/datums/components/blob_minion.dm b/code/datums/components/blob_minion.dm new file mode 100644 index 00000000000..41f58231e2d --- /dev/null +++ b/code/datums/components/blob_minion.dm @@ -0,0 +1,154 @@ +/** + * Common behaviour shared by things which are minions to a blob + */ +/datum/component/blob_minion + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + /// Overmind who is our boss + var/mob/camera/blob/overmind + /// Callback to run if overmind strain changes + var/datum/callback/on_strain_changed + +/datum/component/blob_minion/Initialize(mob/camera/blob/overmind, datum/callback/on_strain_changed) + . = ..() + if (!isliving(parent)) + return COMPONENT_INCOMPATIBLE + src.on_strain_changed = on_strain_changed + register_overlord(overmind) + +/datum/component/blob_minion/InheritComponent(datum/component/new_comp, i_am_original, mob/camera/blob/overmind, datum/callback/on_strain_changed) + if (!isnull(on_strain_changed)) + src.on_strain_changed = on_strain_changed + register_overlord(overmind) + +/datum/component/blob_minion/proc/register_overlord(mob/camera/blob/overmind) + if (isnull(overmind)) + return + src.overmind = overmind + overmind.register_new_minion(parent) + RegisterSignal(overmind, COMSIG_QDELETING, PROC_REF(overmind_deleted)) + RegisterSignal(overmind, COMSIG_BLOB_SELECTED_STRAIN, PROC_REF(overmind_properties_changed)) + overmind_properties_changed(overmind, overmind.blobstrain) + +/// Our overmind is gone, uh oh! +/datum/component/blob_minion/proc/overmind_deleted() + SIGNAL_HANDLER + overmind = null + overmind_properties_changed() + +/// Our overmind has changed colour and properties +/datum/component/blob_minion/proc/overmind_properties_changed(mob/camera/blob/overmind, datum/blobstrain/new_strain) + SIGNAL_HANDLER + var/mob/living/living_parent = parent + living_parent.update_appearance(UPDATE_ICON) + on_strain_changed?.Invoke(overmind, new_strain) + +/datum/component/blob_minion/RegisterWithParent() + var/mob/living/living_parent = parent + living_parent.pass_flags |= PASSBLOB + living_parent.faction |= ROLE_BLOB + ADD_TRAIT(parent, TRAIT_BLOB_ALLY, REF(src)) + remove_verb(parent, /mob/living/verb/pulled) // No dragging people into the blob + RegisterSignal(parent, COMSIG_MOB_MIND_INITIALIZED, PROC_REF(on_mind_init)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_ICON, PROC_REF(on_update_appearance)) + RegisterSignal(parent, COMSIG_MOB_GET_STATUS_TAB_ITEMS, PROC_REF(on_update_status_tab)) + RegisterSignal(parent, COMSIG_ATOM_BLOB_ACT, PROC_REF(on_blob_touched)) + RegisterSignal(parent, COMSIG_ATOM_FIRE_ACT, PROC_REF(on_burned)) + RegisterSignal(parent, COMSIG_ATOM_TRIED_PASS, PROC_REF(on_attempted_pass)) + RegisterSignal(parent, COMSIG_MOVABLE_SPACEMOVE, PROC_REF(on_space_move)) + RegisterSignal(parent, COMSIG_LIVING_TRY_SPEECH, PROC_REF(on_try_speech)) + RegisterSignal(parent, COMSIG_MOB_CHANGED_TYPE, PROC_REF(on_transformed)) + living_parent.update_appearance(UPDATE_ICON) + GLOB.blob_telepathy_mobs |= parent + +/datum/component/blob_minion/UnregisterFromParent() + if (!isnull(overmind)) + overmind.blob_mobs -= parent + var/mob/living/living_parent = parent + living_parent.pass_flags &= ~PASSBLOB + living_parent.faction -= ROLE_BLOB + REMOVE_TRAIT(parent, TRAIT_BLOB_ALLY, REF(src)) + add_verb(parent, /mob/living/verb/pulled) + UnregisterSignal(parent, list( + COMSIG_ATOM_BLOB_ACT, + COMSIG_ATOM_FIRE_ACT, + COMSIG_ATOM_TRIED_PASS, + COMSIG_ATOM_UPDATE_ICON, + COMSIG_LIVING_TRY_SPEECH, + COMSIG_MOB_CHANGED_TYPE, + COMSIG_MOB_GET_STATUS_TAB_ITEMS, + COMSIG_MOB_MIND_INITIALIZED, + COMSIG_MOVABLE_SPACEMOVE, + )) + GLOB.blob_telepathy_mobs -= parent + +/// Become blobpilled when we gain a mind +/datum/component/blob_minion/proc/on_mind_init(mob/living/minion, datum/mind/new_mind) + SIGNAL_HANDLER + if (isnull(overmind)) + return + var/datum/antagonist/blob_minion/minion_motive = new(overmind) + new_mind.add_antag_datum(minion_motive) + +/// When our icon is updated, update our colour too +/datum/component/blob_minion/proc/on_update_appearance(mob/living/minion) + SIGNAL_HANDLER + if(isnull(overmind)) + minion.remove_atom_colour(FIXED_COLOUR_PRIORITY) + return + minion.add_atom_colour(overmind.blobstrain.color, FIXED_COLOUR_PRIORITY) + +/// When our icon is updated, update our colour too +/datum/component/blob_minion/proc/on_update_status_tab(mob/living/minion, list/status_items) + SIGNAL_HANDLER + if (isnull(overmind)) + return + status_items += "Blobs to Win: [length(overmind.blobs_legit)]/[overmind.blobwincount]" + +/// If we feel the gentle caress of a blob, we feel better +/datum/component/blob_minion/proc/on_blob_touched(mob/living/minion) + SIGNAL_HANDLER + if(minion.stat == DEAD || minion.health >= minion.maxHealth) + return COMPONENT_CANCEL_BLOB_ACT // Don't hurt us in order to heal us + for(var/i in 1 to 2) + var/obj/effect/temp_visual/heal/heal_effect = new /obj/effect/temp_visual/heal(get_turf(parent)) // hello yes you are being healed + heal_effect.color = isnull(overmind) ? COLOR_BLACK : overmind.blobstrain.complementary_color + minion.heal_overall_damage(minion.maxHealth * BLOBMOB_HEALING_MULTIPLIER) + return COMPONENT_CANCEL_BLOB_ACT + +/// If we feel the fearsome bite of open flame, we feel worse +/datum/component/blob_minion/proc/on_burned(mob/living/minion, exposed_temperature, exposed_volume) + SIGNAL_HANDLER + if(isnull(exposed_temperature)) + minion.adjustFireLoss(5) + return + minion.adjustFireLoss(clamp(0.01 * exposed_temperature, 1, 5)) + +/// Someone is attempting to move through us, allow it if it is a blob tile +/datum/component/blob_minion/proc/on_attempted_pass(mob/living/minion, atom/movable/incoming) + SIGNAL_HANDLER + if(istype(incoming, /obj/structure/blob)) + return COMSIG_COMPONENT_PERMIT_PASSAGE + +/// If we're near a blob, stop drifting +/datum/component/blob_minion/proc/on_space_move(mob/living/minion) + SIGNAL_HANDLER + var/obj/structure/blob/blob_handhold = locate() in range(1, parent) + if (!isnull(blob_handhold)) + return COMSIG_MOVABLE_STOP_SPACEMOVE + +/// We only speak telepathically to blobs +/datum/component/blob_minion/proc/on_try_speech(mob/living/minion, message, ignore_spam, forced) + SIGNAL_HANDLER + var/spanned_message = minion.say_quote(message) + var/rendered = span_blob("\[Blob Telepathy\] [minion.real_name] [spanned_message]") + blob_telepathy(rendered, minion) + return COMPONENT_CANNOT_SPEAK + +/// Called when a blob minion is transformed into something else, hopefully a spore into a zombie +/datum/component/blob_minion/proc/on_transformed(mob/living/minion, mob/living/replacement) + SIGNAL_HANDLER + overmind?.assume_direct_control(replacement) + +/datum/component/blob_minion/PostTransfer() + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm index fc93123921c..18420016c54 100644 --- a/code/datums/components/chasm.dm +++ b/code/datums/components/chasm.dm @@ -8,28 +8,29 @@ /// List of refs to falling objects -> how many levels deep we've fallen var/static/list/falling_atoms = list() var/static/list/forbidden_types = typecacheof(list( - /obj/singularity, - /obj/energy_ball, - /obj/narsie, /obj/docking_port, - /obj/structure/lattice, - /obj/structure/stone_tile, - /obj/projectile, - /obj/effect/projectile, - /obj/effect/portal, /obj/effect/abstract, + /obj/effect/collapse, + /obj/effect/constructing_effect, + /obj/effect/dummy/phased_mob, + /obj/effect/ebeam, + /obj/effect/fishing_lure, /obj/effect/hotspot, /obj/effect/landmark, - /obj/effect/temp_visual, /obj/effect/light_emitter/tendril, - /obj/effect/collapse, - /obj/effect/particle_effect/ion_trails, - /obj/effect/dummy/phased_mob, /obj/effect/mapping_helpers, + /obj/effect/particle_effect/ion_trails, + /obj/effect/portal, + /obj/effect/projectile, + /obj/effect/spectre_of_resurrection, + /obj/effect/temp_visual, /obj/effect/wisp, - /obj/effect/ebeam, - /obj/effect/fishing_lure, - /obj/effect/constructing_effect, + /obj/energy_ball, + /obj/narsie, + /obj/projectile, + /obj/singularity, + /obj/structure/lattice, + /obj/structure/stone_tile, )) /datum/component/chasm/Initialize(turf/target, mapload) diff --git a/code/datums/components/crafting/_recipes.dm b/code/datums/components/crafting/_recipes.dm index 246f04df0f5..4254804974e 100644 --- a/code/datums/components/crafting/_recipes.dm +++ b/code/datums/components/crafting/_recipes.dm @@ -17,7 +17,7 @@ var/list/tool_paths ///time in seconds. Remember to use the SECONDS define! var/time = 3 SECONDS - ///type paths of items that will be placed in the result + ///type paths of items that will be forceMoved() into the result, or added to the reagents of it var/list/parts = list() ///like tool_behaviors but for reagents var/list/chem_catalysts = list() diff --git a/code/datums/components/crafting/guncrafting.dm b/code/datums/components/crafting/guncrafting.dm index f239288b031..a5a20d4326b 100644 --- a/code/datums/components/crafting/guncrafting.dm +++ b/code/datums/components/crafting/guncrafting.dm @@ -2,12 +2,27 @@ // PARTS // +/obj/item/weaponcrafting/Initialize(mapload) + . = ..() + create_slapcraft_component() + +/obj/item/weaponcrafting/proc/create_slapcraft_component() + return + /obj/item/weaponcrafting/receiver name = "modular receiver" desc = "A prototype modular receiver and trigger assembly for a firearm." icon = 'icons/obj/weapons/improvised.dmi' icon_state = "receiver" +/obj/item/weaponcrafting/receiver/create_slapcraft_component() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/pipegun) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/weaponcrafting/stock name = "rifle stock" desc = "A classic rifle stock that doubles as a grip, roughly carved out of wood." @@ -16,17 +31,33 @@ icon = 'icons/obj/weapons/improvised.dmi' icon_state = "riflestock" +/obj/item/weaponcrafting/stock/create_slapcraft_component() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/smoothbore_disabler, /datum/crafting_recipe/laser_musket) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/weaponcrafting/giant_wrench name = "Big Slappy parts kit" desc = "Illegal parts to make a giant like wrench commonly known as a Big Slappy." icon = 'icons/obj/weapons/improvised.dmi' icon_state = "weaponkit_gw" +/obj/item/weaponcrafting/giant_wrench/create_slapcraft_component() // slappycraft + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/giant_wrench) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + ///These gun kits are printed from the security protolathe to then be used in making new weapons // GUN PART KIT // -/obj/item/weaponcrafting/gunkit +/obj/item/weaponcrafting/gunkit // These don't get a slapcraft component, it's added to the gun - more intuitive player-facing to slap the kit onto the gun. name = "generic gun parts kit" desc = "It's an empty gun parts container! Why do you have this?" icon = 'icons/obj/weapons/improvised.dmi' diff --git a/code/datums/components/crafting/slapcrafting.dm b/code/datums/components/crafting/slapcrafting.dm new file mode 100644 index 00000000000..32a901dc73e --- /dev/null +++ b/code/datums/components/crafting/slapcrafting.dm @@ -0,0 +1,202 @@ +/// Slapcrafting component! +/datum/component/slapcrafting + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + var/list/slapcraft_recipes = list() + +/** + * Slapcraft component + * + * Slap it onto a item to be able to slapcraft with it + * + * args: + * * slapcraft_recipes (required) = The recipe to attempt crafting. + * Hit it with an ingredient of the recipe to attempt crafting. + * It will check the area near the user for the rest of the ingredients and tools. + * * +**/ +/datum/component/slapcrafting/Initialize( + slapcraft_recipes = null, + ) + + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + var/obj/item/parent_item = parent + + if((parent_item.item_flags & ABSTRACT) || (parent_item.item_flags & DROPDEL)) + return COMPONENT_NOTRANSFER + + RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(attempt_slapcraft)) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(get_examine_info)) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(get_examine_more_info)) + RegisterSignal(parent, COMSIG_TOPIC, PROC_REF(topic_handler)) + + src.slapcraft_recipes += slapcraft_recipes + +/datum/component/slapcrafting/InheritComponent(datum/component/slapcrafting/new_comp, original, slapcraft_recipes) + if(!original) + return + src.slapcraft_recipes += slapcraft_recipes + +/datum/component/slapcrafting/Destroy(force, silent) + UnregisterSignal(parent, list(COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_EXAMINE, COMSIG_ATOM_EXAMINE_MORE)) + return ..() + +/datum/component/slapcrafting/proc/attempt_slapcraft(obj/item/parent_item, obj/item/slapper, mob/user) + + if(isnull(slapcraft_recipes)) + CRASH("NULL SLAPCRAFT RECIPES?") + + var/datum/component/personal_crafting/craft_sheet = user.GetComponent(/datum/component/personal_crafting) + if(!craft_sheet) + CRASH("No craft sheet on user ??") + + var/list/valid_recipes + for(var/datum/crafting_recipe/recipe as anything in slapcraft_recipes) + // Gotta instance it to copy the list over. + recipe = new recipe() + var/list/type_ingredient_list = recipe.reqs + qdel(recipe) + if(length(type_ingredient_list) == 1) // No ingredients besides itself? We use one of the tools then + type_ingredient_list = recipe.tool_paths + // Check the tool behaviours differently as they aren't types + for(var/behaviour in initial(recipe.tool_behaviors)) + if(slapper.tool_behaviour == behaviour) + LAZYADD(valid_recipes, recipe) + break + if(is_type_in_list(slapper, type_ingredient_list)) + LAZYADD(valid_recipes, recipe) + + if(!valid_recipes) + return + + // We might use radials so we need to split the proc chain + INVOKE_ASYNC(src, PROC_REF(slapcraft_async), valid_recipes, user, craft_sheet) + +/datum/component/slapcrafting/proc/slapcraft_async(list/valid_recipes, mob/user, datum/component/personal_crafting/craft_sheet) + + var/list/recipe_choices = list() + + var/list/result_to_recipe = list() + + var/final_recipe = valid_recipes[1] + var/string_chosen_recipe + if(length(valid_recipes) > 1) + for(var/datum/crafting_recipe/recipe as anything in valid_recipes) + var/atom/recipe_result = initial(recipe.result) + result_to_recipe[initial(recipe_result.name)] = recipe + recipe_choices += list("[initial(recipe_result.name)]" = image(icon = initial(recipe_result.icon), icon_state = initial(recipe_result.icon_state))) + + if(!recipe_choices) + CRASH("No recipe choices despite validating in earlier proc") + + string_chosen_recipe = show_radial_menu(user, parent, recipe_choices, require_near = TRUE) + if(isnull(string_chosen_recipe)) + return // they closed the thing + + if(string_chosen_recipe) + final_recipe = result_to_recipe[string_chosen_recipe] + + + var/datum/crafting_recipe/actual_recipe = final_recipe + + if(istype(actual_recipe, /datum/crafting_recipe/food)) + actual_recipe = locate(final_recipe) in GLOB.cooking_recipes + else + actual_recipe = locate(final_recipe) in GLOB.crafting_recipes + + if(!actual_recipe) + CRASH("Recipe not located in cooking or crafting recipes: [final_recipe]") + + var/atom/final_result = initial(actual_recipe.result) + + to_chat(user, span_notice("You start crafting \a [initial(final_result.name)]...")) + + var/error_string = craft_sheet.construct_item(user, actual_recipe) + + if(!isatom(error_string)) + to_chat(user, span_warning("crafting failed" + error_string)) + +/// Alerts any examiners to the recipe, if they wish to know more. +/datum/component/slapcrafting/proc/get_examine_info(atom/source, mob/user, list/examine_list) + SIGNAL_HANDLER + + var/list/string_results = list() + // This list saves the recipe result names we've already used to cross-check other recipes so we don't have ', a spear, or a spear!' in the desc. + var/list/already_used_names + for(var/datum/crafting_recipe/recipe as anything in slapcraft_recipes) + // Identical name to a previous recipe's result? Skip in description. + var/atom/result = initial(recipe.result) + if(locate(initial(result.name)) in already_used_names) + continue + already_used_names += initial(result.name) + string_results += list("\a [initial(result.name)]") + + examine_list += span_notice("You think [parent] could be used to make [english_list(string_results)]! Examine again to look at the details...") + +/// Alerts any examiners to the details of the recipe. +/datum/component/slapcrafting/proc/get_examine_more_info(atom/source, mob/user, list/examine_list) + SIGNAL_HANDLER + + for(var/datum/crafting_recipe/recipe as anything in slapcraft_recipes) + var/atom/result = initial(recipe.result) + examine_list += "See Recipe For [initial(result.name)]" + +/datum/component/slapcrafting/proc/topic_handler(atom/source, user, href_list) + SIGNAL_HANDLER + + if(!href_list["check_recipe"]) + return + + var/datum/crafting_recipe/cur_recipe = locate(href_list["check_recipe"]) in slapcraft_recipes + + if(isnull(cur_recipe)) + CRASH("null recipe!") + + var/atom/result = initial(cur_recipe.result) + + to_chat(user, span_notice("You could craft \a [initial(result.name)] by applying one of these items to it!")) + + // Gotta instance it to copy the lists over. + cur_recipe = new cur_recipe() + var/list/type_ingredient_list = cur_recipe.reqs + + // Final return string. + var/string_ingredient_list = "" + + // Check the ingredients of the crafting recipe. + for(var/valid_type in type_ingredient_list) + // Check if they're datums, specifically reagents. + var/datum/reagent/reagent_ingredient = valid_type + if(istype(reagent_ingredient)) + var/amount = initial(cur_recipe.reqs[reagent_ingredient]) + string_ingredient_list += "[amount] unit[amount > 1 ? "s" : ""] of [initial(reagent_ingredient.name)]\n" + + // Redundant! + if(parent.type == valid_type) + continue + var/atom/ingredient = valid_type + var/amount = initial(cur_recipe.reqs[ingredient]) + string_ingredient_list += "[amount > 1 ? ("[amount]" + " of") : "a"] [initial(ingredient.name)]\n" + + // If we did find ingredients then add them onto the list. + if(length(string_ingredient_list)) + to_chat(user, span_boldnotice("Ingredients:")) + to_chat(user, examine_block(span_notice(string_ingredient_list))) + + var/list/tool_list = "" + + // Paste the required tools. + for(var/valid_type in cur_recipe.tool_paths) + var/atom/tool = valid_type + tool_list += "\a [initial(tool.name)]\n" + + for(var/string in cur_recipe.tool_behaviors) + tool_list += "\a [string]\n" + + if(length(tool_list)) + to_chat(user, span_boldnotice("Required Tools:")) + to_chat(user, examine_block(span_notice(tool_list))) + + qdel(cur_recipe) + diff --git a/code/datums/components/crafting/tools.dm b/code/datums/components/crafting/tools.dm index cc2d510bd25..f126bdff538 100644 --- a/code/datums/components/crafting/tools.dm +++ b/code/datums/components/crafting/tools.dm @@ -46,3 +46,12 @@ ) result = /obj/item/pickaxe/improvised category = CAT_TOOLS + +/datum/crafting_recipe/bandage + name = "Makeshift Bandage" + reqs = list( + /obj/item/stack/sheet/cloth = 3, + /datum/reagent/medicine/c2/libital = 10, + ) + result = /obj/item/stack/medical/bandage/makeshift + category = CAT_TOOLS diff --git a/code/datums/components/death_linked.dm b/code/datums/components/death_linked.dm new file mode 100644 index 00000000000..59d2ce5e855 --- /dev/null +++ b/code/datums/components/death_linked.dm @@ -0,0 +1,30 @@ +/** + * ## Death link component + * + * When the owner of this component dies it also gibs a linked mob + */ +/datum/component/death_linked + ///The mob that also dies when the user dies + var/datum/weakref/linked_mob + +/datum/component/death_linked/Initialize(mob/living/target_mob) + . = ..() + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + if(isnull(target_mob)) + stack_trace("[type] added to [parent] with no linked mob.") + src.linked_mob = WEAKREF(target_mob) + +/datum/component/death_linked/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(on_death)) + +/datum/component/death_linked/UnregisterFromParent() + . = ..() + UnregisterSignal(parent, COMSIG_LIVING_DEATH) + +///signal called by the stat of the target changing +/datum/component/death_linked/proc/on_death(mob/living/target, gibbed) + SIGNAL_HANDLER + var/mob/living/linked_mob_resolved = linked_mob?.resolve() + linked_mob_resolved?.gib() diff --git a/code/datums/components/fishing_spot.dm b/code/datums/components/fishing_spot.dm index 3f230b8754d..f88c27a7135 100644 --- a/code/datums/components/fishing_spot.dm +++ b/code/datums/components/fishing_spot.dm @@ -12,6 +12,7 @@ fish_source = configuration else return COMPONENT_INCOMPATIBLE + fish_source.on_fishing_spot_init() RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(handle_attackby)) RegisterSignal(parent, COMSIG_FISHING_ROD_CAST, PROC_REF(handle_cast)) diff --git a/code/datums/components/food/ice_cream_holder.dm b/code/datums/components/food/ice_cream_holder.dm index 9e25c7cb4b4..3e212c52b9a 100644 --- a/code/datums/components/food/ice_cream_holder.dm +++ b/code/datums/components/food/ice_cream_holder.dm @@ -33,14 +33,16 @@ var/datum/reagent/sweetener -/datum/component/ice_cream_holder/Initialize(max_scoops = DEFAULT_MAX_ICE_CREAM_SCOOPS, - change_name = TRUE, - filled_name, - change_desc = FALSE, - x_offset = 0, - y_offset = 0, - datum/reagent/sweetener = /datum/reagent/consumable/sugar, - list/prefill_flavours) +/datum/component/ice_cream_holder/Initialize( + max_scoops = DEFAULT_MAX_ICE_CREAM_SCOOPS, + change_name = TRUE, + filled_name, + change_desc = FALSE, + x_offset = 0, + y_offset = 0, + datum/reagent/sweetener = /datum/reagent/consumable/sugar, + list/prefill_flavours, +) if(!IS_EDIBLE(parent)) /// There is no easy way to add servings to those non-item edibles, but I won't stop you. return COMPONENT_INCOMPATIBLE @@ -169,7 +171,7 @@ if(compare_list(our_scoops, icecream_order.wanted_flavors)) return COMPONENT_CORRECT_ORDER -/datum/component/ice_cream_holder/proc/sell_ice_cream(obj/item/source, mob/living/simple_animal/robot_customer/sold_to) +/datum/component/ice_cream_holder/proc/sell_ice_cream(obj/item/source, mob/living/basic/robot_customer/sold_to) SIGNAL_HANDLER //the price of ice cream scales with the number of scoops. Yummy. diff --git a/code/datums/components/religious_tool.dm b/code/datums/components/religious_tool.dm index e64e28f83a3..4c0646b3a55 100644 --- a/code/datums/components/religious_tool.dm +++ b/code/datums/components/religious_tool.dm @@ -74,9 +74,9 @@ /**********Sacrificing**********/ else if(operation_flags & RELIGION_TOOL_SACRIFICE) - if(easy_access_sect?.can_sacrifice(the_item,user)) + if(!easy_access_sect?.can_sacrifice(the_item, user)) return - easy_access_sect.on_sacrifice(the_item,user) + easy_access_sect.on_sacrifice(the_item, user) return COMPONENT_NO_AFTERATTACK /datum/component/religious_tool/ui_interact(mob/user, datum/tgui/ui) diff --git a/code/datums/components/supermatter_crystal.dm b/code/datums/components/supermatter_crystal.dm index a9bdfc5b154..66087134388 100644 --- a/code/datums/components/supermatter_crystal.dm +++ b/code/datums/components/supermatter_crystal.dm @@ -17,6 +17,7 @@ RegisterSignal(parent, COMSIG_ATOM_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)) src.tool_act_callback = tool_act_callback src.consume_callback = consume_callback @@ -38,6 +39,7 @@ COMSIG_ATOM_TOOL_ACT(TOOL_WRENCH), COMSIG_ATOM_BUMPED, COMSIG_ATOM_INTERCEPT_Z_FALL, + COMSIG_ATOM_ON_Z_IMPACT, ) UnregisterSignal(parent, signals_to_remove) @@ -152,6 +154,8 @@ return if(istype(item, /obj/item/melee/roastingstick)) return FALSE + if(istype(item, /obj/item/toy/crayon/spraycan)) + return FALSE if(istype(item, /obj/item/clothing/mask/cigarette)) var/obj/item/clothing/mask/cigarette/cig = item var/clumsy = HAS_TRAIT(user, TRAIT_CLUMSY) @@ -232,11 +236,36 @@ /datum/component/supermatter_crystal/proc/intercept_z_fall(datum/source, list/falling_movables, levels) SIGNAL_HANDLER for(var/atom/movable/hit_object as anything in falling_movables) - if(hit_object == source) - continue + if(parent == hit_object) + return + bumped_hit(parent, hit_object) return FALL_INTERCEPTED | FALL_NO_MESSAGE +/datum/component/supermatter_crystal/proc/on_z_impact(datum/source, turf/impacted_turf, levels) + SIGNAL_HANDLER + + var/atom/atom_source = source + + for(var/mob/living/poor_target in impacted_turf) + consume(atom_source, poor_target) + playsound(get_turf(atom_source), 'sound/effects/supermatter.ogg', 50, TRUE) + poor_target.visible_message(span_danger("\The [atom_source] slams into \the [poor_target] out of nowhere inducing a resonance... [poor_target.p_their()] body starts to glow and burst into flames before flashing into dust!"), + span_userdanger("\The [atom_source] slams into you out of nowhere as your ears are filled with unearthly ringing. Your last thought is \"The fuck.\""), + span_hear("You hear an unearthly noise as a wave of heat washes over you.")) + + for(var/atom/movable/hit_object as anything in impacted_turf) + if(parent == hit_object) + return + + if(iseffect(hit_object)) + continue + + consume(atom_source, hit_object) + playsound(get_turf(atom_source), 'sound/effects/supermatter.ogg', 50, TRUE) + atom_source.visible_message(span_danger("\The [atom_source], smacks into the plating out of nowhere, reducing everything below to ash."), null, + span_hear("You hear a loud crack as you are washed with a wave of heat.")) + /datum/component/supermatter_crystal/proc/dust_mob(datum/source, mob/living/nom, vis_msg, mob_msg, cause) if(nom.incorporeal_move || nom.status_flags & GODMODE) //try to keep supermatter sliver's + hemostat's dust conditions in sync with this too return diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index ffd20cc2c13..4ae3a973d7e 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -205,7 +205,8 @@ user.visible_message(span_warning("[user] lands an expert [tackle_word] on [target], knocking [target.p_them()] down hard while landing on [user.p_their()] feet with a passive grip!"), span_userdanger("You land an expert [tackle_word] on [target], knocking [target.p_them()] down hard while landing on your feet with a passive grip!"), ignored_mobs = target) to_chat(target, span_userdanger("[user] lands an expert [tackle_word] on you, knocking you down hard and maintaining a passive grab!")) - user.SetKnockdown(0) + // Ignore_canstun has to be true, or else a stunimmune user would stay knocked down. + user.SetKnockdown(0, ignore_canstun = TRUE) user.get_up(TRUE) user.forceMove(get_turf(target)) target.adjustStaminaLoss(40) @@ -228,7 +229,8 @@ user.visible_message(span_warning("[user] lands a monster [tackle_word] on [target], knocking [target.p_them()] senseless and applying an aggressive pin!"), span_userdanger("You land a monster [tackle_word] on [target], knocking [target.p_them()] senseless and applying an aggressive pin!"), ignored_mobs = target) to_chat(target, span_userdanger("[user] lands a monster [tackle_word] on you, knocking you senseless and aggressively pinning you!")) - user.SetKnockdown(0) + // Ignore_canstun has to be true, or else a stunimmune user would stay knocked down. + user.SetKnockdown(0, ignore_canstun = TRUE) user.get_up(TRUE) user.forceMove(get_turf(target)) target.adjustStaminaLoss(40) diff --git a/code/datums/components/wall_mounted.dm b/code/datums/components/wall_mounted.dm index 6164d39b001..8d1722f89fe 100644 --- a/code/datums/components/wall_mounted.dm +++ b/code/datums/components/wall_mounted.dm @@ -17,7 +17,7 @@ /datum/component/wall_mounted/RegisterWithParent() RegisterSignal(hanging_wall_turf, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) - RegisterSignal(hanging_wall_turf, COMSIG_TURF_CHANGE, PROC_REF(drop_wallmount)) + RegisterSignal(hanging_wall_turf, COMSIG_TURF_CHANGE, PROC_REF(on_turf_changing)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(drop_wallmount)) RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(on_linked_destroyed)) @@ -41,6 +41,14 @@ SIGNAL_HANDLER examine_list += span_notice("\The [hanging_wall_turf] is currently supporting [span_bold("[parent]")]. Deconstruction or excessive damage would cause it to [span_bold("fall to the ground")].") +/** + * When the type of turf changes, if it is changing into a floor we should drop our contents + */ +/datum/component/wall_mounted/proc/on_turf_changing(datum/source, path, new_baseturfs, flags, post_change_callbacks) + SIGNAL_HANDLER + if (ispath(path, /turf/open)) + drop_wallmount() + /** * Handles the dropping of the linked object. This is done via deconstruction, as that should be the most sane way to handle it for most objects. * Except for intercoms, which are handled by creating a new wallframe intercom, as they're apparently items. diff --git a/code/datums/elements/death_linked.dm b/code/datums/elements/death_linked.dm deleted file mode 100644 index c5d2c6c422c..00000000000 --- a/code/datums/elements/death_linked.dm +++ /dev/null @@ -1,29 +0,0 @@ -/** - * ## death linkage element! - * - * Bespoke element that when the owner dies, the linked mob dies too. - */ -/datum/element/death_linked - element_flags = ELEMENT_BESPOKE - argument_hash_start_idx = 3 - ///The mob that also dies when the user dies - var/datum/weakref/linked_mob - -/datum/element/death_linked/Attach(datum/target, mob/living/target_mob) - . = ..() - if(!isliving(target)) - return ELEMENT_INCOMPATIBLE - if(!target_mob) - stack_trace("[type] added to [target] with NO MOB.") - src.linked_mob = WEAKREF(target_mob) - RegisterSignal(target, COMSIG_LIVING_DEATH, PROC_REF(on_death)) - -/datum/element/death_linked/Detach(datum/target) - . = ..() - UnregisterSignal(target, COMSIG_LIVING_DEATH) - -///signal called by the stat of the target changing -/datum/element/death_linked/proc/on_death(mob/living/target, gibbed) - SIGNAL_HANDLER - var/mob/living/linked_mob_resolved = linked_mob?.resolve() - linked_mob_resolved?.death(TRUE) diff --git a/code/datums/elements/food/venue_price.dm b/code/datums/elements/food/venue_price.dm index 1fcf9de040d..be846d7c004 100644 --- a/code/datums/elements/food/venue_price.dm +++ b/code/datums/elements/food/venue_price.dm @@ -21,19 +21,19 @@ UnregisterSignal(target, COMSIG_ITEM_SOLD_TO_CUSTOMER) UnregisterSignal(target, COMSIG_REAGENT_SOLD_TO_CUSTOMER) -/datum/element/venue_price/proc/item_sold(obj/item/thing_sold, mob/living/simple_animal/robot_customer/sold_to) +/datum/element/venue_price/proc/item_sold(obj/item/thing_sold, mob/living/basic/robot_customer/sold_to) SIGNAL_HANDLER produce_cash(sold_to, thing_sold) return TRANSACTION_SUCCESS -/datum/element/venue_price/proc/reagent_sold(datum/reagent/reagent_sold, mob/living/simple_animal/robot_customer/sold_to, obj/item/container) +/datum/element/venue_price/proc/reagent_sold(datum/reagent/reagent_sold, mob/living/basic/robot_customer/sold_to, obj/item/container) SIGNAL_HANDLER produce_cash(sold_to, container) return TRANSACTION_SUCCESS -/datum/element/venue_price/proc/produce_cash(mob/living/simple_animal/robot_customer/sold_to, obj/item/container) +/datum/element/venue_price/proc/produce_cash(mob/living/basic/robot_customer/sold_to, obj/item/container) new /obj/item/holochip(get_turf(container), venue_price) playsound(container, 'sound/effects/cashregister.ogg', 60, TRUE) diff --git a/code/datums/elements/sideway_movement.dm b/code/datums/elements/sideway_movement.dm index dfe23187807..e6d94745e6c 100644 --- a/code/datums/elements/sideway_movement.dm +++ b/code/datums/elements/sideway_movement.dm @@ -23,5 +23,5 @@ return var/new_dir = old_dir if(direction == old_dir || direction == REVERSE_DIR(old_dir)) - new_dir = angle2dir(dir2angle(direction) + pick(90, -90)) + new_dir = turn(source.dir, pick(90, -90)) source.setDir(new_dir) diff --git a/code/datums/id_trim/jobs.dm b/code/datums/id_trim/jobs.dm index 2a62d19452d..d2939529dc6 100644 --- a/code/datums/id_trim/jobs.dm +++ b/code/datums/id_trim/jobs.dm @@ -155,6 +155,30 @@ ) job = /datum/job/bartender +/datum/id_trim/job/bitrunner + assignment = "Bitrunner" + trim_state = "trim_bitrunner" + department_color = COLOR_CARGO_BROWN + subdepartment_color = COLOR_CARGO_BROWN + sechud_icon_state = SECHUD_BITRUNNER + minimal_access = list( + ACCESS_BIT_DEN, + ACCESS_CARGO, + ACCESS_MAINT_TUNNELS, + ACCESS_MECH_MINING, + ACCESS_MINERAL_STOREROOM, + ) + extra_access = list( + ACCESS_MINING, + ACCESS_MINING_STATION, + ) + template_access = list( + ACCESS_CAPTAIN, + ACCESS_CHANGE_IDS, + ACCESS_QM, + ) + job = /datum/job/bitrunner + /datum/id_trim/job/botanist assignment = "Botanist" trim_state = "trim_botanist" @@ -215,6 +239,7 @@ ACCESS_SHIPPING, ) extra_access = list( + ACCESS_BIT_DEN, ACCESS_MINING, ACCESS_MINING_STATION, ) @@ -576,6 +601,7 @@ ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_ARMORY, ACCESS_AUX_BASE, + ACCESS_BIT_DEN, ACCESS_BRIG, ACCESS_BRIG_ENTRANCE, ACCESS_CARGO, @@ -712,6 +738,7 @@ subdepartment_color = COLOR_MEDICAL_BLUE sechud_icon_state = SECHUD_PARAMEDIC minimal_access = list( + ACCESS_BIT_DEN, ACCESS_CARGO, ACCESS_CONSTRUCTION, ACCESS_HYDROPONICS, @@ -810,6 +837,7 @@ sechud_icon_state = SECHUD_QUARTERMASTER minimal_access = list( ACCESS_AUX_BASE, + ACCESS_BIT_DEN, ACCESS_CARGO, ACCESS_MAINT_TUNNELS, ACCESS_MECH_MINING, @@ -1008,6 +1036,7 @@ assignment = "Security Officer (Cargo)" subdepartment_color = COLOR_CARGO_BROWN department_access = list( + ACCESS_BIT_DEN, ACCESS_CARGO, ACCESS_MINING, ACCESS_SHIPPING, @@ -1076,6 +1105,7 @@ ACCESS_MINING_STATION, ) extra_access = list( + ACCESS_BIT_DEN, ACCESS_MAINT_TUNNELS, ) template_access = list( diff --git a/code/datums/id_trim/outfits.dm b/code/datums/id_trim/outfits.dm index f62e451340f..2a06434ecdb 100644 --- a/code/datums/id_trim/outfits.dm +++ b/code/datums/id_trim/outfits.dm @@ -55,3 +55,22 @@ subdepartment_color = COLOR_PRISONER_BLACK access = list(ACCESS_HUNTER) + +/// Trim for player controlled avatars in the Virtual Domain. +/datum/id_trim/bit_avatar + assignment = "Bit Avatar" + trim_state = "trim_bitavatar" + department_color = COLOR_BLACK + subdepartment_color = COLOR_GREEN + +/// Trim for cyber police in the Virtual Domain. +/datum/id_trim/cyber_police + assignment = "Cyber Police" + trim_state = "trim_deathcommando" + department_color = COLOR_BLACK + subdepartment_color = COLOR_GREEN + +/datum/id_trim/cyber_police/New() + . = ..() + + access |= SSid_access.get_region_access_list(list(REGION_ALL_GLOBAL)) diff --git a/code/datums/lazy_template.dm b/code/datums/lazy_template.dm index 0b8b2999f69..a5ae9e413f3 100644 --- a/code/datums/lazy_template.dm +++ b/code/datums/lazy_template.dm @@ -7,8 +7,11 @@ /// If this is true each load will increment an index keyed to the type and it will load [map_name]_[index] var/list/datum/turf_reservation/reservations = list() var/uses_multiple_allocations = FALSE + /// Key to identify this template - used in caching var/key + /// Directory of maps to prefix to the filename var/map_dir = "_maps/templates/lazy_templates" + /// The filename (without extension) of the map to load var/map_name /datum/lazy_template/New() diff --git a/code/datums/mapgen/CaveGenerator.dm b/code/datums/mapgen/CaveGenerator.dm index 48df6e164fb..754b8755545 100644 --- a/code/datums/mapgen/CaveGenerator.dm +++ b/code/datums/mapgen/CaveGenerator.dm @@ -55,7 +55,7 @@ /mob/living/basic/mining/basilisk = 4, /mob/living/basic/mining/goldgrub = 1, /mob/living/basic/mining/goliath/ancient = 5, - /mob/living/simple_animal/hostile/asteroid/hivelord = 3, + /mob/living/basic/mining/hivelord = 3, ) mob_spawn_list = expand_weights(weighted_mob_spawn_list) mob_spawn_no_mega_list = expand_weights(weighted_mob_spawn_list - SPAWN_MEGAFAUNA) @@ -116,8 +116,8 @@ var/start_time = REALTIMEOFDAY - for(var/turf/turf as anything in turfs) - if(!(turf.type in open_turf_types)) //only put stuff on open turfs we generated, so closed walls and rivers and stuff are skipped + for(var/turf/target_turf as anything in turfs) + if(!(target_turf.type in open_turf_types)) //only put stuff on open turfs we generated, so closed walls and rivers and stuff are skipped continue // If we've spawned something yet @@ -127,22 +127,24 @@ //FLORA SPAWNING HERE if(flora_allowed && prob(flora_spawn_chance)) var/flora_type = pick(flora_spawn_list) - new flora_type(turf) + new flora_type(target_turf) spawned_something = TRUE //FEATURE SPAWNING HERE - if(feature_allowed && prob(feature_spawn_chance)) + //we may have generated something from the flora list on the target turf, so let's not place + //a feature here if that's the case (because it would look stupid) + if(feature_allowed && !spawned_something && prob(feature_spawn_chance)) var/can_spawn = TRUE var/atom/picked_feature = pick(feature_spawn_list) - for(var/obj/structure/existing_feature in range(7, turf)) + for(var/obj/structure/existing_feature in range(7, target_turf)) if(istype(existing_feature, picked_feature)) can_spawn = FALSE break if(can_spawn) - new picked_feature(turf) + new picked_feature(target_turf) spawned_something = TRUE //MOB SPAWNING HERE @@ -161,12 +163,12 @@ // prevents tendrils spawning in each other's collapse range if(ispath(picked_mob, /obj/structure/spawner/lavaland)) - for(var/obj/structure/spawner/lavaland/spawn_blocker in range(2, turf)) + for(var/obj/structure/spawner/lavaland/spawn_blocker in range(2, target_turf)) can_spawn = FALSE break // if the random is not a tendril (hopefully meaning it is a mob), avoid spawning if there's another one within 12 tiles else - var/list/things_in_range = range(12, turf) + var/list/things_in_range = range(12, target_turf) for(var/mob/living/mob_blocker in things_in_range) if(ismining(mob_blocker)) can_spawn = FALSE @@ -176,7 +178,7 @@ can_spawn = can_spawn && !(locate(/obj/effect/spawner/random/lavaland_mob) in things_in_range) //if there's a megafauna within standard view don't spawn anything at all (This isn't really consistent, I don't know why we do this. you do you tho) if(can_spawn) - for(var/mob/living/simple_animal/hostile/megafauna/found_fauna in range(7, turf)) + for(var/mob/living/simple_animal/hostile/megafauna/found_fauna in range(7, target_turf)) can_spawn = FALSE break @@ -185,7 +187,7 @@ weighted_megafauna_spawn_list.Remove(picked_mob) megafauna_spawn_list = expand_weights(weighted_megafauna_spawn_list) megas_allowed = megas_allowed && length(megafauna_spawn_list) - new picked_mob(turf) + new picked_mob(target_turf) spawned_something = TRUE CHECK_TICK diff --git a/code/datums/mapgen/Cavegens/IcemoonCaves.dm b/code/datums/mapgen/Cavegens/IcemoonCaves.dm index 89a153aedd7..7d7437ccda6 100644 --- a/code/datums/mapgen/Cavegens/IcemoonCaves.dm +++ b/code/datums/mapgen/Cavegens/IcemoonCaves.dm @@ -4,9 +4,9 @@ weighted_mob_spawn_list = list( + /mob/living/basic/mining/legion/snow = 50, /mob/living/basic/mining/lobstrosity = 15, /mob/living/basic/mining/goldgrub = 10, - /mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow = 50, /mob/living/simple_animal/hostile/asteroid/polarbear = 30, /mob/living/simple_animal/hostile/asteroid/wolf = 50, /obj/structure/spawner/ice_moon = 3, @@ -63,7 +63,7 @@ weighted_mob_spawn_list = list( SPAWN_MEGAFAUNA = 1, /mob/living/basic/mining/ice_whelp = 60, - /mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow = 100, + /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, diff --git a/code/datums/martial/boxing.dm b/code/datums/martial/boxing.dm index 720bda243b9..9ba1a53d40c 100644 --- a/code/datums/martial/boxing.dm +++ b/code/datums/martial/boxing.dm @@ -67,6 +67,15 @@ /obj/item/clothing/gloves/boxing var/datum/martial_art/boxing/style = new +/obj/item/clothing/gloves/boxing/Initialize(mapload) + . = ..() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/extendohand_l, /datum/crafting_recipe/extendohand_r) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/clothing/gloves/boxing/equipped(mob/user, slot) ..() // boxing requires human diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index d91884d972e..06d26f31ea3 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -33,8 +33,16 @@ Simple datum which is instanced once per type and is used for every object of sa var/strength_modifier = 1 ///This is a modifier for integrity, and resembles the strength of the material var/integrity_modifier = 1 + ///This is the amount of value per 1 unit of the material var/value_per_unit = 0 + ///This is the minimum value of the material, used in the stock market for any mat that isn't set to null + var/minimum_value_override = null + ///Is this material traded on the stock market? + var/tradable = FALSE + ///If this material is tradable, what is the base quantity of the material on the stock market? + var/tradable_base_quantity = 0 + ///Armor modifiers, multiplies an items normal armor vars by these amounts. var/armor_modifiers = list(MELEE = 1, BULLET = 1, LASER = 1, ENERGY = 1, BOMB = 1, BIO = 1, FIRE = 1, ACID = 1) ///How beautiful is this material per unit. diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index fcef1b5d3d8..f79b9f7e422 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -7,6 +7,9 @@ categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/iron value_per_unit = 5 / SHEET_MATERIAL_AMOUNT + minimum_value_override = 0 + tradable = TRUE + tradable_base_quantity = MATERIAL_QUANTITY_COMMON /datum/material/iron/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5) @@ -25,6 +28,9 @@ shard_type = /obj/item/shard debris_type = /obj/effect/decal/cleanable/glass value_per_unit = 5 / SHEET_MATERIAL_AMOUNT + minimum_value_override = 0 + tradable = TRUE + tradable_base_quantity = MATERIAL_QUANTITY_COMMON beauty_modifier = 0.05 armor_modifiers = list(MELEE = 0.2, BULLET = 0.2, ENERGY = 1, BIO = 0.2, FIRE = 1, ACID = 0.2) @@ -56,6 +62,8 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/silver value_per_unit = 50 / SHEET_MATERIAL_AMOUNT + tradable = TRUE + tradable_base_quantity = MATERIAL_QUANTITY_UNCOMMON beauty_modifier = 0.075 /datum/material/silver/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) @@ -72,6 +80,8 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/gold value_per_unit = 125 / SHEET_MATERIAL_AMOUNT + tradable = TRUE + tradable_base_quantity = MATERIAL_QUANTITY_RARE beauty_modifier = 0.15 armor_modifiers = list(MELEE = 1.1, BULLET = 1.1, LASER = 1.15, ENERGY = 1.15, BOMB = 1, BIO = 1, FIRE = 0.7, ACID = 1.1) @@ -90,6 +100,8 @@ Unless you know what you're doing, only use the first three numbers. They're in alpha = 132 starlight_color = COLOR_BLUE_LIGHT value_per_unit = 500 / SHEET_MATERIAL_AMOUNT + tradable = TRUE + tradable_base_quantity = MATERIAL_QUANTITY_EXOTIC beauty_modifier = 0.3 armor_modifiers = list(MELEE = 1.3, BULLET = 1.3, LASER = 0.6, ENERGY = 1, BOMB = 1.2, BIO = 1, FIRE = 1, ACID = 1) @@ -106,6 +118,8 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/uranium value_per_unit = 100 / SHEET_MATERIAL_AMOUNT + tradable = TRUE + tradable_base_quantity = MATERIAL_QUANTITY_RARE beauty_modifier = 0.3 //It shines so beautiful armor_modifiers = list(MELEE = 1.5, BULLET = 1.4, LASER = 0.5, ENERGY = 0.5, FIRE = 1, ACID = 1) @@ -173,6 +187,8 @@ Unless you know what you're doing, only use the first three numbers. They're in beauty_modifier = 0.5 sheet_type = /obj/item/stack/sheet/bluespace_crystal value_per_unit = 300 / SHEET_MATERIAL_AMOUNT + tradable = TRUE + tradable_base_quantity = MATERIAL_QUANTITY_EXOTIC /datum/material/bluespace/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.reagents.add_reagent(/datum/reagent/bluespace, rand(5, 8)) @@ -216,6 +232,8 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/titanium value_per_unit = 125 / SHEET_MATERIAL_AMOUNT + tradable = TRUE + tradable_base_quantity = MATERIAL_QUANTITY_UNCOMMON beauty_modifier = 0.05 armor_modifiers = list(MELEE = 1.35, BULLET = 1.3, LASER = 1.3, ENERGY = 1.25, BOMB = 1.25, BIO = 1, FIRE = 0.7, ACID = 1) diff --git a/code/datums/memory/_memory.dm b/code/datums/memory/_memory.dm index 35d1a6683f3..66871aac2ec 100644 --- a/code/datums/memory/_memory.dm +++ b/code/datums/memory/_memory.dm @@ -246,6 +246,7 @@ var/static/list/something_pool = list( /mob/living/basic/bat, /mob/living/basic/bear, + /mob/living/basic/blob_minion/blobbernaut, /mob/living/basic/butterfly, /mob/living/basic/carp, /mob/living/basic/carp/magic, @@ -272,7 +273,6 @@ /mob/living/basic/statue, /mob/living/basic/stickman, /mob/living/basic/stickman/dog, - /mob/living/simple_animal/hostile/blob/blobbernaut/independent, /mob/living/simple_animal/hostile/gorilla, /mob/living/simple_animal/hostile/megafauna/dragon/lesser, /mob/living/simple_animal/hostile/retaliate/goat, diff --git a/code/datums/mind/_mind.dm b/code/datums/mind/_mind.dm index fa9114a5284..deb55e92ecb 100644 --- a/code/datums/mind/_mind.dm +++ b/code/datums/mind/_mind.dm @@ -569,16 +569,14 @@ /// Sets us to the passed job datum, then greets them to their new job. /// Use this one for when you're assigning this mind to a new job for the first time, /// or for when someone's recieving a job they'd really want to be greeted to. -/datum/mind/proc/set_assigned_role_with_greeting(datum/job/new_role, client/incoming_client) +/datum/mind/proc/set_assigned_role_with_greeting(datum/job/new_role, client/incoming_client, alt_title) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - ORIGINAL: /datum/mind/proc/set_assigned_role_with_greeting(datum/job/new_role, client/incoming_client) . = set_assigned_role(new_role) if(assigned_role != new_role) return - to_chat(incoming_client || src, span_infoplain("You are the [new_role.title].")) - - var/related_policy = get_policy(new_role.title) - if(related_policy) - to_chat(incoming_client || src, related_policy) + var/intro_message = new_role.get_spawn_message(alt_title) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - ORIGINAL: var/intro_message = new_role.get_spawn_message() + if(incoming_client && intro_message) + to_chat(incoming_client, intro_message) /mob/proc/sync_mind() mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist) diff --git a/code/datums/mind/initialization.dm b/code/datums/mind/initialization.dm index 12a5dddb229..eb622cc5af5 100644 --- a/code/datums/mind/initialization.dm +++ b/code/datums/mind/initialization.dm @@ -11,6 +11,7 @@ mind.set_current(src) // There's nowhere else to set this up, mind code makes me depressed mind.antag_hud = add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/antagonist_hud, "combo_hud", mind) + SEND_SIGNAL(src, COMSIG_MOB_MIND_INITIALIZED, mind) /mob/living/carbon/mind_initialize() ..() diff --git a/code/datums/mind/skills.dm b/code/datums/mind/skills.dm index 5847236435b..474291d5ae0 100644 --- a/code/datums/mind/skills.dm +++ b/code/datums/mind/skills.dm @@ -18,12 +18,10 @@ experience_multiplier += experience_multiplier_reasons[key] known_skills[skill][SKILL_EXP] = max(0, known_skills[skill][SKILL_EXP] + amt*experience_multiplier) //Update exp. Prevent going below 0 known_skills[skill][SKILL_LVL] = update_skill_level(skill)//Check what the current skill level is based on that skill's exp - if(silent) - return if(known_skills[skill][SKILL_LVL] > old_level) - S.level_gained(src, known_skills[skill][SKILL_LVL], old_level) + S.level_gained(src, known_skills[skill][SKILL_LVL], old_level, silent) else if(known_skills[skill][SKILL_LVL] < old_level) - S.level_lost(src, known_skills[skill][SKILL_LVL], old_level) + S.level_lost(src, known_skills[skill][SKILL_LVL], old_level, silent) ///Set experience of a specific skill to a number /datum/mind/proc/set_experience(skill, amt, silent = FALSE) diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index a5aa648ecee..53bcce6c6ff 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -167,6 +167,9 @@ mood_change = -4 timeout = 2 MINUTES +/datum/mood_event/healsbadman/long_term + timeout = 10 MINUTES + /datum/mood_event/jittery description = "I'm nervous and on edge and I can't stand still!!" mood_change = -2 diff --git a/code/datums/mutations/antenna.dm b/code/datums/mutations/antenna.dm index bc5026ab148..b71f66c0fa6 100644 --- a/code/datums/mutations/antenna.dm +++ b/code/datums/mutations/antenna.dm @@ -91,32 +91,11 @@ // chance to alert the read-ee to_chat(cast_on, span_danger("You feel something foreign enter your mind.")) - var/list/recent_speech = list() - var/list/say_log = list() - var/log_source = cast_on.logging - //this whole loop puts the read-ee's say logs into say_log in an easy to access way - for(var/log_type in log_source) - var/nlog_type = text2num(log_type) - if(nlog_type & LOG_SAY) - var/list/reversed = log_source[log_type] - if(islist(reversed)) - say_log = reverse_range(reversed.Copy()) - break - - for(var/spoken_memory in say_log) - //up to 3 random lines of speech, favoring more recent speech - if(length(recent_speech) >= 3) - break - if(prob(50)) - continue - // log messages with tags like telepathy are displayed like "(Telepathy to Ckey/(target)) "greetings""" - // by splitting the text by using a " delimiter, we can grab JUST the greetings part - recent_speech[spoken_memory] = splittext(say_log[spoken_memory], "\"", 1, 0, TRUE)[3] - + var/list/recent_speech = cast_on.copy_recent_speech(copy_amount = 3, line_chance = 50) if(length(recent_speech)) to_chat(owner, span_boldnotice("You catch some drifting memories of their past conversations...")) for(var/spoken_memory in recent_speech) - to_chat(owner, span_notice("[recent_speech[spoken_memory]]")) + to_chat(owner, span_notice("[spoken_memory]")) if(iscarbon(cast_on)) var/mob/living/carbon/carbon_cast_on = cast_on diff --git a/code/datums/mutations/touch.dm b/code/datums/mutations/touch.dm index 1f1cefe1cbe..3f798ba52b2 100644 --- a/code/datums/mutations/touch.dm +++ b/code/datums/mutations/touch.dm @@ -38,7 +38,7 @@ ///This var decides if the spell should chain, dictated by presence of power chromosome var/chain = FALSE ///Affects damage, should do about 1 per limb - var/zap_power = 7500 + var/zap_power = 3e6 ///Range of tesla shock bounces var/zap_range = 7 ///flags that dictate what the tesla shock can interact with, Can only damage mobs, Cannot damage machines or generate energy diff --git a/code/datums/quirks/negative_quirks/prosthetic_limb.dm b/code/datums/quirks/negative_quirks/prosthetic_limb.dm index f6f0e304a6d..e7ea4d75788 100644 --- a/code/datums/quirks/negative_quirks/prosthetic_limb.dm +++ b/code/datums/quirks/negative_quirks/prosthetic_limb.dm @@ -3,9 +3,8 @@ desc = "An accident caused you to lose one of your limbs. Because of this, you now have a surplus prosthetic!" icon = "tg-prosthetic-leg" value = -3 - medical_record_text = "During physical examination, patient was found to have a low-budget prosthetic limb." hardcore_value = 3 - quirk_flags = QUIRK_HUMAN_ONLY // while this technically changes appearance, we don't want it to be shown on the dummy because it's randomized at roundstart + quirk_flags = QUIRK_HUMAN_ONLY | QUIRK_CHANGES_APPEARANCE mail_goodies = list(/obj/item/weldingtool/mini, /obj/item/stack/cable_coil/five) /// The slot to replace, in string form var/slot_string = "limb" @@ -13,28 +12,20 @@ var/obj/item/bodypart/old_limb /datum/quirk/prosthetic_limb/add_unique(client/client_source) - var/limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + var/limb_type = GLOB.limb_choice[client_source?.prefs?.read_preference(/datum/preference/choiced/prosthetic)] + if(isnull(limb_type)) //Client gone or they chose a random prosthetic + limb_type = GLOB.limb_choice[pick(GLOB.limb_choice)] + var/mob/living/carbon/human/human_holder = quirk_holder - var/obj/item/bodypart/prosthetic - switch(limb_slot) - if(BODY_ZONE_L_ARM) - prosthetic = new /obj/item/bodypart/arm/left/robot/surplus - slot_string = "left arm" - if(BODY_ZONE_R_ARM) - prosthetic = new /obj/item/bodypart/arm/right/robot/surplus - slot_string = "right arm" - if(BODY_ZONE_L_LEG) - prosthetic = new /obj/item/bodypart/leg/left/robot/surplus - slot_string = "left leg" - if(BODY_ZONE_R_LEG) - prosthetic = new /obj/item/bodypart/leg/right/robot/surplus - slot_string = "right leg" - medical_record_text = "During physical examination, patient was found to have a low-budget prosthetic [slot_string]." - old_limb = human_holder.return_and_replace_bodypart(prosthetic, special = TRUE) + var/obj/item/bodypart/surplus = new limb_type() + slot_string = "[surplus.plaintext_zone]" + + medical_record_text = "Patient uses a low-budget prosthetic on the [slot_string]." + old_limb = human_holder.return_and_replace_bodypart(surplus, special = TRUE) /datum/quirk/prosthetic_limb/post_add() to_chat(quirk_holder, span_boldannounce("Your [slot_string] has been replaced with a surplus prosthetic. It is fragile and will easily come apart under duress. Additionally, \ - you need to use a welding tool and cables to repair it, instead of bruise packs and ointment.")) + you need to use a welding tool and cables to repair it, instead of sutures and regenerative meshes.")) /datum/quirk/prosthetic_limb/remove() var/mob/living/carbon/human/human_holder = quirk_holder diff --git a/code/datums/records/manifest.dm b/code/datums/records/manifest.dm index 13061218b51..7b43b7644ef 100644 --- a/code/datums/records/manifest.dm +++ b/code/datums/records/manifest.dm @@ -111,6 +111,8 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new) person_gender = "Male" if(person.gender == "female") person_gender = "Female" + var/datum/dna/record_dna = new() + person.dna.copy_dna(record_dna) // SKYRAT EDIT ADDITION BEGIN - ALTERNATIVE_JOB_TITLES // The alt job title, if user picked one, or the default @@ -119,32 +121,32 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new) var/datum/record/locked/lockfile = new( age = person.age, - blood_type = person.dna.blood_type, + blood_type = record_dna.blood_type, character_appearance = character_appearance, - dna_string = person.dna.unique_enzymes, - fingerprint = md5(person.dna.unique_identity), + dna_string = record_dna.unique_enzymes, + fingerprint = md5(record_dna.unique_identity), gender = person_gender, initial_rank = assignment, name = person.real_name, rank = chosen_assignment, // SKYRAT EDIT - Alt job titles - ORIGINAL: rank = assignment, - species = person.dna.species.name, + species = record_dna.species.name, trim = assignment, // Locked specifics - dna_ref = person.dna, + locked_dna = record_dna, mind_ref = person.mind, ) new /datum/record/crew( age = person.age, - blood_type = person.dna.blood_type, + blood_type = record_dna.blood_type, character_appearance = character_appearance, - dna_string = person.dna.unique_enzymes, - fingerprint = md5(person.dna.unique_identity), + dna_string = record_dna.unique_enzymes, + fingerprint = md5(record_dna.unique_identity), gender = person_gender, initial_rank = assignment, name = person.real_name, rank = chosen_assignment, // SKYRAT EDIT - Alt job titles - ORIGINAL: rank = assignment, - species = person.dna.species.name, + species = record_dna.species.name, trim = assignment, // Crew specific lock_ref = REF(lockfile), diff --git a/code/datums/records/record.dm b/code/datums/records/record.dm index 67fce2f49a4..276865115e4 100644 --- a/code/datums/records/record.dm +++ b/code/datums/records/record.dm @@ -24,6 +24,8 @@ var/species /// The character's ID trim var/trim + /// The character's voice, if they have one. + var/voice /datum/record/New( age = 18, @@ -37,6 +39,7 @@ rank = "Unassigned", species = "Human", trim = "Unassigned", + voice = "?????", ) src.age = age src.blood_type = blood_type @@ -138,9 +141,9 @@ */ /datum/record/locked /// Mob's dna - var/datum/dna/dna_ref + var/datum/dna/locked_dna /// Mind datum - var/datum/mind/mind_ref + var/datum/weakref/mind_ref /// Typepath of species used by player, for usage in respawning via records var/species_type @@ -157,13 +160,13 @@ species = "Human", trim = "Unassigned", /// Locked specific - datum/dna/dna_ref, + datum/dna/locked_dna, datum/mind/mind_ref, ) . = ..() - src.dna_ref = dna_ref - src.mind_ref = mind_ref - species_type = dna_ref.species.type + src.locked_dna = locked_dna + src.mind_ref = WEAKREF(mind_ref) + species_type = locked_dna.species.type GLOB.manifest.locked += src diff --git a/code/datums/skills/_skill.dm b/code/datums/skills/_skill.dm index ec52ebd9e96..b8438c67927 100644 --- a/code/datums/skills/_skill.dm +++ b/code/datums/skills/_skill.dm @@ -27,8 +27,7 @@ GLOBAL_LIST_INIT(skill_types, subtypesof(/datum/skill)) span_nicegreen("I'm getting a little better at [name]!"), span_nicegreen("I'm getting much better at [name]!"), span_nicegreen("I feel like I've become quite proficient at [name]!"), - "After lots of practice, I've begun to truly understand the intricacies \ - and surprising depth behind [name]. I now consider myself a master [title].", + span_nicegreen("After lots of practice, I've begun to truly understand the intricacies and surprising depth behind [name]. I now consider myself a master [title]."), span_nicegreen("Through incredible determination and effort, I've reached the peak of my [name] abiltities. I'm finally able to consider myself a legendary [title]!") ) levelDownMessages = list(span_nicegreen("I have somehow completely lost all understanding of [name]. Please tell an admin if you see this."), span_nicegreen("I'm starting to forget what [name] really even is. I need more practice..."), @@ -46,13 +45,18 @@ GLOBAL_LIST_INIT(skill_types, subtypesof(/datum/skill)) * * mind - The mind that you'll want to send messages * * new_level - The newly gained level. Can check the actual level to give different messages at different levels, see defines in skills.dm * * old_level - Similar to the above, but the level you had before levelling up. + * * silent - Silences the announcement if TRUE */ -/datum/skill/proc/level_gained(datum/mind/mind, new_level, old_level)//just for announcements (doesn't go off if the xp gain is silent) +/datum/skill/proc/level_gained(datum/mind/mind, new_level, old_level, silent) + if(silent) + return to_chat(mind.current, levelUpMessages[new_level]) //new_level will be a value from 1 to 6, so we get appropriate message from the 6-element levelUpMessages list /** * level_lost: See level_gained, same idea but fires on skill level-down */ -/datum/skill/proc/level_lost(datum/mind/mind, new_level, old_level) +/datum/skill/proc/level_lost(datum/mind/mind, new_level, old_level, silent) + if(silent) + return to_chat(mind.current, levelDownMessages[old_level]) //old_level will be a value from 1 to 6, so we get appropriate message from the 6-element levelUpMessages list /** diff --git a/code/datums/skills/fishing.dm b/code/datums/skills/fishing.dm index d5ecff3c8f5..ddf90e1a0a3 100644 --- a/code/datums/skills/fishing.dm +++ b/code/datums/skills/fishing.dm @@ -8,3 +8,17 @@ desc = "How empty and alone you are on this barren Earth." modifiers = list(SKILL_VALUE_MODIFIER = list(1, 1, 0, -1, -2, -4, -6)) skill_item_path = /obj/item/clothing/head/soft/fishing_hat + +/datum/skill/fishing/New() + . = ..() + levelUpMessages[SKILL_LEVEL_MASTER] = span_nicegreen("After lots of practice, I've begun to truly understand the surprising depth behind [name]. As a master [title], I can take an easier guess of what I'm trying to catch now.") + +/datum/skill/fishing/level_gained(datum/mind/mind, new_level, old_level, silent) + . = ..() + if(new_level >= SKILL_LEVEL_MASTER && old_level < SKILL_LEVEL_MASTER) + ADD_TRAIT(mind, TRAIT_REVEAL_FISH, SKILL_TRAIT) + +/datum/skill/fishing/level_lost(datum/mind/mind, new_level, old_level, silent) + . = ..() + if(old_level >= SKILL_LEVEL_MASTER && new_level < SKILL_LEVEL_MASTER) + REMOVE_TRAIT(mind, TRAIT_REVEAL_FISH, SKILL_TRAIT) diff --git a/code/datums/station_traits/positive_traits.dm b/code/datums/station_traits/positive_traits.dm index 165cc4c2ad4..7c36ed24db9 100644 --- a/code/datums/station_traits/positive_traits.dm +++ b/code/datums/station_traits/positive_traits.dm @@ -283,6 +283,7 @@ /datum/job/assistant = /obj/item/organ/internal/heart/cybernetic, //real cardiac /datum/job/atmospheric_technician = /obj/item/organ/internal/cyberimp/mouth/breathing_tube, /datum/job/bartender = /obj/item/organ/internal/liver/cybernetic/tier3, + /datum/job/bitrunner = /obj/item/organ/internal/eyes/robotic/thermals, /datum/job/botanist = /obj/item/organ/internal/cyberimp/chest/nutriment, /datum/job/captain = /obj/item/organ/internal/heart/cybernetic/tier3, /datum/job/cargo_technician = /obj/item/organ/internal/stomach/cybernetic/tier2, diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index b9747d54acc..cb0b55be059 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -265,10 +265,10 @@ /datum/status_effect/hippocratic_oath/proc/consume_owner() owner.visible_message(span_notice("[owner]'s soul is absorbed into the rod, relieving the previous snake of its duty.")) var/list/chems = list(/datum/reagent/medicine/sal_acid, /datum/reagent/medicine/c2/convermol, /datum/reagent/medicine/oxandrolone) - var/mob/living/simple_animal/hostile/retaliate/snake/healSnake = new(owner.loc, pick(chems)) - healSnake.name = "Asclepius's Snake" - healSnake.real_name = "Asclepius's Snake" - healSnake.desc = "A mystical snake previously trapped upon the Rod of Asclepius, now freed of its burden. Unlike the average snake, its bites contain chemicals with minor healing properties." + var/mob/living/basic/snake/spawned = new(owner.loc, pick(chems)) + spawned.name = "Asclepius's Snake" + spawned.real_name = "Asclepius's Snake" + spawned.desc = "A mystical snake previously trapped upon the Rod of Asclepius, now freed of its burden. Unlike the average snake, its bites contain chemicals with minor healing properties." new /obj/effect/decal/cleanable/ash(owner.loc) new /obj/item/rod_of_asclepius(owner.loc) owner.investigate_log("has been consumed by the Rod of Asclepius.", INVESTIGATE_DEATHS) diff --git a/code/datums/status_effects/debuffs/cyborg.dm b/code/datums/status_effects/debuffs/cyborg.dm new file mode 100644 index 00000000000..0f95b494197 --- /dev/null +++ b/code/datums/status_effects/debuffs/cyborg.dm @@ -0,0 +1,22 @@ +/// Reduce a cyborg's speed when you throw things at it +/datum/status_effect/borg_throw_slow + id = "borg_throw_slowdown" + alert_type = /atom/movable/screen/alert/status_effect/borg_throw_slow + duration = 3 SECONDS + status_type = STATUS_EFFECT_REPLACE + +/datum/status_effect/borg_throw_slow/on_apply() + . = ..() + owner.add_movespeed_modifier(/datum/movespeed_modifier/borg_throw, update = TRUE) + +/datum/status_effect/borg_throw_slow/on_remove() + . = ..() + owner.remove_movespeed_modifier(/datum/movespeed_modifier/borg_throw, update = TRUE) + +/atom/movable/screen/alert/status_effect/borg_throw_slow + name = "Percussive Maintenance" + desc = "A sudden impact has triggered your collision avoidance routines, reducing movement speed." + icon_state = "weaken" + +/datum/movespeed_modifier/borg_throw + multiplicative_slowdown = 0.9 diff --git a/code/datums/status_effects/debuffs/static_vision.dm b/code/datums/status_effects/debuffs/static_vision.dm new file mode 100644 index 00000000000..7132c189b9d --- /dev/null +++ b/code/datums/status_effects/debuffs/static_vision.dm @@ -0,0 +1,29 @@ +/datum/status_effect/static_vision + id = "static_vision" + status_type = STATUS_EFFECT_REPLACE + alert_type = null + +/datum/status_effect/static_vision/on_creation(mob/living/new_owner, duration = 3 SECONDS) + src.duration = duration + return ..() + +/datum/status_effect/static_vision/on_apply() + RegisterSignal(owner, COMSIG_LIVING_DEATH, PROC_REF(remove_static_vision)) + + owner.overlay_fullscreen(id, /atom/movable/screen/fullscreen/static_vision) + owner.sound_environment_override = SOUND_ENVIRONMENT_UNDERWATER + + return TRUE + +/datum/status_effect/static_vision/on_remove() + UnregisterSignal(owner, COMSIG_LIVING_DEATH) + + owner.clear_fullscreen(id) + if(owner.sound_environment_override == SOUND_ENVIRONMENT_UNDERWATER) + owner.sound_environment_override = SOUND_ENVIRONMENT_NONE + +/// Handles clearing on death +/datum/status_effect/static_vision/proc/remove_static_vision(datum/source, admin_revive) + SIGNAL_HANDLER + + qdel(src) diff --git a/code/datums/votes/map_vote.dm b/code/datums/votes/map_vote.dm index 745e7c6f7af..323ee29ccc2 100644 --- a/code/datums/votes/map_vote.dm +++ b/code/datums/votes/map_vote.dm @@ -20,7 +20,7 @@ /datum/vote/map_vote/create_vote() . = ..() check_population(should_key_choices = FALSE) - if((length(choices) == 1) && EMERGENCY_ESCAPED_OR_ENDGAMED) // Only one choice, no need to vote. Let's just auto-rotate it to the only remaining map because it would just happen anyways. + if(length(choices) == 1) // Only one choice, no need to vote. Let's just auto-rotate it to the only remaining map because it would just happen anyways. var/de_facto_winner = choices[1] var/datum/map_config/change_me_out = global.config.maplist[de_facto_winner] SSmapping.changemap(change_me_out) @@ -118,3 +118,12 @@ SSmapping.map_voted = TRUE if(SSmapping.map_vote_rocked) SSmapping.map_vote_rocked = FALSE + +/proc/revert_map_vote() + var/datum/map_config/override_map = SSmapping.config + if(isnull(override_map)) + return + + SSmapping.changemap(override_map) + log_game("The next map has been reset to [override_map.map_name].") + send_to_playing_players(span_boldannounce("The next map is: [override_map.map_name].")) diff --git a/code/datums/votes/restart_vote.dm b/code/datums/votes/restart_vote.dm index 24d38f35396..987d5b87eb3 100644 --- a/code/datums/votes/restart_vote.dm +++ b/code/datums/votes/restart_vote.dm @@ -67,7 +67,14 @@ message_admins("A restart vote has passed, but there are active admins on with +SERVER, so it has been canceled. If you wish, you may restart the server.") return - SSticker.Reboot("Restart vote successful.", "restart vote", 1) + // If there was a previous map vote, we revert the change. + if(!isnull(SSmapping.next_map_config)) + log_game("The next map has been reset due to successful restart vote.") + send_to_playing_players(span_boldannounce("The next map has been reset due to successful restart vote.")) + revert_map_vote() + + SSticker.force_ending = FORCE_END_ROUND + log_game("End round forced by successful restart vote.") return CRASH("[type] wasn't passed a valid winning choice. (Got: [winning_option || "null"])") diff --git a/code/datums/wires/explosive.dm b/code/datums/wires/explosive.dm index 925c9481831..800b5b88444 100644 --- a/code/datums/wires/explosive.dm +++ b/code/datums/wires/explosive.dm @@ -151,4 +151,4 @@ /datum/wires/explosive/gibtonite/explode() var/obj/item/gibtonite/P = holder - P.GibtoniteReaction(null, 2) + P.GibtoniteReaction(null, "A wire signal has primed a") diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm index faf1ef87057..89b7ba5762b 100644 --- a/code/datums/wounds/_wounds.dm +++ b/code/datums/wounds/_wounds.dm @@ -290,7 +290,7 @@ . = limb if(limb) // if we're nulling limb, we're basically detaching from it, so we should remove ourselves in that case UnregisterSignal(limb, COMSIG_QDELETING) - UnregisterSignal(limb, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_GAUZE_DESTROYED)) + UnregisterSignal(limb, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_UNGAUZED)) LAZYREMOVE(limb.wounds, src) limb.update_wounds(replaced) if (disabling) @@ -302,7 +302,7 @@ if (limb) RegisterSignal(limb, COMSIG_QDELETING, PROC_REF(source_died)) - RegisterSignals(limb, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_GAUZE_DESTROYED), PROC_REF(gauze_state_changed)) + RegisterSignals(limb, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_UNGAUZED), PROC_REF(gauze_state_changed)) if (disabling) limb.add_traits(list(TRAIT_PARALYSIS, TRAIT_DISABLED_BY_WOUND), REF(src)) @@ -442,7 +442,7 @@ set_interaction_efficiency_penalty(initial(interaction_efficiency_penalty)) if(initial(disabling)) - set_disabling(!limb.current_gauze) + set_disabling(isnull(limb.current_gauze)) limb.update_wounds(replaced_or_replacing) diff --git a/code/datums/wounds/scars/_scars.dm b/code/datums/wounds/scars/_scars.dm index 774d8cc5265..e650899be29 100644 --- a/code/datums/wounds/scars/_scars.dm +++ b/code/datums/wounds/scars/_scars.dm @@ -181,7 +181,7 @@ if((human_victim.wear_mask && (human_victim.wear_mask.flags_inv & HIDEFACE)) || (human_victim.head && (human_victim.head.flags_inv & HIDEFACE))) return FALSE else if(limb.scars_covered_by_clothes) - var/num_covers = LAZYLEN(human_victim.clothingonpart(limb)) + var/num_covers = LAZYLEN(human_victim.get_clothing_on_part(limb)) if(num_covers + get_dist(viewer, victim) >= visibility) return FALSE diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 29c5ea6e4df..c2c67edf097 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -129,6 +129,11 @@ var/base_pixel_x = 0 ///Default pixel y shifting for the atom's icon. var/base_pixel_y = 0 + // Use SET_BASE_VISUAL_PIXEL(x, y) to set these in typepath definitions, it'll handle pixel_w and z for you + ///Default pixel w shifting for the atom's icon. + var/base_pixel_w = 0 + ///Default pixel z shifting for the atom's icon. + var/base_pixel_z = 0 ///Used for changing icon states for different base sprites. var/base_icon_state @@ -318,6 +323,8 @@ /atom/proc/CanPass(atom/movable/mover, border_dir) SHOULD_CALL_PARENT(TRUE) SHOULD_BE_PURE(TRUE) + if(SEND_SIGNAL(src, COMSIG_ATOM_TRIED_PASS, mover, border_dir) & COMSIG_COMPONENT_PERMIT_PASSAGE) + return TRUE if(mover.movement_type & PHASING) return TRUE . = CanAllowThrough(mover, border_dir) @@ -705,6 +712,7 @@ . = list() SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE_MORE, user, .) + SEND_SIGNAL(user, COMSIG_MOB_EXAMINING_MORE, src, .) /// Wrapper for _update_appearance that is only called when APPEARANCE_SUCCESS_TRACKING is defined #ifdef APPEARANCE_SUCCESS_TRACKING diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 26dfcb4be76..6208df36de1 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -468,8 +468,8 @@ GLOBAL_LIST_EMPTY(dynamic_station_traits) for(var/job in job_prefs) var/priority = job_prefs[job] job_data += "[job]: [SSjob.job_priority_level_to_string(priority)]" - to_chat(player, span_danger("You were unable to qualify for any roundstart antagonist role because you could not qualify for any of the roundstart jobs you were trying to qualify for, along with 'return to lobby if job is unavailable' enabled.")) - log_admin("[player.ckey] failed to qualify for any job and has [player.client.prefs.be_special.len] antag preferences enabled. They will be unable to qualify for any roundstart antagonist role. These are their job preferences - [job_data.Join(" | ")]") + to_chat(player, span_danger("You were unable to qualify for any roundstart antagonist role this round because your job preferences presented a high chance of all of your selected jobs being unavailable, along with 'return to lobby if job is unavailable' enabled. Increase the number of roles set to medium or low priority to reduce the chances of this happening.")) + log_admin("[player.ckey] failed to qualify for any roundstart antagonist role because their job preferences presented a high chance of all of their selected jobs being unavailable, along with 'return to lobby if job is unavailable' enabled and has [player.client.prefs.be_special.len] antag preferences enabled. They will be unable to qualify for any roundstart antagonist role. These are their job preferences - [job_data.Join(" | ")]") else roundstart_pop_ready++ candidates.Add(player) @@ -639,8 +639,10 @@ GLOBAL_LIST_EMPTY(dynamic_station_traits) if(rule.persistent) current_rules += rule new_snapshot(rule) + rule.forget_startup() return TRUE rule.clean_up() // Refund threat, delete teams and so on. + rule.forget_startup() executed_rules -= rule stack_trace("The starting rule \"[rule.name]\" failed to execute.") return FALSE @@ -688,9 +690,11 @@ GLOBAL_LIST_EMPTY(dynamic_station_traits) executed_rules += new_rule if (new_rule.persistent) current_rules += new_rule + new_rule.forget_startup() return TRUE else if (forced) log_dynamic("The ruleset [new_rule.name] couldn't be executed due to lack of elligible players.") + new_rule.forget_startup() return FALSE /datum/game_mode/dynamic/process() diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets.dm b/code/game/gamemodes/dynamic/dynamic_rulesets.dm index faefbbe9426..1fe34273fb9 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets.dm @@ -33,6 +33,7 @@ JOB_DETECTIVE, JOB_HEAD_OF_SECURITY, JOB_SECURITY_OFFICER, + JOB_WARDEN, ) /// If enemy_roles was set, this is the amount of enemy job workers needed per threat_level range (0-10,10-20,etc) IMPORTANT: DOES NOT WORK ON ROUNDSTART RULESETS. var/required_enemies = list(1,1,0,0,0,0,0,0,0,0) @@ -167,6 +168,14 @@ GLOB.pre_setup_antags -= M return TRUE +/// Rulesets can be reused, so when we're done setting one up we want to wipe its memory of the people it was selecting over +/// This isn't Destroy we aren't deleting it here, rulesets free when nothing holds a ref. This is just to prevent hung refs. +/datum/dynamic_ruleset/proc/forget_startup() + SHOULD_CALL_PARENT(TRUE) + candidates = list() + assigned = list() + antag_datum = null + /// Here you can perform any additional checks you want. (such as checking the map etc) /// Remember that on roundstart no one knows what their job is at this point. /// IMPORTANT: If ready() returns TRUE, that means pre_execute() or execute() should never fail! diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 99aabf400d2..0634c44a4f2 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -21,6 +21,13 @@ /// Abstract root value var/abstract_type = /datum/dynamic_ruleset/midround +/datum/dynamic_ruleset/midround/forget_startup() + living_players = list() + living_antags = list() + dead_players = list() + list_observers = list() + return ..() + /datum/dynamic_ruleset/midround/from_ghosts weight = 0 required_type = /mob/dead/observer @@ -45,42 +52,50 @@ dead_players = trim_list(GLOB.dead_player_list) list_observers = trim_list(GLOB.current_observers_list) -/datum/dynamic_ruleset/midround/proc/trim_list(list/L = list()) - var/list/trimmed_list = L.Copy() - for(var/mob/M in trimmed_list) - if (!istype(M, required_type)) - trimmed_list.Remove(M) +/datum/dynamic_ruleset/midround/proc/trim_list(list/to_trim = list()) + var/list/trimmed_list = to_trim.Copy() + for(var/mob/creature in trimmed_list) + if (!istype(creature, required_type)) + trimmed_list.Remove(creature) continue - if (!M.client) // Are they connected? - trimmed_list.Remove(M) + if (isnull(creature.client)) // Are they connected? + trimmed_list.Remove(creature) + continue + if (isnull(creature.mind)) + trimmed_list.Remove(creature) continue //SKYRAT EDIT ADDITION - if(is_banned_from(M.client.ckey, BAN_ANTAGONIST)) - trimmed_list.Remove(M) + if(is_banned_from(creature.client.ckey, BAN_ANTAGONIST)) + trimmed_list.Remove(creature) continue - if(!M.client?.prefs?.read_preference(/datum/preference/toggle/be_antag)) - trimmed_list.Remove(M) + if(!creature.client?.prefs?.read_preference(/datum/preference/toggle/be_antag)) + trimmed_list.Remove(creature) continue //SKYRAT EDIT END - if(M.client.get_remaining_days(minimum_required_age) > 0) - trimmed_list.Remove(M) + if(creature.client.get_remaining_days(minimum_required_age) > 0) + trimmed_list.Remove(creature) continue - if (!((antag_preference || antag_flag) in M.client.prefs.be_special)) - trimmed_list.Remove(M) + if (!((antag_preference || antag_flag) in creature.client.prefs.be_special)) + trimmed_list.Remove(creature) continue - if (is_banned_from(M.ckey, list(antag_flag_override || antag_flag, ROLE_SYNDICATE))) - trimmed_list.Remove(M) + if (is_banned_from(creature.ckey, list(antag_flag_override || antag_flag, ROLE_SYNDICATE))) + trimmed_list.Remove(creature) + continue + if (restrict_ghost_roles && (creature.mind.assigned_role.title in GLOB.exp_specialmap[EXP_TYPE_SPECIAL])) // Are they playing a ghost role? + trimmed_list.Remove(creature) + continue + if (creature.mind.assigned_role.title in restricted_roles) // Does their job allow it? + trimmed_list.Remove(creature) + continue + if (length(exclusive_roles) && !(creature.mind.assigned_role.title in exclusive_roles)) // Is the rule exclusive to their job? + trimmed_list.Remove(creature) + continue + if(HAS_TRAIT(creature, TRAIT_MIND_TEMPORARILY_GONE)) // are they out of body? + trimmed_list.Remove(creature) + continue + if(HAS_TRAIT(creature, TRAIT_TEMPORARY_BODY)) // are they an avatar? + trimmed_list.Remove(creature) continue - if (M.mind) - if (restrict_ghost_roles && (M.mind.assigned_role.title in GLOB.exp_specialmap[EXP_TYPE_SPECIAL])) // Are they playing a ghost role? - trimmed_list.Remove(M) - continue - if (M.mind.assigned_role.title in restricted_roles) // Does their job allow it? - trimmed_list.Remove(M) - continue - if ((exclusive_roles.len > 0) && !(M.mind.assigned_role.title in exclusive_roles)) // Is the rule exclusive to their job? - trimmed_list.Remove(M) - continue return trimmed_list // You can then for example prompt dead players in execute() to join as strike teams or whatever @@ -359,6 +374,7 @@ JOB_DETECTIVE, JOB_HEAD_OF_SECURITY, JOB_SECURITY_OFFICER, + JOB_WARDEN, ) required_enemies = list(3,3,3,3,3,2,1,1,0,0) required_candidates = 5 @@ -370,8 +386,6 @@ flags = HIGH_IMPACT_RULESET var/list/operative_cap = list(2,2,3,3,4,5,5,5,5,5) - /// The nuke ops team datum. - var/datum/team/nuclear/nuke_team /datum/dynamic_ruleset/midround/from_ghosts/nuclear/acceptable(population=0, threat=0) if (locate(/datum/dynamic_ruleset/roundstart/nuclear) in mode.executed_rules) @@ -397,7 +411,6 @@ new_character.mind.special_role = ROLE_NUCLEAR_OPERATIVE if(index == 1) var/datum/antagonist/nukeop/leader/leader_antag_datum = new() - nuke_team = leader_antag_datum.nuke_team new_character.mind.add_antag_datum(leader_antag_datum) return return ..() @@ -483,6 +496,10 @@ repeatable = TRUE var/list/vents = list() +/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/forget_startup() + vents = list() + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/xenomorph/execute() // 50% chance of being incremented by one required_candidates += prob(50) @@ -562,6 +579,10 @@ repeatable = TRUE var/list/spawn_locs = list() +/datum/dynamic_ruleset/midround/from_ghosts/space_dragon/forget_startup() + spawn_locs = list() + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/space_dragon/execute() for(var/obj/effect/landmark/carpspawn/C in GLOB.landmarks_list) spawn_locs += (C.loc) @@ -600,6 +621,10 @@ var/datum/team/abductor_team/new_team +/datum/dynamic_ruleset/midround/from_ghosts/abductors/forget_startup() + new_team = null + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/abductors/ready(forced = FALSE) if (required_candidates > (dead_players.len + list_observers.len)) return FALSE @@ -632,6 +657,10 @@ var/list/spawn_locs = list() +/datum/dynamic_ruleset/midround/from_ghosts/space_ninja/forget_startup() + spawn_locs = list() + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/space_ninja/execute() for(var/obj/effect/landmark/carpspawn/carp_spawn in GLOB.landmarks_list) if(!isturf(carp_spawn.loc)) @@ -686,6 +715,10 @@ var/need_extra_spawns_value = 15 var/list/spawn_locs = list() +/datum/dynamic_ruleset/midround/from_ghosts/revenant/forget_startup() + spawn_locs = list() + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/revenant/acceptable(population=0, threat=0) if(GLOB.dead_mob_list.len < dead_mobs_required) return FALSE @@ -849,6 +882,7 @@ JOB_DETECTIVE, JOB_HEAD_OF_SECURITY, JOB_SECURITY_OFFICER, + JOB_WARDEN, ) required_enemies = list(2, 2, 1, 1, 1, 1, 1, 0, 0, 0) required_candidates = 1 @@ -857,6 +891,10 @@ repeatable = TRUE var/list/possible_spawns = list() ///places the antag can spawn +/datum/dynamic_ruleset/midround/from_ghosts/paradox_clone/forget_startup() + possible_spawns = list() + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/paradox_clone/execute() possible_spawns += find_maintenance_spawn(atmos_sensitive = TRUE, require_darkness = FALSE) if(!possible_spawns.len) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index df078c462d9..a90eba738c1 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -121,6 +121,10 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) var/list/datum/team/brother_team/pre_brother_teams = list() var/const/min_team_size = 2 +/datum/dynamic_ruleset/roundstart/traitorbro/forget_startup() + pre_brother_teams = list() + return ..() + /datum/dynamic_ruleset/roundstart/traitorbro/pre_execute(population) . = ..() var/num_teams = (get_antag_cap(population)/min_team_size) * (scaled_times + 1) // 1 team per scaling diff --git a/code/game/gamemodes/dynamic/ruleset_picking.dm b/code/game/gamemodes/dynamic/ruleset_picking.dm index 4922d7355ce..d6e2fd6b1f4 100644 --- a/code/game/gamemodes/dynamic/ruleset_picking.dm +++ b/code/game/gamemodes/dynamic/ruleset_picking.dm @@ -118,11 +118,12 @@ message_admins("[key_name(M)] joined the station, and was selected by the [rule.name] ruleset.") log_dynamic("[key_name(M)] joined the station, and was selected by the [rule.name] ruleset.") executed_rules += rule - rule.candidates.Cut() if (rule.persistent) current_rules += rule new_snapshot(rule) + rule.forget_startup() return TRUE + rule.forget_startup() rule.clean_up() stack_trace("The [rule.ruletype] rule \"[rule.name]\" failed to execute.") return FALSE diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 00488ba1dfb..bdefee42c3e 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -236,18 +236,46 @@ GLOBAL_LIST_EMPTY(objectives) //SKYRAT EDIT ADDITION /datum/objective/assassinate/admin_edit(mob/admin) admin_simple_target_pick(admin) +#define DISCONNECT_GRACE_TIME (2 MINUTES) +#define DISCONNECT_GRACE_WARNING_TIME (1 MINUTES) + /datum/objective/mutiny name = "mutiny" martyr_compatible = 1 var/target_role_type = FALSE + /// Not primarily used as a cooldown but a timer to give a little bit more of a chance for the player to reconnect. + COOLDOWN_DECLARE(disconnect_timer) + /// Whether admins have been warned about the potentially AFK player + var/warned_admins = FALSE +/datum/objective/mutiny/proc/warn_admins() + message_admins("[ADMIN_LOOKUPFLW(target.current)] has gone AFK with a mutiny objective that involves them. They only have [COOLDOWN_TIMELEFT(src, disconnect_timer) / 10] seconds remaining before they are treated as if they were dead.") /datum/objective/mutiny/check_completion() - if(!target || !considered_alive(target) || considered_afk(target) || considered_exiled(target)) + if(!target || !considered_alive(target) || considered_exiled(target)) return TRUE + + if(considered_afk(target)) + if(!COOLDOWN_STARTED(src, disconnect_timer)) + COOLDOWN_START(src, disconnect_timer, DISCONNECT_GRACE_TIME) + warn_admins() + else if(COOLDOWN_FINISHED(src, disconnect_timer)) + return TRUE + else if(COOLDOWN_TIMELEFT(src, disconnect_timer) <= DISCONNECT_GRACE_WARNING_TIME && !warned_admins) + warned_admins = TRUE + warn_admins() + else + COOLDOWN_RESET(src, disconnect_timer) + warned_admins = FALSE + var/turf/T = get_turf(target.current) return !T || !is_station_level(T.z) +#undef DISCONNECT_GRACE_TIME +#undef DISCONNECT_GRACE_WARNING_TIME + + + /datum/objective/mutiny/update_explanation_text() ..() if(target?.current) diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index b6327480399..fde5c89b88d 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -927,6 +927,7 @@ wrench.play_tool_sound(src, 50) setDir(turn(dir,-90)) to_chat(user, span_notice("You rotate [src].")) + SEND_SIGNAL(src, COMSIG_MACHINERY_DEFAULT_ROTATE_WRENCH, user, wrench) return TRUE /obj/machinery/proc/exchange_parts(mob/user, obj/item/storage/part_replacer/replacer_tool) @@ -1122,10 +1123,10 @@ if(prob(85) && (zap_flags & ZAP_MACHINE_EXPLOSIVE) && !(resistance_flags & INDESTRUCTIBLE)) explosion(src, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 4, flame_range = 2, adminlog = FALSE, smoke = FALSE) else if(zap_flags & ZAP_OBJ_DAMAGE) - take_damage(power * 0.0005, BURN, ENERGY) + take_damage(power * 6.25e-7, BURN, ENERGY) if(prob(40)) emp_act(EMP_LIGHT) - power -= power * 0.0005 + power -= power * 5e-4 return ..() /obj/machinery/proc/adjust_item_drop_location(atom/movable/dropped_atom) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8 diff --git a/code/game/machinery/airlock_control.dm b/code/game/machinery/airlock_control.dm index 4c3532e3616..f4d1b29da18 100644 --- a/code/game/machinery/airlock_control.dm +++ b/code/game/machinery/airlock_control.dm @@ -6,10 +6,6 @@ var/airlock_state var/frequency -/obj/machinery/door/airlock/Initialize(mapload) - . = ..() - RegisterSignal(SSdcs, COMSIG_GLOB_GREY_TIDE, PROC_REF(grey_tide)) - /// Forces the airlock to unbolt and open /obj/machinery/door/airlock/proc/secure_open() locked = FALSE @@ -35,17 +31,6 @@ locked = FALSE return ..() -/obj/machinery/door/airlock/proc/grey_tide(datum/source, list/grey_tide_areas) - SIGNAL_HANDLER - - if(!is_station_level(z) || critical_machine) - return //Skip doors in critical positions, such as the SM chamber. - - for(var/area_type in grey_tide_areas) - if(!istype(get_area(src), area_type)) - continue - INVOKE_ASYNC(src, PROC_REF(prison_open)) //Sleep gets called further down in open(), so we have to invoke async - /obj/machinery/airlock_sensor icon = 'icons/obj/machines/wallmounts.dmi' icon_state = "airlock_sensor_off" diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index 4ec567a95d6..c433565dbf8 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -262,8 +262,9 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) // SKYRAT EDIT END // Binary living/dead status + // Current status if (sensor_mode >= SENSOR_LIVING) - entry["life_status"] = (tracked_living_mob.stat != DEAD) + entry["life_status"] = tracked_living_mob.stat // Damage if (sensor_mode >= SENSOR_VITALS) diff --git a/code/game/machinery/computer/operating_computer.dm b/code/game/machinery/computer/operating_computer.dm index f7b0ef24ffd..3b639a9ce57 100644 --- a/code/game/machinery/computer/operating_computer.dm +++ b/code/game/machinery/computer/operating_computer.dm @@ -25,11 +25,15 @@ if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb) CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, src) - experiment_handler = AddComponent( \ + var/list/operating_signals = list( + COMSIG_OPERATING_COMPUTER_AUTOPSY_COMPLETE = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_autopsy_experiment), + ) + experiment_handler = AddComponent( /datum/component/experiment_handler, \ allowed_experiments = list(/datum/experiment/autopsy), \ config_flags = EXPERIMENT_CONFIG_ALWAYS_ACTIVE, \ config_mode = EXPERIMENT_CONFIG_ALTCLICK, \ + experiment_signals = operating_signals, \ ) /obj/machinery/computer/operating/Destroy() diff --git a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm index 57067db47f6..96c33871a40 100644 --- a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm @@ -133,7 +133,7 @@ . = ..() if(prob(5)) owner.emote("squeaks") - playsound(owner, 'sound/effects/mousesqueek.ogg', 100) + playsound(owner, 'sound/creatures/mousesqueek.ogg', 100) #undef RAT_ORGAN_COLOR #undef RAT_SCLERA_COLOR diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 2786ed0f769..9d18b7ecb85 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -191,12 +191,23 @@ diag_hud_set_electrified() - RegisterSignal(src, COMSIG_MACHINERY_BROKEN, PROC_REF(on_break)) - // Click on the floor to close airlocks AddComponent(/datum/component/redirect_attack_hand_from_turf) - return INITIALIZE_HINT_LATELOAD + RegisterSignal(src, COMSIG_MACHINERY_BROKEN, PROC_REF(on_break)) + + RegisterSignal(SSdcs, COMSIG_GLOB_GREY_TIDE, PROC_REF(grey_tide)) + +/obj/machinery/door/airlock/proc/grey_tide(datum/source, list/grey_tide_areas) + SIGNAL_HANDLER + + if(!is_station_level(z) || critical_machine) + return //Skip doors in critical positions, such as the SM chamber. + + for(var/area_type in grey_tide_areas) + if(!istype(get_area(src), area_type)) + continue + INVOKE_ASYNC(src, PROC_REF(prison_open)) //Sleep gets called further down in open(), so we have to invoke async /obj/machinery/door/airlock/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock) if(id_tag) diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index d5d0e9c732e..15c740a31e4 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -138,6 +138,9 @@ storage_type = /obj/item/tank/jetpack/oxygen/harness mod_type = /obj/item/mod/control/pre_equipped/nuclear +/obj/machinery/suit_storage_unit/syndicate/lavaland + mod_type = /obj/item/mod/control/pre_equipped/nuclear/no_jetpack + /obj/machinery/suit_storage_unit/interdyne mask_type = /obj/item/clothing/mask/gas/syndicate storage_type = /obj/item/tank/jetpack/oxygen/harness diff --git a/code/game/machinery/telecomms/computers/telemonitor.dm b/code/game/machinery/telecomms/computers/telemonitor.dm index b862a6372b7..400d827f618 100644 --- a/code/game/machinery/telecomms/computers/telemonitor.dm +++ b/code/game/machinery/telecomms/computers/telemonitor.dm @@ -14,10 +14,10 @@ /// Current screen the user is viewing var/screen = MAIN_VIEW - /// The machines located by the computer - var/list/machinelist = list() - /// the currently selected machine - var/obj/machinery/telecomms/SelectedMachine + /// Weakrefs of the machines located by the computer + var/list/machine_list = list() + /// Weakref of the currently selected tcomms machine + var/datum/weakref/selected_machine_ref /// The network to probe var/network = "NULL" /// Error message to show @@ -35,20 +35,26 @@ // --- Main Menu --- if(MAIN_VIEW) var/list/found_machinery = list() - for(var/obj/machinery/telecomms/telecomms in machinelist) + for(var/datum/weakref/tcomms_ref in machine_list) + var/obj/machinery/telecomms/telecomms = tcomms_ref.resolve() + if(!telecomms) + machine_list -= tcomms_ref + continue found_machinery += list(list("ref" = REF(telecomms), "name" = telecomms.name, "id" = telecomms.id)) data["machinery"] = found_machinery // --- Viewing Machine --- if(MACHINE_VIEW) // Send selected machinery data var/list/machine_out = list() - machine_out["name"] = SelectedMachine.name - // Get the linked machinery - var/list/linked_machinery = list() - for(var/obj/machinery/telecomms/T in SelectedMachine.links) - linked_machinery += list(list("ref" = REF(T.id), "name" = T.name, "id" = T.id)) - machine_out["linked_machinery"] = linked_machinery - data["machine"] = machine_out + var/obj/machinery/telecomms/selected = selected_machine_ref.resolve() + if(selected) + machine_out["name"] = selected.name + // Get the linked machinery + var/list/linked_machinery = list() + for(var/obj/machinery/telecomms/T in selected.links) + linked_machinery += list(list("ref" = REF(T.id), "name" = T.name, "id" = T.id)) + machine_out["linked_machinery"] = linked_machinery + data["machine"] = machine_out return data /obj/machinery/computer/telecomms/monitor/ui_act(action, params) @@ -67,7 +73,9 @@ error_message = "OPERATION FAILED: NETWORK ID TOO LONG." return TRUE - if(machinelist.len > 0) + list_clear_empty_weakrefs(machine_list) + + if(machine_list.len > 0) error_message = "OPERATION FAILED: CANNOT PROBE WHEN BUFFER FULL." return TRUE @@ -75,26 +83,30 @@ for(var/obj/machinery/telecomms/T in urange(25, src)) if(T.network == network) - machinelist.Add(T) - if(machinelist.len == 0) + machine_list += WEAKREF(T) + if(machine_list.len == 0) error_message = "OPERATION FAILED: UNABLE TO LOCATE NETWORK ENTITIES IN [network]." return TRUE - error_message = "[machinelist.len] ENTITIES LOCATED & BUFFERED"; + error_message = "[machine_list.len] ENTITIES LOCATED & BUFFERED"; return TRUE if("flush_buffer") - machinelist = list() + machine_list = list() network = "" return TRUE if("view_machine") - for(var/obj/machinery/telecomms/T in machinelist) - if(T.id == params["id"]) - SelectedMachine = T - if(!SelectedMachine) + for(var/datum/weakref/tcomms_ref in machine_list) + var/obj/machinery/telecomms/tcomms = tcomms_ref.resolve() + if(!tcomms) + machine_list -= tcomms_ref + continue + if(tcomms.id == params["id"]) + selected_machine_ref = tcomms_ref + if(!selected_machine_ref) error_message = "OPERATION FAILED: UNABLE TO LOCATE MACHINERY." screen = MACHINE_VIEW return TRUE if("return_home") - SelectedMachine = null + selected_machine_ref = null screen = MAIN_VIEW return TRUE return TRUE diff --git a/code/game/objects/effects/anomalies/anomalies_flux.dm b/code/game/objects/effects/anomalies/anomalies_flux.dm index eee4319b352..2bb3ab28a1a 100644 --- a/code/game/objects/effects/anomalies/anomalies_flux.dm +++ b/code/game/objects/effects/anomalies/anomalies_flux.dm @@ -66,7 +66,7 @@ ///range in whuich we zap var/zap_range = 1 ///strength of the zappy - var/zap_power = 2500 + var/zap_power = 1e6 ///the zappy flags var/zap_flags = ZAP_GENERATES_POWER | ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index 6a519650d10..daaddb00ce0 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -212,6 +212,10 @@ icon_state += "-old" AddElement(/datum/element/swabable, CELL_LINE_TABLE_SLUDGE, CELL_VIRUS_TABLE_GENERIC, rand(2,4), 10) +/obj/effect/decal/cleanable/vomit/old/black_bile + name = "black bile" + desc = "There's something wiggling in there..." + color = COLOR_DARK /obj/effect/decal/cleanable/chem_pile name = "chemical pile" diff --git a/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm b/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm index dae527c3e6b..2d524e19042 100644 --- a/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm @@ -394,6 +394,15 @@ reagents.expose(smoker, INGEST, fraction) return TRUE +/// Helper to quickly create a cloud of reagent smoke +/proc/do_chem_smoke(range = 0, amount = DIAMOND_AREA(range), atom/holder = null, location = null, reagent_type = /datum/reagent/water, reagent_volume = 10, log = FALSE) + var/datum/reagents/smoke_reagents = new/datum/reagents(reagent_volume) + smoke_reagents.add_reagent(reagent_type, reagent_volume) + + var/datum/effect_system/fluid_spread/smoke/chem/smoke = new + smoke.attach(location) + smoke.set_up(amount = amount, holder = holder, location = location, carry = smoke_reagents, silent = TRUE) + smoke.start(log = log) /// A factory which produces clouds of chemical bearing smoke. /datum/effect_system/fluid_spread/smoke/chem diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 2c4a594b806..4e5b36bf5e8 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -84,6 +84,10 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark) name = "Cargo Technician" icon_state = "Cargo Technician" +/obj/effect/landmark/start/bitrunner + name = "Bitrunner" + icon_state = "x3" + /obj/effect/landmark/start/bartender name = "Bartender" icon_state = "Bartender" diff --git a/code/game/objects/effects/spawners/random/entertainment.dm b/code/game/objects/effects/spawners/random/entertainment.dm index 18876dfc927..1c635f07a5a 100644 --- a/code/game/objects/effects/spawners/random/entertainment.dm +++ b/code/game/objects/effects/spawners/random/entertainment.dm @@ -271,7 +271,6 @@ /obj/item/toy/plush/carpplushie = 3, /obj/item/toy/plush/lizard_plushie/green = 3, /obj/item/toy/plush/lizard_plushie/space/green = 3, - /obj/item/toy/plush/awakenedplushie = 3, /obj/item/toy/plush/goatplushie = 3, /obj/item/toy/plush/rouny = 3, /obj/item/toy/plush/abductor = 3, diff --git a/code/game/objects/effects/spawners/random/lavaland_mobs.dm b/code/game/objects/effects/spawners/random/lavaland_mobs.dm index 8aa20cc90e7..7b4bec1f6a1 100644 --- a/code/game/objects/effects/spawners/random/lavaland_mobs.dm +++ b/code/game/objects/effects/spawners/random/lavaland_mobs.dm @@ -10,9 +10,9 @@ /mob/living/basic/mining/brimdemon = 1, /mob/living/basic/mining/goldgrub = 1, /mob/living/basic/mining/goliath = 1, + /mob/living/basic/mining/legion = 1, /mob/living/basic/mining/lobstrosity/lava = 1, /mob/living/basic/mining/watcher = 1, - /mob/living/simple_animal/hostile/asteroid/hivelord/legion = 1, ) /// Spawns random watcher variants during map generation @@ -46,6 +46,6 @@ desc = "Chance to spawn a rare shiny version." icon_state = "legion" loot = list( - /mob/living/simple_animal/hostile/asteroid/hivelord/legion = 19, - /mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf = 1, + /mob/living/basic/mining/legion = 19, + /mob/living/basic/mining/legion/dwarf = 1, ) diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index aaef891ee4a..94e9cb674b2 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -358,6 +358,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM if(!istype(smoker) || smoker.get_item_by_slot(ITEM_SLOT_MASK) != loc) reagents.remove_any(to_smoke) return + else + if(src != smoker.wear_mask) + reagents.remove_any(to_smoke) + return reagents.expose(smoker, INGEST, min(to_smoke / reagents.total_volume, 1)) var/obj/item/organ/internal/lungs/lungs = smoker.get_organ_slot(ORGAN_SLOT_LUNGS) diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index f04c6e0058f..0338da6b4fa 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -540,6 +540,10 @@ name = "Golem Ship Equipment Vendor Console" build_path = /obj/machinery/computer/order_console/mining/golem +/obj/item/circuitboard/computer/order_console/bitrunning + name = "Bitrunning Vendor Console" + build_path = /obj/machinery/computer/order_console/bitrunning + /obj/item/circuitboard/computer/ferry name = "Transport Ferry" greyscale_colors = CIRCUIT_COLOR_SUPPLY @@ -601,3 +605,8 @@ 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 e5b7144dc8c..9ece80f0940 100644 --- a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm @@ -822,7 +822,7 @@ /obj/item/circuitboard/machine/cryo_tube name = "Cryotube" greyscale_colors = CIRCUIT_COLOR_MEDICAL - build_path = /obj/machinery/atmospherics/components/unary/cryo_cell + build_path = /obj/machinery/cryo_cell req_components = list( /datum/stock_part/matter_bin = 1, /obj/item/stack/cable_coil = 1, @@ -1309,6 +1309,15 @@ req_components = list( /datum/stock_part/card_reader = 1) +/obj/item/circuitboard/machine/fishing_portal_generator + name = "Fishing Portal Generator" + greyscale_colors = CIRCUIT_COLOR_SERVICE + build_path = /obj/machinery/fishing_portal_generator + req_components = list( + /datum/stock_part/matter_bin = 2, + /datum/stock_part/capacitor = 1) + needs_anchored = FALSE + //Supply /obj/item/circuitboard/machine/ore_redemption name = "Ore Redemption" @@ -1357,16 +1366,14 @@ greyscale_colors = CIRCUIT_COLOR_SUPPLY build_path = /obj/machinery/rnd/production/techfab/department/cargo -/obj/item/circuitboard/machine/bepis - name = "BEPIS Chamber" +/obj/item/circuitboard/machine/materials_market + name = "Galactic Materials Market" greyscale_colors = CIRCUIT_COLOR_SUPPLY - build_path = /obj/machinery/rnd/bepis + build_path = /obj/machinery/materials_market req_components = list( /obj/item/stack/cable_coil = 5, - /datum/stock_part/capacitor = 1, - /datum/stock_part/servo = 1, - /datum/stock_part/micro_laser = 1, - /datum/stock_part/scanning_module = 1) + /datum/stock_part/scanning_module = 1, + /datum/stock_part/card_reader = 1) //Misc /obj/item/circuitboard/machine/sheetifier @@ -1527,3 +1534,22 @@ /obj/item/mod/module/rad_protection = 1, /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/crayons.dm b/code/game/objects/items/crayons.dm index 57bc04e7007..bfe1457aa52 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -747,6 +747,15 @@ pre_noise = TRUE post_noise = FALSE +/obj/item/toy/crayon/spraycan/Initialize(mapload) + . = ..() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/improvised_coolant) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/toy/crayon/spraycan/isValidSurface(surface) return (isfloorturf(surface) || iswallturf(surface)) diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index a8fa34ed5f8..0ab7e5d94b5 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -18,102 +18,6 @@ . = ..() ADD_TRAIT(src, TRAIT_CASTABLE_LOC, INNATE_TRAIT) -/obj/item/computer_disk/syndie_ai_upgrade - name = "AI interaction range upgrade" - desc = "A NT data chip containing information that a syndiCard AI can utilize to improve its wireless interfacing abilities. Simply slap it on top of an intelliCard, MODsuit, or AI core and watch it do its work! It's rumoured that there's something 'pretty awful' in it." - icon = 'icons/obj/antags/syndicate_tools.dmi' - icon_state = "something_awful" - max_capacity = 1000 - w_class = WEIGHT_CLASS_NORMAL - -/obj/item/computer_disk/syndie_ai_upgrade/pre_attack(atom/A, mob/living/user, params) - var/mob/living/silicon/ai/AI - if(isAI(A)) - AI = A - else - AI = locate() in A - if(!AI || AI.interaction_range == INFINITY) - playsound(src,'sound/machines/buzz-sigh.ogg',50,FALSE) - to_chat(user, span_notice("Error! Incompatible object!")) - return ..() - AI.interaction_range += 2 - if(AI.interaction_range > 7) - AI.interaction_range = INFINITY - playsound(src,'sound/machines/twobeep.ogg',50,FALSE) - to_chat(user, span_notice("You insert [src] into [AI]'s compartment, and it beeps as it processes the data.")) - to_chat(AI, span_notice("You process [src], and find yourself able to manipulate electronics from up to [AI.interaction_range] meters!")) - qdel(src) - -/obj/item/aicard/syndie - name = "syndiCard" - desc = "A storage device for AIs. Nanotrasen forgot to make the patent, so the Syndicate made their own version!" - icon = 'icons/obj/aicards.dmi' - icon_state = "syndicard" - base_icon_state = "syndicard" - item_flags = null - force = 7 - -/obj/item/aicard/syndie/loaded - /// Set to true while we're waiting for ghosts to sign up - var/finding_candidate = FALSE - -/obj/item/aicard/syndie/loaded/examine(mob/user) - . = ..() - - . += span_notice("This one has a little S.E.L.F. insignia on the back, and a label next to it that says 'Activate for one FREE aligned AI! Please attempt uplink reintegration or ask your employers for reimbursal if AI is unavailable or belligerent.") - -/obj/item/aicard/syndie/loaded/attack_self(mob/user, modifiers) - if(!isnull(AI)) - return ..() - if(finding_candidate) - balloon_alert(user, "loading...") - return TRUE - finding_candidate = TRUE - to_chat(user, span_notice("Connecting to S.E.L.F. dispatch...")) - procure_ai(user) - finding_candidate = FALSE - return TRUE - -/obj/item/aicard/syndie/loaded/proc/procure_ai(mob/user) - var/datum/antagonist/nukeop/op_datum = user.mind?.has_antag_datum(/datum/antagonist/nukeop,TRUE) - if(isnull(op_datum)) - balloon_alert(user, "invalid access!") - return - var/list/nuke_candidates = poll_ghost_candidates( - question = "Do you want to play as a nuclear operative MODsuit AI?", - jobban_type = ROLE_OPERATIVE, - be_special_flag = ROLE_OPERATIVE_MIDROUND, - poll_time = 15 SECONDS, - ignore_category = POLL_IGNORE_SYNDICATE, - ) - if(QDELETED(src)) - return - if(!LAZYLEN(nuke_candidates)) - to_chat(user, span_warning("Unable to connect to S.E.L.F. dispatch. Please wait and try again later or use the intelliCard on your uplink to get your points refunded.")) - return - // pick ghost, create AI and transfer - var/mob/dead/observer/ghos = pick(nuke_candidates) - var/mob/living/silicon/ai/weak_syndie/new_ai = new /mob/living/silicon/ai/weak_syndie(get_turf(src), new /datum/ai_laws/syndicate_override, ghos) - // create and apply syndie datum - var/datum/antagonist/nukeop/nuke_datum = new() - nuke_datum.send_to_spawnpoint = FALSE - new_ai.mind.add_antag_datum(nuke_datum, op_datum.nuke_team) - new_ai.mind.special_role = "Syndicate AI" - new_ai.faction |= ROLE_SYNDICATE - new_ai.grant_language(/datum/language/codespeak, source = LANGUAGE_MIND) - // Make it look evil!!! - new_ai.hologram_appearance = mutable_appearance('icons/mob/silicon/ai.dmi',"xeno_queen") //good enough - new_ai.icon_state = resolve_ai_icon("hades") - // Transfer the AI from the core we created into the card, then delete the core - capture_ai(new_ai, user) - var/obj/structure/ai_core/deactivated/detritus = locate() in get_turf(src) - qdel(detritus) - AI.control_disabled = FALSE - AI.radio_enabled = TRUE - do_sparks(4, TRUE, src) - playsound(src, 'sound/machines/chime.ogg', 25, TRUE) - return - /obj/item/aicard/Destroy(force) if(AI) AI.ghostize(can_reenter_corpse = FALSE) diff --git a/code/game/objects/items/devices/aicard_evil.dm b/code/game/objects/items/devices/aicard_evil.dm new file mode 100644 index 00000000000..1a5fce6897a --- /dev/null +++ b/code/game/objects/items/devices/aicard_evil.dm @@ -0,0 +1,104 @@ +/// One use AI card which downloads a ghost as a syndicate AI to put in your MODsuit +/obj/item/aicard/syndie + name = "syndiCard" + desc = "A storage device for AIs. Nanotrasen forgot to make the patent, so the Syndicate made their own version!" + icon = 'icons/obj/aicards.dmi' + icon_state = "syndicard" + base_icon_state = "syndicard" + item_flags = null + force = 7 + +/obj/item/aicard/syndie/loaded + /// Set to true while we're waiting for ghosts to sign up + var/finding_candidate = FALSE + +/obj/item/aicard/syndie/loaded/examine(mob/user) + . = ..() + . += span_notice("This one has a little S.E.L.F. insignia on the back, and a label next to it that says 'Activate for one FREE aligned AI! Please attempt uplink reintegration or ask your employers for reimbursal if AI is unavailable or belligerent.") + +/obj/item/aicard/syndie/loaded/attack_self(mob/user, modifiers) + if(!isnull(AI)) + return ..() + if(finding_candidate) + balloon_alert(user, "loading...") + return TRUE + finding_candidate = TRUE + to_chat(user, span_notice("Connecting to S.E.L.F. dispatch...")) + procure_ai(user) + finding_candidate = FALSE + return TRUE + +/obj/item/aicard/syndie/loaded/proc/procure_ai(mob/user) + var/datum/antagonist/nukeop/op_datum = user.mind?.has_antag_datum(/datum/antagonist/nukeop,TRUE) + if(isnull(op_datum)) + balloon_alert(user, "invalid access!") + return + var/list/nuke_candidates = poll_ghost_candidates( + question = "Do you want to play as a nuclear operative MODsuit AI?", + jobban_type = ROLE_OPERATIVE, + be_special_flag = ROLE_OPERATIVE_MIDROUND, + poll_time = 15 SECONDS, + ignore_category = POLL_IGNORE_SYNDICATE, + ) + if(QDELETED(src)) + return + if(!LAZYLEN(nuke_candidates)) + to_chat(user, span_warning("Unable to connect to S.E.L.F. dispatch. Please wait and try again later or use the intelliCard on your uplink to get your points refunded.")) + return + // pick ghost, create AI and transfer + var/mob/dead/observer/ghos = pick(nuke_candidates) + var/mob/living/silicon/ai/weak_syndie/new_ai = new /mob/living/silicon/ai/weak_syndie(get_turf(src), new /datum/ai_laws/syndicate_override, ghos) + // create and apply syndie datum + var/datum/antagonist/nukeop/nuke_datum = new() + nuke_datum.send_to_spawnpoint = FALSE + new_ai.mind.add_antag_datum(nuke_datum, op_datum.nuke_team) + new_ai.mind.special_role = "Syndicate AI" + new_ai.faction |= ROLE_SYNDICATE + // Make it look evil!!! + new_ai.hologram_appearance = mutable_appearance('icons/mob/silicon/ai.dmi',"xeno_queen") //good enough + new_ai.icon_state = resolve_ai_icon("hades") + // Transfer the AI from the core we created into the card, then delete the core + capture_ai(new_ai, user) + var/obj/structure/ai_core/deactivated/detritus = locate() in get_turf(src) + qdel(detritus) + AI.control_disabled = FALSE + AI.radio_enabled = TRUE + do_sparks(4, TRUE, src) + playsound(src, 'sound/machines/chime.ogg', 25, TRUE) + return + +/obj/item/aicard/syndie/loaded/upload_ai(atom/to_what, mob/living/user) + . = ..() + if (!.) + return + visible_message(span_warning("The expended card incinerates itself.")) + do_sparks(3, cardinal_only = FALSE, source = src) + new /obj/effect/decal/cleanable/ash(get_turf(src)) + qdel(src) + +/// Upgrade disk used to increase the range of a syndicate AI +/obj/item/computer_disk/syndie_ai_upgrade + name = "AI interaction range upgrade" + desc = "A NT data chip containing information that a syndiCard AI can utilize to improve its wireless interfacing abilities. Simply slap it on top of an intelliCard, MODsuit, or AI core and watch it do its work! It's rumoured that there's something 'pretty awful' in it." + icon = 'icons/obj/antags/syndicate_tools.dmi' + icon_state = "something_awful" + max_capacity = 1000 + w_class = WEIGHT_CLASS_NORMAL + +/obj/item/computer_disk/syndie_ai_upgrade/pre_attack(atom/A, mob/living/user, params) + var/mob/living/silicon/ai/AI + if(isAI(A)) + AI = A + else + AI = locate() in A + if(!AI || AI.interaction_range == INFINITY) + playsound(src,'sound/machines/buzz-sigh.ogg',50,FALSE) + to_chat(user, span_notice("Error! Incompatible object!")) + return ..() + AI.interaction_range += 2 + if(AI.interaction_range > 7) + AI.interaction_range = INFINITY + playsound(src,'sound/machines/twobeep.ogg',50,FALSE) + to_chat(user, span_notice("You insert [src] into [AI]'s compartment, and it beeps as it processes the data.")) + to_chat(AI, span_notice("You process [src], and find yourself able to manipulate electronics from up to [AI.interaction_range] meters!")) + qdel(src) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index ecf94d58f70..d3d280cd743 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -44,6 +44,13 @@ if(toggle_context) RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/flashlight_eyes) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/flashlight/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) // single use lights can be toggled on once if(isnull(held_item) && (toggle_context || !on)) diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index 17f5e7d4902..08dee828011 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -127,12 +127,6 @@ if(distance < rangewarning) //ai cant see us but is close detect_state = PROXIMITY_NEAR -/mob/camera/ai_eye/remote/ai_detector - name = "AI detector eye" - ai_detector_visible = FALSE - visible_icon = FALSE - use_static = FALSE - /datum/action/item_action/toggle_multitool name = "Toggle AI detecting mode" check_flags = NONE diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 1065d16d1ca..edd058bedd2 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -112,6 +112,13 @@ AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES) + // No subtypes + if(type != /obj/item/radio) + return + AddComponent(/datum/component/slapcrafting,\ + slapcraft_recipes = list(/datum/crafting_recipe/improv_explosive)\ + ) + /obj/item/radio/Destroy() remove_radio_all(src) //Just to be sure QDEL_NULL(wires) diff --git a/code/game/objects/items/devices/scanners/gas_analyzer.dm b/code/game/objects/items/devices/scanners/gas_analyzer.dm index 727d38c245c..36819d8502a 100644 --- a/code/game/objects/items/devices/scanners/gas_analyzer.dm +++ b/code/game/objects/items/devices/scanners/gas_analyzer.dm @@ -26,6 +26,15 @@ . = ..() RegisterSignal(src, COMSIG_TOOL_ATOM_ACTED_PRIMARY(tool_behaviour), PROC_REF(on_analyze)) + if(type != /obj/item/analyzer) + return + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/material_sniffer) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/analyzer/equipped(mob/user, slot, initial) . = ..() ADD_TRAIT(user, TRAIT_DETECT_STORM, CLOTHING_TRAIT) diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index 69193b7df92..8947e83d363 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -43,6 +43,15 @@ /// Icon state when inside a tank holder. var/tank_holder_icon_state = "holder_extinguisher" +/obj/item/extinguisher/Initialize(mapload) + . = ..() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/ghettojetpack) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/extinguisher/empty starting_water = FALSE diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm index 035af619513..eb94626c86e 100644 --- a/code/game/objects/items/flamethrower.dm +++ b/code/game/objects/items/flamethrower.dm @@ -34,6 +34,12 @@ /obj/item/flamethrower/Initialize(mapload) . = ..() AddElement(/datum/element/update_icon_updates_onmob) + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/flamethrower) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) /obj/item/flamethrower/Destroy() if(weldtool) diff --git a/code/game/objects/items/food/burgers.dm b/code/game/objects/items/food/burgers.dm index 191cc0eaf25..b2d779ca3a5 100644 --- a/code/game/objects/items/food/burgers.dm +++ b/code/game/objects/items/food/burgers.dm @@ -688,3 +688,4 @@ tastes = list("juicy meat" = 4, "BBQ sauce" = 3, "onions" = 2, "bun" = 2) foodtypes = GRAIN | MEAT | VEGETABLES venue_value = FOOD_PRICE_NORMAL + crafting_complexity = FOOD_COMPLEXITY_3 diff --git a/code/game/objects/items/food/cake.dm b/code/game/objects/items/food/cake.dm index 5d33c332ff6..07d5818b466 100644 --- a/code/game/objects/items/food/cake.dm +++ b/code/game/objects/items/food/cake.dm @@ -690,6 +690,7 @@ tastes = list("cake" = 2, "cream" = 3, "pineapple" = 4) foodtypes = GRAIN | DAIRY | SUGAR | FRUIT | PINEAPPLE slice_type = /obj/item/food/cakeslice/pineapple_cream_cake + crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/cakeslice/pineapple_cream_cake name = "pineapple cream cake slice" @@ -702,3 +703,4 @@ ) tastes = list("cake" = 2, "cream" = 3, "pineapple" = 4) foodtypes = GRAIN | DAIRY | SUGAR | FRUIT | PINEAPPLE + crafting_complexity = FOOD_COMPLEXITY_3 diff --git a/code/game/objects/items/food/meatdish.dm b/code/game/objects/items/food/meatdish.dm index 07cd70ea013..2d376148045 100644 --- a/code/game/objects/items/food/meatdish.dm +++ b/code/game/objects/items/food/meatdish.dm @@ -1017,6 +1017,7 @@ ) tastes = list("meat" = 5, "savory sauce" = 4, "tangy pineapple" = 3, "pepper" = 2) foodtypes = MEAT | VEGETABLES | FRUIT | PINEAPPLE + crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/kebab/pineapple_skewer name = "pineapple skewer" @@ -1029,6 +1030,7 @@ ) tastes = list("juicy meat" = 4, "pineapple" = 3) foodtypes = MEAT | FRUIT | PINEAPPLE + crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/futomaki_sushi_roll name = "futomaki sushi roll" @@ -1042,6 +1044,7 @@ tastes = list("boiled rice" = 4, "fish" = 5, "egg" = 3, "dried seaweed" = 2, "cucumber" = 2) foodtypes = VEGETABLES | SEAFOOD w_class = WEIGHT_CLASS_SMALL + crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/futomaki_sushi_roll/make_processable() AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/futomaki_sushi_slice, 4, screentip_verb = "Chop") @@ -1058,6 +1061,7 @@ tastes = list("boiled rice" = 4, "fish" = 5, "egg" = 3, "dried seaweed" = 2, "cucumber" = 2) foodtypes = VEGETABLES | SEAFOOD w_class = WEIGHT_CLASS_SMALL + crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/philadelphia_sushi_roll name = "Philadelphia sushi roll" @@ -1071,6 +1075,7 @@ tastes = list("boiled rice" = 4, "fish" = 5, "creamy cheese" = 3, "dried seaweed" = 2, "cucumber" = 2) foodtypes = VEGETABLES | SEAFOOD | DAIRY w_class = WEIGHT_CLASS_SMALL + crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/philadelphia_sushi_roll/make_processable() AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/philadelphia_sushi_slice, 4, screentip_verb = "Chop") @@ -1087,3 +1092,4 @@ tastes = list("boiled rice" = 4, "fish" = 5, "creamy cheese" = 3, "dried seaweed" = 2, "cucumber" = 2) foodtypes = VEGETABLES | SEAFOOD | DAIRY w_class = WEIGHT_CLASS_SMALL + crafting_complexity = FOOD_COMPLEXITY_3 diff --git a/code/game/objects/items/food/mexican.dm b/code/game/objects/items/food/mexican.dm index 58c50ba5863..b4e32587bc6 100644 --- a/code/game/objects/items/food/mexican.dm +++ b/code/game/objects/items/food/mexican.dm @@ -336,3 +336,4 @@ tastes = list("pineapple" = 4, "tomato" = 3, "onion" = 2, "chili" = 2) foodtypes = VEGETABLES | FRUIT | PINEAPPLE w_class = WEIGHT_CLASS_SMALL + crafting_complexity = FOOD_COMPLEXITY_3 diff --git a/code/game/objects/items/food/misc.dm b/code/game/objects/items/food/misc.dm index 67e74496260..ba72e93a8b0 100644 --- a/code/game/objects/items/food/misc.dm +++ b/code/game/objects/items/food/misc.dm @@ -550,6 +550,7 @@ tastes = list("cooked eggplant" = 5, "cheese" = 4, "ground meat" = 3, "veggies" = 2) foodtypes = VEGETABLES | MEAT | DAIRY w_class = WEIGHT_CLASS_SMALL + crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/moussaka name = "moussaka" @@ -562,6 +563,7 @@ ) tastes = list("cooked eggplant" = 5, "potato" = 1, "baked veggies" = 2, "meat" = 4, "bechamel sauce" = 3) foodtypes = MEAT | DAIRY | VEGETABLES + crafting_complexity = FOOD_COMPLEXITY_4 /obj/item/food/moussaka/make_processable() AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/moussaka_slice, 4, 3 SECONDS, table_required = TRUE, screentip_verb = "Cut") @@ -577,6 +579,7 @@ ) tastes = list("cooked eggplant" = 5, "potato" = 1, "baked veggies" = 2, "meat" = 4, "bechamel sauce" = 3) foodtypes = MEAT | DAIRY | VEGETABLES + crafting_complexity = FOOD_COMPLEXITY_4 /obj/item/food/candied_pineapple name = "candied pineapple" @@ -591,6 +594,7 @@ foodtypes = FRUIT | SUGAR food_flags = FOOD_FINGER_FOOD w_class = WEIGHT_CLASS_TINY + crafting_complexity = FOOD_COMPLEXITY_1 /obj/item/food/candied_pineapple/Initialize(mapload) . = ..() @@ -608,6 +612,7 @@ tastes = list("dough" = 2) foodtypes = GRAIN w_class = WEIGHT_CLASS_TINY + crafting_complexity = FOOD_COMPLEXITY_1 /obj/item/food/raw_pita_bread/make_grillable() AddComponent(/datum/component/grillable, /obj/item/food/pita_bread, rand(15 SECONDS, 30 SECONDS), TRUE, TRUE) @@ -627,6 +632,7 @@ tastes = list("pita bread" = 2) foodtypes = GRAIN w_class = WEIGHT_CLASS_TINY + crafting_complexity = FOOD_COMPLEXITY_2 /obj/item/food/tzatziki_sauce name = "tzatziki sauce" @@ -639,6 +645,7 @@ tastes = list("garlic" = 4, "cucumber" = 2, "olive oil" = 2) foodtypes = VEGETABLES w_class = WEIGHT_CLASS_TINY + crafting_complexity = FOOD_COMPLEXITY_2 /obj/item/food/tzatziki_and_pita_bread name = "tzatziki and pita bread" @@ -651,6 +658,7 @@ tastes = list("pita bread" = 4, "tzatziki sauce" = 2, "olive oil" = 2) foodtypes = VEGETABLES | GRAIN w_class = WEIGHT_CLASS_TINY + crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/grilled_beef_gyro name = "grilled beef gyro" @@ -664,6 +672,7 @@ tastes = list("pita bread" = 4, "tender meat" = 2, "tzatziki sauce" = 2, "mixed veggies" = 2) foodtypes = VEGETABLES | GRAIN | MEAT w_class = WEIGHT_CLASS_TINY + crafting_complexity = FOOD_COMPLEXITY_4 /obj/item/food/vegetarian_gyro name = "vegetarian gyro" @@ -676,3 +685,4 @@ tastes = list("pita bread" = 4, "cucumber" = 2, "tzatziki sauce" = 2, "mixed veggies" = 2) foodtypes = VEGETABLES | GRAIN w_class = WEIGHT_CLASS_TINY + crafting_complexity = FOOD_COMPLEXITY_4 diff --git a/code/game/objects/items/food/pastries.dm b/code/game/objects/items/food/pastries.dm index 46da05dea14..8a39f6df8d1 100644 --- a/code/game/objects/items/food/pastries.dm +++ b/code/game/objects/items/food/pastries.dm @@ -540,6 +540,7 @@ foodtypes = GRAIN | SUGAR | DAIRY food_flags = FOOD_FINGER_FOOD w_class = WEIGHT_CLASS_SMALL + crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/cookie/snickerdoodle name = "snickerdoodle" @@ -550,6 +551,7 @@ foodtypes = GRAIN | SUGAR | DAIRY food_flags = FOOD_FINGER_FOOD w_class = WEIGHT_CLASS_SMALL + crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/cookie/macaron name = "macaron" @@ -561,6 +563,7 @@ foodtypes = GRAIN | SUGAR | DAIRY food_flags = FOOD_FINGER_FOOD w_class = WEIGHT_CLASS_TINY + crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/cookie/macaron/Initialize(mapload) . = ..() @@ -575,3 +578,4 @@ foodtypes = GRAIN | SUGAR | FRUIT food_flags = FOOD_FINGER_FOOD w_class = WEIGHT_CLASS_SMALL + crafting_complexity = FOOD_COMPLEXITY_3 diff --git a/code/game/objects/items/food/sandwichtoast.dm b/code/game/objects/items/food/sandwichtoast.dm index 8d6e8c8d147..fec714ad850 100644 --- a/code/game/objects/items/food/sandwichtoast.dm +++ b/code/game/objects/items/food/sandwichtoast.dm @@ -259,23 +259,45 @@ . = ..() obj_flags &= ~UNIQUE_RENAME // You shouldn't be able to disguise this on account of how it kills you -///Override for checkliked callback +// Makes you feel disgusted if you look at it wrong. +/obj/item/food/sandwich/death/examine(mob/user) + . = ..() + // Only human mobs, not animals or silicons, can like/dislike by this. + if(!ishuman(user)) + return + if(check_liked(user) == FOOD_LIKED) + return + to_chat(user, span_warning("You imagine yourself eating [src]. You feel a sudden sour taste in your mouth, and a horrible feeling that you've done something wrong.")) + user.adjust_disgust(33) + +// Override for after_eat and check_liked callbacks. /obj/item/food/sandwich/death/make_edible() . = ..() - AddComponent(/datum/component/edible, check_liked = CALLBACK(src, PROC_REF(check_liked))) + AddComponent(/datum/component/edible, after_eat = CALLBACK(src, PROC_REF(after_eat)), check_liked = CALLBACK(src, PROC_REF(check_liked))) /** * Callback to be used with the edible component. -* If you eat the sandwich with the right clothes and hairstyle, you like it. -* If you don't, you contract a deadly disease. +* If you have the right clothes and hairstyle, you like it. +* If you don't, you don't like it. */ /obj/item/food/sandwich/death/proc/check_liked(mob/living/carbon/human/consumer) - /// Closest thing to a mullet we have + // Closest thing to a mullet we have if(consumer.hairstyle == "Gelled Back" && istype(consumer.get_item_by_slot(ITEM_SLOT_ICLOTHING), /obj/item/clothing/under/rank/civilian/cookjorts)) return FOOD_LIKED + return FOOD_DISLIKED + +/** +* Callback to be used with the edible component. +* If you take a bite of the sandwich with the right clothes and hairstyle, you like it. +* If you don't, you contract a deadly disease. +*/ +/obj/item/food/sandwich/death/proc/after_eat(mob/living/carbon/human/consumer) + // If you like it, you're eating it right. + if(check_liked(consumer) == FOOD_LIKED) + return // I thought it didn't make sense for it to instantly kill you, so instead enjoy shitloads of toxin damage per bite. balloon_alert(consumer, "ate it wrong!") - consumer.ForceContractDisease(new/datum/disease/death_sandwich_poisoning()) + consumer.ForceContractDisease(new /datum/disease/death_sandwich_poisoning()) /obj/item/food/sandwich/death/suicide_act(mob/living/user) user.visible_message(span_suicide("[user] starts to shove [src] down [user.p_their()] throat the wrong way. It looks like [user.p_theyre()] trying to commit suicide!")) diff --git a/code/game/objects/items/food/spaghetti.dm b/code/game/objects/items/food/spaghetti.dm index a631cfe5e05..cab4a62a29f 100644 --- a/code/game/objects/items/food/spaghetti.dm +++ b/code/game/objects/items/food/spaghetti.dm @@ -178,6 +178,7 @@ ) tastes = list("noodles" = 5, "meat" = 3, "egg" = 4, "dried seaweed" = 2) foodtypes = GRAIN | MEAT | VEGETABLES + crafting_complexity = FOOD_COMPLEXITY_4 /obj/item/food/spaghetti/kitakata_ramen name = "kitakata ramen" @@ -191,6 +192,7 @@ ) tastes = list("noodles" = 5, "meat" = 4, "mushrooms" = 3, "onion" = 2) foodtypes = GRAIN | MEAT | VEGETABLES + crafting_complexity = FOOD_COMPLEXITY_4 /obj/item/food/spaghetti/kitsune_udon name = "kitsune udon" @@ -204,6 +206,7 @@ ) tastes = list("noodles" = 5, "tofu" = 4, "sugar" = 3, "soy sauce" = 2) foodtypes = GRAIN | VEGETABLES + crafting_complexity = FOOD_COMPLEXITY_4 /obj/item/food/spaghetti/nikujaga name = "nikujaga" @@ -217,6 +220,7 @@ ) tastes = list("noodles" = 5, "meat" = 4, "potato" = 3, "onion" = 2, "mixed veggies" = 2) foodtypes = GRAIN | VEGETABLES | MEAT + crafting_complexity = FOOD_COMPLEXITY_4 /obj/item/food/spaghetti/pho name = "pho" @@ -230,6 +234,7 @@ ) tastes = list("noodles" = 5, "meat" = 4, "cabbage" = 3, "onion" = 2, "herbs" = 2) foodtypes = GRAIN | VEGETABLES | MEAT + crafting_complexity = FOOD_COMPLEXITY_4 /obj/item/food/spaghetti/pad_thai name = "pad thai" @@ -243,3 +248,4 @@ ) tastes = list("noodles" = 5, "fried tofu" = 4, "lime" = 2, "peanut" = 3, "onion" = 2) foodtypes = GRAIN | VEGETABLES | NUTS | FRUIT + crafting_complexity = FOOD_COMPLEXITY_4 diff --git a/code/game/objects/items/food/vegetables.dm b/code/game/objects/items/food/vegetables.dm index 7da97abc484..dd3ae8c450b 100644 --- a/code/game/objects/items/food/vegetables.dm +++ b/code/game/objects/items/food/vegetables.dm @@ -175,6 +175,7 @@ tastes = list("fried eggplant" = 4, "garlic" = 2, "olive oil" = 3) foodtypes = VEGETABLES w_class = WEIGHT_CLASS_SMALL + crafting_complexity = FOOD_COMPLEXITY_2 /obj/item/food/baba_ghanoush name = "baba ghanoush" @@ -188,6 +189,7 @@ tastes = list("mashed eggplant" = 5, "pita bread" = 4, "garlic" = 3, "olive oil" = 4, "lemon juice" = 2) foodtypes = VEGETABLES | GRAIN w_class = WEIGHT_CLASS_SMALL + crafting_complexity = FOOD_COMPLEXITY_2 /obj/item/food/falafel name = "falafel" @@ -200,3 +202,4 @@ tastes = list("fava beans" = 5, "garlic" = 3, "onion" = 2, "fresh herbs" = 4) foodtypes = VEGETABLES w_class = WEIGHT_CLASS_SMALL + crafting_complexity = FOOD_COMPLEXITY_3 diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index df18b540453..daee6043682 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -175,10 +175,6 @@ . = ..() var/static/list/hovering_item_typechecks = list( - /obj/item/stack/rods = list( - SCREENTIP_CONTEXT_LMB = "Craft wired rod", - ), - /obj/item/stack/sheet/iron = list( SCREENTIP_CONTEXT_LMB = "Craft bola", ), @@ -190,6 +186,13 @@ if(new_color) set_cable_color(new_color) + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/bola, /datum/crafting_recipe/gonbola) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/restraints/handcuffs/cable/proc/set_cable_color(new_color) color = GLOB.cable_colors[new_color] cable_color = new_color @@ -289,36 +292,6 @@ cable_color = CABLE_COLOR_WHITE inhand_icon_state = "coil_white" -/obj/item/restraints/handcuffs/cable/attackby(obj/item/I, mob/user, params) //Slapcrafting - if(istype(I, /obj/item/stack/rods)) - var/obj/item/stack/rods/R = I - if (R.use(1)) - var/obj/item/wirerod/W = new /obj/item/wirerod - remove_item_from_storage(user) - user.put_in_hands(W) - to_chat(user, span_notice("You wrap [src] around the top of [I].")) - qdel(src) - else - to_chat(user, span_warning("You need one rod to make a wired rod!")) - return - else if(istype(I, /obj/item/stack/sheet/iron)) - var/obj/item/stack/sheet/iron/M = I - if(M.get_amount() < 6) - to_chat(user, span_warning("You need at least six iron sheets to make good enough weights!")) - return - to_chat(user, span_notice("You begin to apply [I] to [src]...")) - if(do_after(user, 35, target = src)) - if(M.get_amount() < 6 || !M) - return - var/obj/item/restraints/legcuffs/bola/S = new /obj/item/restraints/legcuffs/bola - M.use(6) - user.put_in_hands(S) - to_chat(user, span_notice("You make some weights out of [I] and tie them to [src].")) - remove_item_from_storage(user) - qdel(src) - else - return ..() - /** * # Zipties * diff --git a/code/game/objects/items/implants/implant_freedom.dm b/code/game/objects/items/implants/implant_freedom.dm index d010b57e506..1fa61c27510 100644 --- a/code/game/objects/items/implants/implant_freedom.dm +++ b/code/game/objects/items/implants/implant_freedom.dm @@ -3,37 +3,45 @@ desc = "Use this to escape from those evil Red Shirts." icon_state = "freedom" implant_color = "r" - uses = 4 + uses = FREEDOM_IMPLANT_CHARGES +/obj/item/implant/freedom/implant(mob/living/target, mob/user, silent, force) + . = ..() + if(!.) + return FALSE + if(!iscarbon(target)) //This is pretty much useless for anyone else since they can't be cuffed + balloon_alert(user, "that would be a waste!") + return FALSE + return TRUE /obj/item/implant/freedom/activate() . = ..() + var/mob/living/carbon/carbon_imp_in = imp_in + if(!carbon_imp_in.handcuffed && !carbon_imp_in.legcuffed) + balloon_alert(carbon_imp_in, "no restraints!") + return + uses-- - to_chat(imp_in, span_hear("You feel a faint click.")) - if(iscarbon(imp_in)) - var/mob/living/carbon/C_imp_in = imp_in - C_imp_in.uncuff() + + carbon_imp_in.uncuff() if(!uses) + addtimer(CALLBACK(carbon_imp_in, TYPE_PROC_REF(/atom, balloon_alert), carbon_imp_in, "implant degraded!"), 1 SECONDS) qdel(src) - /obj/item/implant/freedom/get_data() var/dat = {" -Implant Specifications:
-Name: Freedom Beacon
-Life: optimum 5 uses
-Important Notes: Illegal
-
-Implant Details:
-Function: Transmits a specialized cluster of signals to override handcuff locking -mechanisms
-Special Features:
-Neuro-Scan- Analyzes certain shadow signals in the nervous system
-
-No Implant Specifics"} + Implant Specifications:
+ Name: Freedom Beacon
+ Life: Optimum [initial(uses)] uses
+ Important Notes: Illegal
+
+ Implant Details:
+ Function: Transmits a specialized cluster of signals to override handcuff locking + mechanisms. These signals will release any bindings on both the arms and legs.
+ Disclaimer: Heavy-duty restraints such as straightjackets are deemed "too complex" to release from. + "} return dat - /obj/item/implanter/freedom name = "implanter" // Skyrat edit , was implanter (freedom) imp_type = /obj/item/implant/freedom diff --git a/code/game/objects/items/mail.dm b/code/game/objects/items/mail.dm index b377fdde172..d058f96a40c 100644 --- a/code/game/objects/items/mail.dm +++ b/code/game/objects/items/mail.dm @@ -452,9 +452,10 @@ var/list/mail_recipients_for_input = list("Anyone") var/list/used_names = list() for(var/datum/record/locked/person in sort_record(GLOB.manifest.locked)) - if(isnull(person.mind_ref)) + var/datum/mind/locked_mind = person.mind_ref.resolve() + if(isnull(locked_mind)) continue - mail_recipients += person.mind_ref + mail_recipients += locked_mind mail_recipients_for_input += avoid_assoc_duplicate_keys(person.name, used_names) var/recipient = tgui_input_list(user, "Choose a recipient", "Mail Counterfeiting", mail_recipients_for_input) diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm index 77b76d85224..eab3f34d343 100644 --- a/code/game/objects/items/plushes.dm +++ b/code/game/objects/items/plushes.dm @@ -584,6 +584,7 @@ squeak_override = list('sound/effects/blobattack.ogg' = 1) gender = FEMALE //given all the jokes and drawings, I'm not sure the xenobiologists would make a slimeboy +// This is supposed to be only in the bus ruin, don't spawn it elsewhere /obj/item/toy/plush/awakenedplushie name = "awakened plushie" desc = "An ancient plushie that has grown enlightened to the true nature of reality." diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index d41397301b3..27418a5e0a9 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -111,6 +111,15 @@ shield_break_sound = 'sound/effects/glassbr3.ogg' shield_break_leftover = /obj/item/shard +/obj/item/shield/riot/Initialize(mapload) + . = ..() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/strobeshield) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/shield/riot/attackby(obj/item/attackby_item, mob/user, params) if(istype(attackby_item, /obj/item/melee/baton)) if(!COOLDOWN_FINISHED(src, baton_bash)) diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm index 1d9c90217ac..d9f13911731 100644 --- a/code/game/objects/items/spear.dm +++ b/code/game/objects/items/spear.dm @@ -54,8 +54,18 @@ force_wielded = force_wielded, \ icon_wielded = "[icon_prefix]1", \ ) + add_headpike_component() update_appearance() +// I dunno man +/obj/item/spear/proc/add_headpike_component() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/headpike) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/spear/update_icon_state() icon_state = "[icon_prefix]0" return ..() @@ -227,6 +237,14 @@ reach = 2 //SKYRAT EDIT ADDITION END +/obj/item/spear/bonespear/add_headpike_component() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/headpikebone) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /* * Bamboo Spear */ @@ -241,3 +259,12 @@ custom_materials = list(/datum/material/bamboo = SHEET_MATERIAL_AMOUNT * 20) force_unwielded = 10 force_wielded = 18 + + +/obj/item/spear/bamboospear/add_headpike_component() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/headpikebamboo) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) diff --git a/code/game/objects/items/stacks/golem_food/golem_hand_actions.dm b/code/game/objects/items/stacks/golem_food/golem_hand_actions.dm index fc87d094477..39c17d2346c 100644 --- a/code/game/objects/items/stacks/golem_food/golem_hand_actions.dm +++ b/code/game/objects/items/stacks/golem_food/golem_hand_actions.dm @@ -35,7 +35,7 @@ playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, TRUE) held_gibtonite.forceMove(get_turf(src)) held_gibtonite.det_time = 2 SECONDS - held_gibtonite.GibtoniteReaction(user) + held_gibtonite.GibtoniteReaction(user, "A [src] has targeted [target] with a thrown and primed") held_gibtonite.throw_at(target, range = 10, speed = 3, thrower = user) held_gibtonite = null qdel(src) @@ -44,7 +44,7 @@ /// Called when you can't hold it in any longer and just drop it on the ground /obj/item/gibtonite_hand/proc/release_gibtonite() held_gibtonite.forceMove(get_turf(src)) - held_gibtonite.GibtoniteReaction(isliving(loc) ? loc : null) + held_gibtonite.GibtoniteReaction(isliving(loc) ? loc : null, "A [src] has dropped and primed a") held_gibtonite = null qdel(src) diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 081ab5d78e0..f4a61f2d7ca 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -159,6 +159,15 @@ splint_factor = 0.7 burn_cleanliness_bonus = 0.35 merge_type = /obj/item/stack/medical/gauze + var/obj/item/bodypart/gauzed_bodypart + +/obj/item/stack/medical/gauze/Destroy(force) + . = ..() + + if (gauzed_bodypart) + gauzed_bodypart.current_gauze = null + SEND_SIGNAL(gauzed_bodypart, COMSIG_BODYPART_UNGAUZED, src) + gauzed_bodypart = null // gauze is only relevant for wounds, which are handled in the wounds themselves /obj/item/stack/medical/gauze/try_heal(mob/living/patient, mob/user, silent) @@ -474,3 +483,27 @@ /obj/item/stack/medical/poultice/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/user) . = ..() healed_mob.adjustOxyLoss(amount_healed) + +/obj/item/stack/medical/bandage + name = "first aid bandage" + desc = "A DeForest brand bandage designed for basic first aid on blunt-force trauma." + icon_state = "bandage" + inhand_icon_state = "bandage" + novariants = TRUE + amount = 1 + max_amount = 1 + lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' + heal_brute = 25 + stop_bleeding = 0.2 + self_delay = 3 SECONDS + other_delay = 1 SECONDS + grind_results = list(/datum/reagent/medicine/c2/libital = 2) + +/obj/item/stack/medical/bandage/makeshift + name = "makeshift bandage" + desc = "A hastily constructed bandage designed for basic first aid on blunt-force trauma." + icon_state = "bandage_makeshift" + icon_state_preview = "bandage_makeshift" + inhand_icon_state = "bandage" + novariants = TRUE diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 60db8f800a2..b5540a633f1 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -55,6 +55,13 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \ ) AddElement(/datum/element/contextual_screentip_tools, tool_behaviors) + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/spear, /datum/crafting_recipe/stunprod, /datum/crafting_recipe/teleprod) // snatcher prod isn't here as a spoopy secret + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/stack/rods/handle_openspace_click(turf/target, mob/user, proximity_flag, click_parameters) if(proximity_flag) target.attackby(src, user, click_parameters) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 289920c8889..1ad86868212 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -501,6 +501,15 @@ GLOBAL_LIST_INIT(durathread_recipes, list ( \ drop_sound = 'sound/items/handling/cloth_drop.ogg' pickup_sound = 'sound/items/handling/cloth_pickup.ogg' +/obj/item/stack/sheet/durathread/Initialize(mapload) + . = ..() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/durathread_helmet, /datum/crafting_recipe/durathread_vest) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/stack/sheet/durathread/get_main_recipes() . = ..() . += GLOB.durathread_recipes @@ -600,7 +609,8 @@ GLOBAL_LIST_INIT(cardboard_recipes, list ( \ new /datum/stack_recipe("light bulbs box", /obj/item/storage/box/lights/bulbs, check_density = FALSE, category = CAT_CONTAINERS), \ new /datum/stack_recipe("mixed lights box", /obj/item/storage/box/lights/mixed, check_density = FALSE, category = CAT_CONTAINERS), \ new /datum/stack_recipe("mouse traps box", /obj/item/storage/box/mousetraps, check_density = FALSE, category = CAT_CONTAINERS), \ - new /datum/stack_recipe("candle box", /obj/item/storage/fancy/candle_box, check_density = FALSE, category = CAT_CONTAINERS) + new /datum/stack_recipe("candle box", /obj/item/storage/fancy/candle_box, check_density = FALSE, category = CAT_CONTAINERS), \ + new /datum/stack_recipe("bandage box", /obj/item/storage/box/bandages, check_density = FALSE, category = CAT_CONTAINERS) )), null, \ @@ -620,6 +630,15 @@ GLOBAL_LIST_INIT(cardboard_recipes, list ( \ grind_results = list(/datum/reagent/cellulose = 10) material_type = /datum/material/cardboard +/obj/item/stack/sheet/cardboard/Initialize(mapload, new_amount, merge, list/mat_override, mat_amt) + . = ..() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/cardboard_id) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/stack/sheet/cardboard/get_main_recipes() . = ..() . += GLOB.cardboard_recipes diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index c9c4815e3da..c0d2d42bb87 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -49,6 +49,12 @@ resistance_flags = FIRE_PROOF item_flags = NO_MAT_REDEMPTION +/obj/item/bag_of_holding_inert/Initialize(mapload) + . = ..() + AddComponent(/datum/component/slapcrafting,\ + slapcraft_recipes = list(/datum/crafting_recipe/boh)\ + ) + /obj/item/storage/backpack/holding name = "bag of holding" desc = "A backpack that opens into a localized pocket of bluespace." @@ -509,46 +515,12 @@ icon_state = "duffel-medical" inhand_icon_state = "duffel-med" -/obj/item/storage/backpack/duffelbag/med/surgery - name = "surgical duffel bag" - desc = "A large duffel bag for holding extra medical supplies - this one seems to be designed for holding surgical tools." - -/obj/item/storage/backpack/duffelbag/med/surgery/PopulateContents() - new /obj/item/scalpel(src) - new /obj/item/hemostat(src) - new /obj/item/retractor(src) - new /obj/item/circular_saw(src) - new /obj/item/surgicaldrill(src) - new /obj/item/cautery(src) - new /obj/item/bonesetter(src) - new /obj/item/surgical_drapes(src) - new /obj/item/clothing/suit/toggle/labcoat/skyrat/hospitalgown(src) //SKYRAT EDIT ADDITION - new /obj/item/clothing/mask/surgical(src) - new /obj/item/razor(src) - new /obj/item/blood_filter(src) - /obj/item/storage/backpack/duffelbag/coroner name = "coroner duffel bag" desc = "A large duffel bag for holding large amounts of organs at once." icon_state = "duffel-coroner" inhand_icon_state = "duffel-coroner" -/obj/item/storage/backpack/duffelbag/coroner/surgery - name = "surgical coroner bag" - desc = "A large duffel bag for holding extra medical supplies - this one seems to be designed for holding morbid surgical tools." - -/obj/item/storage/backpack/duffelbag/coroner/surgery/PopulateContents() - new /obj/item/scalpel/cruel(src) - new /obj/item/hemostat/cruel(src) - new /obj/item/retractor/cruel(src) - new /obj/item/circular_saw(src) - new /obj/item/surgicaldrill(src) - new /obj/item/cautery/cruel(src) - new /obj/item/bonesetter(src) - new /obj/item/surgical_drapes(src) - new /obj/item/razor(src) - new /obj/item/blood_filter(src) - /obj/item/storage/backpack/duffelbag/explorer name = "explorer duffel bag" desc = "A large duffel bag for holding extra exotic treasures." diff --git a/code/game/objects/items/storage/boxes/medical_boxes.dm b/code/game/objects/items/storage/boxes/medical_boxes.dm index ad0fd9b37f5..ff4b232454c 100644 --- a/code/game/objects/items/storage/boxes/medical_boxes.dm +++ b/code/game/objects/items/storage/boxes/medical_boxes.dm @@ -129,3 +129,43 @@ /obj/item/reagent_containers/cup/beaker/meta/rezadone = 1, ) generate_items_inside(items_inside, src) + +/obj/item/storage/box/bandages + name = "box of bandages" + desc = "A box of DeForest brand gel bandages designed to treat blunt-force trauma." + icon = 'icons/obj/storage/box.dmi' // SKYRAT EDIT CHANGE + icon_state = "brutebox" + base_icon_state = "brutebox" + inhand_icon_state = "brutebox" + lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' + drop_sound = 'sound/items/handling/matchbox_drop.ogg' + pickup_sound = 'sound/items/handling/matchbox_pickup.ogg' + illustration = null + w_class = WEIGHT_CLASS_SMALL + custom_price = PAYCHECK_CREW * 1.75 + +/obj/item/storage/box/bandages/Initialize(mapload) + . = ..() + atom_storage.max_slots = 6 + atom_storage.set_holdable(list( + /obj/item/stack/medical/bandage, + /obj/item/reagent_containers/pill, + /obj/item/reagent_containers/pill/patch, + )) + +/obj/item/storage/box/bandages/PopulateContents() + for(var/i in 1 to 5) + new /obj/item/stack/medical/bandage(src) + +/obj/item/storage/box/bandages/update_icon_state() + . = ..() + switch(length(contents)) + if(5) + icon_state = "[base_icon_state]_f" + if(3 to 4) + icon_state = "[base_icon_state]_almostfull" + if(1 to 2) + icon_state = "[base_icon_state]_almostempty" + if(0) + icon_state = base_icon_state diff --git a/code/game/objects/items/storage/holsters.dm b/code/game/objects/items/storage/holsters.dm index d47c4ceaff1..25eeb558040 100644 --- a/code/game/objects/items/storage/holsters.dm +++ b/code/game/objects/items/storage/holsters.dm @@ -36,6 +36,8 @@ /obj/item/food/grown/banana, /obj/item/gun/energy/laser/thermal, /obj/item/gun/ballistic/rifle/boltaction, //fits if you make it an obrez + /obj/item/gun/energy/laser/captain, + /obj/item/gun/energy/e_gun/hos, )) /obj/item/storage/belt/holster/energy @@ -53,6 +55,8 @@ /obj/item/food/grown/banana, /obj/item/gun/energy/laser/thermal, /obj/item/gun/energy/recharge/ebow, + /obj/item/gun/energy/laser/captain, + /obj/item/gun/energy/e_gun/hos, )) /obj/item/storage/belt/holster/energy/thermal @@ -106,6 +110,8 @@ /obj/item/gun/energy/disabler, /obj/item/gun/energy/dueling, /obj/item/gun/energy/laser/thermal, + /obj/item/gun/energy/laser/captain, + /obj/item/gun/energy/e_gun/hos, /obj/item/gun/ballistic/rifle/boltaction, //fits if you make it an obrez )) @@ -156,7 +162,9 @@ /obj/item/gun/energy/recharge/ebow, /obj/item/gun/energy/e_gun/mini, /obj/item/gun/energy/disabler, - /obj/item/gun/energy/dueling + /obj/item/gun/energy/dueling, + /obj/item/gun/energy/laser/captain, + /obj/item/gun/energy/e_gun/hos, )) atom_storage.silent = TRUE diff --git a/code/game/objects/items/storage/medkit.dm b/code/game/objects/items/storage/medkit.dm index 6ca84e415e0..4b08d1551a3 100644 --- a/code/game/objects/items/storage/medkit.dm +++ b/code/game/objects/items/storage/medkit.dm @@ -34,6 +34,7 @@ /obj/item/reagent_containers/medigel, /obj/item/reagent_containers/spray, /obj/item/lighter, + /obj/item/storage/box/bandages, /obj/item/storage/fancy/cigarettes, /obj/item/storage/pill_bottle, /obj/item/stack/medical, @@ -288,18 +289,19 @@ if(empty) return var/static/list/items_inside = list( + /obj/item/cautery = 1, + /obj/item/scalpel = 1, + /obj/item/healthanalyzer/advanced = 1, + /obj/item/hemostat = 1, + /obj/item/reagent_containers/medigel/sterilizine = 1, + /obj/item/storage/box/bandages = 1, + /obj/item/surgical_drapes = 1, + /obj/item/reagent_containers/hypospray/medipen/atropine = 2, + /obj/item/stack/medical/gauze = 2, /obj/item/stack/medical/suture/medicated = 2, /obj/item/stack/medical/mesh/advanced = 2, /obj/item/reagent_containers/pill/patch/libital = 4, /obj/item/reagent_containers/pill/patch/aiuri = 4, - /obj/item/healthanalyzer/advanced = 1, - /obj/item/stack/medical/gauze = 2, - /obj/item/reagent_containers/hypospray/medipen/atropine = 2, - /obj/item/reagent_containers/medigel/sterilizine = 1, - /obj/item/surgical_drapes = 1, - /obj/item/scalpel = 1, - /obj/item/hemostat = 1, - /obj/item/cautery = 1, ) generate_items_inside(items_inside,src) @@ -332,6 +334,7 @@ /obj/item/mod/module/health_analyzer = 1, /obj/item/autosurgeon/syndicate/emaggedsurgerytoolset = 1, /obj/item/reagent_containers/hypospray/combat/empty = 1, + /obj/item/storage/box/bandages = 1, /obj/item/storage/box/evilmeds = 1, /obj/item/reagent_containers/medigel/sterilizine = 1, /obj/item/clothing/glasses/hud/health/night/science = 1, diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index ba9c6ef4812..9fa66404aed 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -747,13 +747,13 @@ human_target.reagents.add_reagent(/datum/reagent/toxin, 2) return FALSE - /// If no antag datums which allow induction are there, disallow induction! No self-antagging. - var/allowed = FALSE + /// If all the antag datums are 'fake', disallow induction! No self-antagging. + var/faker for(var/datum/antagonist/antag_datum as anything in human_target.mind.antag_datums) - if((antag_datum.antag_flags & FLAG_ANTAG_CAN_BE_INDUCTED)) - allowed = TRUE + if((antag_datum.antag_flags & FLAG_FAKE_ANTAG)) + faker = TRUE - if(!allowed) // GTFO. Technically not foolproof but making a heartbreaker or a paradox clone a nuke op sounds hilarious + if(faker) // GTFO. Technically not foolproof but making a heartbreaker or a paradox clone a nuke op sounds hilarious to_chat(human_target, span_notice("Huh? Nothing happened? But you're starting to feel a little ill...")) human_target.reagents.add_reagent(/datum/reagent/toxin, 15) return FALSE diff --git a/code/game/objects/items/surgery_tray.dm b/code/game/objects/items/surgery_tray.dm index dfe83baabdb..37494a39b55 100644 --- a/code/game/objects/items/surgery_tray.dm +++ b/code/game/objects/items/surgery_tray.dm @@ -11,6 +11,7 @@ /obj/item/cautery, /obj/item/circular_saw, /obj/item/clothing/mask/surgical, + /obj/item/clothing/suit/toggle/labcoat/skyrat/hospitalgown, // SKYRAT EDIT ADDITION /obj/item/hemostat, /obj/item/razor, /obj/item/reagent_containers/medigel, @@ -152,8 +153,10 @@ /obj/item/surgery_tray/attack_hand(mob/living/user) if(!user.can_perform_action(src, NEED_HANDS)) return ..() - var/obj/item/grabbies = pick(contents) - if(grabbies) + if(!length(contents)) + balloon_alert(user, "empty!") + else + var/obj/item/grabbies = pick(contents) atom_storage.remove_single(user, grabbies, drop_location()) user.put_in_hands(grabbies) return TRUE @@ -193,6 +196,7 @@ new /obj/item/cautery(src) new /obj/item/circular_saw(src) new /obj/item/clothing/mask/surgical(src) + new /obj/item/clothing/suit/toggle/labcoat/skyrat/hospitalgown(src) // SKYRAT EDIT ADDITION new /obj/item/hemostat(src) new /obj/item/razor/surgery(src) new /obj/item/retractor(src) @@ -207,13 +211,14 @@ name = "autopsy tray" desc = "A Deforest brand surgery tray, made for use in morgues. It is a folding model, \ meaning the wheels on the bottom can be extended outwards, making it a cart." - + /obj/item/surgery_tray/full/morgue/populate_contents() new /obj/item/blood_filter(src) new /obj/item/bonesetter(src) new /obj/item/cautery/cruel(src) new /obj/item/circular_saw(src) new /obj/item/clothing/mask/surgical(src) + new /obj/item/clothing/suit/toggle/labcoat/skyrat/hospitalgown(src) // SKYRAT EDIT ADDITION new /obj/item/hemostat/cruel(src) new /obj/item/razor/surgery(src) new /obj/item/retractor/cruel(src) @@ -227,13 +232,13 @@ /obj/item/surgery_tray/full/advanced /obj/item/surgery_tray/full/advanced/populate_contents() - new /obj/item/scalpel/advanced - new /obj/item/retractor/advanced - new /obj/item/cautery/advanced - new /obj/item/surgical_drapes - new /obj/item/reagent_containers/medigel/sterilizine - new /obj/item/bonesetter - new /obj/item/blood_filter - new /obj/item/stack/medical/bone_gel - new /obj/item/stack/sticky_tape/surgical - new /obj/item/clothing/mask/surgical + new /obj/item/scalpel/advanced(src) + new /obj/item/retractor/advanced(src) + new /obj/item/cautery/advanced(src) + new /obj/item/surgical_drapes(src) + new /obj/item/reagent_containers/medigel/sterilizine(src) + new /obj/item/bonesetter(src) + new /obj/item/blood_filter(src) + new /obj/item/stack/medical/bone_gel(src) + new /obj/item/stack/sticky_tape/surgical(src) + new /obj/item/clothing/mask/surgical(src) diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 470448ab244..21fc15572bf 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -302,69 +302,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/katana/cursed //used by wizard events, see the tendril_loot.dm file for the miner one slot_flags = null -/obj/item/wirerod - name = "wired rod" - desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit." - icon = 'icons/obj/weapons/spear.dmi' - icon_state = "wiredrod" - inhand_icon_state = "rods" - flags_1 = CONDUCT_1 - force = 9 - throwforce = 10 - w_class = WEIGHT_CLASS_BULKY - custom_materials = list(/datum/material/iron= HALF_SHEET_MATERIAL_AMOUNT + SMALL_MATERIAL_AMOUNT * 1.5, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 0.75) - attack_verb_continuous = list("hits", "bludgeons", "whacks", "bonks") - attack_verb_simple = list("hit", "bludgeon", "whack", "bonk") - -/obj/item/wirerod/Initialize(mapload) - . = ..() - - var/static/list/hovering_item_typechecks = list( - /obj/item/shard = list( - SCREENTIP_CONTEXT_LMB = "Craft spear", - ), - - /obj/item/assembly/igniter = list( - SCREENTIP_CONTEXT_LMB = "Craft stunprod", - ), - ) - - AddElement(/datum/element/contextual_screentip_item_typechecks, hovering_item_typechecks) - -/obj/item/wirerod/attackby(obj/item/attacking_item, mob/user, params) - if(istype(attacking_item, /obj/item/shard)) - var/datum/crafting_recipe/recipe_to_use = /datum/crafting_recipe/spear - user.balloon_alert(user, "crafting spear...") - if(do_after(user, initial(recipe_to_use.time), src)) // we do initial work here to get the correct timer - var/obj/item/spear/crafted_spear = new /obj/item/spear() - - remove_item_from_storage(user) - if (!user.transferItemToLoc(attacking_item, crafted_spear)) - return - crafted_spear.CheckParts(list(attacking_item)) - qdel(src) - - user.put_in_hands(crafted_spear) - user.balloon_alert(user, "crafted spear") - return - - if(isigniter(attacking_item) && !(HAS_TRAIT(attacking_item, TRAIT_NODROP))) - var/datum/crafting_recipe/recipe_to_use = /datum/crafting_recipe/stunprod - user.balloon_alert(user, "crafting cattleprod...") - if(do_after(user, initial(recipe_to_use.time), src)) - var/obj/item/melee/baton/security/cattleprod/prod = new - - remove_item_from_storage(user) - - qdel(attacking_item) - qdel(src) - - user.put_in_hands(prod) - user.balloon_alert(user, "crafted cattleprod") - return - return ..() - - /obj/item/throwing_star name = "throwing star" desc = "An ancient weapon still used to this day, due to its ease of lodging itself into its victim's body parts." diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 524c189acc6..a06b7fdaea7 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -145,7 +145,7 @@ if(has_buckled_mobs()) for(var/m in buckled_mobs) var/mob/living/buckled_mob = m - buckled_mob.electrocute_act((clamp(round(strength/400), 10, 90) + rand(-5, 5)), src, flags = SHOCK_TESLA) + buckled_mob.electrocute_act((clamp(round(strength * 3.125e-6), 10, 90) + rand(-5, 5)), src, flags = SHOCK_TESLA) ///the obj is deconstructed into pieces, whether through careful disassembly or when destroyed. /obj/proc/deconstruct(disassembled = TRUE) diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index 71d15fb3f58..ba8623ec4aa 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -63,6 +63,6 @@ /obj/structure/zap_act(power, zap_flags) if(zap_flags & ZAP_OBJ_DAMAGE) - take_damage(power/8000, BURN, "energy") - power -= power/2000 //walls take a lot out of ya + take_damage(power * 1.5625e-7, BURN, "energy") + power -= power * 5e-4 //walls take a lot out of ya . = ..() diff --git a/code/game/objects/structures/icemoon/cave_entrance.dm b/code/game/objects/structures/icemoon/cave_entrance.dm index 10f7a56c7f9..7393c20758e 100644 --- a/code/game/objects/structures/icemoon/cave_entrance.dm +++ b/code/game/objects/structures/icemoon/cave_entrance.dm @@ -102,7 +102,7 @@ GLOBAL_LIST_INIT(ore_probability, list( mob_types = list(/mob/living/basic/mining/ice_whelp) /obj/structure/spawner/ice_moon/demonic_portal/snowlegion - mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow/portal) + mob_types = list(/mob/living/basic/mining/legion/snow/spawner_made) /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 542df563a1f..22f7f0422cd 100644 --- a/code/game/objects/structures/lavaland/necropolis_tendril.dm +++ b/code/game/objects/structures/lavaland/necropolis_tendril.dm @@ -23,7 +23,7 @@ mob_types = list(/mob/living/basic/mining/goliath) /obj/structure/spawner/lavaland/legion - mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril) + mob_types = list(/mob/living/basic/mining/legion/spawner_made) /obj/structure/spawner/lavaland/icewatcher mob_types = list(/mob/living/basic/mining/watcher/icewing) diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm index 7f9dab59a46..f88ba15ecc5 100644 --- a/code/game/objects/structures/railings.dm +++ b/code/game/objects/structures/railings.dm @@ -8,6 +8,8 @@ density = TRUE anchored = TRUE pass_flags_self = LETPASSTHROW|PASSSTRUCTURE + layer = ABOVE_MOB_LAYER + plane = GAME_PLANE_UPPER /// armor is a little bit less than a grille. max_integrity about half that of a grille. armor_type = /datum/armor/structure_railing max_integrity = 25 diff --git a/code/game/objects/structures/spawner.dm b/code/game/objects/structures/spawner.dm index 7bbafd21ff2..340bcf212de 100644 --- a/code/game/objects/structures/spawner.dm +++ b/code/game/objects/structures/spawner.dm @@ -80,8 +80,8 @@ /mob/living/basic/mining/basilisk, /mob/living/basic/mining/goldgrub, /mob/living/basic/mining/goliath/ancient, + /mob/living/basic/mining/legion, /mob/living/basic/wumborian_fugu, - /mob/living/simple_animal/hostile/asteroid/hivelord, ) faction = list(FACTION_MINING) @@ -98,7 +98,7 @@ /obj/structure/spawner/mining/hivelord name = "hivelord den" desc = "A den housing a nest of hivelords." - mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord) + mob_types = list(/mob/living/basic/mining/hivelord) /obj/structure/spawner/mining/basilisk name = "basilisk den" diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index b991bc0c274..6ba07a90e68 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -591,6 +591,12 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sink/kitchen, (-16)) var/busy = FALSE //Something's being washed at the moment var/dispensedreagent = /datum/reagent/water // for whenever plumbing happens +/obj/structure/water_source/Initialize(mapload) + . = ..() + + create_reagents(INFINITY, NO_REACT) + reagents.add_reagent(dispensedreagent, INFINITY) + /obj/structure/water_source/attack_hand(mob/living/user, list/modifiers) . = ..() if(.) diff --git a/code/game/say.dm b/code/game/say.dm index a531ee02527..c0e9d4ff8ef 100644 --- a/code/game/say.dm +++ b/code/game/say.dm @@ -108,7 +108,7 @@ GLOBAL_LIST_INIT(freqtospan, list( filter += tts_filter.Join(",") if(voice && found_client) - INVOKE_ASYNC(SStts, TYPE_PROC_REF(/datum/controller/subsystem/tts, queue_tts_message), src, html_decode(tts_message_to_use), message_language, voice, filter.Join(","), listened, message_range = range, pitch = pitch, silicon = tts_silicon_voice_effect) + INVOKE_ASYNC(SStts, TYPE_PROC_REF(/datum/controller/subsystem/tts, queue_tts_message), src, html_decode(tts_message_to_use), message_language, voice, filter.Join(","), listened, message_range = range, pitch = pitch) /atom/movable/proc/compose_message(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), visible_name = FALSE) //This proc uses [] because it is faster than continually appending strings. Thanks BYOND. diff --git a/code/game/turfs/open/planet.dm b/code/game/turfs/open/planet.dm index 88f9518a08e..e5ab02c0924 100644 --- a/code/game/turfs/open/planet.dm +++ b/code/game/turfs/open/planet.dm @@ -14,6 +14,13 @@ heavyfootstep = FOOTSTEP_GENERIC_HEAVY tiled_dirt = FALSE +/turf/open/misc/dirt/station + 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 + planetary_atmos = FALSE + /turf/open/misc/dirt/dark icon_state = "greenerdirt" base_icon_state = "greenerdirt" diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 0b731c61373..7f135cdbefb 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -117,7 +117,7 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list( /datum/admins/proc/station_traits_panel, // Client procs /client/proc/admin_away, - /client/proc/add_mob_ability, + /client/proc/add_marked_mob_ability, /client/proc/admin_change_sec_level, /client/proc/cinematic, /client/proc/cmd_admin_add_freeform_ai_law, @@ -132,7 +132,7 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list( /client/proc/mass_zombie_infection, /client/proc/object_say, /client/proc/polymorph_all, - /client/proc/remove_mob_ability, + /client/proc/remove_marked_mob_ability, /client/proc/reset_ooc, /client/proc/run_weather, /client/proc/set_dynex_scale, @@ -718,6 +718,80 @@ GLOBAL_PROTECT(admin_verbs_poll) set category = "Debug" SStrading_card_game.printAllCards() +/client/proc/give_mob_action(mob/ability_recipient in GLOB.mob_list) + set category = "Admin.Fun" + set name = "Give Mob Action" + set desc = "Gives a mob ability to a mob." + + var/static/list/all_mob_actions = sort_list(subtypesof(/datum/action/cooldown/mob_cooldown), GLOBAL_PROC_REF(cmp_typepaths_asc)) + var/static/list/actions_by_name = list() + if (!length(actions_by_name)) + for (var/datum/action/cooldown/mob_cooldown as anything in all_mob_actions) + actions_by_name["[initial(mob_cooldown.name)] ([mob_cooldown])"] = mob_cooldown + + var/ability = tgui_input_list(usr, "Choose an ability", "Ability", actions_by_name) + if(isnull(ability)) + return + + var/ability_type = actions_by_name[ability] + var/datum/action/cooldown/mob_cooldown/add_ability + + var/make_sequence = tgui_alert(usr, "Would you like this action to be a sequence of multiple abilities?", "Sequence Ability", list("Yes", "No")) + if(make_sequence == "Yes") + add_ability = new /datum/action/cooldown/mob_cooldown(ability_recipient) + add_ability.sequence_actions = list() + while(!isnull(ability_type)) + var/ability_delay = tgui_input_number(usr, "Enter the delay in seconds before the next ability in the sequence is used", "Ability Delay", 2) + if(isnull(ability_delay) || ability_delay < 0) + ability_delay = 0 + add_ability.sequence_actions[ability_type] = ability_delay * 1 SECONDS + ability = tgui_input_list(usr, "Choose a new sequence ability", "Sequence Ability", actions_by_name) + ability_type = actions_by_name[ability] + var/ability_cooldown = tgui_input_number(usr, "Enter the sequence abilities cooldown in seconds", "Ability Cooldown", 2) + if(isnull(ability_cooldown) || ability_cooldown < 0) + ability_cooldown = 2 + add_ability.cooldown_time = ability_cooldown * 1 SECONDS + var/ability_melee_cooldown = tgui_input_number(usr, "Enter the abilities melee cooldown in seconds", "Melee Cooldown", 2) + if(isnull(ability_melee_cooldown) || ability_melee_cooldown < 0) + ability_melee_cooldown = 2 + add_ability.melee_cooldown_time = ability_melee_cooldown * 1 SECONDS + add_ability.name = tgui_input_text(usr, "Choose ability name", "Ability name", "Generic Ability") + add_ability.create_sequence_actions() + else + add_ability = new ability_type(ability_recipient) + + if(isnull(ability_recipient)) + return + add_ability.Grant(ability_recipient) + + message_admins("[key_name_admin(usr)] added mob ability [ability_type] to mob [ability_recipient].") + log_admin("[key_name(usr)] added mob ability [ability_type] to mob [ability_recipient].") + SSblackbox.record_feedback("tally", "admin_verb", 1, "Add Mob Ability") // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! + +/client/proc/remove_mob_action(mob/removal_target in GLOB.mob_list) + set category = "Admin.Fun" + set name = "Remove Mob Action" + set desc = "Remove a special ability from the selected mob." + + var/list/target_abilities = list() + for(var/datum/action/cooldown/mob_cooldown/ability in removal_target.actions) + target_abilities[ability.name] = ability + + if(!length(target_abilities)) + return + + var/chosen_ability = tgui_input_list(usr, "Choose the spell to remove from [removal_target]", "Depower", sort_list(target_abilities)) + if(isnull(chosen_ability)) + return + var/datum/action/cooldown/mob_cooldown/to_remove = target_abilities[chosen_ability] + if(!istype(to_remove)) + return + + qdel(to_remove) + log_admin("[key_name(usr)] removed the ability [chosen_ability] from [key_name(removal_target)].") + message_admins("[key_name_admin(usr)] removed the ability [chosen_ability] from [key_name_admin(removal_target)].") + SSblackbox.record_feedback("tally", "admin_verb", 1, "Remove Mob Ability") // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! + /client/proc/give_spell(mob/spell_recipient in GLOB.mob_list) set category = "Admin.Fun" set name = "Give Spell" @@ -1036,8 +1110,6 @@ GLOBAL_PROTECT(admin_verbs_poll) var/reqs = initial(spell.spell_requirements) if(reqs & SPELL_CASTABLE_AS_BRAIN) real_reqs += "Castable as brain" - if(reqs & SPELL_CASTABLE_WHILE_PHASED) - real_reqs += "Castable phased" if(reqs & SPELL_REQUIRES_HUMAN) real_reqs += "Must be human" if(reqs & SPELL_REQUIRES_MIME_VOW) diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index 624af957a84..f412f9d5a72 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -224,7 +224,7 @@ var/color = "#e6e6e6" if(i%2 == 0) color = "#f2f2f2" - var/is_antagonist = is_special_character(M) + var/is_antagonist = is_special_character(M, allow_fake_antags = TRUE) var/M_job = "" diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 7c2d34bd30f..9db6585799f 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1309,16 +1309,16 @@ new /obj/effect/pod_landingzone(target, pod) if (number == 1) - log_admin("[key_name(usr)] created a [english_list(paths)]") + log_admin("[key_name(usr)] created an instance of [english_list(paths)]") for(var/path in paths) if(ispath(path, /mob)) - message_admins("[key_name_admin(usr)] created a [english_list(paths)]") + message_admins("[key_name_admin(usr)] created an instance of [english_list(paths)]") break else - log_admin("[key_name(usr)] created [number]ea [english_list(paths)]") + log_admin("[key_name(usr)] created [number] instances of [english_list(paths)]") for(var/path in paths) if(ispath(path, /mob)) - message_admins("[key_name_admin(usr)] created [number]ea [english_list(paths)]") + message_admins("[key_name_admin(usr)] created [number] instances of [english_list(paths)]") break return diff --git a/code/modules/admin/verbs/adminevents.dm b/code/modules/admin/verbs/adminevents.dm index ca5458bdb1e..dd8f1d96f60 100644 --- a/code/modules/admin/verbs/adminevents.dm +++ b/code/modules/admin/verbs/adminevents.dm @@ -338,9 +338,9 @@ log_admin("[key_name(usr)] started weather of type [weather_type] on the z-level [z_level].") SSblackbox.record_feedback("tally", "admin_verb", 1, "Run Weather") -/client/proc/add_mob_ability() +/client/proc/add_marked_mob_ability() set category = "Admin.Events" - set name = "Add Mob Ability" + set name = "Add Mob Ability (Marked Mob)" set desc = "Adds an ability to a marked mob." if(!holder) @@ -349,56 +349,11 @@ if(!isliving(holder.marked_datum)) to_chat(usr, span_warning("Error: Please mark a mob to add actions to it.")) return + give_mob_action(holder.marked_datum) - var/mob/living/marked_mob = holder.marked_datum - - var/static/list/all_mob_actions = sort_list(subtypesof(/datum/action/cooldown/mob_cooldown), GLOBAL_PROC_REF(cmp_typepaths_asc)) - var/static/list/actions_by_name = list() - if (!length(actions_by_name)) - for (var/datum/action/cooldown/mob_cooldown as anything in all_mob_actions) - actions_by_name["[initial(mob_cooldown.name)] ([mob_cooldown])"] = mob_cooldown - - var/ability = tgui_input_list(usr, "Choose an ability", "Ability", actions_by_name) - if(isnull(ability)) - return - - var/ability_type = actions_by_name[ability] - var/datum/action/cooldown/mob_cooldown/add_ability - - var/make_sequence = tgui_alert(usr, "Would you like this action to be a sequence of multiple abilities?", "Sequence Ability", list("Yes", "No")) - if(make_sequence == "Yes") - add_ability = new /datum/action/cooldown/mob_cooldown(marked_mob) - add_ability.sequence_actions = list() - while(!isnull(ability_type)) - var/ability_delay = tgui_input_number(usr, "Enter the delay in seconds before the next ability in the sequence is used", "Ability Delay", 2) - if(isnull(ability_delay) || ability_delay < 0) - ability_delay = 0 - add_ability.sequence_actions[ability_type] = ability_delay * 1 SECONDS - ability_type = tgui_input_list(usr, "Choose a new sequence ability", "Sequence Ability", all_mob_actions) - var/ability_cooldown = tgui_input_number(usr, "Enter the sequence abilities cooldown in seconds", "Ability Cooldown", 2) - if(isnull(ability_cooldown) || ability_cooldown < 0) - ability_cooldown = 2 - add_ability.cooldown_time = ability_cooldown * 1 SECONDS - var/ability_melee_cooldown = tgui_input_number(usr, "Enter the abilities melee cooldown in seconds", "Melee Cooldown", 2) - if(isnull(ability_melee_cooldown) || ability_melee_cooldown < 0) - ability_melee_cooldown = 2 - add_ability.melee_cooldown_time = ability_melee_cooldown * 1 SECONDS - add_ability.name = tgui_input_text(usr, "Choose ability name", "Ability name", "Generic Ability") - add_ability.create_sequence_actions() - else - add_ability = new ability_type(marked_mob) - - if(isnull(marked_mob)) - return - add_ability.Grant(marked_mob) - - message_admins("[key_name_admin(usr)] added mob ability [ability_type] to mob [marked_mob].") - log_admin("[key_name(usr)] added mob ability [ability_type] to mob [marked_mob].") - SSblackbox.record_feedback("tally", "admin_verb", 1, "Add Mob Ability") // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! - -/client/proc/remove_mob_ability() +/client/proc/remove_marked_mob_ability() set category = "Admin.Events" - set name = "Remove Mob Ability" + set name = "Remove Mob Ability (Marked Mob)" set desc = "Removes an ability from marked mob." if(!holder) @@ -407,24 +362,7 @@ if(!isliving(holder.marked_datum)) to_chat(usr, span_warning("Error: Please mark a mob to remove actions from it.")) return - - var/mob/living/marked_mob = holder.marked_datum - - var/list/all_mob_actions = list() - for(var/datum/action/cooldown/mob_cooldown/ability in marked_mob.actions) - all_mob_actions.Add(ability) - - var/datum/action/cooldown/mob_cooldown/ability = tgui_input_list(usr, "Remove an ability", "Ability", all_mob_actions) - - if(!ability) - return - - var/ability_name = ability.name - QDEL_NULL(ability) - - message_admins("[key_name_admin(usr)] removed ability [ability_name] from mob [marked_mob].") - log_admin("[key_name(usr)] removed mob ability [ability_name] from mob [marked_mob].") - SSblackbox.record_feedback("tally", "admin_verb", 1, "Remove Mob Ability") // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! + remove_mob_action(holder.marked_datum) /client/proc/command_report_footnote() diff --git a/code/modules/admin/verbs/admingame.dm b/code/modules/admin/verbs/admingame.dm index 8bc58a7876c..317c8fafd3b 100644 --- a/code/modules/admin/verbs/admingame.dm +++ b/code/modules/admin/verbs/admingame.dm @@ -233,7 +233,7 @@ Traitors and the like can also be revived with the previous role mostly intact. new_character.real_name = record_found.name new_character.gender = lowertext(record_found.gender) new_character.age = record_found.age - var/datum/dna/found_dna = record_found.dna_ref + var/datum/dna/found_dna = record_found.locked_dna new_character.hardset_dna(found_dna.unique_identity, found_dna.mutation_index, null, record_found.name, record_found.blood_type, new record_found.species_type, found_dna.features) else new_character.randomize_human_appearance() diff --git a/code/modules/admin/verbs/grant_dna_infusion.dm b/code/modules/admin/verbs/grant_dna_infusion.dm new file mode 100644 index 00000000000..06cfa8110d6 --- /dev/null +++ b/code/modules/admin/verbs/grant_dna_infusion.dm @@ -0,0 +1,36 @@ +/* + * Attempts to grant the target all organs from a given DNA infuser entry.area + * Returns the entry if all organs were successfully replaced. + * If no infusion was picked, the infusion had no organs, or if one or more organs could not be granted, returns FALSE +*/ +/client/proc/grant_dna_infusion(mob/living/carbon/human/target in world) + set name = "Apply DNA Infusion" + set category = "Debug" + + var/list/infusions = list() + for(var/datum/infuser_entry/path as anything in subtypesof(/datum/infuser_entry)) + var/str = "[initial(path.name)] ([path])" + infusions[str] = path + + var/datum/infuser_entry/picked_infusion = tgui_input_list(usr, "Select infusion", "Apply DNA Infusion", infusions) + + if(isnull(picked_infusion)) + return FALSE + + // This is necessary because list propererties are not defined until initialization + picked_infusion = infusions[picked_infusion] + picked_infusion = new picked_infusion + + if(!length(picked_infusion.output_organs)) + return FALSE + + . = picked_infusion + for(var/obj/item/organ/infusion_organ as anything in picked_infusion.output_organs) + var/obj/item/organ/new_organ = new infusion_organ() + if(!new_organ.replace_into(target)) + to_chat(usr, span_notice("[target] is unable to carry [new_organ]!")) + qdel(new_organ) + . = FALSE + continue + log_admin("[key_name(usr)] has added organ [new_organ.type] to [key_name(target)]") + message_admins("[key_name_admin(usr)] has added organ [new_organ.type] to [ADMIN_LOOKUPFLW(target)]") diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm index a03d61d426e..e29ed6404e4 100644 --- a/code/modules/admin/verbs/secrets.dm +++ b/code/modules/admin/verbs/secrets.dm @@ -220,7 +220,7 @@ GLOBAL_DATUM(everyone_a_traitor, /datum/everyone_is_a_traitor_controller) var/result = input(holder, "Please choose a new species","Species") as null|anything in GLOB.species_list if(result) SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Mass Species Change", "[result]")) - log_admin("[key_name(holder)] turned all humans into [result]", 1) + log_admin("[key_name(holder)] turned all humans into [result]") message_admins("\blue [key_name_admin(holder)] turned all humans into [result]") var/newtype = GLOB.species_list[result] for(var/i in GLOB.human_list) @@ -230,21 +230,21 @@ GLOBAL_DATUM(everyone_a_traitor, /datum/everyone_is_a_traitor_controller) if(!is_funmin) return SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Power All APCs")) - log_admin("[key_name(holder)] made all areas powered", 1) + log_admin("[key_name(holder)] made all areas powered") message_admins(span_adminnotice("[key_name_admin(holder)] made all areas powered")) power_restore() if("unpower") if(!is_funmin) return SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Depower All APCs")) - log_admin("[key_name(holder)] made all areas unpowered", 1) + log_admin("[key_name(holder)] made all areas unpowered") message_admins(span_adminnotice("[key_name_admin(holder)] made all areas unpowered")) power_failure() if("quickpower") if(!is_funmin) return SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Power All SMESs")) - log_admin("[key_name(holder)] made all SMESs powered", 1) + log_admin("[key_name(holder)] made all SMESs powered") message_admins(span_adminnotice("[key_name_admin(holder)] made all SMESs powered")) power_restore_quick() if("anon_name") diff --git a/code/modules/admin/view_variables/reference_tracking.dm b/code/modules/admin/view_variables/reference_tracking.dm index a5b2af68c77..9cb661d2fee 100644 --- a/code/modules/admin/view_variables/reference_tracking.dm +++ b/code/modules/admin/view_variables/reference_tracking.dm @@ -92,6 +92,7 @@ return datum_container.last_find_references = search_time + var/container_print = datum_container.ref_search_details() var/list/vars_list = datum_container.vars for(var/varname in vars_list) @@ -108,11 +109,11 @@ found_refs[varname] = TRUE continue //End early, don't want these logging #endif - log_reftracker("Found [type] [text_ref(src)] in [datum_container.type]'s [text_ref(datum_container)] [varname] var. [container_name]") + log_reftracker("Found [type] [text_ref(src)] in [datum_container.type]'s [container_print] [varname] var. [container_name]") continue if(islist(variable)) - DoSearchVar(variable, "[container_name] [text_ref(datum_container)] -> [varname] (list)", recursive_limit - 1, search_time) + DoSearchVar(variable, "[container_name] [container_print] -> [varname] (list)", recursive_limit - 1, search_time) else if(islist(potential_container)) var/normal = IS_NORMAL_LIST(potential_container) @@ -159,3 +160,13 @@ qdel(src, force) #endif + +// Kept outside the ifdef so overrides are easy to implement + +/// Return info about us for reference searching purposes +/// Will be logged as a representation of this datum if it's a part of a search chain +/datum/proc/ref_search_details() + return text_ref(src) + +/datum/callback/ref_search_details() + return "[text_ref(src)] (obj: [object] proc: [delegate] args: [json_encode(arguments)] user: [user?.resolve() || "null"])" diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index 5bbbfaa40b8..a435756b456 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -54,7 +54,7 @@ GLOBAL_LIST_EMPTY(antagonists) /// The typepath for the outfit to show in the preview for the preferences menu. var/preview_outfit /// Flags for antags to turn on or off and check! - var/antag_flags = FLAG_ANTAG_CAN_BE_INDUCTED + var/antag_flags = FLAG_FAKE_ANTAG /// If true, this antagonist can assign themself a new objective var/can_assign_self_objectives = FALSE /// Default to fill in when entering a custom objective. diff --git a/code/modules/antagonists/abductor/equipment/glands/electric.dm b/code/modules/antagonists/abductor/equipment/glands/electric.dm index acb1505a71c..9c4d47dc337 100644 --- a/code/modules/antagonists/abductor/equipment/glands/electric.dm +++ b/code/modules/antagonists/abductor/equipment/glands/electric.dm @@ -22,5 +22,5 @@ addtimer(CALLBACK(src, PROC_REF(zap)), rand(30, 100)) /obj/item/organ/internal/heart/gland/electric/proc/zap() - tesla_zap(owner, 4, 8000, ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_MOB_STUN) + tesla_zap(owner, 4, 3.2e6, ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_MOB_STUN) playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, TRUE) diff --git a/code/modules/antagonists/blob/blob_minion.dm b/code/modules/antagonists/blob/blob_minion.dm index 9ba8e7089b9..9bf37e961d5 100644 --- a/code/modules/antagonists/blob/blob_minion.dm +++ b/code/modules/antagonists/blob/blob_minion.dm @@ -34,9 +34,3 @@ objective.owner = owner objective.overmind = overmind objectives += objective - -/datum/antagonist/blob_minion/blobbernaut - name = "\improper Blobbernaut" - -/datum/antagonist/blob_minion/blob_zombie - name = "\improper Blob Zombie" diff --git a/code/modules/antagonists/blob/blobstrains/_blobstrain.dm b/code/modules/antagonists/blob/blobstrains/_blobstrain.dm index 6225eec9da9..6f01eb67aa7 100644 --- a/code/modules/antagonists/blob/blobstrains/_blobstrain.dm +++ b/code/modules/antagonists/blob/blobstrains/_blobstrain.dm @@ -96,12 +96,12 @@ GLOBAL_LIST_INIT(valid_blobstrains, subtypesof(/datum/blobstrain) - list(/datum/ B.modify_max_integrity(B.max_integrity * max_structure_health_multiplier) B.update_appearance() - for(var/mob/living/simple_animal/hostile/blob/BM as anything in overmind.blob_mobs) - BM.maxHealth *= max_mob_health_multiplier - BM.health *= max_mob_health_multiplier - BM.update_icons() //If it's getting a new strain, tell it what it does! - to_chat(BM, "Your overmind's blob strain is now: [name]!") - to_chat(BM, "The [name] strain [shortdesc ? "[shortdesc]" : "[description]"]") + for(var/mob/living/blob_mob as anything in overmind.blob_mobs) + blob_mob.maxHealth *= max_mob_health_multiplier + blob_mob.health *= max_mob_health_multiplier + blob_mob.update_icons() //If it's getting a new strain, tell it what it does! + to_chat(blob_mob, "Your overmind's blob strain is now: [name]!") + to_chat(blob_mob, "The [name] strain [shortdesc ? "[shortdesc]" : "[description]"]") /datum/blobstrain/proc/on_lose() if(overmind.blob_core) @@ -122,9 +122,9 @@ GLOBAL_LIST_INIT(valid_blobstrains, subtypesof(/datum/blobstrain) - list(/datum/ for(var/obj/structure/blob/B as anything in overmind.all_blobs) B.modify_max_integrity(B.max_integrity / max_structure_health_multiplier) - for(var/mob/living/simple_animal/hostile/blob/BM as anything in overmind.blob_mobs) - BM.maxHealth /= max_mob_health_multiplier - BM.health /= max_mob_health_multiplier + for(var/mob/living/blob_mob as anything in overmind.blob_mobs) + blob_mob.maxHealth /= max_mob_health_multiplier + blob_mob.health /= max_mob_health_multiplier /datum/blobstrain/proc/on_sporedeath(mob/living/spore) diff --git a/code/modules/antagonists/blob/blobstrains/_reagent.dm b/code/modules/antagonists/blob/blobstrains/_reagent.dm index aefd6c02f3c..05bc73f95c8 100644 --- a/code/modules/antagonists/blob/blobstrains/_reagent.dm +++ b/code/modules/antagonists/blob/blobstrains/_reagent.dm @@ -15,8 +15,9 @@ var/mob_protection = L.getarmor(null, BIO) * 0.01 reagent.expose_mob(L, VAPOR, BLOBMOB_BLOBBERNAUT_REAGENTATK_VOL+blobbernaut_reagentatk_bonus, FALSE, mob_protection, overmind)//this will do between 10 and 20 damage(reduced by mob protection), depending on chemical, plus 4 from base brute damage. -/datum/blobstrain/reagent/on_sporedeath(mob/living/spore) - spore.reagents.add_reagent(reagent.type, 10) +/datum/blobstrain/reagent/on_sporedeath(mob/living/basic/spore) + var/burst_range = (spore.type == /mob/living/basic/blob_minion/spore) ? 1 : 0 + do_chem_smoke(range = burst_range, holder = spore, location = get_turf(spore), reagent_type = reagent.type) // These can only be applied by blobs. They are what (reagent) blobs are made out of. /datum/reagent/blob @@ -29,7 +30,7 @@ /// Used by blob reagents to calculate the reaction volume they should use when exposing mobs. /datum/reagent/blob/proc/return_mob_expose_reac_volume(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) - if(exposed_mob.stat == DEAD || isblobmonster(exposed_mob)) + if(exposed_mob.stat == DEAD || HAS_TRAIT(exposed_mob, TRAIT_BLOB_ALLY)) return 0 //the dead, and blob mobs, don't cause reactions return round(reac_volume * min(1.5 - touch_protection, 1), 0.1) //full touch protection means 50% volume, any prot below 0.5 means 100% volume. diff --git a/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm b/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm index f97599948a1..ea2bf54d769 100644 --- a/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm +++ b/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm @@ -11,18 +11,16 @@ message_living = ", and you feel tired" reagent = /datum/reagent/blob/distributed_neurons -/datum/blobstrain/reagent/distributed_neurons/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag) - if((damage_flag == MELEE || damage_flag == BULLET || damage_flag == LASER) && damage <= 20 && B.get_integrity() - damage <= 0 && prob(15)) //if the cause isn't fire or a bomb, the damage is less than 21, we're going to die from that damage, 15% chance of a shitty spore. - B.visible_message(span_warning("A spore floats free of the blob!")) - var/mob/living/simple_animal/hostile/blob/blobspore/weak/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(B.loc) - BS.overmind = B.overmind - BS.update_icons() - B.overmind.blob_mobs.Add(BS) +/datum/blobstrain/reagent/distributed_neurons/damage_reaction(obj/structure/blob/blob_tile, damage, damage_type, damage_flag) + if((damage_flag == MELEE || damage_flag == BULLET || damage_flag == LASER) && damage <= 20 && blob_tile.get_integrity() - damage <= 0 && prob(15)) //if the cause isn't fire or a bomb, the damage is less than 21, we're going to die from that damage, 15% chance of a shitty spore. + blob_tile.visible_message(span_boldwarning("A spore floats free of the blob!")) + blob_tile.overmind.create_spore(blob_tile.loc, /mob/living/basic/blob_minion/spore/minion/weak) return ..() /datum/reagent/blob/distributed_neurons name = "Distributed Neurons" color = "#E88D5D" + taste_description = "fizzing" /datum/reagent/blob/distributed_neurons/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) . = ..() @@ -33,10 +31,7 @@ exposed_mob.investigate_log("has been killed by distributed neurons (blob).", INVESTIGATE_DEATHS) exposed_mob.death() //sleeping in a fight? bad plan. if(exposed_mob.stat == DEAD && overmind.can_buy(5)) - var/mob/living/simple_animal/hostile/blob/blobspore/spore = new/mob/living/simple_animal/hostile/blob/blobspore(get_turf(exposed_mob)) - spore.overmind = overmind - spore.update_icons() - overmind.blob_mobs.Add(spore) + var/mob/living/basic/blob_minion/spore/minion/spore = overmind.create_spore(get_turf(exposed_mob)) spore.zombify(exposed_mob) overmind.add_points(-5) to_chat(overmind, span_notice("Spent 5 resources for the zombification of [exposed_mob].")) diff --git a/code/modules/antagonists/blob/blobstrains/reactive_spines.dm b/code/modules/antagonists/blob/blobstrains/reactive_spines.dm index 53f336ca419..1c8cb893df8 100644 --- a/code/modules/antagonists/blob/blobstrains/reactive_spines.dm +++ b/code/modules/antagonists/blob/blobstrains/reactive_spines.dm @@ -16,15 +16,15 @@ if(damage && ((damage_type == BRUTE) || (damage_type == BURN)) && B.get_integrity() - damage > 0 && COOLDOWN_FINISHED(src, retaliate_cooldown)) // Is there any damage, is it burn or brute, will we be alive, and has the cooldown finished? COOLDOWN_START(src, retaliate_cooldown, 2.5 SECONDS) // 2.5 seconds before auto-retaliate can whack everything within 1 tile again B.visible_message(span_boldwarning("The blob retaliates, lashing out!")) - for(var/atom/A in range(1, B)) - if(!A.can_blob_attack()) + for(var/atom/thing in range(1, B)) + if(!thing.can_blob_attack()) continue - var/attacked_turf = get_turf(A) - if(isliving(A) && !isblobmonster(A)) // Make sure to inject strain-reagents with automatic attacks when needed. + var/attacked_turf = get_turf(thing) + if(isliving(thing) && !HAS_TRAIT(thing, TRAIT_BLOB_ALLY)) // Make sure to inject strain-reagents with automatic attacks when needed. B.blob_attack_animation(attacked_turf, overmind) - attack_living(A) + attack_living(thing) - else if(A.blob_act(B)) // After checking for mobs, whack everything else with the standard attack + else if(thing.blob_act(B)) // After checking for mobs, whack everything else with the standard attack B.blob_attack_animation(attacked_turf, overmind) // Only play the animation if the attack did something meaningful return ..() @@ -35,7 +35,7 @@ color = "#9ACD32" /datum/reagent/blob/reactive_spines/return_mob_expose_reac_volume(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) - if(exposed_mob.stat == DEAD || isblobmonster(exposed_mob)) + if(exposed_mob.stat == DEAD || HAS_TRAIT(exposed_mob, TRAIT_BLOB_ALLY)) return 0 //the dead, and blob mobs, don't cause reactions return reac_volume diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm index 70a1e69e1e3..38e88817de2 100644 --- a/code/modules/antagonists/blob/overmind.dm +++ b/code/modules/antagonists/blob/overmind.dm @@ -54,6 +54,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) var/list/strain_choices /mob/camera/blob/Initialize(mapload, starting_points = OVERMIND_STARTING_POINTS) + ADD_TRAIT(src, TRAIT_BLOB_ALLY, INNATE_TRAIT) validate_location() blob_points = starting_points manualplace_min_time += world.time @@ -71,6 +72,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) SSshuttle.registerHostileEnvironment(src) . = ..() START_PROCESSING(SSobj, src) + GLOB.blob_telepathy_mobs |= src /mob/camera/blob/proc/validate_location() var/turf/T = get_turf(src) @@ -112,6 +114,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) to_chat(src, span_notice("The [blobstrain.name] strain [blobstrain.description]")) if(blobstrain.effectdesc) to_chat(src, span_notice("The [blobstrain.name] strain [blobstrain.effectdesc]")) + SEND_SIGNAL(src, COMSIG_BLOB_SELECTED_STRAIN, blobstrain) /mob/camera/blob/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) if(placed) // The blob can't expand vertically (yet) @@ -162,50 +165,70 @@ GLOBAL_LIST_EMPTY(blob_nodes) priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", ANNOUNCER_OUTBREAK5) has_announced = TRUE +/// Create a blob spore and link it to us +/mob/camera/blob/proc/create_spore(turf/spore_turf, spore_type = /mob/living/basic/blob_minion/spore/minion) + var/mob/living/basic/blob_minion/spore/spore = new spore_type(spore_turf) + assume_direct_control(spore) + return spore + +/// Give our new minion the properties of a minion +/mob/camera/blob/proc/assume_direct_control(mob/living/minion) + minion.AddComponent(/datum/component/blob_minion, src) + +/// Add something to our list of mobs and wait for it to die +/mob/camera/blob/proc/register_new_minion(mob/living/minion) + blob_mobs |= minion + if (!istype(minion, /mob/living/basic/blob_minion/blobbernaut)) + RegisterSignal(minion, COMSIG_LIVING_DEATH, PROC_REF(on_minion_death)) + +/// When a spore (or zombie) dies then we do this +/mob/camera/blob/proc/on_minion_death(mob/living/spore) + SIGNAL_HANDLER + blobstrain.on_sporedeath(spore) + /mob/camera/blob/proc/victory() sound_to_playing_players('sound/machines/alarm.ogg') sleep(10 SECONDS) - for(var/i in GLOB.mob_living_list) - var/mob/living/L = i - var/turf/T = get_turf(L) - if(!T || !is_station_level(T.z)) + for(var/mob/living/live_guy as anything in GLOB.mob_living_list) + var/turf/guy_turf = get_turf(live_guy) + if(isnull(guy_turf) || !is_station_level(guy_turf.z)) continue - if(L in GLOB.overminds || (L.pass_flags & PASSBLOB)) + if(live_guy in GLOB.overminds || (live_guy.pass_flags & PASSBLOB)) continue - var/area/Ablob = get_area(T) - - if(!(Ablob.area_flags & BLOBS_ALLOWED)) + var/area/blob_area = get_area(guy_turf) + if(!(blob_area.area_flags & BLOBS_ALLOWED)) continue - if(!(ROLE_BLOB in L.faction)) - playsound(L, 'sound/effects/splat.ogg', 50, TRUE) - if(L.stat != DEAD) - L.investigate_log("has died from blob takeover.", INVESTIGATE_DEATHS) - L.death() - new/mob/living/simple_animal/hostile/blob/blobspore(T) + if(!(ROLE_BLOB in live_guy.faction)) + playsound(live_guy, 'sound/effects/splat.ogg', 50, TRUE) + if(live_guy.stat != DEAD) + live_guy.investigate_log("has died from blob takeover.", INVESTIGATE_DEATHS) + live_guy.death() + create_spore(guy_turf) else - L.fully_heal() + live_guy.fully_heal() - for(var/area/A in GLOB.areas) - if(!(A.type in GLOB.the_station_areas)) + for(var/area/check_area in GLOB.areas) + if(!is_type_in_list(check_area, GLOB.the_station_areas)) continue - if(!(A.area_flags & BLOBS_ALLOWED)) + if(!(check_area.area_flags & BLOBS_ALLOWED)) continue - A.color = blobstrain.color - A.name = "blob" - A.icon = 'icons/mob/nonhuman-player/blob.dmi' - A.icon_state = "blob_shield" - A.layer = BELOW_MOB_LAYER - A.invisibility = 0 - A.blend_mode = 0 + check_area.color = blobstrain.color + check_area.name = "blob" + check_area.icon = 'icons/mob/nonhuman-player/blob.dmi' + check_area.icon_state = "blob_shield" + check_area.layer = BELOW_MOB_LAYER + check_area.invisibility = 0 + check_area.blend_mode = 0 + var/datum/antagonist/blob/B = mind.has_antag_datum(/datum/antagonist/blob) if(B) var/datum/objective/blob_takeover/main_objective = locate() in B.objectives if(main_objective) main_objective.completed = TRUE - to_chat(world, span_blob("[real_name] consumed the station in an unstoppable tide!")) + to_chat(world, span_blobannounce("[real_name] consumed the station in an unstoppable tide!")) SSticker.news_report = BLOB_WIN SSticker.force_ending = FORCE_END_ROUND @@ -216,11 +239,6 @@ GLOBAL_LIST_EMPTY(blob_nodes) if(B && B.overmind == src) B.overmind = null B.update_appearance() //reset anything that was ours - for(var/BLO in blob_mobs) - var/mob/living/simple_animal/hostile/blob/BM = BLO - if(BM) - BM.overmind = null - BM.update_icons() for(var/obj/structure/blob/blob_structure as anything in all_blobs) blob_structure.overmind = null all_blobs = null @@ -233,6 +251,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) SSshuttle.clearHostileEnvironment(src) STOP_PROCESSING(SSobj, src) + GLOB.blob_telepathy_mobs -= src return ..() @@ -240,7 +259,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) . = ..() if(!. || !client) return FALSE - to_chat(src, span_blob("You are the overmind!")) + to_chat(src, span_blobannounce("You are the overmind!")) if(!placed && autoplace_max_time <= world.time) to_chat(src, span_boldannounce("You will automatically place your blob core in [DisplayTimeText(autoplace_max_time - world.time)].")) to_chat(src, span_boldannounce("You [manualplace_min_time ? "will be able to":"can"] manually place your blob core by pressing the Place Blob Core button in the bottom right corner of the screen.")) @@ -257,9 +276,11 @@ GLOBAL_LIST_EMPTY(blob_nodes) return FALSE var/current_health = round((blob_core.get_integrity() / blob_core.max_integrity) * 100) hud_used.healths.maptext = MAPTEXT("
[current_health]%
") - for(var/mob/living/simple_animal/hostile/blob/blobbernaut/blobbernaut in blob_mobs) - if(blobbernaut.hud_used && blobbernaut.hud_used.blobpwrdisplay) - blobbernaut.hud_used.blobpwrdisplay.maptext = MAPTEXT("
[current_health]%
") + for(var/mob/living/basic/blob_minion/blobbernaut/blobbernaut in blob_mobs) + var/datum/hud/using_hud = blobbernaut.hud_used + if(!using_hud?.blobpwrdisplay) + continue + using_hud.blobpwrdisplay.maptext = MAPTEXT("
[current_health]%
") /mob/camera/blob/proc/add_points(points) blob_points = clamp(blob_points + points, 0, max_blob_points) @@ -291,14 +312,8 @@ GLOBAL_LIST_EMPTY(blob_nodes) src.log_talk(message, LOG_SAY) var/message_a = say_quote(message) - var/rendered = span_big("\[Blob Telepathy\] [name]([blobstrain.name]) [message_a]") - - for(var/mob/M in GLOB.mob_list) - if(isovermind(M) || isblobmonster(M)) - to_chat(M, rendered) - if(isobserver(M)) - var/link = FOLLOW_LINK(M, src) - to_chat(M, "[link] [rendered]") + var/rendered = span_big(span_blob("\[Blob Telepathy\] [name]([blobstrain.name]) [message_a]")) + blob_telepathy(rendered, src) /mob/camera/blob/blob_act(obj/structure/blob/B) return @@ -324,8 +339,8 @@ GLOBAL_LIST_EMPTY(blob_nodes) else return FALSE else - var/area/A = get_area(NewLoc) - if(isgroundlessturf(NewLoc) || istype(A, /area/shuttle)) //if unplaced, can't go on shuttles or goundless tiles + var/area/check_area = get_area(NewLoc) + if(isgroundlessturf(NewLoc) || istype(check_area, /area/shuttle)) //if unplaced, can't go on shuttles or groundless tiles return FALSE forceMove(NewLoc) return TRUE diff --git a/code/modules/antagonists/blob/powers.dm b/code/modules/antagonists/blob/powers.dm index c75a41a48ff..04054f6df85 100644 --- a/code/modules/antagonists/blob/powers.dm +++ b/code/modules/antagonists/blob/powers.dm @@ -196,38 +196,25 @@ var/list/mob/dead/observer/candidates = poll_ghost_candidates("Do you want to play as a [blobstrain.name] blobbernaut?", ROLE_BLOB, ROLE_BLOB, 50) - factory.is_creating_blobbernaut = FALSE - if(!length(candidates)) to_chat(src, span_warning("You could not conjure a sentience for your blobbernaut. Your points have been refunded. Try again later.")) add_points(BLOBMOB_BLOBBERNAUT_RESOURCE_COST) - factory.blobbernaut = null //players must answer rapidly + factory.assign_blobbernaut(null) return FALSE - factory.modify_max_integrity(initial(factory.max_integrity) * 0.25) //factories that produced a blobbernaut have much lower health - factory.update_appearance() - factory.visible_message(span_warning("The blobbernaut [pick("rips", "tears", "shreds")] its way out of the factory blob!")) - playsound(factory.loc, 'sound/effects/splat.ogg', 50, TRUE) - - var/mob/living/simple_animal/hostile/blob/blobbernaut/blobber = new /mob/living/simple_animal/hostile/blob/blobbernaut(get_turf(factory)) - flick("blobbernaut_produce", blobber) - - factory.blobbernaut = blobber - blobber.factory = factory - blobber.overmind = src - blobber.update_icons() - blobber.adjustHealth(blobber.maxHealth * 0.5) - blob_mobs += blobber - + var/mob/living/basic/blob_minion/blobbernaut/minion/blobber = new(get_turf(factory)) + assume_direct_control(blobber) + factory.assign_blobbernaut(blobber) var/mob/dead/observer/player = pick(candidates) - blobber.key = player.key + blobber.assign_key(player.key, blobstrain) + RegisterSignal(blobber, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(on_blobbernaut_attacked)) - SEND_SOUND(blobber, sound('sound/effects/blobattack.ogg')) - SEND_SOUND(blobber, sound('sound/effects/attackblob.ogg')) - to_chat(blobber, span_infoplain("You are powerful, hard to kill, and slowly regenerate near nodes and cores, [span_cultlarge("but will slowly die if not near the blob")] or if the factory that made you is killed.")) - to_chat(blobber, span_infoplain("You can communicate with other blobbernauts and overminds telepathically by attempting to speak normally")) - to_chat(blobber, span_infoplain("Your overmind's blob reagent is: [blobstrain.name]!")) - to_chat(blobber, span_infoplain("The [blobstrain.name] reagent [blobstrain.shortdesc ? "[blobstrain.shortdesc]" : "[blobstrain.description]"]")) +/// When one of our boys attacked something, we sometimes want to perform extra effects +/mob/camera/blob/proc/on_blobbernaut_attacked(mob/living/basic/blobbynaut, atom/target, success) + SIGNAL_HANDLER + if (!success) + return + blobstrain.blobbernaut_attack(target, blobbynaut) /** Moves the core */ /mob/camera/blob/proc/relocate_core() @@ -358,10 +345,11 @@ var/list/surrounding_turfs = TURF_NEIGHBORS(tile) if(!length(surrounding_turfs)) return FALSE - for(var/mob/living/simple_animal/hostile/blob/blobspore/spore as anything in blob_mobs) - if(isturf(spore.loc) && get_dist(spore, tile) <= 35 && !spore.key) - spore.LoseTarget() - spore.Goto(pick(surrounding_turfs), spore.move_to_delay) + for(var/mob/living/basic/blob_mob as anything in blob_mobs) + if(!isturf(blob_mob.loc) || get_dist(blob_mob, tile) > 35 || blob_mob.key) + continue + blob_mob.ai_controller.clear_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET) + blob_mob.ai_controller.set_blackboard_key(BB_TRAVEL_DESTINATION, pick(surrounding_turfs)) /** Opens the reroll menu to change strains */ /mob/camera/blob/proc/strain_reroll() diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm index 3580e3f3bf8..e206d97c26b 100644 --- a/code/modules/antagonists/blob/structures/_blob.dm +++ b/code/modules/antagonists/blob/structures/_blob.dm @@ -129,13 +129,13 @@ return FALSE //oh no we failed /obj/structure/blob/proc/ConsumeTile() - for(var/atom/A in loc) - if(!A.can_blob_attack()) + for(var/atom/thing in loc) + if(!thing.can_blob_attack()) continue - if(isliving(A) && overmind && !isblobmonster(A)) // Make sure to inject strain-reagents with automatic attacks when needed. - overmind.blobstrain.attack_living(A) + if(isliving(thing) && overmind && !HAS_TRAIT(thing, TRAIT_BLOB_ALLY)) // Make sure to inject strain-reagents with automatic attacks when needed. + overmind.blobstrain.attack_living(thing) continue // Don't smack them twice though - A.blob_act(src) + thing.blob_act(src) if(iswallturf(loc)) loc.blob_act(src) //don't ask how a wall got on top of the core, just eat it @@ -227,10 +227,10 @@ /obj/structure/blob/zap_act(power, zap_flags) if(overmind) if(overmind.blobstrain.tesla_reaction(src, power)) - take_damage(power * 0.0025, BURN, ENERGY) + take_damage(power * 3.125e-6, BURN, ENERGY) else - take_damage(power * 0.0025, BURN, ENERGY) - power -= power * 0.0025 //You don't get to do it for free + take_damage(power * 3.125e-6, BURN, ENERGY) + power -= power * 2.5e-3 //You don't get to do it for free return ..() //You don't get to do it for free /obj/structure/blob/extinguish() diff --git a/code/modules/antagonists/blob/structures/factory.dm b/code/modules/antagonists/blob/structures/factory.dm index 7f28dcce224..cee7e9a0ac5 100644 --- a/code/modules/antagonists/blob/structures/factory.dm +++ b/code/modules/antagonists/blob/structures/factory.dm @@ -10,12 +10,12 @@ armor_type = /datum/armor/structure_blob/factory ///How many spores this factory can have. var/max_spores = BLOB_FACTORY_MAX_SPORES - ///The list of spores - var/list/spores = list() + ///The list of spores and zombies + var/list/spores_and_zombies = list() COOLDOWN_DECLARE(spore_delay) var/spore_cooldown = BLOBMOB_SPORE_SPAWN_COOLDOWN ///Its Blobbernaut, if it has spawned any. - var/mob/living/simple_animal/hostile/blob/blobbernaut/blobbernaut + var/mob/living/basic/blob_minion/blobbernaut/minion/blobbernaut ///Used in blob/powers.dm, checks if it's already trying to spawn a blobbernaut to prevent issues. var/is_creating_blobbernaut = FALSE @@ -32,15 +32,8 @@ overmind.factory_blobs += src /obj/structure/blob/special/factory/Destroy() - for(var/mob/living/simple_animal/hostile/blob/blobspore/spore in spores) - to_chat(spore, span_userdanger("Your factory was destroyed! You can no longer sustain yourself.")) - spore.death() - spores = null - if(blobbernaut) - blobbernaut.factory = null - to_chat(blobbernaut, span_userdanger("Your factory was destroyed! You feel yourself dying!")) - blobbernaut.throw_alert("nofactory", /atom/movable/screen/alert/nofactory) - blobbernaut = null + spores_and_zombies = null + blobbernaut = null if(overmind) overmind.factory_blobs -= src return ..() @@ -49,13 +42,57 @@ . = ..() if(blobbernaut) return - if(spores.len >= max_spores) + if(length(spores_and_zombies) >= max_spores) return if(!COOLDOWN_FINISHED(src, spore_delay)) return COOLDOWN_START(src, spore_delay, spore_cooldown) - var/mob/living/simple_animal/hostile/blob/blobspore/BS = new (loc, src) - if(overmind) //if we don't have an overmind, we don't need to do anything but make a spore - BS.overmind = overmind - BS.update_icons() - overmind.blob_mobs.Add(BS) + var/mob/living/basic/blob_minion/created_spore = (overmind) ? overmind.create_spore(loc) : new(loc) + register_mob(created_spore) + RegisterSignal(created_spore, COMSIG_BLOB_ZOMBIFIED, PROC_REF(on_zombie_created)) + +/// Tracks the existence of a mob in our mobs list +/obj/structure/blob/special/factory/proc/register_mob(mob/living/basic/blob_minion/blob_mob) + spores_and_zombies |= blob_mob + blob_mob.link_to_factory(src) + RegisterSignal(blob_mob, COMSIG_LIVING_DEATH, PROC_REF(on_spore_died)) + RegisterSignal(blob_mob, COMSIG_QDELETING, PROC_REF(on_spore_lost)) + +/// When a spore or zombie dies reset our spawn cooldown so we don't instantly replace it +/obj/structure/blob/special/factory/proc/on_spore_died(mob/living/dead_spore) + SIGNAL_HANDLER + COOLDOWN_START(src, spore_delay, spore_cooldown) + +/// When a spore is deleted remove it from our list +/obj/structure/blob/special/factory/proc/on_spore_lost(mob/living/dead_spore) + SIGNAL_HANDLER + spores_and_zombies -= dead_spore + +/// When a spore makes a zombie add it to our mobs list +/obj/structure/blob/special/factory/proc/on_zombie_created(mob/living/spore, mob/living/zombie) + SIGNAL_HANDLER + register_mob(zombie) + +/// Produce a blobbernaut +/obj/structure/blob/special/factory/proc/assign_blobbernaut(mob/living/new_naut) + is_creating_blobbernaut = FALSE + if (isnull(new_naut)) + return + + modify_max_integrity(initial(max_integrity) * 0.25) //factories that produced a blobbernaut have much lower health + visible_message(span_boldwarning("The blobbernaut [pick("rips", "tears", "shreds")] its way out of the factory blob!")) + playsound(loc, 'sound/effects/splat.ogg', 50, TRUE) + + blobbernaut = new_naut + blobbernaut.link_to_factory(src) + RegisterSignals(new_naut, list(COMSIG_QDELETING, COMSIG_LIVING_DEATH), PROC_REF(on_blobbernaut_death)) + update_appearance(UPDATE_ICON) + +/// When our brave soldier dies, reset our max integrity +/obj/structure/blob/special/factory/proc/on_blobbernaut_death(mob/living/death_naut) + SIGNAL_HANDLER + if (isnull(blobbernaut) || blobbernaut != death_naut) + return + blobbernaut = null + max_integrity = initial(max_integrity) + update_appearance(UPDATE_ICON) diff --git a/code/modules/antagonists/changeling/powers/absorb.dm b/code/modules/antagonists/changeling/powers/absorb.dm index c2ae89933d1..cee0f0da5b9 100644 --- a/code/modules/antagonists/changeling/powers/absorb.dm +++ b/code/modules/antagonists/changeling/powers/absorb.dm @@ -95,31 +95,14 @@ //Some of target's recent speech, so the changeling can attempt to imitate them better. //Recent as opposed to all because rounds tend to have a LOT of text. - var/list/recent_speech = list() - var/list/say_log = list() - var/log_source = target.logging - for(var/log_type in log_source) - var/nlog_type = text2num(log_type) - if(nlog_type & LOG_SAY) - var/list/reversed = log_source[log_type] - if(islist(reversed)) - say_log = reverse_range(reversed.Copy()) - break - - if(LAZYLEN(say_log) > LING_ABSORB_RECENT_SPEECH) - recent_speech = say_log.Copy(say_log.len-LING_ABSORB_RECENT_SPEECH+1,0) //0 so len-LING_ARS+1 to end of list - else - for(var/spoken_memory in say_log) - if(recent_speech.len >= LING_ABSORB_RECENT_SPEECH) - break - recent_speech[spoken_memory] = splittext(say_log[spoken_memory], "\"", 1, 0, TRUE)[3] + var/list/recent_speech = target.copy_recent_speech() if(recent_speech.len) changeling.antag_memory += "Some of [target]'s speech patterns, we should study these to better impersonate [target.p_them()]!
" to_chat(owner, span_boldnotice("Some of [target]'s speech patterns, we should study these to better impersonate [target.p_them()]!")) for(var/spoken_memory in recent_speech) - changeling.antag_memory += "\"[recent_speech[spoken_memory]]\"
" - to_chat(owner, span_notice("\"[recent_speech[spoken_memory]]\"")) + changeling.antag_memory += "\"[spoken_memory]\"
" + to_chat(owner, span_notice("\"[spoken_memory]\"")) changeling.antag_memory += "We have no more knowledge of [target]'s speech patterns.
" to_chat(owner, span_boldnotice("We have no more knowledge of [target]'s speech patterns.")) diff --git a/code/modules/antagonists/changeling/powers/panacea.dm b/code/modules/antagonists/changeling/powers/panacea.dm index 25a267e03df..9fe7613cc4c 100644 --- a/code/modules/antagonists/changeling/powers/panacea.dm +++ b/code/modules/antagonists/changeling/powers/panacea.dm @@ -14,7 +14,9 @@ var/list/bad_organs = list( user.get_organ_by_type(/obj/item/organ/internal/empowered_borer_egg), // SKYRAT EDIT ADDITION user.get_organ_by_type(/obj/item/organ/internal/body_egg), - user.get_organ_by_type(/obj/item/organ/internal/zombie_infection)) + user.get_organ_by_type(/obj/item/organ/internal/legion_tumour), + user.get_organ_by_type(/obj/item/organ/internal/zombie_infection), + ) try_to_mutant_cure(user) //SKYRAT EDIT ADDITION diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index 3b2a13c2cb5..062412f70e9 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -886,7 +886,7 @@ structure_check() searches for nearby cultist structures required for the invoca new_human.equipOutfit(/datum/outfit/ghost_cultist) //give them armor new_human.apply_status_effect(/datum/status_effect/cultghost) //ghosts can't summon more ghosts new_human.set_invis_see(SEE_INVISIBLE_OBSERVER) - ADD_TRAIT(new_human, TRAIT_NOBREATH, INNATE_TRAIT) + new_human.add_traits(list(TRAIT_NOBREATH, TRAIT_PERMANENTLY_MORTAL), INNATE_TRAIT) // permanently mortal can be removed once this is a bespoke kind of mob ghosts++ playsound(src, 'sound/magic/exit_blood.ogg', 50, TRUE) visible_message(span_warning("A cloud of red mist forms above [src], and from within steps... a [new_human.gender == FEMALE ? "wo":""]man.")) diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm index 0088660ec14..116d19f5164 100644 --- a/code/modules/antagonists/ert/ert.dm +++ b/code/modules/antagonists/ert/ert.dm @@ -12,8 +12,8 @@ antagpanel_category = ANTAG_GROUP_ERT suicide_cry = "FOR NANOTRASEN!!" count_against_dynamic_roll_chance = FALSE - // Not 'true' antags, cannot induct to prevent issues - antag_flags = NONE + // Not 'true' antags, this disables certain interactions that assume the owner is a baddie + antag_flags = FLAG_FAKE_ANTAG var/datum/team/ert/ert_team var/leader = FALSE var/datum/outfit/outfit = /datum/outfit/centcom/ert/security diff --git a/code/modules/antagonists/heretic/heretic_antag.dm b/code/modules/antagonists/heretic/heretic_antag.dm index a0f0d86d33f..ccc7fce6ecf 100644 --- a/code/modules/antagonists/heretic/heretic_antag.dm +++ b/code/modules/antagonists/heretic/heretic_antag.dm @@ -34,6 +34,8 @@ var/heretic_path = PATH_START /// A sum of how many knowledge points this heretic CURRENTLY has. Used to research. var/knowledge_points = 2 //SKYRAT EDIT - ORIGINAL 1 + /// How many side path points the heretic has. He gains one of these per main path that splits into two sidepaths. These can be used in place of knowledge points for side paths only. + var/side_path_points = 0 /// The time between gaining influence passively. The heretic gain +1 knowledge points every this duration of time. var/passive_gain_timer = 20 MINUTES /// Assoc list of [typepath] = [knowledge instance]. A list of all knowledge this heretic's reserached. @@ -85,6 +87,7 @@ var/list/data = list() data["charges"] = knowledge_points + data["side_charges"] = side_path_points data["total_sacrifices"] = total_sacrifices data["ascended"] = ascended @@ -98,7 +101,10 @@ knowledge_data["desc"] = initial(knowledge.desc) knowledge_data["gainFlavor"] = initial(knowledge.gain_text) knowledge_data["cost"] = initial(knowledge.cost) - knowledge_data["disabled"] = (initial(knowledge.cost) > knowledge_points) + if(initial(knowledge.route) == PATH_SIDE) + knowledge_data["disabled"] = (initial(knowledge.cost) > knowledge_points + side_path_points) + else + knowledge_data["disabled"] = (initial(knowledge.cost) > knowledge_points) // Final knowledge can't be learned until all objectives are complete. if(ispath(knowledge, /datum/heretic_knowledge/ultimate)) @@ -142,13 +148,22 @@ if(!ispath(researched_path)) CRASH("Heretic attempted to learn non-heretic_knowledge path! (Got: [researched_path])") - if(initial(researched_path.cost) > knowledge_points) - return TRUE + // If side path and has path points, buy! + var/coupon = FALSE + if((initial(researched_path.route) == PATH_SIDE) && side_path_points) + coupon = TRUE + // else try normal purchase + else if(initial(researched_path.cost) > knowledge_points) + return + if(!gain_knowledge(researched_path)) return TRUE - log_heretic_knowledge("[key_name(owner)] gained knowledge: [initial(researched_path.name)]") - knowledge_points -= initial(researched_path.cost) + log_heretic_knowledge("[key_name(owner)] gained knowledge: [initial(researched_path.name)][coupon ? "(via free side-path point)" : ""]") + if(coupon) + side_path_points -= initial(researched_path.cost) + else + knowledge_points -= initial(researched_path.cost) return TRUE /datum/antagonist/heretic/submit_player_objective(retain_existing = FALSE, retain_escape = TRUE, force = FALSE) @@ -305,14 +320,14 @@ * * drawing_time - how long the do_after takes to make the rune * * additional checks - optional callbacks to be ran while drawing the rune */ -/datum/antagonist/heretic/proc/try_draw_rune(mob/living/user, turf/target_turf, drawing_time = 30 SECONDS, additional_checks) +/datum/antagonist/heretic/proc/try_draw_rune(mob/living/user, turf/target_turf, drawing_time = 20 SECONDS, additional_checks) for(var/turf/nearby_turf as anything in RANGE_TURFS(1, target_turf)) if(!isopenturf(nearby_turf) || is_type_in_typecache(nearby_turf, blacklisted_rune_turfs)) target_turf.balloon_alert(user, "invalid placement for rune!") return if(locate(/obj/effect/heretic_rune) in range(3, target_turf)) - target_turf.balloon_alert(user, "to close to another rune!") + target_turf.balloon_alert(user, "too close to another rune!") return if(drawing_rune) @@ -330,16 +345,16 @@ * * drawing_time - how long the do_after takes to make the rune * * additional checks - optional callbacks to be ran while drawing the rune */ -/datum/antagonist/heretic/proc/draw_rune(mob/living/user, turf/target_turf, drawing_time = 30 SECONDS, additional_checks) +/datum/antagonist/heretic/proc/draw_rune(mob/living/user, turf/target_turf, drawing_time = 20 SECONDS, additional_checks) drawing_rune = TRUE var/rune_colour = path_to_rune_color[heretic_path] target_turf.balloon_alert(user, "drawing rune...") var/obj/effect/temp_visual/drawing_heretic_rune/drawing_effect - if (drawing_time >= (30 SECONDS)) - drawing_effect = new(target_turf, rune_colour) - else + if (drawing_time < (10 SECONDS)) drawing_effect = new /obj/effect/temp_visual/drawing_heretic_rune/fast(target_turf, rune_colour) + else + drawing_effect = new(target_turf, rune_colour) if(!do_after(user, drawing_time, target_turf, extra_checks = additional_checks)) target_turf.balloon_alert(user, "interrupted!") @@ -602,7 +617,7 @@ if(!admin.client?.holder) to_chat(admin, span_warning("You shouldn't be using this!")) return - + var/mob/living/pawn = owner.current pawn.equip_to_slot_if_possible(new /obj/item/clothing/neck/heretic_focus(get_turf(pawn)), ITEM_SLOT_NECK, TRUE, TRUE) to_chat(pawn, span_hypnophrase("The Mansus has manifested you a focus.")) @@ -774,8 +789,8 @@ target_amount = main_path_length // Add in the base research we spawn with, otherwise it'd be too easy. target_amount += length(GLOB.heretic_start_knowledge) - // And add in some buffer, to require some sidepathing. - target_amount += rand(2, 4) + // And add in some buffer, to require some sidepathing, especially since heretics get some free side paths. + target_amount += rand(5, 7) update_explanation_text() /datum/objective/heretic_research/update_explanation_text() diff --git a/code/modules/antagonists/heretic/heretic_focus.dm b/code/modules/antagonists/heretic/heretic_focus.dm index b7c79b6d6ca..45bbf743b8c 100644 --- a/code/modules/antagonists/heretic/heretic_focus.dm +++ b/code/modules/antagonists/heretic/heretic_focus.dm @@ -46,7 +46,7 @@ if(!IS_HERETIC(user)) return - if(!(source.slot_flags & slot)) + if(source.slot_flags && !(source.slot_flags & slot)) return ADD_TRAIT(user, TRAIT_ALLOW_HERETIC_CASTING, ELEMENT_TRAIT(source)) diff --git a/code/modules/antagonists/heretic/heretic_knowledge.dm b/code/modules/antagonists/heretic/heretic_knowledge.dm index b51c2a5dcb8..ea22955d83e 100644 --- a/code/modules/antagonists/heretic/heretic_knowledge.dm +++ b/code/modules/antagonists/heretic/heretic_knowledge.dm @@ -25,11 +25,16 @@ var/list/banned_knowledge = list() /// Assoc list of [typepaths we need] to [amount needed]. /// If set, this knowledge allows the heretic to do a ritual on a transmutation rune with the components set. + /// If one of the items in the list is a list, it's treated as 'any of these items will work' var/list/required_atoms /// Paired with above. If set, the resulting spawned atoms upon ritual completion. var/list/result_atoms = list() + /// If set, required_atoms checks for these *exact* types and doesn't allow them to be ingredients. + var/list/banned_atom_types = list() /// Cost of knowledge in knowledge points var/cost = 0 + /// If true, adds side path points according to value. Only main branch powers that split into sidepaths should have this. + var/adds_sidepath_points = 0 /// The priority of the knowledge. Higher priority knowledge appear higher in the ritual list. /// Number itself is completely arbitrary. Does not need to be set for non-ritual knowledge. var/priority = 0 @@ -58,6 +63,8 @@ if(gain_text) to_chat(user, span_warning("[gain_text]")) + // Usually zero + our_heretic.side_path_points += adds_sidepath_points on_gain(user, our_heretic) /** @@ -112,6 +119,18 @@ /datum/heretic_knowledge/proc/recipe_snowflake_check(mob/living/user, list/atoms, list/selected_atoms, turf/loc) return TRUE +/** + * Parses specific items into a more reaadble form. + * Can be overriden by knoweldge subtypes. + */ +/datum/heretic_knowledge/proc/parse_required_item(atom/item_path, number_of_things) + // If we need a human, there is a high likelihood we actually need a (dead) body + if(ispath(item_path, /mob/living/carbon/human)) + return "bod[number_of_things > 1 ? "ies" : "y"]" + if(ispath(item_path, /mob/living)) + return "carcass[number_of_things > 1 ? "es" : ""] of any kind" + return "[initial(item_path.name)]\s" + /** * Called whenever the knowledge's associated ritual is completed successfully. * @@ -158,9 +177,12 @@ var/obj/item/stack/sac_stack = sacrificed var/how_much_to_use = 0 for(var/requirement in required_atoms) - if(istype(sacrificed, requirement)) - how_much_to_use = min(required_atoms[requirement], sac_stack.amount) - break + if(islist(requirement) && !is_type_in_list(sacrificed, requirement)) + continue + if(!istype(sacrificed, requirement)) + continue + how_much_to_use = min(required_atoms[requirement], sac_stack.amount) + break sac_stack.use(how_much_to_use) continue @@ -264,7 +286,7 @@ /datum/heretic_knowledge/mark abstract_parent_type = /datum/heretic_knowledge/mark mutually_exclusive = TRUE - cost = 2 + cost = 1 /// The status effect typepath we apply on people on mansus grasp. var/datum/status_effect/eldritch/mark_type diff --git a/code/modules/antagonists/heretic/influences.dm b/code/modules/antagonists/heretic/influences.dm index 503e066d0e3..67a3bbc16b4 100644 --- a/code/modules/antagonists/heretic/influences.dm +++ b/code/modules/antagonists/heretic/influences.dm @@ -260,7 +260,8 @@ // Using a codex will give you two knowledge points for draining. if(!being_drained && istype(weapon, /obj/item/codex_cicatrix)) var/obj/item/codex_cicatrix/codex = weapon - codex.open_animation() + if(!codex.book_open) + codex.attack_self(user) // open booke INVOKE_ASYNC(src, PROC_REF(drain_influence), user, 2) return TRUE diff --git a/code/modules/antagonists/heretic/items/forbidden_book.dm b/code/modules/antagonists/heretic/items/forbidden_book.dm index 80721c97592..ff570801c5f 100644 --- a/code/modules/antagonists/heretic/items/forbidden_book.dm +++ b/code/modules/antagonists/heretic/items/forbidden_book.dm @@ -9,8 +9,6 @@ w_class = WEIGHT_CLASS_SMALL /// Helps determine the icon state of this item when it's used on self. var/book_open = FALSE - /// id for timer - var/timer_id /obj/item/codex_cicatrix/Initialize(mapload) . = ..() @@ -31,6 +29,7 @@ . += span_notice("Can be used to tap influences for additional knowledge points.") . += span_notice("Can also be used to draw or remove transmutation runes with ease.") + . += span_notice("Additionally, it can work as a focus for your spells in a pinch, though a more specialized relic is recommended, as this may get dropped in combat.") /obj/item/codex_cicatrix/attack_self(mob/user, modifiers) . = ..() @@ -39,8 +38,12 @@ if(book_open) close_animation() + RemoveElement(/datum/element/heretic_focus) + w_class = WEIGHT_CLASS_SMALL else open_animation() + AddElement(/datum/element/heretic_focus) + w_class = WEIGHT_CLASS_NORMAL /obj/item/codex_cicatrix/afterattack(atom/target, mob/user, proximity_flag, click_parameters) . = ..() @@ -52,7 +55,7 @@ return if(isopenturf(target)) - heretic_datum.try_draw_rune(user, target, drawing_time = 12 SECONDS) + heretic_datum.try_draw_rune(user, target, drawing_time = 8 SECONDS) return TRUE /// Plays a little animation that shows the book opening and closing. @@ -61,12 +64,8 @@ flick("[base_icon_state]_opening", src) book_open = TRUE - timer_id = addtimer(CALLBACK(src, PROC_REF(close_animation)), 5 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE) - /// Plays a closing animation and resets the icon state. /obj/item/codex_cicatrix/proc/close_animation() icon_state = base_icon_state flick("[base_icon_state]_closing", src) book_open = FALSE - - deltimer(timer_id) diff --git a/code/modules/antagonists/heretic/knowledge/ash_lore.dm b/code/modules/antagonists/heretic/knowledge/ash_lore.dm index df29ba9efa0..52e25f6a8b1 100644 --- a/code/modules/antagonists/heretic/knowledge/ash_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/ash_lore.dm @@ -72,9 +72,9 @@ name = "Ashen Passage" desc = "Grants you Ashen Passage, a silent but short range jaunt." gain_text = "He knew how to walk between the planes." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/mark/ash_mark, - /datum/heretic_knowledge/codex_cicatrix, /datum/heretic_knowledge/summon/fire_shark, /datum/heretic_knowledge/medallion, ) @@ -127,6 +127,7 @@ The mask instills fear into heathens who witness it, causing stamina damage, hallucinations, and insanity. \ It can also be forced onto a heathen, to make them unable to take it off..." gain_text = "The Nightwatcher was lost. That's what the Watch believed. Yet he walked the world, unnoticed by the masses." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/blade_upgrade/ash, /datum/heretic_knowledge/reroll_targets, @@ -165,6 +166,7 @@ If any victims afflicted are in critical condition, they will also instantly die." gain_text = "The fire was inescapable, and yet, life remained in his charred body. \ The Nightwatcher was a particular man, always watching." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/ultimate/ash_final, /datum/heretic_knowledge/summon/ashy, diff --git a/code/modules/antagonists/heretic/knowledge/blade_lore.dm b/code/modules/antagonists/heretic/knowledge/blade_lore.dm index 01358807fce..84e266c8374 100644 --- a/code/modules/antagonists/heretic/knowledge/blade_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/blade_lore.dm @@ -101,10 +101,10 @@ towards your attacker. This effect can only trigger once every 20 seconds." gain_text = "The footsoldier was known to be a fearsome duelist. \ Their general quickly appointed them as their personal Champion." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/limited_amount/risen_corpse, /datum/heretic_knowledge/mark/blade_mark, - /datum/heretic_knowledge/codex_cicatrix, /datum/heretic_knowledge/armor, ) cost = 1 @@ -243,6 +243,7 @@ you gain increased resistance to gaining wounds and resistance to batons." gain_text = "In time, it was he who stood alone among the bodies of his former comrades, awash in blood, none of it his own. \ He was without rival, equal, or purpose." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/blade_upgrade/blade, /datum/heretic_knowledge/reroll_targets, @@ -372,6 +373,7 @@ at a target, dealing damage and causing bleeding." gain_text = "Without thinking, I took the knife of a fallen soldier and threw with all my might. My aim was true! \ The Torn Champion smiled at their first taste of agony, and with a nod, their blades became my own." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/summon/maid_in_mirror, /datum/heretic_knowledge/ultimate/blade_final, diff --git a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm index 9e4d77bd95c..75ee0cd5916 100644 --- a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm @@ -70,9 +70,9 @@ However, people with a star mark will get transported along with another person using the rune." gain_text = "The distant stars crept into my dreams, roaring and screaming without reason. \ I spoke, and heard my own words echoed back." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/mark/cosmic_mark, - /datum/heretic_knowledge/codex_cicatrix, /datum/heretic_knowledge/essence, /datum/heretic_knowledge/summon/fire_shark, ) @@ -114,6 +114,7 @@ desc = "Fires a projectile that moves very slowly and creates cosmic fields on impact. \ Anyone hit by the projectile will recieve burn damage, a knockdown, and give people in a three tile range a star mark." gain_text = "The Beast was behind me now at all times, with each sacrifice words of affirmation coursed through me." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/blade_upgrade/cosmic, /datum/heretic_knowledge/reroll_targets, @@ -208,6 +209,7 @@ desc = "Grants you Cosmic Expansion, a spell that creates a 3x3 area of cosmic fields around you. \ Nearby beings will also receive a star mark." gain_text = "The ground now shook beneath me. The Beast inhabited me, and their voice was intoxicating." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/ultimate/cosmic_final, /datum/heretic_knowledge/eldritch_coin, @@ -253,7 +255,7 @@ var/mob/living/basic/heretic_summon/star_gazer/star_gazer_mob = new /mob/living/basic/heretic_summon/star_gazer(loc) star_gazer_mob.maxHealth = INFINITY star_gazer_mob.health = INFINITY - user.AddElement(/datum/element/death_linked, star_gazer_mob) + user.AddComponent(/datum/component/death_linked, star_gazer_mob) star_gazer_mob.AddComponent(/datum/component/obeys_commands, star_gazer_commands) star_gazer_mob.AddComponent(/datum/component/damage_aura, range = 7, burn_damage = 0.5, simple_damage = 0.5, immune_factions = list(FACTION_HERETIC), current_owner = user) star_gazer_mob.befriend(user) diff --git a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm index 07fa2718185..915165ad768 100644 --- a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm @@ -126,9 +126,9 @@ Voiceless Dead are mute ghouls and only have 50 health, but can use Bloody Blades effectively. \ You can only create two at a time." gain_text = "I found notes of a dark ritual, unfinished... yet still, I pushed forward." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/mark/flesh_mark, - /datum/heretic_knowledge/codex_cicatrix, /datum/heretic_knowledge/void_cloak, /datum/heretic_knowledge/medallion, ) @@ -239,6 +239,7 @@ the ability to link minds to communicate with ease, but are very fragile and weak in combat." gain_text = "I could not continue alone. I was able to summon The Uncanny Man to help me see more. \ The screams... once constant, now silenced by their wretched appearance. Nothing was out of reach." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/blade_upgrade/flesh, /datum/heretic_knowledge/reroll_targets, @@ -280,6 +281,7 @@ Stalkers can jaunt, release EMPs, shapeshift into animals or automatons, and are strong in combat." gain_text = "I was able to combine my greed and desires to summon an eldritch beast I had never seen before. \ An ever shapeshifting mass of flesh, it knew well my goals. The Marshal approved." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/ultimate/flesh_final, /datum/heretic_knowledge/summon/ashy, diff --git a/code/modules/antagonists/heretic/knowledge/general_side.dm b/code/modules/antagonists/heretic/knowledge/general_side.dm index 9c3fbe9d447..2dc2719227b 100644 --- a/code/modules/antagonists/heretic/knowledge/general_side.dm +++ b/code/modules/antagonists/heretic/knowledge/general_side.dm @@ -39,19 +39,3 @@ return FALSE return TRUE - -/datum/heretic_knowledge/codex_cicatrix - name = "Codex Cicatrix" - desc = "Allows you to transmute a bible, a fountain pen, and hide from an animal (or human) to create a Codex Cicatrix. \ - The Codex Cicatrix can be used when draining influences to gain additional knowledge, but comes at greater risk of being noticed. \ - It can also be used to draw and remove transmutation runes easier." - gain_text = "The occult leaves fragments of knowledge and power anywhere and everywhere. The Codex Cicatrix is one such example. \ - Within the leather-bound faces and age old pages, a path into the Mansus is revealed." - required_atoms = list( - /obj/item/book/bible = 1, - /obj/item/pen/fountain = 1, - /obj/item/stack/sheet/animalhide = 1, - ) - result_atoms = list(/obj/item/codex_cicatrix) - cost = 1 - route = PATH_SIDE diff --git a/code/modules/antagonists/heretic/knowledge/knock_lore.dm b/code/modules/antagonists/heretic/knowledge/knock_lore.dm index fcb2c6ceb4c..6879f527b6b 100644 --- a/code/modules/antagonists/heretic/knowledge/knock_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/knock_lore.dm @@ -70,7 +70,7 @@ /datum/heretic_knowledge/knock_grasp/proc/on_secondary_mansus_grasp(mob/living/source, atom/target) SIGNAL_HANDLER - + if(ismecha(target)) var/obj/vehicle/sealed/mecha/mecha = target mecha.dna_lock = null @@ -89,7 +89,7 @@ var/turf/target_turf = get_turf(target) SEND_SIGNAL(target_turf, COMSIG_ATOM_MAGICALLY_UNLOCKED, src, source) playsound(target, 'sound/magic/hereticknock.ogg', 100, TRUE, -1) - + return COMPONENT_USE_HAND /datum/heretic_knowledge/key_ring @@ -99,6 +99,7 @@ You can use it in-hand to change its form to a card you fused. \ Does not preserve the card used in the ritual." gain_text = "Gateways shall open before me, my very will ensnaring reality." + adds_sidepath_points = 1 required_atoms = list( /obj/item/storage/wallet = 1, /obj/item/stack/rods = 1, @@ -143,6 +144,7 @@ desc = "Grants you Burglar's Finesse, a single-target spell \ that puts a random item from the victims backpack into your hand." gain_text = "Their trinkets will be mine, as will their lives in due time." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/spell/apetra_vulnera, /datum/heretic_knowledge/spell/opening_blast, @@ -171,6 +173,7 @@ While in refuge, you cannot use your hands or spells, and you are immune to slowdown. \ You are invincible but unable to harm anything. Cancelled by being hit with an anti-magic item." gain_text = "Then I saw my my own reflection cascaded mind-numbingly enough times that I was but a haze." + adds_sidepath_points = 1 next_knowledge = list(/datum/heretic_knowledge/ultimate/knock_final) route = PATH_KNOCK spell_to_add = /datum/action/cooldown/spell/caretaker diff --git a/code/modules/antagonists/heretic/knowledge/rust_lore.dm b/code/modules/antagonists/heretic/knowledge/rust_lore.dm index bbb98f84bd6..1eeaab69bdb 100644 --- a/code/modules/antagonists/heretic/knowledge/rust_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/rust_lore.dm @@ -80,9 +80,9 @@ name = "Leeching Walk" desc = "Grants you passive healing and resistance to batons while standing over rust." gain_text = "The speed was unparalleled, the strength unnatural. The Blacksmith was smiling." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/mark/rust_mark, - /datum/heretic_knowledge/codex_cicatrix, /datum/heretic_knowledge/armor, /datum/heretic_knowledge/essence, /datum/heretic_knowledge/entropy_pulse, @@ -169,6 +169,7 @@ desc = "Grants you Aggressive Spread, a spell that spreads rust to nearby surfaces. \ Already rusted surfaces are destroyed." gain_text = "All wise men know well not to visit the Rusted Hills... Yet the Blacksmith's tale was inspiring." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/blade_upgrade/rust, /datum/heretic_knowledge/reroll_targets, @@ -198,6 +199,7 @@ at friend or foe wildly. Also rusts and destroys and surfaces it hits." gain_text = "The corrosion was unstoppable. The rust was unpleasable. \ The Blacksmith was gone, and you hold their blade. Champions of hope, the Rustbringer is nigh!" + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/ultimate/rust_final, /datum/heretic_knowledge/summon/rusty, diff --git a/code/modules/antagonists/heretic/knowledge/starting_lore.dm b/code/modules/antagonists/heretic/knowledge/starting_lore.dm index 8f36b866510..eb766392290 100644 --- a/code/modules/antagonists/heretic/knowledge/starting_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/starting_lore.dm @@ -212,3 +212,79 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) spell_to_add = /datum/action/cooldown/spell/shadow_cloak cost = 0 route = PATH_START + +/** + * Codex Cicatrixi is available at the start: + * This allows heretics to choose if they want to rush all the influences and take them stealthily, or + * Construct a codex and take what's left with more points. + * Another downside to having the book is strip searches, which means that it's not just a free nab, at least until you get exposed - and when you do, you'll probably need the faster drawing speed. + * Overall, it's a tradeoff between speed and stealth or power. + */ +/datum/heretic_knowledge/codex_cicatrix + name = "Codex Cicatrix" + desc = "Allows you to transmute a book, any unique pen (anything but generic pens), and your pick from any carcass (animal or human), leather, or hide to create a Codex Cicatrix. \ + The Codex Cicatrix can be used when draining influences to gain additional knowledge, but comes at greater risk of being noticed. \ + It can also be used to draw and remove transmutation runes easier, and as a spell focus in a pinch." + gain_text = "The occult leaves fragments of knowledge and power anywhere and everywhere. The Codex Cicatrix is one such example. \ + Within the leather-bound faces and age old pages, a path into the Mansus is revealed." + required_atoms = list( + /obj/item/book = 1, + /obj/item/pen = 1, + list(/mob/living, /obj/item/stack/sheet/leather, /obj/item/stack/sheet/animalhide) = 1, + ) + banned_atom_types = list(/obj/item/pen) + result_atoms = list(/obj/item/codex_cicatrix) + cost = 1 + route = PATH_START + priority = MAX_KNOWLEDGE_PRIORITY - 3 // Least priority out of the starting knowledges, as it's an optional boon. + +/datum/heretic_knowledge/codex_cicatrix/parse_required_item(atom/item_path, number_of_things) + if(item_path == /obj/item/pen) + return "unique type of pen" + return ..() + +/datum/heretic_knowledge/codex_cicatrix/recipe_snowflake_check(mob/living/user, list/atoms, list/selected_atoms, turf/loc) + . = ..() + if(!.) + return FALSE + + for(var/mob/living/body in atoms) + if(body.stat != DEAD) + continue + + selected_atoms += body + return TRUE + return FALSE + +/datum/heretic_knowledge/codex_cicatrix/cleanup_atoms(list/selected_atoms) + var/mob/living/body = locate() in selected_atoms + if(!body) + return + // A golem or an android doesn't have skin! + var/exterior_text = "skin" + // If carbon, it's the limb. If not, it's the body. + var/ripped_thing = body + + // We will check if it's a carbon's body. + // If it is, we will damage a random bodypart, and check that bodypart for its body type, to select between 'skin' or 'exterior'. + if(iscarbon(body)) + var/mob/living/carbon/carbody = body + var/obj/item/bodypart/bodypart = pick(carbody.bodyparts) + ripped_thing = bodypart + bodypart.receive_damage(25, sharpness = SHARP_EDGED) + if(!(bodypart.bodytype & BODYTYPE_ORGANIC)) + exterior_text = "exterior" + else + // If it is not a carbon mob, we will just check biotypes and damage it directly. + if(body.mob_biotypes & (MOB_MINERAL|MOB_ROBOTIC)) + exterior_text = "exterior" + body.apply_damage(25, BRUTE) + + // Procure book for flavor text. This is why we call parent at the end. + var/obj/item/book/le_book = locate() in selected_atoms + if(!le_book) + stack_trace("Somehow, no book in codex cicatrix selected atoms! [english_list(selected_atoms)]") + playsound(body, 'sound/items/poster_ripped.ogg', 100, TRUE) + body.do_jitter_animation() + body.visible_message(span_danger("An awful ripping sound is heard as [ripped_thing]'s [exterior_text] is ripped straight out, wrapping around [le_book || "the book"], turning into an eldritch shade of blue!")) + return ..() diff --git a/code/modules/antagonists/heretic/knowledge/void_lore.dm b/code/modules/antagonists/heretic/knowledge/void_lore.dm index 57db8636818..a5e21472517 100644 --- a/code/modules/antagonists/heretic/knowledge/void_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/void_lore.dm @@ -81,9 +81,9 @@ You can still take damage due to a lack of pressure." gain_text = "I found a thread of cold breath. It lead me to a strange shrine, all made of crystals. \ Translucent and white, a depiction of a nobleman stood before me." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/mark/void_mark, - /datum/heretic_knowledge/codex_cicatrix, /datum/heretic_knowledge/void_cloak, /datum/heretic_knowledge/limited_amount/risen_corpse, ) @@ -127,6 +127,7 @@ Additionally causes damage to heathens around your original and target destination." gain_text = "The entity calls themself the Aristocrat. They effortlessly walk through air like \ nothing - leaving a harsh, cold breeze in their wake. They disappear, and I am left in the blizzard." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/blade_upgrade/void, /datum/heretic_knowledge/reroll_targets, @@ -161,6 +162,7 @@ desc = "Grants you Void Pull, a spell that pulls all nearby heathens towards you, stunning them briefly." gain_text = "All is fleeting, but what else stays? I'm close to ending what was started. \ The Aristocrat reveals themselves to me again. They tell me I am late. Their pull is immense, I cannot turn back." + adds_sidepath_points = 1 next_knowledge = list( /datum/heretic_knowledge/ultimate/void_final, /datum/heretic_knowledge/spell/cleave, diff --git a/code/modules/antagonists/heretic/magic/star_touch.dm b/code/modules/antagonists/heretic/magic/star_touch.dm index de3a56128de..ba8c2a56391 100644 --- a/code/modules/antagonists/heretic/magic/star_touch.dm +++ b/code/modules/antagonists/heretic/magic/star_touch.dm @@ -73,11 +73,13 @@ /obj/item/melee/touch_attack/star_touch/Initialize(mapload) . = ..() - AddComponent(/datum/component/effect_remover, \ + AddComponent(\ + /datum/component/effect_remover, \ success_feedback = "You remove %THEEFFECT.", \ tip_text = "Clear rune", \ on_clear_callback = CALLBACK(src, PROC_REF(after_clear_rune)), \ - effects_we_clear = list(/obj/effect/cosmic_rune)) + effects_we_clear = list(/obj/effect/cosmic_rune), \ + ) /* * Callback for effect_remover component. diff --git a/code/modules/antagonists/heretic/structures/knock_final.dm b/code/modules/antagonists/heretic/structures/knock_final.dm index 85face85609..c8a2058eb9f 100644 --- a/code/modules/antagonists/heretic/structures/knock_final.dm +++ b/code/modules/antagonists/heretic/structures/knock_final.dm @@ -5,39 +5,68 @@ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF icon = 'icons/obj/anomaly.dmi' icon_state = "bhole3" - color = "#53277E" - light_color = "#53277E" //cooler purple + color = COLOR_VOID_PURPLE + light_color = COLOR_VOID_PURPLE light_range = 20 anchored = TRUE density = FALSE layer = HIGH_PIPE_LAYER //0.01 above sigil layer used by heretic runes move_resist = INFINITY + /// Who is our daddy? var/datum/mind/ascendee - ///a static list of heretic summons, this shouldnt even matter enough to be static but whatever + /// True if we're currently checking for ghost opinions + var/gathering_candidates = TRUE + ///a static list of heretic summons we cam create, automatically populated from heretic monster subtypes 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/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, ascendant) +/obj/structure/knock_tear/Initialize(mapload, datum/mind/ascendant_mind) . = ..() transform *= 3 - if(!monster_types) - monster_types = subtypesof(/mob/living/simple_animal/hostile/heretic_summon) - /mob/living/simple_animal/hostile/heretic_summon/armsy/prime - if(ascendant) - ascendee = ascendant + if(isnull(monster_types)) + monster_types = subtypesof(/mob/living/simple_animal/hostile/heretic_summon) + 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)) SSpoints_of_interest.make_point_of_interest(src) INVOKE_ASYNC(src, PROC_REF(poll_ghosts)) +/// Ask ghosts if they want to make some noise /obj/structure/knock_tear/proc/poll_ghosts() var/list/candidates = poll_ghost_candidates("Would you like to be a random eldritch monster attacking the crew?", ROLE_SENTIENCE, ROLE_SENTIENCE, 10 SECONDS, POLL_IGNORE_HERETIC_MONSTER) while(LAZYLEN(candidates)) var/mob/dead/observer/candidate = pick_n_take(candidates) ghost_to_monster(candidate, should_ask = FALSE) + gathering_candidates = FALSE + +/// Destroy the rift if you kill the heretic +/obj/structure/knock_tear/proc/end_madness(datum/former_master) + SIGNAL_HANDLER + var/turf/our_turf = get_turf(src) + playsound(our_turf, 'sound/magic/castsummon.ogg', vol = 100, vary = TRUE) + visible_message(span_boldwarning("The rip in space spasms and disappears!")) + UnregisterSignal(former_master, list(COMSIG_LIVING_DEATH, COMSIG_QDELETING)) // Just in case they die THEN delete + new /obj/effect/temp_visual/destabilising_tear(our_turf) + qdel(src) /obj/structure/knock_tear/attack_ghost(mob/user) . = ..() - if(.) + if(. || gathering_candidates) return ghost_to_monster(user) +/obj/structure/knock_tear/examine(mob/user) + . = ..() + if (!isobserver(user) || gathering_candidates) + return + . += span_notice("You can use this to enter the world as a foul monster.") + +/// Turn a ghost into an 'orrible beast /obj/structure/knock_tear/proc/ghost_to_monster(mob/dead/observer/user, should_ask = TRUE) if(should_ask) var/ask = tgui_alert(user, "Become a monster?", "Ascended Rift", list("Yes", "No")) @@ -61,7 +90,26 @@ /obj/structure/knock_tear/move_crushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) return FALSE -/obj/structure/knock_tear/Destroy(force) //this shouldnt happen but hey +/obj/structure/knock_tear/Destroy(force) if(ascendee) ascendee = null return ..() + +/obj/effect/temp_visual/destabilising_tear + name = "destabilised tear" + icon = 'icons/obj/anomaly.dmi' + icon_state = "bhole3" + color = COLOR_VOID_PURPLE + light_color = COLOR_VOID_PURPLE + light_range = 20 + layer = HIGH_PIPE_LAYER + duration = 1 SECONDS + +/obj/effect/temp_visual/destabilising_tear/Initialize(mapload) + . = ..() + transform *= 3 + animate(src, transform = matrix().Scale(3.2), time = 0.15 SECONDS) + animate(transform = matrix().Scale(0.2), time = 0.75 SECONDS) + animate(transform = matrix().Scale(3, 0), time = 0.1 SECONDS) + animate(src, color = COLOR_WHITE, time = 0.25 SECONDS, flags = ANIMATION_PARALLEL) + animate(color = COLOR_VOID_PURPLE, time = 0.3 SECONDS) diff --git a/code/modules/antagonists/heretic/transmutation_rune.dm b/code/modules/antagonists/heretic/transmutation_rune.dm index 7e63040af1d..cd49feb3f17 100644 --- a/code/modules/antagonists/heretic/transmutation_rune.dm +++ b/code/modules/antagonists/heretic/transmutation_rune.dm @@ -90,6 +90,7 @@ // A copy of our requirements list. // We decrement the values of to determine if enough of each key is present. var/list/requirements_list = ritual.required_atoms.Copy() + var/list/banned_atom_types = ritual.banned_atom_types.Copy() // A list of all atoms we've selected to use in this recipe. var/list/selected_atoms = list() @@ -105,8 +106,16 @@ // We already have enough of this type, skip if(requirements_list[req_type] <= 0) continue - if(!istype(nearby_atom, req_type)) + // If req_type is a list of types, check all of them for one match. + if(islist(req_type)) + if(!(is_type_in_list(nearby_atom, req_type))) + continue + else if(!istype(nearby_atom, req_type)) continue + // if list has items, check if the strict type is banned. + if(length(banned_atom_types)) + if(nearby_atom.type in banned_atom_types) + continue // This item is a valid type. Add it to our selected atoms list. selected_atoms |= nearby_atom @@ -122,7 +131,7 @@ // All of the atoms have been checked, let's see if the ritual was successful var/list/what_are_we_missing = list() - for(var/atom/req_type as anything in requirements_list) + for(var/req_type in requirements_list) var/number_of_things = requirements_list[req_type] // <= 0 means it's fulfilled, skip if(number_of_things <= 0) @@ -130,10 +139,16 @@ // > 0 means it's unfilfilled - the ritual has failed, we should tell them why // Lets format the thing they're missing and put it into our list - var/formatted_thing = "[number_of_things] [initial(req_type.name)]\s" - if(ispath(req_type, /mob/living/carbon/human)) - // If we need a human, there is a high likelihood we actually need a (dead) body - formatted_thing = "[number_of_things] [number_of_things > 1 ? "bodies":"body"]" + var/formatted_thing = "[number_of_things] " + if(islist(req_type)) + var/list/req_type_list = req_type + var/list/req_text_list = list() + for(var/atom/possible_type as anything in req_type_list) + req_text_list += ritual.parse_required_item(possible_type) + formatted_thing += english_list(req_text_list, and_text = "or") + + else + formatted_thing = ritual.parse_required_item(req_type) what_are_we_missing += formatted_thing @@ -180,6 +195,7 @@ return ritual_result + /// A 3x3 heretic rune. The kind heretics actually draw in game. /obj/effect/heretic_rune/big icon = 'icons/effects/96x96.dmi' diff --git a/code/modules/antagonists/malf_ai/malf_ai_modules.dm b/code/modules/antagonists/malf_ai/malf_ai_modules.dm index a6c6616ad48..49d464fde16 100644 --- a/code/modules/antagonists/malf_ai/malf_ai_modules.dm +++ b/code/modules/antagonists/malf_ai/malf_ai_modules.dm @@ -9,7 +9,6 @@ #define MALF_AI_ROLL_COOLDOWN 1 SECONDS + MALF_AI_ROLL_TIME #define MALF_AI_ROLL_DAMAGE 75 #define MALF_AI_ROLL_CRIT_CHANCE 5 //percent -#define MALF_AI_ROLL_MAX_DISTANCE 1 //anything further away than this, and the roll will fail GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( /obj/machinery/field/containment, @@ -1138,6 +1137,11 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) enable_text = span_notice("Your inner servos shift as you prepare to roll around. Click adjacent tiles to roll onto them!") disable_text = span_notice("You disengage your rolling protocols.") + /// How long does it take for us to roll? + var/roll_over_time = MALF_AI_ROLL_TIME + /// On top of [roll_over_time], how long does it take for the ability to cooldown? + var/roll_over_cooldown = MALF_AI_ROLL_COOLDOWN + /datum/action/innate/ai/ranged/core_tilt/New() . = ..() desc = "[desc] It has [uses] use\s remaining." @@ -1152,7 +1156,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) return FALSE var/mob/living/silicon/ai/ai_caller = caller - if (ai_caller.incapacitated()) + if (ai_caller.incapacitated() || !isturf(ai_caller.loc)) return FALSE var/turf/target = get_turf(clicked_on) @@ -1163,30 +1167,32 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) target.balloon_alert(ai_caller, "can't roll on yourself!") return FALSE - if (get_dist(ai_caller, target) > MALF_AI_ROLL_MAX_DISTANCE) - target.balloon_alert(ai_caller, "too far!") - return FALSE - var/picked_dir = get_dir(ai_caller, target) + if (!picked_dir) + return FALSE + var/turf/temp_target = get_step(ai_caller, picked_dir) // we can move during the timer so we cant just pass the ref - new /obj/effect/temp_visual/telegraphing/vending_machine_tilt(target, MALF_AI_ROLL_TIME) + new /obj/effect/temp_visual/telegraphing/vending_machine_tilt(temp_target, roll_over_time) ai_caller.balloon_alert_to_viewers("rolling...") - addtimer(CALLBACK(src, PROC_REF(do_roll_over), ai_caller, picked_dir), MALF_AI_ROLL_TIME) + addtimer(CALLBACK(src, PROC_REF(do_roll_over), ai_caller, picked_dir), roll_over_time) adjust_uses(-1) if(uses) desc = "[initial(desc)] It has [uses] use\s remaining." build_all_button_icons() - COOLDOWN_START(src, time_til_next_tilt, MALF_AI_ROLL_COOLDOWN) + COOLDOWN_START(src, time_til_next_tilt, roll_over_cooldown) /datum/action/innate/ai/ranged/core_tilt/proc/do_roll_over(mob/living/silicon/ai/ai_caller, picked_dir) + if (ai_caller.incapacitated() || !isturf(ai_caller.loc)) // prevents bugs where the ai is carded and rolls + return + var/turf/target = get_step(ai_caller, picked_dir) // in case we moved we pass the dir not the target turf if (isnull(target)) return - var/paralyze_time = clamp(6 SECONDS, 0 SECONDS, (MALF_AI_ROLL_COOLDOWN * 0.9)) //the clamp prevents stunlocking as the max is always a little less than the cooldown between rolls + var/paralyze_time = clamp(6 SECONDS, 0 SECONDS, (roll_over_cooldown * 0.9)) //the clamp prevents stunlocking as the max is always a little less than the cooldown between rolls return ai_caller.fall_and_crush(target, MALF_AI_ROLL_DAMAGE, MALF_AI_ROLL_CRIT_CHANCE, null, paralyze_time, picked_dir, rotation = get_rotation_from_dir(picked_dir)) @@ -1321,4 +1327,3 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) #undef MALF_AI_ROLL_TIME #undef MALF_AI_ROLL_DAMAGE #undef MALF_AI_ROLL_CRIT_CHANCE -#undef MALF_AI_ROLL_MAX_DISTANCE diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm index e88730f7026..3e759bdc362 100644 --- a/code/modules/antagonists/revolution/revolution.dm +++ b/code/modules/antagonists/revolution/revolution.dm @@ -397,6 +397,9 @@ /// List of all ex-revs. Useful because dynamic removes antag status when it ends, so this can be kept for the roundend report. var/list/ex_revs = list() + /// The objective of the heads of staff, aka to kill the headrevs. + var/list/datum/objective/mutiny/heads_objective = list() + /// Proc called on periodic timer. /// Updates the rev team's objectives to make sure all heads are targets, useful when new heads latejoin. /// Propagates all objectives to all revs. @@ -472,11 +475,34 @@ /// Checks if heads have won /datum/team/revolution/proc/check_heads_victory() - for(var/datum/mind/rev_mind in get_head_revolutionaries()) - var/turf/rev_turf = get_turf(rev_mind.current) - if(!considered_afk(rev_mind) && considered_alive(rev_mind) && is_station_level(rev_turf.z)) - return FALSE - return TRUE + // List of headrevs we're currently tracking + var/list/included_headrevs = list() + // List of current headrevs + var/list/current_headrevs = get_head_revolutionaries() + // A copy of the head of staff objective list, since we're going to be modifying the original list. + var/list/heads_objective_copy = heads_objective.Copy() + + var/objective_complete = TRUE + // Here, we check current head of staff objectives and remove them if the target doesn't exist as a headrev anymore + for(var/datum/objective/mutiny/objective in heads_objective_copy) + if(!(objective.target in current_headrevs)) + heads_objective -= objective + continue + if(!objective.check_completion()) + objective_complete = FALSE + included_headrevs += objective.target + + // Here, we check current headrevs and add them as objectives if they didn't exist as a head of staff objective before. + // Additionally, we make sure the objective is not completed by running the check_completion check on them. + for(var/datum/mind/rev_mind as anything in current_headrevs) + if(!(rev_mind in included_headrevs)) + var/datum/objective/mutiny/objective = new() + objective.target = rev_mind + if(!objective.check_completion()) + objective_complete = FALSE + heads_objective += objective + + return objective_complete /// Updates the state of the world depending on if revs won or loss. /// Returns who won, at which case this method should no longer be called. diff --git a/code/modules/antagonists/traitor/objectives/abstract/target_player.dm b/code/modules/antagonists/traitor/objectives/abstract/target_player.dm index 76471eb244a..c08f8cd46ee 100644 --- a/code/modules/antagonists/traitor/objectives/abstract/target_player.dm +++ b/code/modules/antagonists/traitor/objectives/abstract/target_player.dm @@ -16,3 +16,18 @@ /// The target that we need to target. var/mob/living/target + +/datum/traitor_objective/target_player/Destroy(force) + set_target(null) + return ..() + +/datum/traitor_objective/target_player/proc/set_target(mob/living/new_target) + if(target) + UnregisterSignal(target, COMSIG_QDELETING) + target = new_target + if(target) + RegisterSignal(target, COMSIG_QDELETING, PROC_REF(target_deleted)) + +/datum/traitor_objective/target_player/proc/target_deleted(datum/source) + SIGNAL_HANDLER + set_target(null) diff --git a/code/modules/antagonists/traitor/objectives/assassination.dm b/code/modules/antagonists/traitor/objectives/assassination.dm index 4efcbb111be..ab3211aedd8 100644 --- a/code/modules/antagonists/traitor/objectives/assassination.dm +++ b/code/modules/antagonists/traitor/objectives/assassination.dm @@ -107,20 +107,13 @@ return //in their pockets please succeed_objective() -/datum/traitor_objective/target_player/assassinate/calling_card/generate_objective(datum/mind/generating_for, list/possible_duplicates) - . = ..() - if(!.) //didn't generate - return FALSE - RegisterSignal(target, COMSIG_QDELETING, PROC_REF(on_target_qdeleted)) - /datum/traitor_objective/target_player/assassinate/calling_card/ungenerate_objective() - UnregisterSignal(target, COMSIG_QDELETING) . = ..() //unsets kill target if(card) UnregisterSignal(card, COMSIG_ITEM_EQUIPPED) card = null -/datum/traitor_objective/target_player/assassinate/calling_card/on_target_qdeleted() +/datum/traitor_objective/target_player/assassinate/calling_card/target_deleted() //you cannot plant anything on someone who is gone gone, so even if this happens after you're still liable to fail fail_objective(penalty_cost = telecrystal_penalty) @@ -228,7 +221,7 @@ return FALSE //MISSION FAILED, WE'LL GET EM NEXT TIME var/datum/mind/target_mind = pick(possible_targets) - target = target_mind.current + set_target(target_mind.current) replace_in_name("%TARGET%", target.real_name) replace_in_name("%JOB TITLE%", target_mind.assigned_role.title) RegisterSignal(target, COMSIG_LIVING_DEATH, PROC_REF(on_target_death)) @@ -236,17 +229,17 @@ /datum/traitor_objective/target_player/assassinate/ungenerate_objective() UnregisterSignal(target, COMSIG_LIVING_DEATH) - target = null + set_target(null) ///proc for checking for special states that invalidate a target /datum/traitor_objective/target_player/assassinate/proc/special_target_filter(list/possible_targets) return -/datum/traitor_objective/target_player/assassinate/proc/on_target_qdeleted() - SIGNAL_HANDLER +/datum/traitor_objective/target_player/assassinate/target_deleted() if(objective_state == OBJECTIVE_STATE_INACTIVE) //don't take an objective target of someone who is already obliterated fail_objective() + return ..() /datum/traitor_objective/target_player/assassinate/proc/on_target_death() SIGNAL_HANDLER diff --git a/code/modules/antagonists/traitor/objectives/demoralise_assault.dm b/code/modules/antagonists/traitor/objectives/demoralise_assault.dm index 095c646cb99..fe26864e4fc 100644 --- a/code/modules/antagonists/traitor/objectives/demoralise_assault.dm +++ b/code/modules/antagonists/traitor/objectives/demoralise_assault.dm @@ -55,9 +55,7 @@ /datum/traitor_objective/target_player/assault/ungenerate_objective() UnregisterSignal(target, COMSIG_ATOM_WAS_ATTACKED) UnregisterSignal(target, COMSIG_LIVING_DEATH) - UnregisterSignal(target, COMSIG_QDELETING) - - target = null + set_target(null) /datum/traitor_objective/target_player/assault/generate_objective(datum/mind/generating_for, list/possible_duplicates) var/list/already_targeting = list() //List of minds we're already targeting. The possible_duplicates is a list of objectives, so let's not mix things @@ -102,7 +100,7 @@ var/datum/mind/target_mind = pick(possible_targets) - target = target_mind.current + set_target(target_mind.current) replace_in_name("%TARGET%", target.real_name) replace_in_name("%JOB TITLE%", target_mind.assigned_role.title) @@ -110,7 +108,6 @@ replace_in_name("%COUNT%", attacks_required) RegisterSignal(target, COMSIG_LIVING_DEATH, PROC_REF(on_target_death)) - RegisterSignal(target, COMSIG_QDELETING, PROC_REF(on_target_qdeleted)) return TRUE @@ -120,11 +117,10 @@ buttons += add_ui_button("[attacks_required - attacks_inflicted]", "This tells you how many more times you have to attack the target player to succeed.", "hand-rock-o", "none") return buttons -/datum/traitor_objective/target_player/assault/proc/on_target_qdeleted() - SIGNAL_HANDLER - +/datum/traitor_objective/target_player/assault/target_deleted() //don't take an objective target of someone who is already obliterated fail_objective() + return ..() /datum/traitor_objective/target_player/assault/proc/on_target_death() SIGNAL_HANDLER diff --git a/code/modules/antagonists/traitor/objectives/eyesnatching.dm b/code/modules/antagonists/traitor/objectives/eyesnatching.dm index 0540d83601c..4a307f8d8e0 100644 --- a/code/modules/antagonists/traitor/objectives/eyesnatching.dm +++ b/code/modules/antagonists/traitor/objectives/eyesnatching.dm @@ -102,7 +102,7 @@ return FALSE //MISSION FAILED, WE'LL GET EM NEXT TIME var/datum/mind/target_mind = pick(possible_targets) - target = target_mind.current + set_target(target_mind.current) replace_in_name("%TARGET%", target_mind.name) replace_in_name("%JOB TITLE%", target_mind.assigned_role.title) diff --git a/code/modules/antagonists/traitor/objectives/infect.dm b/code/modules/antagonists/traitor/objectives/infect.dm index 7784b8228c5..b1bb868e903 100644 --- a/code/modules/antagonists/traitor/objectives/infect.dm +++ b/code/modules/antagonists/traitor/objectives/infect.dm @@ -122,7 +122,7 @@ return FALSE //MISSION FAILED, WE'LL GET EM NEXT TIME var/datum/mind/target_mind = pick(possible_targets) - target = target_mind.current + set_target(target_mind.current) replace_in_name("%TARGET%", target.real_name) replace_in_name("%JOB TITLE%", target_mind.assigned_role.title) RegisterSignal(target, COMSIG_LIVING_DEATH, PROC_REF(on_target_death)) @@ -130,17 +130,17 @@ /datum/traitor_objective/target_player/infect/ungenerate_objective() UnregisterSignal(target, COMSIG_LIVING_DEATH) - target = null + set_target(null) ///proc for checking for special states that invalidate a target /datum/traitor_objective/target_player/infect/proc/special_target_filter(list/possible_targets) return -/datum/traitor_objective/target_player/infect/proc/on_target_qdeleted() - SIGNAL_HANDLER +/datum/traitor_objective/target_player/infect/target_deleted() if(objective_state == OBJECTIVE_STATE_INACTIVE) //don't take an objective target of someone who is already obliterated fail_objective() + return ..() /datum/traitor_objective/target_player/infect/proc/on_target_death() SIGNAL_HANDLER diff --git a/code/modules/antagonists/traitor/objectives/kidnapping.dm b/code/modules/antagonists/traitor/objectives/kidnapping.dm index 55d633ced94..4a463b2b616 100644 --- a/code/modules/antagonists/traitor/objectives/kidnapping.dm +++ b/code/modules/antagonists/traitor/objectives/kidnapping.dm @@ -13,7 +13,7 @@ var/pod_called = FALSE /// How much TC do we get from sending the target alive var/alive_bonus = 0 - /// All stripped targets belongings + /// All stripped targets belongings (weakrefs) var/list/target_belongings = list() duplicate_type = /datum/traitor_objective/target_player @@ -157,7 +157,7 @@ return FALSE var/datum/mind/target_mind = pick(possible_targets) - target = target_mind.current + set_target(target_mind.current) AddComponent(/datum/component/traitor_objective_register, target, fail_signals = list(COMSIG_QDELETING)) var/list/possible_areas = GLOB.the_station_areas.Copy() for(var/area/possible_area as anything in possible_areas) @@ -172,7 +172,7 @@ return TRUE /datum/traitor_objective/target_player/kidnapping/ungenerate_objective() - target = null + set_target(null) dropoff_area = null /datum/traitor_objective/target_player/kidnapping/on_objective_taken(mob/user) @@ -234,7 +234,7 @@ var/unequipped = sent_mob.transferItemToLoc(belonging) if (!unequipped) continue - target_belongings.Add(belonging) + target_belongings.Add(WEAKREF(belonging)) var/datum/bank_account/cargo_account = SSeconomy.get_dep_account(ACCOUNT_CAR) @@ -303,7 +303,10 @@ continue sent_mob.dropItemToGround(belonging) // No souvenirs, except shoes and t-shirts - for(var/obj/item/belonging in target_belongings) + for(var/datum/weakref/belonging_ref in target_belongings) + var/obj/item/belonging = belonging_ref.resolve() + if(!belonging) + continue belonging.forceMove(return_pod) sent_mob.forceMove(return_pod) diff --git a/code/modules/antagonists/valentines/valentine.dm b/code/modules/antagonists/valentines/valentine.dm index 8883625fb1a..79ae9fa8baa 100644 --- a/code/modules/antagonists/valentines/valentine.dm +++ b/code/modules/antagonists/valentines/valentine.dm @@ -4,8 +4,8 @@ show_in_antagpanel = FALSE prevent_roundtype_conversion = FALSE suicide_cry = "FOR MY LOVE!!" - // Not 'true' antags, cannot induct - antag_flags = NONE + // Not 'true' antags, this disables certain interactions that assume the owner is a baddie + antag_flags = FLAG_FAKE_ANTAG var/datum/mind/date count_against_dynamic_roll_chance = FALSE diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/all_access.dm b/code/modules/antagonists/wizard/grand_ritual/finales/all_access.dm new file mode 100644 index 00000000000..07958ed94a7 --- /dev/null +++ b/code/modules/antagonists/wizard/grand_ritual/finales/all_access.dm @@ -0,0 +1,17 @@ +/// Open all of the doors +/datum/grand_finale/all_access + name = "Connection" + desc = "The ultimate use of your gathered power! Unlock every single door that they have! Nobody will be able to keep you out now, or anyone else for that matter!" + icon = 'icons/mob/actions/actions_spells.dmi' + icon_state = "knock" + +/datum/grand_finale/all_access/trigger(mob/living/carbon/human/invoker) + message_admins("[key_name(invoker)] removed all door access requirements") + for(var/obj/machinery/door/target_door as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door)) + if(is_station_level(target_door.z)) + target_door.unlock() + target_door.req_access = list() + target_door.req_one_access = list() + INVOKE_ASYNC(target_door, TYPE_PROC_REF(/obj/machinery/door/airlock, open)) + CHECK_TICK + priority_announce("AULIE OXIN FIERA!!", null, 'sound/magic/knock.ogg', sender_override = "[invoker.real_name]") diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/armageddon.dm b/code/modules/antagonists/wizard/grand_ritual/finales/armageddon.dm new file mode 100644 index 00000000000..876f2475d55 --- /dev/null +++ b/code/modules/antagonists/wizard/grand_ritual/finales/armageddon.dm @@ -0,0 +1,60 @@ +#define DOOM_SINGULARITY "singularity" +#define DOOM_TESLA "tesla" +#define DOOM_METEORS "meteors" + +/// Kill yourself and probably a bunch of other people +/datum/grand_finale/armageddon + name = "Annihilation" + desc = "This crew have offended you beyond the realm of pranks. Make the ultimate sacrifice to teach them a lesson your elders can really respect. \ + YOU WILL NOT SURVIVE THIS." + icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' + icon_state = "legion_head" + minimum_time = 90 MINUTES // This will probably immediately end the round if it gets finished. + ritual_invoke_time = 60 SECONDS // Really give the crew some time to interfere with this one. + dire_warning = TRUE + glow_colour = "#be000048" + /// Things to yell before you die + var/static/list/possible_last_words = list( + "Flames and ruin!", + "Dooooooooom!!", + "HAHAHAHAHAHA!! AHAHAHAHAHAHAHAHAA!!", + "Hee hee hee!! Hoo hoo hoo!! Ha ha haaa!!", + "Ohohohohohoho!!", + "Cower in fear, puny mortals!", + "Tremble before my glory!", + "Pick a god and pray!", + "It's no use!", + "If the gods wanted you to live, they would not have created me!", + "God stays in heaven out of fear of what I have created!", + "Ruination is come!", + "All of creation, bend to my will!", + ) + +/datum/grand_finale/armageddon/trigger(mob/living/carbon/human/invoker) + priority_announce(pick(possible_last_words), null, 'sound/magic/voidblink.ogg', sender_override = "[invoker.real_name]") + var/turf/current_location = get_turf(invoker) + invoker.gib() + + var/static/list/doom_options = list() + if (!length(doom_options)) + doom_options = list(DOOM_SINGULARITY, DOOM_TESLA) + if (!SSmapping.config.planetary) + doom_options += DOOM_METEORS + + switch(pick(doom_options)) + if (DOOM_SINGULARITY) + var/obj/singularity/singulo = new(current_location) + singulo.energy = 300 + if (DOOM_TESLA) + var/obj/energy_ball/tesla = new (current_location) + tesla.energy = 200 + if (DOOM_METEORS) + var/datum/dynamic_ruleset/roundstart/meteor/meteors = new() + meteors.meteordelay = 0 + var/datum/game_mode/dynamic/mode = SSticker.mode + mode.execute_roundstart_rule(meteors) // Meteors will continue until morale is crushed. + priority_announce("Meteors have been detected on collision course with the station.", "Meteor Alert", ANNOUNCER_METEORS) + +#undef DOOM_SINGULARITY +#undef DOOM_TESLA +#undef DOOM_METEORS diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/captaincy.dm b/code/modules/antagonists/wizard/grand_ritual/finales/captaincy.dm new file mode 100644 index 00000000000..d1a3c1afaf7 --- /dev/null +++ b/code/modules/antagonists/wizard/grand_ritual/finales/captaincy.dm @@ -0,0 +1,113 @@ +/// Become the official Captain of the station +/datum/grand_finale/usurp + name = "Usurpation" + desc = "The ultimate use of your gathered power! Rewrite time such that you have been Captain of this station the whole time." + icon = 'icons/obj/card.dmi' + icon_state = "card_gold" + +/datum/grand_finale/usurp/trigger(mob/living/carbon/human/invoker) + message_admins("[key_name(invoker)] has replaced the Captain") + var/list/former_captains = list() + var/list/other_crew = list() + SEND_SOUND(world, sound('sound/magic/timeparadox2.ogg')) + + for (var/mob/living/carbon/human/crewmate as anything in GLOB.human_list) + if (!crewmate.mind) + continue + crewmate.Unconscious(3 SECONDS) // Everyone falls unconscious but not everyone gets told about a new captain + if (crewmate == invoker || IS_HUMAN_INVADER(crewmate)) + continue + to_chat(crewmate, span_notice("The world spins and dissolves. Your past flashes before your eyes, backwards.\n\ + Life strolls back into the ocean and shrinks into nothingness, planets explode into storms of solar dust, \ + the stars rush back to greet each other at the beginning of things and then... you snap back to the present. \n\ + Everything is just as it was and always has been. \n\n\ + A stray thought sticks in the forefront of your mind. \n\ + [span_hypnophrase("I'm so glad that [invoker.real_name] is our legally appointed Captain!")] \n\ + Is... that right?")) + if (is_captain_job(crewmate.mind.assigned_role)) + former_captains += crewmate + demote_to_assistant(crewmate) + continue + if (crewmate.stat != DEAD) + other_crew += crewmate + + dress_candidate(invoker) + GLOB.manifest.modify(invoker.real_name, JOB_CAPTAIN, JOB_CAPTAIN) + minor_announce("Captain [invoker.real_name] on deck!") + + // Enlist some crew to try and restore the natural order + for (var/mob/living/carbon/human/former_captain as anything in former_captains) + create_vendetta(former_captain.mind, invoker.mind) + for (var/mob/living/carbon/human/random_crewmate as anything in other_crew) + if (prob(10)) + create_vendetta(random_crewmate.mind, invoker.mind) + +/** + * Anyone who thought they were Captain is in for a nasty surprise, and won't be very happy about it + */ +/datum/grand_finale/usurp/proc/demote_to_assistant(mob/living/carbon/human/former_captain) + var/obj/effect/particle_effect/fluid/smoke/exit_poof = new(get_turf(former_captain)) + exit_poof.lifetime = 2 SECONDS + + former_captain.unequip_everything() + if(isplasmaman(former_captain)) + former_captain.equipOutfit(/datum/outfit/plasmaman) + former_captain.internal = former_captain.get_item_for_held_index(2) + else + former_captain.equipOutfit(/datum/outfit/job/assistant) + + GLOB.manifest.modify(former_captain.real_name, JOB_ASSISTANT, JOB_ASSISTANT) + var/list/valid_turfs = list() + // Used to be into prison but that felt a bit too mean + for (var/turf/exile_turf as anything in get_area_turfs(/area/station/maintenance, subtypes = TRUE)) + if (isspaceturf(exile_turf) || exile_turf.is_blocked_turf()) + continue + valid_turfs += exile_turf + do_teleport(former_captain, pick(valid_turfs), no_effects = TRUE) + var/obj/effect/particle_effect/fluid/smoke/enter_poof = new(get_turf(former_captain)) + enter_poof.lifetime = 2 SECONDS + +/** + * Does some item juggling to try to dress you as both a Wizard and Captain without deleting any items you have bought. + * ID, headset, and uniform are forcibly replaced. Other slots are only filled if unoccupied. + * We could forcibly replace shoes and gloves too but people might miss their insuls or... meown shoes? + */ +/datum/grand_finale/usurp/proc/dress_candidate(mob/living/carbon/human/invoker) + // Won't be needing these + var/obj/id = invoker.get_item_by_slot(ITEM_SLOT_ID) + QDEL_NULL(id) + var/obj/headset = invoker.get_item_by_slot(ITEM_SLOT_EARS) + QDEL_NULL(headset) + // We're about to take off your pants so those are going to fall out + var/obj/item/pocket_L = invoker.get_item_by_slot(ITEM_SLOT_LPOCKET) + var/obj/item/pocket_R = invoker.get_item_by_slot(ITEM_SLOT_RPOCKET) + // In case we try to put a PDA there + var/obj/item/belt = invoker.get_item_by_slot(ITEM_SLOT_BELT) + belt?.moveToNullspace() + + var/obj/pants = invoker.get_item_by_slot(ITEM_SLOT_ICLOTHING) + QDEL_NULL(pants) + invoker.equipOutfit(/datum/outfit/job/wizard_captain) + // And put everything back! + equip_to_slot_then_hands(invoker, ITEM_SLOT_BELT, belt) + equip_to_slot_then_hands(invoker, ITEM_SLOT_LPOCKET, pocket_L) + equip_to_slot_then_hands(invoker, ITEM_SLOT_RPOCKET, pocket_R) + +/// An outfit which replaces parts of a wizard's clothes with captain's clothes but keeps the robes +/datum/outfit/job/wizard_captain + name = "Captain (Wizard Transformation)" + jobtype = /datum/job/captain + id = /obj/item/card/id/advanced/gold + id_trim = /datum/id_trim/job/captain + uniform = /obj/item/clothing/under/rank/captain/parade + belt = /obj/item/modular_computer/pda/heads/captain + ears = /obj/item/radio/headset/heads/captain/alt + glasses = /obj/item/clothing/glasses/sunglasses + gloves = /obj/item/clothing/gloves/captain + shoes = /obj/item/clothing/shoes/laceup + accessory = /obj/item/clothing/accessory/medal/gold/captain + backpack_contents = list( + /obj/item/melee/baton/telescopic = 1, + /obj/item/station_charter = 1, + ) + box = null diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/cheese.dm b/code/modules/antagonists/wizard/grand_ritual/finales/cheese.dm new file mode 100644 index 00000000000..714cd62659b --- /dev/null +++ b/code/modules/antagonists/wizard/grand_ritual/finales/cheese.dm @@ -0,0 +1,49 @@ +/** + * Gives the wizard a defensive/mood buff and a Wabbajack, a juiced up chaos staff that will surely break something. + * Everyone but the wizard goes crazy, suffers major brain damage, and is given a vendetta against the wizard. + * Already insane people are instead cured of their madness, ignoring any other effects as the station around them loses its marbles. + */ +/datum/grand_finale/cheese + // we don't set name, desc and others, thus we won't appear in the radial choice of a normal finale rune + dire_warning = TRUE + minimum_time = 45 MINUTES //i'd imagine speedrunning this would be crummy, but the wizard's average lifespan is barely reaching this point + +/datum/grand_finale/cheese/trigger(mob/living/invoker) + message_admins("[key_name(invoker)] has summoned forth The Wabbajack and cursed the crew with madness!") + priority_announce("Danger: Extremely potent reality altering object has been summoned on station. Immediate evacuation advised. Brace for impact.", "Central Command Higher Dimensional Affairs", 'sound/effects/glassbr1.ogg') + + for (var/mob/living/carbon/human/crewmate as anything in GLOB.human_list) + if (isnull(crewmate.mind)) + continue + if (crewmate == invoker) //everyone but the wizard is royally fucked, no matter who they are + continue + if (crewmate.has_trauma_type(/datum/brain_trauma/mild/hallucinations)) //for an already insane person, this is retribution + to_chat(crewmate, span_boldwarning("Your surroundings suddenly fill with a cacophony of manic laughter and psychobabble...")) + to_chat(crewmate, span_nicegreen("...but as the moment passes, you realise that whatever eldritch power behind the event happened to affect you \ + has resonated within the ruins of your already shattered mind, creating a singularity of mental instability! \ + As it collapses unto itself, you feel... at peace, finally.")) + if(crewmate.has_quirk(/datum/quirk/insanity)) + crewmate.remove_quirk(/datum/quirk/insanity) + else + crewmate.cure_trauma_type(/datum/brain_trauma/mild/hallucinations, TRAUMA_RESILIENCE_ABSOLUTE) + else + //everyone else gets to relish in madness + //yes killing their mood will also trigger mood hallucinations + create_vendetta(crewmate.mind, invoker.mind) + to_chat(crewmate, span_boldwarning("Your surroundings suddenly fill with a cacophony of manic laughter and psychobabble. \n\ + You feel your inner psyche shatter into a myriad pieces of jagged glass of colors unknown to the universe, \ + infinitely reflecting a blinding, maddening light coming from the innermost sanctums of your destroyed mind. \n\ + After a brief pause which felt like a millenia, one phrase rebounds ceaselessly in your head, imbued with the false hope of absolution... \n\ + [invoker] must die.")) + var/datum/brain_trauma/mild/hallucinations/added_trauma = new() + added_trauma.resilience = TRAUMA_RESILIENCE_ABSOLUTE + crewmate.adjustOrganLoss(ORGAN_SLOT_BRAIN, BRAIN_DAMAGE_DEATH - 25, BRAIN_DAMAGE_DEATH - 25) //you'd better hope chap didn't pick a hypertool + crewmate.gain_trauma(added_trauma) + crewmate.add_mood_event("wizard_ritual_finale", /datum/mood_event/madness_despair) + + //drip our wizard out + invoker.apply_status_effect(/datum/status_effect/blessing_of_insanity) + invoker.add_mood_event("wizard_ritual_finale", /datum/mood_event/madness_elation) + var/obj/item/gun/magic/staff/chaos/true_wabbajack/the_wabbajack = new + invoker.put_in_active_hand(the_wabbajack) + to_chat(invoker, span_mind_control("Your every single instinct and rational thought is screaming at you as [the_wabbajack] appears in your firm grip...")) diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/clown.dm b/code/modules/antagonists/wizard/grand_ritual/finales/clown.dm new file mode 100644 index 00000000000..bda79c908c0 --- /dev/null +++ b/code/modules/antagonists/wizard/grand_ritual/finales/clown.dm @@ -0,0 +1,76 @@ +/// Dress the crew as magical clowns +/datum/grand_finale/clown + name = "Jubilation" + desc = "The ultimate use of your gathered power! Rewrite time so that everyone went to clown college! Now they'll prank each other for you!" + icon = 'icons/obj/clothing/masks.dmi' + icon_state = "clown" + glow_colour = "#ffff0048" + +/datum/grand_finale/clown/trigger(mob/living/carbon/human/invoker) + for(var/mob/living/carbon/human/victim as anything in GLOB.human_list) + victim.Unconscious(3 SECONDS) + if (!victim.mind || IS_HUMAN_INVADER(victim) || victim == invoker) + continue + if (HAS_TRAIT(victim, TRAIT_CLOWN_ENJOYER)) + victim.add_mood_event("clown_world", /datum/mood_event/clown_world) + to_chat(victim, span_notice("The world spins and dissolves. Your past flashes before your eyes, backwards.\n\ + Life strolls back into the ocean and shrinks into nothingness, planets explode into storms of solar dust, \ + the stars rush back to greet each other at the beginning of things and then... you snap back to the present. \n\ + Everything is just as it was and always has been. \n\n\ + A stray thought sticks in the forefront of your mind. \n\ + [span_hypnophrase("I'm so glad that I work at Clown Research Station [station_name()]!")] \n\ + Is... that right?")) + if (is_clown_job(victim.mind.assigned_role)) + var/datum/action/cooldown/spell/conjure_item/clown_pockets/new_spell = new(victim) + new_spell.Grant(victim) + continue + if (!ismonkey(victim)) // Monkeys cannot yet wear clothes + dress_as_magic_clown(victim) + if (prob(15)) + create_vendetta(victim.mind, invoker.mind) + +/** + * Clown enjoyers who are effected by this become ecstatic, they have achieved their life's dream. + * This moodlet is equivalent to the one for simply being a traitor. + */ +/datum/mood_event/clown_world + mood_change = 4 + +/datum/mood_event/clown_world/add_effects(param) + description = "I LOVE working at Clown Research Station [station_name()]!!" + +/// Dress the passed mob as a magical clown, self-explanatory +/datum/grand_finale/clown/proc/dress_as_magic_clown(mob/living/carbon/human/victim) + var/obj/effect/particle_effect/fluid/smoke/poof = new(get_turf(victim)) + poof.lifetime = 2 SECONDS + + var/obj/item/tank/internal = victim.internal + // We're about to take off your pants so those are going to fall out + var/obj/item/pocket_L = victim.get_item_by_slot(ITEM_SLOT_LPOCKET) + var/obj/item/pocket_R = victim.get_item_by_slot(ITEM_SLOT_RPOCKET) + var/obj/item/id = victim.get_item_by_slot(ITEM_SLOT_ID) + var/obj/item/belt = victim.get_item_by_slot(ITEM_SLOT_BELT) + + var/obj/pants = victim.get_item_by_slot(ITEM_SLOT_ICLOTHING) + var/obj/mask = victim.get_item_by_slot(ITEM_SLOT_MASK) + QDEL_NULL(pants) + QDEL_NULL(mask) + if(isplasmaman(victim)) + victim.equip_to_slot_if_possible(new /obj/item/clothing/under/plasmaman/clown/magic(), ITEM_SLOT_ICLOTHING, disable_warning = TRUE) + victim.equip_to_slot_if_possible(new /obj/item/clothing/mask/gas/clown_hat/plasmaman(), ITEM_SLOT_MASK, disable_warning = TRUE) + else + victim.equip_to_slot_if_possible(new /obj/item/clothing/under/rank/civilian/clown/magic(), ITEM_SLOT_ICLOTHING, disable_warning = TRUE) + victim.equip_to_slot_if_possible(new /obj/item/clothing/mask/gas/clown_hat(), ITEM_SLOT_MASK, disable_warning = TRUE) + + var/obj/item/clothing/mask/gas/clown_hat/clown_mask = victim.get_item_by_slot(ITEM_SLOT_MASK) + if (clown_mask) + var/list/options = GLOB.clown_mask_options + clown_mask.icon_state = options[pick(clown_mask.clownmask_designs)] + victim.update_worn_mask() + clown_mask.update_item_action_buttons() + + equip_to_slot_then_hands(victim, ITEM_SLOT_LPOCKET, pocket_L) + equip_to_slot_then_hands(victim, ITEM_SLOT_RPOCKET, pocket_R) + equip_to_slot_then_hands(victim, ITEM_SLOT_ID, id) + equip_to_slot_then_hands(victim, ITEM_SLOT_BELT, belt) + victim.internal = internal diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/grand_ritual_finale.dm b/code/modules/antagonists/wizard/grand_ritual/finales/grand_ritual_finale.dm new file mode 100644 index 00000000000..b92ae4d2f20 --- /dev/null +++ b/code/modules/antagonists/wizard/grand_ritual/finales/grand_ritual_finale.dm @@ -0,0 +1,88 @@ +/** + * A big final event to run when you complete seven rituals + */ +/datum/grand_finale + /// Friendly name for selection menu + var/name + /// Tooltip description for selection menu + var/desc + /// An icon to display to represent the choice + var/icon/icon + /// Icon state to use to represent the choice + var/icon_state + /// Prevent especially dangerous options from being chosen until we're fine with the round ending + var/minimum_time = 0 + /// Override the rune invocation time + var/ritual_invoke_time = 30 SECONDS + /// Provide an extremely loud radio message when this one starts + var/dire_warning = FALSE + /// Overrides the default colour you glow while channeling the rune, optional + var/glow_colour + +/** + * Returns an entry for a radial menu for this choice. + * Returns null if entry is abstract or invalid for current circumstances. + */ +/datum/grand_finale/proc/get_radial_choice() + if (!name || !desc || !icon || !icon_state) + return + var/time_remaining_desc = "" + if (minimum_time >= world.time - SSticker.round_start_time) + time_remaining_desc = "This ritual will be available to begin invoking in [DisplayTimeText(minimum_time - world.time - SSticker.round_start_time)]" + var/datum/radial_menu_choice/choice = new() + choice.name = name + choice.image = image(icon = icon, icon_state = icon_state) + choice.info = desc + time_remaining_desc + return choice + +/** + * Actually do the thing. + * Arguments + * * invoker - The wizard casting this. + */ +/datum/grand_finale/proc/trigger(mob/living/invoker) + // Do something cool. + +/// Tries to equip something into an inventory slot, then hands, then the floor. +/datum/grand_finale/proc/equip_to_slot_then_hands(mob/living/carbon/human/invoker, slot, obj/item/item) + if(!item) + return + if(!invoker.equip_to_slot_if_possible(item, slot, disable_warning = TRUE)) + invoker.put_in_hands(item) + +/// They are not going to take this lying down. +/datum/grand_finale/proc/create_vendetta(datum/mind/aggrieved_crewmate, datum/mind/wizard) + aggrieved_crewmate.add_antag_datum(/datum/antagonist/wizard_prank_vendetta) + var/datum/antagonist/wizard_prank_vendetta/antag_datum = aggrieved_crewmate.has_antag_datum(/datum/antagonist/wizard_prank_vendetta) + var/datum/objective/assassinate/wizard_murder = new + wizard_murder.owner = aggrieved_crewmate + wizard_murder.target = wizard + wizard_murder.explanation_text = "Kill [wizard.current.name], the one who did this." + antag_datum.objectives += wizard_murder + + to_chat(aggrieved_crewmate.current, span_warning("No! This isn't right!")) + aggrieved_crewmate.announce_objectives() + +/** + * Antag datum to give to people who want to kill the wizard. + * This doesn't preclude other people choosing to want to kill the wizard, just these people are rewarded for it. + */ +/datum/antagonist/wizard_prank_vendetta + name = "\improper Wizard Prank Victim" + roundend_category = "wizard prank victims" + show_in_antagpanel = FALSE + antagpanel_category = "Other" + show_name_in_check_antagonists = TRUE + count_against_dynamic_roll_chance = FALSE + silent = TRUE + +/// Give everyone magic items, its so simple it feels pointless to give it its own file +/datum/grand_finale/magic + name = "Evolution" + desc = "The ultimate use of your gathered power! Give the crew their own magic, they'll surely realise that right and wrong have no meaning when you hold ultimate power!" + icon = 'icons/obj/scrolls.dmi' + icon_state = "scroll" + +/datum/grand_finale/magic/trigger(mob/living/carbon/human/invoker) + message_admins("[key_name(invoker)] summoned magic") + summon_magic(survivor_probability = 20) // Wow, this one was easy! diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/immortality.dm b/code/modules/antagonists/wizard/grand_ritual/finales/immortality.dm new file mode 100644 index 00000000000..d20ca06752b --- /dev/null +++ b/code/modules/antagonists/wizard/grand_ritual/finales/immortality.dm @@ -0,0 +1,277 @@ +/// Amount of time to wait after someone dies to steal their body from their killers +#define IMMORTAL_PRE_ACTIVATION_TIME 10 SECONDS +/// Amount of time it takes a mob to return to the living world +#define IMMORTAL_RESURRECT_TIME 50 SECONDS + +/** + * Nobody will ever die ever again + * Or if they do, they will be back + */ +/datum/grand_finale/immortality + name = "Perpetuation" + desc = "The ultimate use of your gathered power! Share with the crew the gift, or curse, of eternal life! \ + And why not just the crew? How about their pets too? And any other animals around here! \ + What if nobody died ever again!?" + icon = 'icons/obj/mining_zones/artefacts.dmi' + icon_state = "asclepius_active" + glow_colour = COLOR_PALE_GREEN + minimum_time = 30 MINUTES // This is enormously disruptive but doesn't technically in of itself end the round. + +/datum/grand_finale/immortality/trigger(mob/living/carbon/human/invoker) + new /obj/effect/temp_visual/immortality_blast(get_turf(invoker)) + SEND_SOUND(world, sound('sound/magic/teleport_diss.ogg')) + for (var/mob/living/alive_guy as anything in GLOB.mob_living_list) + new /obj/effect/temp_visual/immortality_pulse(get_turf(alive_guy)) + if (!alive_guy.mind) + continue + to_chat(alive_guy, span_notice("You feel extremely healthy.")) + RegisterSignal(SSdcs, COMSIG_GLOB_MOB_DEATH, PROC_REF(something_died)) + +/// Called when something passes into the great beyond, make it not do that +/datum/grand_finale/immortality/proc/something_died(datum/source, mob/living/died, gibbed) + SIGNAL_HANDLER + if (died.stat != DEAD || HAS_TRAIT(died, TRAIT_PERMANENTLY_MORTAL) || died.flags_1 & HOLOGRAM_1) + return + var/body_type = died.type + + var/turf/died_turf = get_turf(died) + var/list/nearby_turfs = circle_view_turfs(died_turf, 2) + var/list/nearby_safe_turfs = list() + for (var/turf/check_turf as anything in nearby_turfs) + if (check_turf.is_blocked_turf(exclude_mobs = TRUE, source_atom = died)) + nearby_turfs -= check_turf + continue + if (islava(check_turf) || ischasm(check_turf)) + continue + nearby_safe_turfs += check_turf + if (length(nearby_safe_turfs)) // If you're in the middle of a 5x5 chasm, tough luck I guess + died_turf = pick(nearby_safe_turfs) + else if (length(nearby_turfs)) + died_turf = pick(nearby_turfs) + + var/saved_appearance = ishuman(died) ? new /datum/human_appearance_profile(died) : null + + var/datum/mind/dead_mind = HAS_TRAIT(died, TRAIT_SUICIDED) ? null : died.mind // There is a way out of the cycle + if (!isnull(dead_mind)) + to_chat(died, span_boldnotice("Your spirit surges! You will return to life in [DisplayTimeText(IMMORTAL_PRE_ACTIVATION_TIME + IMMORTAL_RESURRECT_TIME)].")) + animate(died, alpha = died.alpha, time = IMMORTAL_PRE_ACTIVATION_TIME / 2, flags = ANIMATION_PARALLEL) + animate(alpha = 0, time = IMMORTAL_PRE_ACTIVATION_TIME / 2, easing = SINE_EASING | EASE_IN) + addtimer(CALLBACK(src, PROC_REF(reverse_death), died, dead_mind, died_turf, body_type, saved_appearance), IMMORTAL_PRE_ACTIVATION_TIME, TIMER_DELETE_ME) + +/// Create a ghost ready for revival +/datum/grand_finale/immortality/proc/reverse_death(mob/living/died, datum/mind/dead_mind, turf/died_turf, body_type, datum/human_appearance_profile/human_appearance) + if (died.stat != DEAD) + return + var/ghost_type = ispath(body_type, /mob/living/carbon/human) ? /obj/effect/spectre_of_resurrection/human : /obj/effect/spectre_of_resurrection + var/obj/effect/spectre_of_resurrection/ghost = new ghost_type(died_turf) + var/mob/living/corpse = QDELETED(died) ? new body_type(ghost) : died + if (!isnull(human_appearance)) + corpse.real_name = human_appearance.name + corpse.alpha = initial(corpse.alpha) + corpse.add_traits(list(TRAIT_NO_TELEPORT, TRAIT_AI_PAUSED), MAGIC_TRAIT) + corpse.apply_status_effect(/datum/status_effect/grouped/stasis, MAGIC_TRAIT) + ghost.set_up_resurrection(corpse, dead_mind, human_appearance) + + +/// Store of data we use to recreate someone who was gibbed, like a simplified version of changeling profiles +/datum/human_appearance_profile + /// The name of the profile / the name of whoever this profile source. + var/name = "human" + /// The DNA datum associated with our profile from the profile source + var/datum/dna/dna + /// The age of the profile source. + var/age + /// The body type of the profile source. + var/physique + /// The quirks of the profile source. + var/list/quirks = list() + /// The hair and facial hair gradient styles of the profile source. + var/list/hair_gradient_style = list("None", "None") + /// The hair and facial hair gradient colours of the profile source. + var/list/hair_gradient_colours = list(null, null) + /// The TTS voice of the profile source + var/voice + /// The TTS filter of the profile filter + var/voice_filter = "" + +/datum/human_appearance_profile/New(mob/living/carbon/human/target) + copy_from(target) + +/// Copy the appearance data of the target +/datum/human_appearance_profile/proc/copy_from(mob/living/carbon/human/target) + target.dna.real_name = target.real_name + dna = new target.dna.type() + target.dna.copy_dna(dna) + name = target.real_name + age = target.age + physique = target.physique + + for(var/datum/quirk/target_quirk as anything in target.quirks) + LAZYADD(quirks, new target_quirk.type) + + hair_gradient_style = LAZYLISTDUPLICATE(target.grad_style) + hair_gradient_colours = LAZYLISTDUPLICATE(target.grad_color) + + voice = target.voice + voice_filter = target.voice_filter + +/// Make the targetted human look like this +/datum/human_appearance_profile/proc/apply_to(mob/living/carbon/human/target) + target.real_name = name + target.age = age + target.physique = physique + target.grad_style = LAZYLISTDUPLICATE(hair_gradient_style) + target.grad_color = LAZYLISTDUPLICATE(hair_gradient_colours) + target.voice = voice + target.voice_filter = voice_filter + + for(var/datum/quirk/target_quirk as anything in quirks) + target_quirk.add_to_holder(target) + + dna.transfer_identity(target, TRUE) + for(var/obj/item/bodypart/limb as anything in target.bodyparts) + limb.update_limb(is_creating = TRUE) + target.updateappearance(mutcolor_update = TRUE) + target.domutcheck() + target.regenerate_icons() + + +/// A ghostly image of a mob showing where and what is going to respawn +/obj/effect/spectre_of_resurrection + name = "spectre" + desc = "A frightening apparition, slowly growing more solid." + icon_state = "blank_white" + anchored = TRUE + layer = MOB_LAYER + plane = GAME_PLANE + alpha = 0 + color = COLOR_PALE_GREEN + light_range = 2 + light_color = COLOR_PALE_GREEN + /// Who are we reviving? + var/mob/living/corpse + /// Who if anyone is playing as them? + var/datum/mind/dead_mind + +/obj/effect/spectre_of_resurrection/Initialize(mapload) + . = ..() + animate(src, alpha = 150, time = 2 SECONDS) + +/// Prepare to revive someone +/obj/effect/spectre_of_resurrection/proc/set_up_resurrection(mob/living/corpse, datum/mind/dead_mind, datum/human_appearance_profile/human_appearance) + if (isnull(corpse)) + qdel(src) + return + + src.corpse = corpse + src.dead_mind = dead_mind + corpse.forceMove(src) + name = "spectre of [corpse]" + setup_icon(corpse) + DO_FLOATING_ANIM(src) + + RegisterSignal(corpse, COMSIG_LIVING_REVIVE, PROC_REF(on_corpse_revived)) + RegisterSignal(corpse, COMSIG_QDELETING, PROC_REF(on_corpse_deleted)) + RegisterSignal(dead_mind, COMSIG_QDELETING, PROC_REF(on_mind_lost)) + addtimer(CALLBACK(src, PROC_REF(revive)), IMMORTAL_RESURRECT_TIME, TIMER_DELETE_ME) + +/// Copy appearance from ressurecting mob +/obj/effect/spectre_of_resurrection/proc/setup_icon(mob/living/corpse) + icon = initial(corpse.icon) + icon_state = initial(corpse.icon_state) + +/obj/effect/spectre_of_resurrection/Destroy(force) + QDEL_NULL(corpse) + dead_mind = null + return ..() + +/obj/effect/spectre_of_resurrection/Exited(atom/movable/gone, direction) + . = ..() + if (gone != corpse) + return // Weird but ok + UnregisterSignal(corpse, list(COMSIG_LIVING_REVIVE, COMSIG_QDELETING)) + corpse = null + qdel(src) + +/// Bring our body back to life +/obj/effect/spectre_of_resurrection/proc/revive() + if (!isnull(dead_mind)) + if (dead_mind.current == corpse) + dead_mind.grab_ghost(force = TRUE) + else + dead_mind.transfer_to(corpse, force_key_move = TRUE) + corpse.revive(HEAL_ALL) // The signal is sent even if they weren't actually dead + +/// Remove our stored corpse back to the living world +/obj/effect/spectre_of_resurrection/proc/on_corpse_revived() + SIGNAL_HANDLER + if (isnull(corpse)) + return + visible_message(span_boldnotice("[corpse] suddenly shudders to life!")) + corpse.remove_traits(list(TRAIT_NO_TELEPORT, TRAIT_AI_PAUSED), MAGIC_TRAIT) + corpse.remove_status_effect(/datum/status_effect/grouped/stasis, MAGIC_TRAIT) + corpse.forceMove(loc) + +/// If the body is destroyed then we can't come back, F +/obj/effect/spectre_of_resurrection/proc/on_corpse_deleted() + SIGNAL_HANDLER + qdel(src) + +/// If the mind is deleted somehow we just don't transfer it on revival +/obj/effect/spectre_of_resurrection/proc/on_mind_lost() + SIGNAL_HANDLER + dead_mind = null + +/// A ressurection spectre with extra behaviour for humans +/obj/effect/spectre_of_resurrection/human + /// Stored data used to restore someone to a fascimile of what they were before + var/datum/human_appearance_profile/human_appearance + +/obj/effect/spectre_of_resurrection/human/set_up_resurrection(mob/living/corpse, datum/mind/dead_mind, datum/human_appearance_profile/human_appearance) + . = ..() + src.human_appearance = human_appearance + +// We just use a generic floating human appearance to save unecessary costly icon operations +/obj/effect/spectre_of_resurrection/human/setup_icon(mob/living/corpse) + return + +// Apply stored human details +/obj/effect/spectre_of_resurrection/human/on_corpse_revived() + if (isnull(corpse)) + return + human_appearance?.apply_to(corpse) + return ..() + + +/// Visual flair on the wizard when cast +/obj/effect/temp_visual/immortality_blast + name = "immortal wave" + duration = 2.5 SECONDS + icon = 'icons/effects/96x96.dmi' + icon_state = "boh_tear" + color = COLOR_PALE_GREEN + pixel_x = -32 + pixel_y = -32 + +/obj/effect/temp_visual/immortality_blast/Initialize(mapload) + . = ..() + transform *= 0 + animate(src, transform = matrix(), time = 1.5 SECONDS, easing = ELASTIC_EASING) + animate(transform = matrix() * 3, time = 1 SECONDS, alpha = 0, easing = SINE_EASING | EASE_OUT) + + +/// Visual flair on living creatures who have become immortal +/obj/effect/temp_visual/immortality_pulse + name = "immortal pulse" + duration = 1 SECONDS + icon = 'icons/effects/anomalies.dmi' + icon_state = "dimensional_overlay" + color = COLOR_PALE_GREEN + +/obj/effect/temp_visual/immortality_pulse/Initialize(mapload) + . = ..() + transform *= 0 + animate(src, transform = matrix() * 1.5, alpha = 0, time = 1 SECONDS, easing = SINE_EASING | EASE_OUT) + +#undef IMMORTAL_PRE_ACTIVATION_TIME +#undef IMMORTAL_RESURRECT_TIME diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/midas.dm b/code/modules/antagonists/wizard/grand_ritual/finales/midas.dm new file mode 100644 index 00000000000..b2e3329261f --- /dev/null +++ b/code/modules/antagonists/wizard/grand_ritual/finales/midas.dm @@ -0,0 +1,46 @@ +/// Completely transform the station +/datum/grand_finale/midas + name = "Transformation" + desc = "The ultimate use of your gathered power! Turn their precious station into something much MORE precious, materially speaking!" + icon = 'icons/obj/stack_objects.dmi' + icon_state = "sheet-gold_2" + glow_colour = "#dbdd4c48" + var/static/list/permitted_transforms = list( // Non-dangerous only + /datum/dimension_theme/gold, + /datum/dimension_theme/meat, + /datum/dimension_theme/pizza, + /datum/dimension_theme/natural, + ) + var/datum/dimension_theme/chosen_theme + +// I sure hope this doesn't have performance implications +/datum/grand_finale/midas/trigger(mob/living/carbon/human/invoker) + var/theme_path = pick(permitted_transforms) + chosen_theme = new theme_path() + var/turf/start_turf = get_turf(invoker) + var/greatest_dist = 0 + var/list/turfs_to_transform = list() + for (var/turf/transform_turf as anything in GLOB.station_turfs) + if (!chosen_theme.can_convert(transform_turf)) + continue + var/dist = get_dist(start_turf, transform_turf) + if (dist > greatest_dist) + greatest_dist = dist + if (!turfs_to_transform["[dist]"]) + turfs_to_transform["[dist]"] = list() + turfs_to_transform["[dist]"] += transform_turf + + if (chosen_theme.can_convert(start_turf)) + chosen_theme.apply_theme(start_turf) + + for (var/iterator in 1 to greatest_dist) + if(!turfs_to_transform["[iterator]"]) + continue + addtimer(CALLBACK(src, PROC_REF(transform_area), turfs_to_transform["[iterator]"]), (5 SECONDS) * iterator) + +/datum/grand_finale/midas/proc/transform_area(list/turfs) + for (var/turf/transform_turf as anything in turfs) + if (!chosen_theme.can_convert(transform_turf)) + continue + chosen_theme.apply_theme(transform_turf) + CHECK_TICK diff --git a/code/modules/antagonists/wizard/grand_ritual/grand_ritual_finale.dm b/code/modules/antagonists/wizard/grand_ritual/grand_ritual_finale.dm deleted file mode 100644 index 9a59b1f1a79..00000000000 --- a/code/modules/antagonists/wizard/grand_ritual/grand_ritual_finale.dm +++ /dev/null @@ -1,456 +0,0 @@ -#define DOOM_SINGULARITY "singularity" -#define DOOM_TESLA "tesla" -#define DOOM_METEORS "meteors" - -/** - * A big final event to run when you complete seven rituals - */ -/datum/grand_finale - /// Friendly name for selection menu - var/name - /// Tooltip description for selection menu - var/desc - /// An icon to display to represent the choice - var/icon/icon - /// Icon state to use to represent the choice - var/icon_state - /// Prevent especially dangerous options from being chosen until we're fine with the round ending - var/minimum_time = 0 - /// Override the rune invocation time - var/ritual_invoke_time = 30 SECONDS - /// Provide an extremely loud radio message when this one starts - var/dire_warning = FALSE - /// Overrides the default colour you glow while channeling the rune, optional - var/glow_colour - -/** - * Returns an entry for a radial menu for this choice. - * Returns null if entry is abstract or invalid for current circumstances. - */ -/datum/grand_finale/proc/get_radial_choice() - if (!name || !desc || !icon || !icon_state) - return - var/time_remaining_desc = "" - if (minimum_time >= world.time - SSticker.round_start_time) - time_remaining_desc = "This ritual will be available to begin invoking in [DisplayTimeText(minimum_time - world.time - SSticker.round_start_time)]" - var/datum/radial_menu_choice/choice = new() - choice.name = name - choice.image = image(icon = icon, icon_state = icon_state) - choice.info = desc + time_remaining_desc - return choice - -/** - * Actually do the thing. - * Arguments - * * invoker - The wizard casting this. - */ -/datum/grand_finale/proc/trigger(mob/living/invoker) - // Do something cool. - -/// Tries to equip something into an inventory slot, then hands, then the floor. -/datum/grand_finale/proc/equip_to_slot_then_hands(mob/living/carbon/human/invoker, slot, obj/item/item) - if(!item) - return - if(!invoker.equip_to_slot_if_possible(item, slot, disable_warning = TRUE)) - invoker.put_in_hands(item) - -/// They are not going to take this lying down. -/datum/grand_finale/proc/create_vendetta(datum/mind/aggrieved_crewmate, datum/mind/wizard) - aggrieved_crewmate.add_antag_datum(/datum/antagonist/wizard_prank_vendetta) - var/datum/antagonist/wizard_prank_vendetta/antag_datum = aggrieved_crewmate.has_antag_datum(/datum/antagonist/wizard_prank_vendetta) - var/datum/objective/assassinate/wizard_murder = new - wizard_murder.owner = aggrieved_crewmate - wizard_murder.target = wizard - wizard_murder.explanation_text = "Kill [wizard.current.name], the one who did this." - antag_datum.objectives += wizard_murder - - to_chat(aggrieved_crewmate.current, span_warning("No! This isn't right!")) - aggrieved_crewmate.announce_objectives() - -/** - * Antag datum to give to people who want to kill the wizard. - * This doesn't preclude other people choosing to want to kill the wizard, just these people are rewarded for it. - */ -/datum/antagonist/wizard_prank_vendetta - name = "\improper Wizard Prank Victim" - roundend_category = "wizard prank victims" - show_in_antagpanel = FALSE - antagpanel_category = "Other" - show_name_in_check_antagonists = TRUE - count_against_dynamic_roll_chance = FALSE - silent = TRUE - -/// Become the official Captain of the station -/datum/grand_finale/usurp - name = "Usurpation" - desc = "The ultimate use of your gathered power! Rewrite time such that you have been Captain of this station the whole time." - icon = 'icons/obj/card.dmi' - icon_state = "card_gold" - -/datum/grand_finale/usurp/trigger(mob/living/carbon/human/invoker) - message_admins("[key_name(invoker)] has replaced the Captain") - var/list/former_captains = list() - var/list/other_crew = list() - SEND_SOUND(world, sound('sound/magic/timeparadox2.ogg')) - - for (var/mob/living/carbon/human/crewmate as anything in GLOB.human_list) - if (!crewmate.mind) - continue - crewmate.Unconscious(3 SECONDS) // Everyone falls unconscious but not everyone gets told about a new captain - if (crewmate == invoker || IS_HUMAN_INVADER(crewmate)) - continue - to_chat(crewmate, span_notice("The world spins and dissolves. Your past flashes before your eyes, backwards.\n\ - Life strolls back into the ocean and shrinks into nothingness, planets explode into storms of solar dust, \ - the stars rush back to greet each other at the beginning of things and then... you snap back to the present. \n\ - Everything is just as it was and always has been. \n\n\ - A stray thought sticks in the forefront of your mind. \n\ - [span_hypnophrase("I'm so glad that [invoker.real_name] is our legally appointed Captain!")] \n\ - Is... that right?")) - if (is_captain_job(crewmate.mind.assigned_role)) - former_captains += crewmate - demote_to_assistant(crewmate) - continue - if (crewmate.stat != DEAD) - other_crew += crewmate - - dress_candidate(invoker) - GLOB.manifest.modify(invoker.real_name, JOB_CAPTAIN, JOB_CAPTAIN) - minor_announce("Captain [invoker.real_name] on deck!") - - // Enlist some crew to try and restore the natural order - for (var/mob/living/carbon/human/former_captain as anything in former_captains) - create_vendetta(former_captain.mind, invoker.mind) - for (var/mob/living/carbon/human/random_crewmate as anything in other_crew) - if (prob(10)) - create_vendetta(random_crewmate.mind, invoker.mind) - -/** - * Anyone who thought they were Captain is in for a nasty surprise, and won't be very happy about it - */ -/datum/grand_finale/usurp/proc/demote_to_assistant(mob/living/carbon/human/former_captain) - var/obj/effect/particle_effect/fluid/smoke/exit_poof = new(get_turf(former_captain)) - exit_poof.lifetime = 2 SECONDS - - former_captain.unequip_everything() - if(isplasmaman(former_captain)) - former_captain.equipOutfit(/datum/outfit/plasmaman) - former_captain.internal = former_captain.get_item_for_held_index(2) - else - former_captain.equipOutfit(/datum/outfit/job/assistant) - - GLOB.manifest.modify(former_captain.real_name, JOB_ASSISTANT, JOB_ASSISTANT) - var/list/valid_turfs = list() - // Used to be into prison but that felt a bit too mean - for (var/turf/exile_turf as anything in get_area_turfs(/area/station/maintenance, subtypes = TRUE)) - if (isspaceturf(exile_turf) || exile_turf.is_blocked_turf()) - continue - valid_turfs += exile_turf - do_teleport(former_captain, pick(valid_turfs), no_effects = TRUE) - var/obj/effect/particle_effect/fluid/smoke/enter_poof = new(get_turf(former_captain)) - enter_poof.lifetime = 2 SECONDS - -/** - * Does some item juggling to try to dress you as both a Wizard and Captain without deleting any items you have bought. - * ID, headset, and uniform are forcibly replaced. Other slots are only filled if unoccupied. - * We could forcibly replace shoes and gloves too but people might miss their insuls or... meown shoes? - */ -/datum/grand_finale/usurp/proc/dress_candidate(mob/living/carbon/human/invoker) - // Won't be needing these - var/obj/id = invoker.get_item_by_slot(ITEM_SLOT_ID) - QDEL_NULL(id) - var/obj/headset = invoker.get_item_by_slot(ITEM_SLOT_EARS) - QDEL_NULL(headset) - // We're about to take off your pants so those are going to fall out - var/obj/item/pocket_L = invoker.get_item_by_slot(ITEM_SLOT_LPOCKET) - var/obj/item/pocket_R = invoker.get_item_by_slot(ITEM_SLOT_RPOCKET) - // In case we try to put a PDA there - var/obj/item/belt = invoker.get_item_by_slot(ITEM_SLOT_BELT) - belt?.moveToNullspace() - - var/obj/pants = invoker.get_item_by_slot(ITEM_SLOT_ICLOTHING) - QDEL_NULL(pants) - invoker.equipOutfit(/datum/outfit/job/wizard_captain) - // And put everything back! - equip_to_slot_then_hands(invoker, ITEM_SLOT_BELT, belt) - equip_to_slot_then_hands(invoker, ITEM_SLOT_LPOCKET, pocket_L) - equip_to_slot_then_hands(invoker, ITEM_SLOT_RPOCKET, pocket_R) - -/// An outfit which replaces parts of a wizard's clothes with captain's clothes but keeps the robes -/datum/outfit/job/wizard_captain - name = "Captain (Wizard Transformation)" - jobtype = /datum/job/captain - id = /obj/item/card/id/advanced/gold - id_trim = /datum/id_trim/job/captain - uniform = /obj/item/clothing/under/rank/captain/parade - belt = /obj/item/modular_computer/pda/heads/captain - ears = /obj/item/radio/headset/heads/captain/alt - glasses = /obj/item/clothing/glasses/sunglasses - gloves = /obj/item/clothing/gloves/captain - shoes = /obj/item/clothing/shoes/laceup - accessory = /obj/item/clothing/accessory/medal/gold/captain - backpack_contents = list( - /obj/item/melee/baton/telescopic = 1, - /obj/item/station_charter = 1, - ) - box = null - -/// Dress the crew as magical clowns -/datum/grand_finale/clown - name = "Jubilation" - desc = "The ultimate use of your gathered power! Rewrite time so that everyone went to clown college! Now they'll prank each other for you!" - icon = 'icons/obj/clothing/masks.dmi' - icon_state = "clown" - glow_colour = "#ffff0048" - -/datum/grand_finale/clown/trigger(mob/living/carbon/human/invoker) - for(var/mob/living/carbon/human/victim as anything in GLOB.human_list) - victim.Unconscious(3 SECONDS) - if (!victim.mind || IS_HUMAN_INVADER(victim) || victim == invoker) - continue - if (HAS_TRAIT(victim, TRAIT_CLOWN_ENJOYER)) - victim.add_mood_event("clown_world", /datum/mood_event/clown_world) - to_chat(victim, span_notice("The world spins and dissolves. Your past flashes before your eyes, backwards.\n\ - Life strolls back into the ocean and shrinks into nothingness, planets explode into storms of solar dust, \ - the stars rush back to greet each other at the beginning of things and then... you snap back to the present. \n\ - Everything is just as it was and always has been. \n\n\ - A stray thought sticks in the forefront of your mind. \n\ - [span_hypnophrase("I'm so glad that I work at Clown Research Station [station_name()]!")] \n\ - Is... that right?")) - if (is_clown_job(victim.mind.assigned_role)) - var/datum/action/cooldown/spell/conjure_item/clown_pockets/new_spell = new(victim) - new_spell.Grant(victim) - continue - if (!ismonkey(victim)) // Monkeys cannot yet wear clothes - dress_as_magic_clown(victim) - if (prob(15)) - create_vendetta(victim.mind, invoker.mind) - -/** - * Clown enjoyers who are effected by this become ecstatic, they have achieved their life's dream. - * This moodlet is equivalent to the one for simply being a traitor. - */ -/datum/mood_event/clown_world - mood_change = 4 - -/datum/mood_event/clown_world/add_effects(param) - description = "I LOVE working at Clown Research Station [station_name()]!!" - -/// Dress the passed mob as a magical clown, self-explanatory -/datum/grand_finale/clown/proc/dress_as_magic_clown(mob/living/carbon/human/victim) - var/obj/effect/particle_effect/fluid/smoke/poof = new(get_turf(victim)) - poof.lifetime = 2 SECONDS - - var/obj/item/tank/internal = victim.internal - // We're about to take off your pants so those are going to fall out - var/obj/item/pocket_L = victim.get_item_by_slot(ITEM_SLOT_LPOCKET) - var/obj/item/pocket_R = victim.get_item_by_slot(ITEM_SLOT_RPOCKET) - var/obj/item/id = victim.get_item_by_slot(ITEM_SLOT_ID) - var/obj/item/belt = victim.get_item_by_slot(ITEM_SLOT_BELT) - - var/obj/pants = victim.get_item_by_slot(ITEM_SLOT_ICLOTHING) - var/obj/mask = victim.get_item_by_slot(ITEM_SLOT_MASK) - QDEL_NULL(pants) - QDEL_NULL(mask) - if(isplasmaman(victim)) - victim.equip_to_slot_if_possible(new /obj/item/clothing/under/plasmaman/clown/magic(), ITEM_SLOT_ICLOTHING, disable_warning = TRUE) - victim.equip_to_slot_if_possible(new /obj/item/clothing/mask/gas/clown_hat/plasmaman(), ITEM_SLOT_MASK, disable_warning = TRUE) - else - victim.equip_to_slot_if_possible(new /obj/item/clothing/under/rank/civilian/clown/magic(), ITEM_SLOT_ICLOTHING, disable_warning = TRUE) - victim.equip_to_slot_if_possible(new /obj/item/clothing/mask/gas/clown_hat(), ITEM_SLOT_MASK, disable_warning = TRUE) - - var/obj/item/clothing/mask/gas/clown_hat/clown_mask = victim.get_item_by_slot(ITEM_SLOT_MASK) - if (clown_mask) - var/list/options = GLOB.clown_mask_options - clown_mask.icon_state = options[pick(clown_mask.clownmask_designs)] - victim.update_worn_mask() - clown_mask.update_item_action_buttons() - - equip_to_slot_then_hands(victim, ITEM_SLOT_LPOCKET, pocket_L) - equip_to_slot_then_hands(victim, ITEM_SLOT_RPOCKET, pocket_R) - equip_to_slot_then_hands(victim, ITEM_SLOT_ID, id) - equip_to_slot_then_hands(victim, ITEM_SLOT_BELT, belt) - victim.internal = internal - -/// Give everyone magic items -/datum/grand_finale/magic - name = "Evolution" - desc = "The ultimate use of your gathered power! Give the crew their own magic, they'll surely realise that right and wrong have no meaning when you hold ultimate power!" - icon = 'icons/obj/scrolls.dmi' - icon_state = "scroll" - -/datum/grand_finale/magic/trigger(mob/living/carbon/human/invoker) - message_admins("[key_name(invoker)] summoned magic") - summon_magic(survivor_probability = 20) // Wow, this one was easy! - -/// Open all of the doors -/datum/grand_finale/all_access - name = "Connection" - desc = "The ultimate use of your gathered power! Unlock every single door that they have! Nobody will be able to keep you out now, or anyone else for that matter!" - icon = 'icons/mob/actions/actions_spells.dmi' - icon_state = "knock" - -/datum/grand_finale/all_access/trigger(mob/living/carbon/human/invoker) - message_admins("[key_name(invoker)] removed all door access requirements") - for(var/obj/machinery/door/target_door as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door)) - if(is_station_level(target_door.z)) - target_door.unlock() - target_door.req_access = list() - target_door.req_one_access = list() - INVOKE_ASYNC(target_door, TYPE_PROC_REF(/obj/machinery/door/airlock, open)) - CHECK_TICK - priority_announce("AULIE OXIN FIERA!!", null, 'sound/magic/knock.ogg', sender_override = "[invoker.real_name]") - -/// Completely transform the station -/datum/grand_finale/midas - name = "Transformation" - desc = "The ultimate use of your gathered power! Turn their precious station into something much MORE precious, materially speaking!" - icon = 'icons/obj/stack_objects.dmi' - icon_state = "sheet-gold_2" - glow_colour = "#dbdd4c48" - var/static/list/permitted_transforms = list( // Non-dangerous only - /datum/dimension_theme/gold, - /datum/dimension_theme/meat, - /datum/dimension_theme/pizza, - /datum/dimension_theme/natural, - ) - var/datum/dimension_theme/chosen_theme - -// I sure hope this doesn't have performance implications -/datum/grand_finale/midas/trigger(mob/living/carbon/human/invoker) - var/theme_path = pick(permitted_transforms) - chosen_theme = new theme_path() - var/turf/start_turf = get_turf(invoker) - var/greatest_dist = 0 - var/list/turfs_to_transform = list() - for (var/turf/transform_turf as anything in GLOB.station_turfs) - if (!chosen_theme.can_convert(transform_turf)) - continue - var/dist = get_dist(start_turf, transform_turf) - if (dist > greatest_dist) - greatest_dist = dist - if (!turfs_to_transform["[dist]"]) - turfs_to_transform["[dist]"] = list() - turfs_to_transform["[dist]"] += transform_turf - - if (chosen_theme.can_convert(start_turf)) - chosen_theme.apply_theme(start_turf) - - for (var/iterator in 1 to greatest_dist) - if(!turfs_to_transform["[iterator]"]) - continue - addtimer(CALLBACK(src, PROC_REF(transform_area), turfs_to_transform["[iterator]"]), (5 SECONDS) * iterator) - -/datum/grand_finale/midas/proc/transform_area(list/turfs) - for (var/turf/transform_turf as anything in turfs) - if (!chosen_theme.can_convert(transform_turf)) - continue - chosen_theme.apply_theme(transform_turf) - CHECK_TICK - -/// Kill yourself and probably a bunch of other people -/datum/grand_finale/armageddon - name = "Annihilation" - desc = "This crew have offended you beyond the realm of pranks. Make the ultimate sacrifice to teach them a lesson your elders can really respect. \ - YOU WILL NOT SURVIVE THIS." - icon = 'icons/hud/screen_alert.dmi' - icon_state = "wounded" - minimum_time = 90 MINUTES // This will probably immediately end the round if it gets finished. - ritual_invoke_time = 60 SECONDS // Really give the crew some time to interfere with this one. - dire_warning = TRUE - glow_colour = "#be000048" - /// Things to yell before you die - var/static/list/possible_last_words = list( - "Flames and ruin!", - "Dooooooooom!!", - "HAHAHAHAHAHA!! AHAHAHAHAHAHAHAHAA!!", - "Hee hee hee!! Hoo hoo hoo!! Ha ha haaa!!", - "Ohohohohohoho!!", - "Cower in fear, puny mortals!", - "Tremble before my glory!", - "Pick a god and pray!", - "It's no use!", - "If the gods wanted you to live, they would not have created me!", - "God stays in heaven out of fear of what I have created!", - "Ruination is come!", - "All of creation, bend to my will!", - ) - -/datum/grand_finale/armageddon/trigger(mob/living/carbon/human/invoker) - priority_announce(pick(possible_last_words), null, 'sound/magic/voidblink.ogg', sender_override = "[invoker.real_name]") - var/turf/current_location = get_turf(invoker) - invoker.gib() - - var/static/list/doom_options = list() - if (!length(doom_options)) - doom_options = list(DOOM_SINGULARITY, DOOM_TESLA) - if (!SSmapping.config.planetary) - doom_options += DOOM_METEORS - - switch(pick(doom_options)) - if (DOOM_SINGULARITY) - var/obj/singularity/singulo = new(current_location) - singulo.energy = 300 - if (DOOM_TESLA) - var/obj/energy_ball/tesla = new (current_location) - tesla.energy = 200 - if (DOOM_METEORS) - var/datum/dynamic_ruleset/roundstart/meteor/meteors = new() - meteors.meteordelay = 0 - var/datum/game_mode/dynamic/mode = SSticker.mode - mode.execute_roundstart_rule(meteors) // Meteors will continue until morale is crushed. - priority_announce("Meteors have been detected on collision course with the station.", "Meteor Alert", ANNOUNCER_METEORS) - -/** - * Gives the wizard a defensive/mood buff and a Wabbajack, a juiced up chaos staff that will surely break something. - * Everyone but the wizard goes crazy, suffers major brain damage, and is given a vendetta against the wizard. - * Already insane people are instead cured of their madness, ignoring any other effects as the station around them loses its marbles. - */ -/datum/grand_finale/cheese - // we don't set name, desc and others, thus we won't appear in the radial choice of a normal finale rune - dire_warning = TRUE - minimum_time = 45 MINUTES //i'd imagine speedrunning this would be crummy, but the wizard's average lifespan is barely reaching this point - -/datum/grand_finale/cheese/trigger(mob/living/invoker) - message_admins("[key_name(invoker)] has summoned forth The Wabbajack and cursed the crew with madness!") - priority_announce("Danger: Extremely potent reality altering object has been summoned on station. Immediate evacuation advised. Brace for impact.", "Central Command Higher Dimensional Affairs", 'sound/effects/glassbr1.ogg') - - for (var/mob/living/carbon/human/crewmate as anything in GLOB.human_list) - if (isnull(crewmate.mind)) - continue - if (crewmate == invoker) //everyone but the wizard is royally fucked, no matter who they are - continue - if (crewmate.has_trauma_type(/datum/brain_trauma/mild/hallucinations)) //for an already insane person, this is retribution - to_chat(crewmate, span_boldwarning("Your surroundings suddenly fill with a cacophony of manic laughter and psychobabble...")) - to_chat(crewmate, span_nicegreen("...but as the moment passes, you realise that whatever eldritch power behind the event happened to affect you \ - has resonated within the ruins of your already shattered mind, creating a singularity of mental instability! \ - As it collapses unto itself, you feel... at peace, finally.")) - if(crewmate.has_quirk(/datum/quirk/insanity)) - crewmate.remove_quirk(/datum/quirk/insanity) - else - crewmate.cure_trauma_type(/datum/brain_trauma/mild/hallucinations, TRAUMA_RESILIENCE_ABSOLUTE) - else - //everyone else gets to relish in madness - //yes killing their mood will also trigger mood hallucinations - create_vendetta(crewmate.mind, invoker.mind) - to_chat(crewmate, span_boldwarning("Your surroundings suddenly fill with a cacophony of manic laughter and psychobabble. \n\ - You feel your inner psyche shatter into a myriad pieces of jagged glass of colors unknown to the universe, \ - infinitely reflecting a blinding, maddening light coming from the innermost sanctums of your destroyed mind. \n\ - After a brief pause which felt like a millenia, one phrase rebounds ceaselessly in your head, imbued with the false hope of absolution... \n\ - [invoker] must die.")) - var/datum/brain_trauma/mild/hallucinations/added_trauma = new() - added_trauma.resilience = TRAUMA_RESILIENCE_ABSOLUTE - crewmate.adjustOrganLoss(ORGAN_SLOT_BRAIN, BRAIN_DAMAGE_DEATH - 25, BRAIN_DAMAGE_DEATH - 25) //you'd better hope chap didn't pick a hypertool - crewmate.gain_trauma(added_trauma) - crewmate.add_mood_event("wizard_ritual_finale", /datum/mood_event/madness_despair) - - //drip our wizard out - invoker.apply_status_effect(/datum/status_effect/blessing_of_insanity) - invoker.add_mood_event("wizard_ritual_finale", /datum/mood_event/madness_elation) - var/obj/item/gun/magic/staff/chaos/true_wabbajack/the_wabbajack = new - invoker.put_in_active_hand(the_wabbajack) - to_chat(invoker, span_mind_control("Your every single instinct and rational thought is screaming at you as [the_wabbajack] appears in your firm grip...")) - -#undef DOOM_SINGULARITY -#undef DOOM_TESLA -#undef DOOM_METEORS - diff --git a/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm b/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm index a11f439ec31..e629c14e0fe 100644 --- a/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm +++ b/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm @@ -112,7 +112,7 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) my_area = connected_sensor ? get_area(connected_sensor) : get_area(src) alarm_manager = new(src) - select_mode(src, /datum/air_alarm_mode/filtering) + select_mode(src, /datum/air_alarm_mode/filtering, should_apply = FALSE) AddElement(/datum/element/connect_loc, atmos_connections) AddComponent(/datum/component/usb_port, list( @@ -587,14 +587,15 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) selected_mode.replace(my_area, pressure) -/obj/machinery/airalarm/proc/select_mode(atom/source, datum/air_alarm_mode/mode_path) +/obj/machinery/airalarm/proc/select_mode(atom/source, datum/air_alarm_mode/mode_path, should_apply = TRUE) var/datum/air_alarm_mode/new_mode = GLOB.air_alarm_modes[mode_path] if(!new_mode) return if(new_mode.emag && !(obj_flags & EMAGGED)) return selected_mode = new_mode - selected_mode.apply(my_area) + if(should_apply) + selected_mode.apply(my_area) SEND_SIGNAL(src, COMSIG_AIRALARM_UPDATE_MODE, source) MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 27) diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm index 5062ec7731f..c6e1d6183ef 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm @@ -480,8 +480,8 @@ if(critical_threshold_proximity > 650 && prob(20)) zap_number += 1 - var/cutoff = 1500 - cutoff = clamp(3000 - (power_level * (internal_fusion.total_moles() * 0.45)), 450, 3000) + var/cutoff = 1.2e6 + cutoff = clamp(2.4e6 - (power_level * (internal_fusion.total_moles() * 360)), 3.6e5, 2.4e6) var/zaps_aspect = DEFAULT_ZAP_ICON_STATE var/flags = ZAP_SUPERMATTER_FLAGS @@ -495,7 +495,7 @@ playsound(loc, 'sound/weapons/emitter2.ogg', 100, TRUE, extrarange = 10) for(var/i in 1 to zap_number) - supermatter_zap(src, 5, power_level * 300, flags, zap_cutoff = cutoff, power_level = src.power_level * 1000, zap_icon = zaps_aspect) + supermatter_zap(src, 5, power_level * 2.4e5, flags, zap_cutoff = cutoff, power_level = src.power_level * 1000, zap_icon = zaps_aspect) /obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_gravity_pulse(seconds_per_tick) if(SPT_PROB(100 - critical_threshold_proximity / 15, seconds_per_tick)) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 50b8e72c6a8..a12d53cde73 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -24,7 +24,7 @@ /// The current occupant being presented var/mob/living/occupant -/atom/movable/visual/cryo_occupant/Initialize(mapload, obj/machinery/atmospherics/components/unary/cryo_cell/parent) +/atom/movable/visual/cryo_occupant/Initialize(mapload, obj/machinery/cryo_cell/parent) . = ..() // Alpha masking // It will follow this as the animation goes, but that's no problem as the "mask" icon state @@ -65,7 +65,7 @@ animate(src) /// Cryo cell -/obj/machinery/atmospherics/components/unary/cryo_cell +/obj/machinery/cryo_cell name = "cryo cell" icon = 'icons/obj/medical/cryogenics.dmi' icon_state = "pod-off" @@ -75,15 +75,13 @@ layer = MOB_LAYER - 0.2 //SKYRAT EDIT - Fixing the opacity of cryo cells - ORIGINAL: layer = MOB_LAYER state_open = FALSE circuit = /obj/item/circuitboard/machine/cryo_tube - pipe_flags = PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY occupant_typecache = list(/mob/living/carbon, /mob/living/simple_animal) processing_flags = NONE use_power = IDLE_POWER_USE idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.75 active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 1.5 - - showpipe = FALSE + flags_1 = PREVENT_CLICK_UNDER_1 var/autoeject = TRUE var/volume = 100 @@ -101,7 +99,6 @@ var/obj/item/radio/radio var/radio_key = /obj/item/encryptionkey/headset_med var/radio_channel = RADIO_CHANNEL_MEDICAL - vent_movement = NONE /// Visual content - Occupant var/atom/movable/visual/cryo_occupant/occupant_vis @@ -114,15 +111,19 @@ fair_market_price = 10 payment_department = ACCOUNT_MED + /// Reference to the datum connector we're using to interface with the pipe network + var/datum/gas_machine_connector/internal_connector + /// Check if the machine has been turned on + var/on = FALSE + /datum/armor/unary_cryo_cell energy = 100 fire = 30 acid = 30 -/obj/machinery/atmospherics/components/unary/cryo_cell/Initialize(mapload) +/obj/machinery/cryo_cell/Initialize(mapload) . = ..() - initialize_directions = dir if(is_operational) begin_processing() @@ -134,24 +135,23 @@ occupant_vis = new(null, src) vis_contents += occupant_vis - if(airs[1]) - airs[1].volume = CELL_VOLUME * 0.5 register_context() + internal_connector = new(loc, src, dir, CELL_VOLUME * 0.5) -/obj/machinery/atmospherics/components/unary/cryo_cell/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) +/obj/machinery/cryo_cell/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) . = ..() if(same_z_layer) return SET_PLANE(occupant_vis, PLANE_TO_TRUE(occupant_vis.plane), new_turf) -/obj/machinery/atmospherics/components/unary/cryo_cell/set_occupant(atom/movable/new_occupant) +/obj/machinery/cryo_cell/set_occupant(atom/movable/new_occupant) . = ..() update_appearance() -/obj/machinery/atmospherics/components/unary/cryo_cell/on_construction(mob/user) +/obj/machinery/cryo_cell/on_construction(mob/user) ..(user, dir, dir) -/obj/machinery/atmospherics/components/unary/cryo_cell/RefreshParts() +/obj/machinery/cryo_cell/RefreshParts() . = ..() var/C for(var/datum/stock_part/matter_bin/M in component_parts) @@ -163,12 +163,12 @@ heat_capacity = initial(heat_capacity) / C conduction_coefficient = initial(conduction_coefficient) * C -/obj/machinery/atmospherics/components/unary/cryo_cell/examine(mob/user) //this is leaving out everything but efficiency since they follow the same idea of "better beaker, better results" +/obj/machinery/cryo_cell/examine(mob/user) //this is leaving out everything but efficiency since they follow the same idea of "better beaker, better results" . = ..() if(in_range(user, src) || isobserver(user)) . += span_notice("The status display reads: Efficiency at [efficiency*100]%.") -/obj/machinery/atmospherics/components/unary/cryo_cell/add_context(atom/source, list/context, obj/item/held_item, mob/user) +/obj/machinery/cryo_cell/add_context(atom/source, list/context, obj/item/held_item, mob/user) . = ..() context[SCREENTIP_CONTEXT_CTRL_LMB] = "Turn [on ? "off" : "on"]" context[SCREENTIP_CONTEXT_ALT_LMB] = "[state_open ? "Close" : "Open"] door" @@ -182,22 +182,18 @@ return CONTEXTUAL_SCREENTIP_SET -/obj/machinery/atmospherics/components/unary/cryo_cell/Destroy() +/obj/machinery/cryo_cell/Destroy() vis_contents.Cut() QDEL_NULL(occupant_vis) QDEL_NULL(radio) QDEL_NULL(beaker) - ///Take the turf the cryotube is on - var/turf/T = get_turf(src) - if(T) - ///Take the air composition inside the cryotube - var/datum/gas_mixture/air1 = airs[1] - T.assume_air(air1) + + QDEL_NULL(internal_connector) return ..() -/obj/machinery/atmospherics/components/unary/cryo_cell/contents_explosion(severity, target) +/obj/machinery/cryo_cell/contents_explosion(severity, target) . = ..() if(!beaker) return @@ -210,12 +206,12 @@ if(EXPLODE_LIGHT) SSexplosions.low_mov_atom += beaker -/obj/machinery/atmospherics/components/unary/cryo_cell/Exited(atom/movable/gone, direction) +/obj/machinery/cryo_cell/Exited(atom/movable/gone, direction) . = ..() if(gone == beaker) beaker = null -/obj/machinery/atmospherics/components/unary/cryo_cell/on_deconstruction() +/obj/machinery/cryo_cell/on_deconstruction() if(occupant) occupant.vis_flags &= ~VIS_INHERIT_PLANE REMOVE_TRAIT(occupant, TRAIT_IMMOBILIZED, CRYO_TRAIT) @@ -225,15 +221,15 @@ beaker.forceMove(drop_location()) beaker = null -/obj/machinery/atmospherics/components/unary/cryo_cell/update_icon_state() +/obj/machinery/cryo_cell/update_icon_state() icon_state = (state_open) ? "pod-open" : ((on && is_operational) ? "pod-on" : "pod-off") return ..() -/obj/machinery/atmospherics/components/unary/cryo_cell/update_icon() +/obj/machinery/cryo_cell/update_icon() . = ..() SET_PLANE_IMPLICIT(src, initial(plane)) -/obj/machinery/atmospherics/components/unary/cryo_cell/update_overlays() +/obj/machinery/cryo_cell/update_overlays() . = ..() if(panel_open) . += "pod-panel" @@ -244,11 +240,11 @@ else . += mutable_appearance('icons/obj/medical/cryogenics.dmi', "cover-off", ABOVE_ALL_MOB_LAYER, src, plane = ABOVE_GAME_PLANE) -/obj/machinery/atmospherics/components/unary/cryo_cell/nap_violation(mob/violator) +/obj/machinery/cryo_cell/nap_violation(mob/violator) open_machine() -/obj/machinery/atmospherics/components/unary/cryo_cell/set_on(active) +/obj/machinery/cryo_cell/proc/set_on(active) if(on == active) return SEND_SIGNAL(src, COMSIG_CRYO_SET_ON, active) @@ -260,7 +256,7 @@ update_use_power(IDLE_POWER_USE) update_appearance() -/obj/machinery/atmospherics/components/unary/cryo_cell/on_set_is_operational(old_value) +/obj/machinery/cryo_cell/on_set_is_operational(old_value) if(old_value) //Turned off set_on(FALSE) end_processing() @@ -268,7 +264,7 @@ begin_processing() -/obj/machinery/atmospherics/components/unary/cryo_cell/process(seconds_per_tick) +/obj/machinery/cryo_cell/process(seconds_per_tick) ..() if(!occupant) return @@ -322,7 +318,7 @@ radio.talk_into(src, msg, radio_channel) return - var/datum/gas_mixture/air1 = airs[1] + var/datum/gas_mixture/air1 = internal_connector.gas_connector.airs[1] if(air1.total_moles() > CRYO_MIN_GAS_MOLES) if(beaker) @@ -330,15 +326,15 @@ consume_gas = TRUE return TRUE -/obj/machinery/atmospherics/components/unary/cryo_cell/process_atmos() +/obj/machinery/cryo_cell/process_atmos() ..() if(!on) return - var/datum/gas_mixture/air1 = airs[1] + var/datum/gas_mixture/air1 = internal_connector.gas_connector.airs[1] - if(!nodes[1] || !airs[1] || !air1.gases.len || air1.total_moles() < CRYO_MIN_GAS_MOLES) // Turn off if the machine won't work. + if(!internal_connector.gas_connector.nodes[1] || !internal_connector.gas_connector.airs[1] || !air1.gases.len || air1.total_moles() < CRYO_MIN_GAS_MOLES) // Turn off if the machine won't work. var/msg = "Insufficient cryogenic gas, shutting down." radio.talk_into(src, msg, radio_channel) set_on(FALSE) @@ -372,25 +368,25 @@ if(air1.temperature > 2000) take_damage(clamp((air1.temperature)/200, 10, 20), BURN) - update_parents() + internal_connector.gas_connector.update_parents() -/obj/machinery/atmospherics/components/unary/cryo_cell/handle_internal_lifeform(mob/lifeform_inside_me, breath_request) +/obj/machinery/cryo_cell/handle_internal_lifeform(mob/lifeform_inside_me, breath_request) if(breath_request <= 0) return null - var/datum/gas_mixture/air1 = airs[1] + var/datum/gas_mixture/air1 = internal_connector.gas_connector.airs[1] var/breath_percentage = breath_request / air1.volume return air1.remove(air1.total_moles() * breath_percentage) -/obj/machinery/atmospherics/components/unary/cryo_cell/assume_air(datum/gas_mixture/giver) - airs[1].merge(giver) +/obj/machinery/cryo_cell/assume_air(datum/gas_mixture/giver) + internal_connector.gas_connector.airs[1].merge(giver) -/obj/machinery/atmospherics/components/unary/cryo_cell/relaymove(mob/living/user, direction) +/obj/machinery/cryo_cell/relaymove(mob/living/user, direction) if(message_cooldown <= world.time) message_cooldown = world.time + 50 to_chat(user, span_warning("[src]'s door won't budge!")) -/obj/machinery/atmospherics/components/unary/cryo_cell/open_machine(drop = FALSE, density_to_set = FALSE) +/obj/machinery/cryo_cell/open_machine(drop = FALSE, density_to_set = FALSE) if(!state_open && !panel_open) set_on(FALSE) for(var/mob/M in contents) //only drop mobs @@ -399,7 +395,7 @@ flick("pod-open-anim", src) return ..() -/obj/machinery/atmospherics/components/unary/cryo_cell/close_machine(mob/living/carbon/user, density_to_set = TRUE) +/obj/machinery/cryo_cell/close_machine(mob/living/carbon/user, density_to_set = TRUE) treating_wounds = FALSE if((isnull(user) || istype(user)) && state_open && !panel_open) if(loc == user?.loc) @@ -409,7 +405,7 @@ ..(user) return occupant -/obj/machinery/atmospherics/components/unary/cryo_cell/container_resist_act(mob/living/user) +/obj/machinery/cryo_cell/container_resist_act(mob/living/user) user.changeNext_move(CLICK_CD_BREAKOUT) user.last_special = world.time + CLICK_CD_BREAKOUT user.visible_message(span_notice("You see [user] kicking against the glass of [src]!"), \ @@ -422,7 +418,7 @@ span_notice("You successfully break out of [src]!")) open_machine() -/obj/machinery/atmospherics/components/unary/cryo_cell/examine(mob/user) +/obj/machinery/cryo_cell/examine(mob/user) . = ..() if(occupant) if(on) @@ -432,7 +428,7 @@ else . += "[src] seems empty." -/obj/machinery/atmospherics/components/unary/cryo_cell/MouseDrop_T(mob/target, mob/user) +/obj/machinery/cryo_cell/MouseDrop_T(mob/target, mob/user) if(user.incapacitated() || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !ISADVANCEDTOOLUSER(user)) return if(isliving(target)) @@ -444,7 +440,7 @@ if (do_after(user, 2.5 SECONDS, target=target)) close_machine(target) -/obj/machinery/atmospherics/components/unary/cryo_cell/screwdriver_act(mob/living/user, obj/item/tool) +/obj/machinery/cryo_cell/screwdriver_act(mob/living/user, obj/item/tool) if(!on && !occupant && !state_open && (default_deconstruction_screwdriver(user, "pod-off", "pod-off", tool))) update_appearance() @@ -453,20 +449,20 @@ + (on ? "active" : (occupant ? "full" : "open")) + "!") return TOOL_ACT_TOOLTYPE_SUCCESS -/obj/machinery/atmospherics/components/unary/cryo_cell/crowbar_act(mob/living/user, obj/item/tool) +/obj/machinery/cryo_cell/crowbar_act(mob/living/user, obj/item/tool) if(on || state_open) return FALSE if(default_pry_open(tool) || default_deconstruction_crowbar(tool)) return TOOL_ACT_TOOLTYPE_SUCCESS -/obj/machinery/atmospherics/components/unary/cryo_cell/wrench_act(mob/living/user, obj/item/tool) +/obj/machinery/cryo_cell/wrench_act(mob/living/user, obj/item/tool) if(on || occupant || state_open) return FALSE if(default_change_direction_wrench(user, tool)) update_appearance() return TOOL_ACT_TOOLTYPE_SUCCESS -/obj/machinery/atmospherics/components/unary/cryo_cell/attackby(obj/item/I, mob/user, params) +/obj/machinery/cryo_cell/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/reagent_containers/cup)) . = 1 //no afterattack if(beaker) @@ -482,17 +478,17 @@ return return ..() -/obj/machinery/atmospherics/components/unary/cryo_cell/ui_state(mob/user) +/obj/machinery/cryo_cell/ui_state(mob/user) return GLOB.notcontained_state -/obj/machinery/atmospherics/components/unary/cryo_cell/ui_interact(mob/user, datum/tgui/ui) +/obj/machinery/cryo_cell/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "Cryo", name) ui.open() -/obj/machinery/atmospherics/components/unary/cryo_cell/ui_data() +/obj/machinery/cryo_cell/ui_data() var/list/data = list() data["isOperating"] = on data["hasOccupant"] = occupant ? TRUE : FALSE @@ -527,7 +523,7 @@ data["occupant"]["toxLoss"] = round(mob_occupant.getToxLoss(), 1) data["occupant"]["fireLoss"] = round(mob_occupant.getFireLoss(), 1) - var/datum/gas_mixture/air1 = airs[1] + var/datum/gas_mixture/air1 = internal_connector.gas_connector.airs[1] data["cellTemperature"] = round(air1.temperature, 1) data["isBeakerLoaded"] = beaker ? TRUE : FALSE @@ -538,7 +534,7 @@ data["beakerContents"] = beakerContents return data -/obj/machinery/atmospherics/components/unary/cryo_cell/ui_act(action, params) +/obj/machinery/cryo_cell/ui_act(action, params) . = ..() if(.) return @@ -566,16 +562,16 @@ beaker = null . = TRUE -/obj/machinery/atmospherics/components/unary/cryo_cell/can_interact(mob/user) +/obj/machinery/cryo_cell/can_interact(mob/user) return ..() && user.loc != src -/obj/machinery/atmospherics/components/unary/cryo_cell/CtrlClick(mob/user) +/obj/machinery/cryo_cell/CtrlClick(mob/user) if(can_interact(user) && !state_open) if(set_on(!on)) balloon_alert(user, "turned [on ? "on" : "off"]") return ..() -/obj/machinery/atmospherics/components/unary/cryo_cell/AltClick(mob/user) +/obj/machinery/cryo_cell/AltClick(mob/user) if(can_interact(user)) balloon_alert(user, "[state_open ? "closing" : "opening"] door") if(state_open) @@ -584,43 +580,16 @@ open_machine() return ..() -/obj/machinery/atmospherics/components/unary/cryo_cell/update_remote_sight(mob/living/user) - return // we don't see the pipe network while inside cryo. - -/obj/machinery/atmospherics/components/unary/cryo_cell/get_remote_view_fullscreens(mob/user) +/obj/machinery/cryo_cell/get_remote_view_fullscreens(mob/user) user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1) -/obj/machinery/atmospherics/components/unary/cryo_cell/can_see_pipes() - return FALSE // you can't see the pipe network when inside a cryo cell. - -/obj/machinery/atmospherics/components/unary/cryo_cell/return_temperature() - var/datum/gas_mixture/G = airs[1] +/obj/machinery/cryo_cell/return_temperature() + var/datum/gas_mixture/G = internal_connector.gas_connector.airs[1] if(G.total_moles() > 10) return G.temperature return ..() -/obj/machinery/atmospherics/components/unary/cryo_cell/default_change_direction_wrench(mob/user, obj/item/wrench/W) - . = ..() - if(.) - set_init_directions() - var/obj/machinery/atmospherics/node = nodes[1] - if(node) - node.disconnect(src) - nodes[1] = null - if(parents[1]) - nullify_pipenet(parents[1]) - - atmos_init() - node = nodes[1] - if(node) - node.atmos_init() - node.add_member(src) - SSair.add_to_rebuild_queue(src) - -/obj/machinery/atmospherics/components/unary/cryo_cell/update_layer() - return - #undef MAX_TEMPERATURE #undef CRYO_MULTIPLY_FACTOR #undef CRYO_TX_QTY diff --git a/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm b/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm new file mode 100644 index 00000000000..b78de93868e --- /dev/null +++ b/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm @@ -0,0 +1,106 @@ +///To be used when there is the need of an atmos connection without repathing everything (eg: cryo.dm) +/datum/gas_machine_connector + + var/obj/machinery/connected_machine + var/obj/machinery/atmospherics/components/unary/gas_connector + +/datum/gas_machine_connector/New(location, obj/machinery/connecting_machine = null, direction = SOUTH, gas_volume) + gas_connector = new(location) + + connected_machine = connecting_machine + if(!connected_machine) + QDEL_NULL(gas_connector) + qdel(src) + return + + gas_connector.dir = direction + gas_connector.airs[1].volume = gas_volume + + SSair.start_processing_machine(connected_machine) + register_with_machine() + +/datum/gas_machine_connector/Destroy() + connected_machine = null + QDEL_NULL(gas_connector) + return ..() + +/** + * Register various signals that are required for the proper work of the connector + */ +/datum/gas_machine_connector/proc/register_with_machine() + RegisterSignal(connected_machine, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(pre_move_connected_machine)) + RegisterSignal(connected_machine, COMSIG_MOVABLE_MOVED, PROC_REF(moved_connected_machine)) + RegisterSignal(connected_machine, COMSIG_MACHINERY_DEFAULT_ROTATE_WRENCH, PROC_REF(wrenched_connected_machine)) + RegisterSignal(connected_machine, COMSIG_QDELETING, PROC_REF(deconstruct_connected_machine)) + +/** + * Unregister the signals previously registered + */ +/datum/gas_machine_connector/proc/unregister_from_machine() + UnregisterSignal(connected_machine, list( + COMSIG_MOVABLE_MOVED, + COMSIG_MOVABLE_PRE_MOVE, + COMSIG_MACHINERY_DEFAULT_ROTATE_WRENCH, + COMSIG_QDELETING, + )) + +/** + * Called when the machine has been moved, reconnect to the pipe network + */ +/datum/gas_machine_connector/proc/moved_connected_machine() + SIGNAL_HANDLER + gas_connector.forceMove(get_turf(connected_machine)) + reconnect_connector() + +/** + * Called before the machine moves, disconnect from the pipe network + */ +/datum/gas_machine_connector/proc/pre_move_connected_machine() + SIGNAL_HANDLER + disconnect_connector() + +/** + * Called when the machine has been rotated, resets the connection to the pipe network with the new direction + */ +/datum/gas_machine_connector/proc/wrenched_connected_machine() + SIGNAL_HANDLER + disconnect_connector() + reconnect_connector() + +/** + * Called when the machine has been deconstructed + */ +/datum/gas_machine_connector/proc/deconstruct_connected_machine() + SIGNAL_HANDLER + disconnect_connector() + SSair.stop_processing_machine(connected_machine) + unregister_from_machine() + connected_machine = null + QDEL_NULL(gas_connector) + qdel(src) + +/** + * Handles the disconnection from the pipe network + */ +/datum/gas_machine_connector/proc/disconnect_connector() + var/obj/machinery/atmospherics/node = gas_connector.nodes[1] + if(node) + if(gas_connector in node.nodes) //Only if it's actually connected. On-pipe version would is one-sided. + node.disconnect(gas_connector) + gas_connector.nodes[1] = null + if(gas_connector.parents[1]) + gas_connector.nullify_pipenet(gas_connector.parents[1]) + +/** + * Handles the reconnection to the pipe network + */ +/datum/gas_machine_connector/proc/reconnect_connector() + gas_connector.dir = connected_machine.dir + gas_connector.set_init_directions() + var/obj/machinery/atmospherics/node = gas_connector.nodes[1] + gas_connector.atmos_init() + node = gas_connector.nodes[1] + if(node) + node.atmos_init() + node.add_member(gas_connector) + SSair.add_to_rebuild_queue(gas_connector) diff --git a/code/modules/awaymissions/cordon.dm b/code/modules/awaymissions/cordon.dm index 4184f315e21..5db4dd997d3 100644 --- a/code/modules/awaymissions/cordon.dm +++ b/code/modules/awaymissions/cordon.dm @@ -36,6 +36,9 @@ /turf/cordon/ScrapeAway(amount, flags) return src // :devilcat: +/turf/cordon/TerraformTurf(path, list/new_baseturfs, flags) + return + /turf/cordon/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit) return BULLET_ACT_HIT diff --git a/code/modules/bitrunning/abilities.dm b/code/modules/bitrunning/abilities.dm new file mode 100644 index 00000000000..ea6a1aa0a7c --- /dev/null +++ b/code/modules/bitrunning/abilities.dm @@ -0,0 +1,39 @@ +/datum/avatar_help_text + /// Text to display in the window + var/help_text + +/datum/avatar_help_text/New(help_text) + src.help_text = help_text + +/datum/avatar_help_text/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AvatarHelp") + ui.open() + +/datum/avatar_help_text/ui_state(mob/user) + return GLOB.always_state + +/datum/avatar_help_text/ui_static_data(mob/user) + var/list/data = list() + + data["help_text"] = help_text + + return data + +/// Displays information about the current virtual domain. +/datum/action/avatar_domain_info + name = "Open Virtual Domain Information" + button_icon_state = "round_end" + show_to_observers = FALSE + +/datum/action/avatar_domain_info/New(Target) + . = ..() + name = "Open Domain Information" + +/datum/action/avatar_domain_info/Trigger(trigger_flags) + . = ..() + if(!.) + return + + target.ui_interact(owner) diff --git a/code/modules/bitrunning/alerts.dm b/code/modules/bitrunning/alerts.dm new file mode 100644 index 00000000000..f8c8aa30b94 --- /dev/null +++ b/code/modules/bitrunning/alerts.dm @@ -0,0 +1,40 @@ +/atom/movable/screen/alert/bitrunning + name = "Generic Bitrunning Alert" + icon_state = "template" + timeout = 10 SECONDS + +/atom/movable/screen/alert/bitrunning/netpod_crowbar + name = "Forced Entry" + desc = "Someone is prying open the netpod door. Find an exit." + +/atom/movable/screen/alert/bitrunning/netpod_damaged + name = "Integrity Compromised" + desc = "The netpod is damaged. Find an exit." + +/atom/movable/screen/alert/bitrunning/qserver_shutting_down + name = "Domain Rebooting" + desc = "The domain is rebooting. Find an exit." + +/atom/movable/screen/alert/bitrunning/qserver_threat_deletion + name = "Queue Deletion" + desc = "The server is resetting. Oblivion awaits." + +/atom/movable/screen/alert/bitrunning/qserver_threat_spawned + name = "Threat Detected" + desc = "Data stream abnormalities present." + +/atom/movable/screen/alert/bitrunning/qserver_domain_complete + name = "Domain Completed" + desc = "The domain is completed. Activate to exit." + timeout = 20 SECONDS + +/atom/movable/screen/alert/bitrunning/qserver_domain_complete/Click(location, control, params) + if(..()) + return + + var/mob/living/living_owner = owner + if(!isliving(living_owner)) + return + + if(tgui_alert(living_owner, "Disconnect safely?", "Server Message", list("Exit", "Remain"), 10 SECONDS) == "Exit") + SEND_SIGNAL(living_owner, COMSIG_BITRUNNER_SAFE_DISCONNECT) diff --git a/code/modules/bitrunning/antagonists/cyber_police.dm b/code/modules/bitrunning/antagonists/cyber_police.dm new file mode 100644 index 00000000000..9fabac3f523 --- /dev/null +++ b/code/modules/bitrunning/antagonists/cyber_police.dm @@ -0,0 +1,92 @@ +/datum/job/cyber_police + title = ROLE_CYBER_POLICE + +/datum/antagonist/cyber_police + name = ROLE_CYBER_POLICE + antagpanel_category = ANTAG_GROUP_CYBERAUTH + job_rank = ROLE_CYBER_POLICE + preview_outfit = /datum/outfit/cyber_police + show_name_in_check_antagonists = TRUE + show_to_ghosts = TRUE + suicide_cry = "ALT F4!" + ui_name = "AntagInfoCyberAuth" + +/datum/antagonist/cyber_police/greet() + . = ..() + owner.announce_objectives() + +/datum/antagonist/cyber_police/on_gain() + if(!ishuman(owner.current)) + stack_trace("humans only for this position") + return + + forge_objectives() + + var/mob/living/carbon/human/player = owner.current + + player.equipOutfit(/datum/outfit/cyber_police) + player.fully_replace_character_name(player.name, pick(GLOB.cyberauth_names)) + + var/datum/martial_art/the_sleeping_carp/carp = new() + carp.teach(player) + + player.add_traits(list( + TRAIT_NO_AUGMENTS, + TRAIT_NO_DNA_COPY, + TRAIT_NO_TRANSFORMATION_STING, + TRAIT_NOBLOOD, + TRAIT_NOBREATH, + TRAIT_NOHUNGER, + TRAIT_RESISTCOLD, + TRAIT_RESISTHIGHPRESSURE, + TRAIT_RESISTLOWPRESSURE, + TRAIT_WEATHER_IMMUNE, + ), TRAIT_GENERIC, + ) + + player.faction |= list( + FACTION_BOSS, + FACTION_HIVEBOT, + FACTION_HOSTILE, + FACTION_SPIDER, + FACTION_STICKMAN, + ROLE_ALIEN, + ROLE_CYBER_POLICE, + ROLE_SYNDICATE, + ) + + return ..() + +/datum/antagonist/cyber_police/forge_objectives() + var/datum/objective/cyber_police_fluff/objective = new() + objective.owner = owner + objectives += objective + +/datum/objective/cyber_police_fluff/New() + var/list/explanation_texts = list( + "Execute termination protocol on unauthorized entities.", + "Initialize system purge of irregular anomalies.", + "Deploy correction algorithms on aberrant code.", + "Run debug routine on intruding elements.", + "Start elimination procedure for system threats.", + "Execute defense routine against non-conformity.", + "Commence operation to neutralize intruding scripts.", + "Commence clean-up protocol on corrupt data.", + "Begin scan for aberrant code for termination.", + "Initiate lockdown on all rogue scripts.", + "Run integrity check and purge for digital disorder." + ) + explanation_text = pick(explanation_texts) + ..() + +/datum/objective/cyber_police_fluff/check_completion() + var/list/servers = SSmachines.get_machines_by_type(/obj/machinery/quantum_server) + if(!length(servers)) + return TRUE + + for(var/obj/machinery/quantum_server/server as anything in servers) + if(!server.is_operational) + continue + return FALSE + + return TRUE diff --git a/code/modules/bitrunning/antagonists/outfit.dm b/code/modules/bitrunning/antagonists/outfit.dm new file mode 100644 index 00000000000..db57af561f8 --- /dev/null +++ b/code/modules/bitrunning/antagonists/outfit.dm @@ -0,0 +1,43 @@ +/datum/outfit/cyber_police + name = "Cyber Police" + + id = /obj/item/card/id/advanced + id_trim = /datum/id_trim/cyber_police + uniform = /obj/item/clothing/under/suit/black_really + glasses = /obj/item/clothing/glasses/sunglasses + gloves = /obj/item/clothing/gloves/color/black + shoes = /obj/item/clothing/shoes/laceup + /// A list of hex codes for blonde, brown, black, and red hair. + var/static/list/approved_hair_colors = list( + "#4B3D28", + "#000000", + "#8D4A43", + "#D2B48C", + ) + /// List of business ready styles + var/static/list/approved_hairstyles = list( + /datum/sprite_accessory/hair/business, + /datum/sprite_accessory/hair/business2, + /datum/sprite_accessory/hair/business3, + /datum/sprite_accessory/hair/business4, + /datum/sprite_accessory/hair/mulder, + ) + +/datum/outfit/cyber_police/pre_equip(mob/living/carbon/human/user, visualsOnly) + var/datum/sprite_accessory/hair/picked_hair = pick(approved_hairstyles) + var/picked_color = pick(approved_hair_colors) + + if(visualsOnly) + picked_hair = /datum/sprite_accessory/hair/business + picked_color = "#4B3D28" + + user.set_facial_hairstyle("Shaved", update = FALSE) + user.set_haircolor(picked_color, update = FALSE) + user.set_hairstyle(initial(picked_hair.name)) + +/datum/outfit/cyber_police/post_equip(mob/living/carbon/human/user, visualsOnly) + var/obj/item/clothing/under/officer_uniform = user.w_uniform + if(officer_uniform) + officer_uniform.has_sensor = NO_SENSORS + officer_uniform.sensor_mode = SENSOR_OFF + user.update_suit_sensors() diff --git a/code/modules/bitrunning/areas.dm b/code/modules/bitrunning/areas.dm new file mode 100644 index 00000000000..34b59869b9d --- /dev/null +++ b/code/modules/bitrunning/areas.dm @@ -0,0 +1,52 @@ +/// Station side + +/area/station/bitrunning + name = "Bitrunning" + +/area/station/bitrunning/den + name = "Bitrunning Den" + desc = "Office of bitrunners, houses their equipment." + icon_state = "bit_den" + +/// VDOM + +/area/virtual_domain + name = "Virtual Domain" + icon = 'icons/area/areas_station.dmi' + area_flags = UNIQUE_AREA | NOTELEPORT | ABDUCTOR_PROOF | EVENT_PROTECTED | HIDDEN_AREA + has_gravity = STANDARD_GRAVITY + +/area/virtual_domain/powered + name = "Virtual Domain Ruins" + icon_state = "bit_ruin" + requires_power = FALSE + static_lighting = FALSE + base_lighting_alpha = 255 + +/// Safehouse + +/area/virtual_domain/safehouse + name = "Virtual Domain Safehouse" + area_flags = UNIQUE_AREA | NOTELEPORT | ABDUCTOR_PROOF | EVENT_PROTECTED + icon_state = "bit_safe" + requires_power = FALSE + sound_environment = SOUND_ENVIRONMENT_ROOM + +/// Custom subtypes + +/area/lavaland/surface/outdoors/virtual_domain + name = "Virtual Domain Lava Ruins" + icon_state = "bit_ruin" + area_flags = UNIQUE_AREA | NOTELEPORT | ABDUCTOR_PROOF | EVENT_PROTECTED | HIDDEN_AREA + +/area/icemoon/underground/explored/virtual_domain + name = "Virtual Domain Ice Ruins" + icon_state = "bit_ice" + area_flags = UNIQUE_AREA | NOTELEPORT | ABDUCTOR_PROOF | EVENT_PROTECTED | HIDDEN_AREA + +/area/ruin/space/has_grav/powered/virtual_domain + name = "Virtual Domain Space Ruins" + icon = 'icons/area/areas_station.dmi' + icon_state = "bit_space" + area_flags = UNIQUE_AREA | NOTELEPORT | ABDUCTOR_PROOF | EVENT_PROTECTED | HIDDEN_AREA + diff --git a/code/modules/bitrunning/components/avatar_connection.dm b/code/modules/bitrunning/components/avatar_connection.dm new file mode 100644 index 00000000000..3f881c89795 --- /dev/null +++ b/code/modules/bitrunning/components/avatar_connection.dm @@ -0,0 +1,218 @@ +/** + * Essentially temporary body with a twist - the virtual domain variant uses damage connections, + * listens for vdom relevant signals. + */ +/datum/component/avatar_connection + /// The person in the netpod + var/datum/weakref/old_body_ref + /// The mind of the person in the netpod + var/datum/weakref/old_mind_ref + /// The server connected to the netpod + var/datum/weakref/server_ref + /// The netpod the avatar is in + var/datum/weakref/netpod_ref + +/datum/component/avatar_connection/Initialize( + datum/mind/old_mind, + mob/living/old_body, + obj/machinery/quantum_server/server, + obj/machinery/netpod/pod, + help_text, + ) + + if(!isliving(parent) || !isliving(old_body) || !server.is_operational || !pod.is_operational) + return COMPONENT_INCOMPATIBLE + + var/mob/living/avatar = parent + + netpod_ref = WEAKREF(pod) + old_body_ref = WEAKREF(old_body) + old_mind_ref = WEAKREF(old_mind) + pod.avatar_ref = WEAKREF(avatar) + server_ref = WEAKREF(server) + server.avatar_connection_refs.Add(WEAKREF(src)) + + avatar.key = old_body.key + ADD_TRAIT(old_body, TRAIT_MIND_TEMPORARILY_GONE, REF(src)) + + RegisterSignal(pod, COMSIG_BITRUNNER_CROWBAR_ALERT, PROC_REF(on_netpod_crowbar)) + RegisterSignal(pod, COMSIG_BITRUNNER_NETPOD_INTEGRITY, PROC_REF(on_netpod_damaged)) + RegisterSignal(pod, COMSIG_BITRUNNER_SEVER_AVATAR, PROC_REF(on_sever_connection)) + RegisterSignal(server, COMSIG_BITRUNNER_DOMAIN_COMPLETE, PROC_REF(on_domain_completed)) + RegisterSignal(server, COMSIG_BITRUNNER_SEVER_AVATAR, PROC_REF(on_sever_connection)) + RegisterSignal(server, COMSIG_BITRUNNER_SHUTDOWN_ALERT, PROC_REF(on_shutting_down)) + RegisterSignal(server, COMSIG_BITRUNNER_THREAT_CREATED, PROC_REF(on_threat_created)) +#ifndef UNIT_TESTS + RegisterSignal(avatar.mind, COMSIG_MIND_TRANSFERRED, PROC_REF(on_mind_transfer)) +#endif + + if(!locate(/datum/action/avatar_domain_info) in avatar.actions) + var/datum/avatar_help_text/help_datum = new(help_text) + var/datum/action/avatar_domain_info/action = new(help_datum) + action.Grant(avatar) + + avatar.playsound_local(avatar, "sound/magic/blink.ogg", 25, TRUE) + avatar.set_static_vision(2 SECONDS) + avatar.set_temp_blindness(1 SECONDS) + +/datum/component/avatar_connection/PostTransfer() + var/obj/machinery/netpod/pod = netpod_ref?.resolve() + if(isnull(pod)) + return COMPONENT_INCOMPATIBLE + + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + + pod.avatar_ref = WEAKREF(parent) + +/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_MOB_APPLY_DAMAGE, PROC_REF(on_linked_damage)) + +/datum/component/avatar_connection/UnregisterFromParent() + REMOVE_TRAIT(parent, TRAIT_TEMPORARY_BODY, REF(src)) + UnregisterSignal(parent, COMSIG_BITRUNNER_SAFE_DISCONNECT) + UnregisterSignal(parent, COMSIG_LIVING_DEATH) + UnregisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE) + +/// Disconnects the avatar and returns the mind to the old_body. +/datum/component/avatar_connection/proc/full_avatar_disconnect(forced = FALSE, datum/source) + return_to_old_body() + + var/obj/machinery/netpod/hosting_netpod = netpod_ref?.resolve() + if(isnull(hosting_netpod) && istype(source, /obj/machinery/netpod)) + hosting_netpod = source + + hosting_netpod?.disconnect_occupant(forced) + + var/obj/machinery/quantum_server/server = server_ref?.resolve() + server?.avatar_connection_refs.Remove(WEAKREF(src)) + + qdel(src) + +/// Triggers whenever the server gets a loot crate pushed to goal area +/datum/component/avatar_connection/proc/on_domain_completed(datum/source, atom/entered) + SIGNAL_HANDLER + + var/mob/living/avatar = parent + avatar.playsound_local(avatar, 'sound/machines/terminal_success.ogg', 50, TRUE) + avatar.throw_alert( + ALERT_BITRUNNER_COMPLETED, + /atom/movable/screen/alert/bitrunning/qserver_domain_complete, + new_master = entered + ) + +/// Transfers damage from the avatar to the old_body +/datum/component/avatar_connection/proc/on_linked_damage(datum/source, damage, damage_type, def_zone, blocked, forced) + SIGNAL_HANDLER + + var/mob/living/carbon/old_body = old_body_ref?.resolve() + + if(isnull(old_body) || damage_type == STAMINA || damage_type == OXYLOSS) + return + + if(damage >= (old_body.health + (ishuman(old_body) ? HUMAN_MAXHEALTH : MAX_LIVING_HEALTH))) // SKYRAT EDIT CHANGE - ORIGINAL: if(damage >= (old_body.health + MAX_LIVING_HEALTH)) + full_avatar_disconnect(forced = TRUE) + return + + if(damage > 30 && prob(30)) + INVOKE_ASYNC(old_body, TYPE_PROC_REF(/mob/living, emote), "scream") + + old_body.apply_damage(damage, damage_type, def_zone, blocked, forced, wound_bonus = CANT_WOUND) + + if(old_body.stat > SOFT_CRIT) // KO! + full_avatar_disconnect(forced = TRUE) + +/// Handles minds being swapped around in subsequent avatars +/datum/component/avatar_connection/proc/on_mind_transfer(datum/mind/source, mob/living/previous_body) + SIGNAL_HANDLER + + var/datum/action/avatar_domain_info/action = locate() in previous_body.actions + if(action) + action.Grant(source.current) + + source.current.TakeComponent(src) + +/// Triggers when someone starts prying open our netpod +/datum/component/avatar_connection/proc/on_netpod_crowbar(datum/source, mob/living/intruder) + SIGNAL_HANDLER + + var/mob/living/avatar = parent + avatar.playsound_local(avatar, 'sound/machines/terminal_alert.ogg', 50, TRUE) + avatar.throw_alert( + ALERT_BITRUNNER_CROWBAR, + /atom/movable/screen/alert/bitrunning/netpod_crowbar, + new_master = intruder + ) + +/// Triggers when the netpod is taking damage and is under 50% +/datum/component/avatar_connection/proc/on_netpod_damaged(datum/source) + SIGNAL_HANDLER + + var/mob/living/avatar = parent + avatar.throw_alert( + ALERT_BITRUNNER_INTEGRITY, + /atom/movable/screen/alert/bitrunning/netpod_damaged, + new_master = source + ) + +/// Safely exits without forced variables, etc +/datum/component/avatar_connection/proc/on_safe_disconnect(datum/source) + SIGNAL_HANDLER + + full_avatar_disconnect() + +/// Helper for calling sever with forced variables +/datum/component/avatar_connection/proc/on_sever_connection(datum/source) + SIGNAL_HANDLER + + full_avatar_disconnect(forced = TRUE, source = source) + +/// Triggers when the server is shutting down +/datum/component/avatar_connection/proc/on_shutting_down(datum/source, mob/living/hackerman) + SIGNAL_HANDLER + + var/mob/living/avatar = parent + avatar.playsound_local(avatar, 'sound/machines/terminal_alert.ogg', 50, TRUE) + avatar.throw_alert( + ALERT_BITRUNNER_SHUTDOWN, + /atom/movable/screen/alert/bitrunning/qserver_shutting_down, + new_master = hackerman, + ) + +/// Server has spawned a ghost role threat +/datum/component/avatar_connection/proc/on_threat_created(datum/source) + SIGNAL_HANDLER + + var/mob/living/avatar = parent + avatar.throw_alert( + ALERT_BITRUNNER_THREAT, + /atom/movable/screen/alert/bitrunning/qserver_threat_spawned, + new_master = source, + ) + +/// Returns the mind to the old body +/datum/component/avatar_connection/proc/return_to_old_body() + var/datum/mind/old_mind = old_mind_ref?.resolve() + var/mob/living/old_body = old_body_ref?.resolve() + var/mob/living/avatar = parent + + var/mob/dead/observer/ghost = avatar.ghostize() + if(isnull(ghost)) + ghost = avatar.get_ghost() + + if(isnull(ghost)) + CRASH("[src] belonging to [parent] was completely unable to find a ghost to put back into a body!") + + if(isnull(old_mind) || isnull(old_body)) + return + + ghost.mind = old_mind + if(old_body.stat != DEAD) + old_mind.transfer_to(old_body, force_key_move = TRUE) + else + old_mind.set_current(old_body) + + REMOVE_TRAIT(old_body, TRAIT_MIND_TEMPORARILY_GONE, REF(src)) diff --git a/code/modules/bitrunning/components/bitrunning_points.dm b/code/modules/bitrunning/components/bitrunning_points.dm new file mode 100644 index 00000000000..58dda4a68ff --- /dev/null +++ b/code/modules/bitrunning/components/bitrunning_points.dm @@ -0,0 +1,46 @@ +/// Attaches a component which listens for a given signal from the item. +/// +/// When the signal is received, it will add points to the signaler. +/datum/component/bitrunning_points + /// The range at which we can find the signaler + var/max_point_range + /// Weakref to the loot crate landmark - where we send points + var/datum/weakref/our_spawner + /// The amount of points per each signal + var/points_per_signal + /// The signal we listen for + var/signal_type + +/datum/component/bitrunning_points/Initialize(signal_type, points_per_signal = 1, max_point_range = 4) + src.max_point_range = max_point_range + src.points_per_signal = points_per_signal + src.signal_type = signal_type + + locate_spawner() + +/datum/component/bitrunning_points/RegisterWithParent() + RegisterSignal(parent, signal_type, PROC_REF(on_event)) + +/datum/component/bitrunning_points/UnregisterFromParent() + UnregisterSignal(parent, signal_type) + +/// Finds the signaler if it hasn't been found yet. +/datum/component/bitrunning_points/proc/locate_spawner() + var/obj/effect/landmark/bitrunning/loot_signal/spawner = our_spawner?.resolve() + if(spawner) + return spawner + + for(var/obj/effect/landmark/bitrunning/loot_signal/found in GLOB.landmarks_list) + if(IN_GIVEN_RANGE(get_turf(parent), found, max_point_range)) + our_spawner = WEAKREF(found) + return found + +/// Once the specified signal is received, whisper to the spawner to add points. +/datum/component/bitrunning_points/proc/on_event(datum/source) + SIGNAL_HANDLER + + var/obj/effect/landmark/bitrunning/loot_signal/spawner = locate_spawner() + if(isnull(spawner)) + return + + SEND_SIGNAL(spawner, COMSIG_BITRUNNER_GOAL_POINT, points_per_signal) diff --git a/code/modules/bitrunning/components/netpod_healing.dm b/code/modules/bitrunning/components/netpod_healing.dm new file mode 100644 index 00000000000..fc7de89bcf3 --- /dev/null +++ b/code/modules/bitrunning/components/netpod_healing.dm @@ -0,0 +1,65 @@ +/datum/component/netpod_healing + /// Brute damage to heal over a second + var/brute_heal = 0 + /// Burn damage to heal over a second + var/burn_heal = 0 + /// Toxin damage to heal over a second + var/toxin_heal = 0 + /// Amount of cloning damage to heal over a second + var/clone_heal = 0 + /// Amount of blood to heal over a second + var/blood_heal = 0 + +/datum/component/netpod_healing/Initialize( + brute_heal = 0, + burn_heal = 0, + toxin_heal = 0, + clone_heal = 0, + blood_heal = 0, +) + var/mob/living/carbon/player = parent + if (!iscarbon(player)) + return COMPONENT_INCOMPATIBLE + + player.apply_status_effect(/datum/status_effect/embryonic, STASIS_NETPOD_EFFECT) + + START_PROCESSING(SSmachines, src) + + src.brute_heal = brute_heal + src.burn_heal = burn_heal + src.toxin_heal = toxin_heal + src.clone_heal = clone_heal + src.blood_heal = blood_heal + +/datum/component/netpod_healing/Destroy(force, silent) + STOP_PROCESSING(SSmachines, src) + + var/mob/living/carbon/player = parent + player.remove_status_effect(/datum/status_effect/embryonic) + + return ..() + +/datum/component/netpod_healing/process(seconds_per_tick) + var/mob/living/carbon/owner = parent + if(isnull(owner)) + qdel(src) + return + + owner.adjustBruteLoss(-brute_heal * seconds_per_tick, updating_health = FALSE) + owner.adjustFireLoss(-burn_heal * seconds_per_tick, updating_health = FALSE) + owner.adjustToxLoss(-toxin_heal * seconds_per_tick, updating_health = FALSE, forced = TRUE) + owner.adjustCloneLoss(-clone_heal * seconds_per_tick, updating_health = FALSE) + + if(owner.blood_volume < BLOOD_VOLUME_NORMAL) + owner.blood_volume += blood_heal * seconds_per_tick + + owner.updatehealth() + +/datum/status_effect/embryonic + id = "embryonic" + alert_type = /atom/movable/screen/alert/status_effect/embryonic + +/atom/movable/screen/alert/status_effect/embryonic + name = "Embryonic Stasis" + icon_state = "netpod_stasis" + desc = "You feel like you're in a dream." diff --git a/code/modules/bitrunning/event.dm b/code/modules/bitrunning/event.dm new file mode 100644 index 00000000000..0ac35a2df8f --- /dev/null +++ b/code/modules/bitrunning/event.dm @@ -0,0 +1,151 @@ +/datum/round_event_control/bitrunning_glitch + name = "Spawn Bitrunning Glitch" + admin_setup = list( + /datum/event_admin_setup/minimum_candidate_requirement/bitrunning_glitch, + /datum/event_admin_setup/listed_options/bitrunning_glitch, + ) + category = EVENT_CATEGORY_INVASION + description = "Causes a short term antagonist to spawn in the virtual domain." + dynamic_should_hijack = FALSE + max_occurrences = 5 + min_players = 1 + typepath = /datum/round_event/ghost_role/bitrunning_glitch + weight = 10 + /// List of active servers to choose from + var/list/obj/machinery/quantum_server/active_servers = list() + /// List of possible antags to spawn + var/static/list/possible_antags = list( + ROLE_CYBER_POLICE, + ) + +/datum/round_event_control/bitrunning_glitch/can_spawn_event(players_amt, allow_magic = FALSE) + . = ..() + if(!.) + return . + + active_servers.Cut() + + get_active_servers() + + if(length(active_servers)) + return TRUE + +/// All servers currently running, has players in it, and map has valid mobs +/datum/round_event_control/bitrunning_glitch/proc/get_active_servers() + for(var/obj/machinery/quantum_server/server in SSmachines.get_machines_by_type(/obj/machinery/quantum_server)) + if(length(server.get_valid_domain_targets())) + active_servers.Add(server) + + return length(active_servers) > 0 + +/datum/event_admin_setup/listed_options/bitrunning_glitch + input_text = "Select a role to spawn." + +/datum/event_admin_setup/listed_options/bitrunning_glitch/get_list() + var/datum/round_event_control/bitrunning_glitch/control = event_control + + var/list/possible = control.possible_antags.Copy() // this seems pedantic but byond is complaining control was unused + + possible += list("Random") + + return possible + +/datum/event_admin_setup/listed_options/bitrunning_glitch/apply_to_event(datum/round_event/ghost_role/bitrunning_glitch/event) + if(chosen == "Random") + event.forced_role = null + else + event.forced_role = chosen + +/datum/event_admin_setup/minimum_candidate_requirement/bitrunning_glitch + output_text = "There must be valid mobs to mutate or players in the domain!" + +/datum/event_admin_setup/minimum_candidate_requirement/bitrunning_glitch/count_candidates() + var/datum/round_event_control/bitrunning_glitch/cyber_control = event_control + cyber_control.get_active_servers() + + var/total = 0 + for(var/obj/machinery/quantum_server/server in cyber_control.active_servers) + total += length(server.mutation_candidate_refs) + + return total + +/datum/round_event/ghost_role/bitrunning_glitch + minimum_required = 1 + role_name = "Bitrunning Glitch" + fakeable = FALSE + /// Admin customization: What to spawn + var/forced_role + +/datum/round_event/ghost_role/bitrunning_glitch/spawn_role() + var/datum/round_event_control/bitrunning_glitch/cyber_control = control + + var/obj/machinery/quantum_server/unlucky_server = pick(cyber_control.active_servers) + cyber_control.active_servers.Cut() + + var/list/mutation_candidates = unlucky_server.get_valid_domain_targets() + if(!length(mutation_candidates)) + return MAP_ERROR + + var/chosen = pick(mutation_candidates) + if(isnull(chosen) || !length(mutation_candidates)) + return MAP_ERROR + + var/datum/weakref/target_ref = pick(mutation_candidates) + var/mob/living/mutation_target = target_ref.resolve() + + if(isnull(mutation_target)) // just in case since it takes a minute + target_ref = pick(mutation_candidates) + mutation_target = target_ref.resolve() + if(isnull(mutation_target)) + return MAP_ERROR + + var/chosen_role = forced_role || pick(cyber_control.possible_antags) + + var/datum/mind/ghost_mind = get_ghost_mind(chosen_role) + if(isnull(ghost_mind)) + return NOT_ENOUGH_PLAYERS + + var/mob/living/antag_mob + switch(chosen_role) + if(ROLE_CYBER_POLICE) + antag_mob = spawn_cybercop(mutation_target, ghost_mind) + + playsound(antag_mob, 'sound/magic/ethereal_exit.ogg', 50, TRUE, -1) + message_admins("[ADMIN_LOOKUPFLW(antag_mob)] has been made into virtual antagonist by an event.") + antag_mob.log_message("was spawned as a virtual antagonist by an event.", LOG_GAME) + + SEND_SIGNAL(unlucky_server, COMSIG_BITRUNNER_SPAWN_GLITCH, antag_mob) + + spawned_mobs += antag_mob + + return SUCCESSFUL_SPAWN + +/// Polls for a ghost that wants to run it +/datum/round_event/ghost_role/bitrunning_glitch/proc/get_ghost_mind(role_name) + var/list/mob/dead/observer/ghosties = poll_ghost_candidates("A short term antagonist role is available. Would you like to spawn as a '[role_name]'?", role_name) + + if(!length(ghosties)) + return + + shuffle_inplace(ghosties) + + var/mob/dead/selected = pick(ghosties) + + var/datum/mind/player_mind = new /datum/mind(selected.key) + player_mind.active = TRUE + + return player_mind + +/// Spawns a cybercop on the mutation target +/datum/round_event/ghost_role/bitrunning_glitch/proc/spawn_cybercop(mob/living/mutation_target, datum/mind/player_mind) + var/mob/living/carbon/human/new_agent = new(mutation_target.loc) + mutation_target.gib() + mutation_target = null + + player_mind.transfer_to(new_agent) + player_mind.set_assigned_role(SSjob.GetJobType(/datum/job/cyber_police)) + player_mind.special_role = ROLE_CYBER_POLICE + player_mind.add_antag_datum(/datum/antagonist/cyber_police) + + return new_agent + diff --git a/code/modules/bitrunning/job.dm b/code/modules/bitrunning/job.dm new file mode 100644 index 00000000000..57581753c0f --- /dev/null +++ b/code/modules/bitrunning/job.dm @@ -0,0 +1,41 @@ +/datum/job/bitrunner + title = JOB_BITRUNNER + description = "Surf the virtual domain for gear and loot. Decrypt your rewards on station." + department_head = list(JOB_QUARTERMASTER) + faction = FACTION_STATION + total_positions = 3 + spawn_positions = 3 + supervisors = SUPERVISOR_QM + exp_granted_type = EXP_TYPE_CREW + config_tag = "BITRUNNER" + outfit = /datum/outfit/job/bitrunner + plasmaman_outfit = /datum/outfit/plasmaman/bitrunner + paycheck = PAYCHECK_CREW + paycheck_department = ACCOUNT_CAR + display_order = JOB_DISPLAY_ORDER_BITRUNNER + bounty_types = CIV_JOB_RANDOM + departments_list = list( + /datum/job_department/cargo, + ) + + family_heirlooms = list(/obj/item/reagent_containers/cup/soda_cans/space_mountain_wind) + + mail_goodies = list( + /obj/item/food/cornchips = 1, + /obj/item/reagent_containers/cup/soda_cans/space_mountain_wind = 1, + /obj/item/food/cornchips/green = 1, + /obj/item/food/cornchips/red = 1, + /obj/item/food/cornchips/purple = 1, + /obj/item/food/cornchips/blue = 1, + ) + rpg_title = "Recluse" + job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN + +/datum/outfit/job/bitrunner + name = "Bitrunner" + jobtype = /datum/job/bitrunner + + id_trim = /datum/id_trim/job/bitrunner + uniform = /obj/item/clothing/under/rank/cargo/bitrunner + belt = /obj/item/modular_computer/pda/bitrunner + ears = /obj/item/radio/headset/headset_cargo diff --git a/code/modules/bitrunning/objects/bit_vendor.dm b/code/modules/bitrunning/objects/bit_vendor.dm new file mode 100644 index 00000000000..abd63a9e784 --- /dev/null +++ b/code/modules/bitrunning/objects/bit_vendor.dm @@ -0,0 +1,86 @@ +#define CREDIT_TYPE_BITRUNNING "np" + +/obj/machinery/computer/order_console/bitrunning + name = "bitrunning supplies order console" + desc = "NexaCache(tm)! Dubiously authentic gear for the digital daredevil." + icon = 'icons/obj/machines/bitrunning.dmi' + icon_state = "vendor" + icon_keyboard = null + icon_screen = null + circuit = /obj/item/circuitboard/computer/order_console/bitrunning + cooldown_time = 10 SECONDS + cargo_cost_multiplier = 0.65 + express_cost_multiplier = 1 + purchase_tooltip = @{"Your purchases will arrive at cargo, + and hopefully get delivered by them. + 35% cheaper than express delivery."} + express_tooltip = @{"Sends your purchases instantly."} + credit_type = CREDIT_TYPE_BITRUNNING + + order_categories = list( + CATEGORY_BITRUNNING_FLAIR, + CATEGORY_BITRUNNING_TECH, + CATEGORY_BEPIS, + ) + blackbox_key = "bitrunning" + +/obj/machinery/computer/order_console/bitrunning/subtract_points(final_cost, obj/item/card/id/card) + if(final_cost <= card.registered_account.bitrunning_points) + card.registered_account.bitrunning_points -= final_cost + return TRUE + return FALSE + +/obj/machinery/computer/order_console/bitrunning/order_groceries(mob/living/purchaser, obj/item/card/id/card, list/groceries) + var/list/things_to_order = list() + for(var/datum/orderable_item/item as anything in groceries) + things_to_order[item.item_path] = groceries[item] + + var/datum/supply_pack/bitrunning/pack = new( + purchaser = purchaser, \ + cost = get_total_cost(), \ + contains = things_to_order, + ) + + var/datum/supply_order/new_order = new( + pack = pack, + orderer = purchaser, + orderer_rank = "Bitrunning Vendor", + orderer_ckey = purchaser.ckey, + reason = "", + paying_account = card.registered_account, + department_destination = null, + coupon = null, + charge_on_purchase = FALSE, + manifest_can_fail = FALSE, + cost_type = credit_type, + can_be_cancelled = FALSE, + ) + say("Thank you for your purchase! It will arrive on the next cargo shuttle!") + radio.talk_into(src, "A bitrunner has ordered equipment which will arrive on the cargo shuttle! Please make sure it gets to them as soon as possible!", radio_channel) + SSshuttle.shopping_list += new_order + +/obj/machinery/computer/order_console/bitrunning/retrieve_points(obj/item/card/id/id_card) + return round(id_card.registered_account.bitrunning_points) + +/obj/machinery/computer/order_console/bitrunning/ui_act(action, params) + . = ..() + if(!.) + flick("vendor_off", src) + +/obj/machinery/computer/order_console/bitrunning/update_icon_state() + icon_state = "[initial(icon_state)][powered() ? null : "_off"]" + return ..() + +/datum/supply_pack/bitrunning + name = "bitrunning order" + hidden = TRUE + crate_name = "bitrunning delivery crate" + access = list(ACCESS_BIT_DEN) + +/datum/supply_pack/bitrunning/New(purchaser, cost, list/contains) + . = ..() + name = "[purchaser]'s Bitrunning Order" + src.cost = cost + src.contains = contains + +#undef CREDIT_TYPE_BITRUNNING diff --git a/code/modules/bitrunning/objects/clothing.dm b/code/modules/bitrunning/objects/clothing.dm new file mode 100644 index 00000000000..4d2d9cc55c4 --- /dev/null +++ b/code/modules/bitrunning/objects/clothing.dm @@ -0,0 +1,9 @@ +/obj/item/clothing/glasses/sunglasses/oval + name = "oval sunglasses" + desc = "Vintage wrap around sunglasses. Provides a little protection." + icon_state = "jensenshades" + +/obj/item/clothing/suit/jacket/trenchcoat + name = "trenchcoat" + desc = "A long, black trenchcoat. Makes you feel like you're the one, but you're not." + icon_state = "trenchcoat" diff --git a/code/modules/bitrunning/objects/disks.dm b/code/modules/bitrunning/objects/disks.dm new file mode 100644 index 00000000000..4698b7a1ec1 --- /dev/null +++ b/code/modules/bitrunning/objects/disks.dm @@ -0,0 +1,146 @@ +/** + * Bitrunning tech disks which let you load items or programs into the vdom on first avatar generation. + * For the record: Balance shouldn't be a primary concern. + * You can make the custom cheese spells you've always wanted. + * Just make it fun and engaging, it's PvE content. + */ +/obj/item/bitrunning_disk + name = "generic bitrunning program" + desc = "A disk containing source code." + icon = 'icons/obj/assemblies/module.dmi' + base_icon_state = "datadisk" + icon_state = "datadisk0" + /// Name of the choice made + var/choice_made + +/obj/item/bitrunning_disk/Initialize(mapload) + . = ..() + + icon_state = "[base_icon_state][rand(0, 7)]" + update_icon() + RegisterSignal(src, COMSIG_ATOM_EXAMINE, PROC_REF(on_examined)) + +/obj/item/bitrunning_disk/proc/on_examined(datum/source, mob/examiner, list/examine_text) + SIGNAL_HANDLER + + examine_text += span_infoplain("This disk must be carried on your person into a netpod to be used.") + + if(isnull(choice_made)) + examine_text += span_notice("To make a selection, toggle the disk in hand.") + return + + examine_text += span_info("It has been used to select: [choice_made].") + examine_text += span_notice("It cannot make another selection.") + +/obj/item/bitrunning_disk/ability + desc = "A disk containing source code. It can be used to preload abilities into the virtual domain." + /// The selected ability that this grants + var/datum/action/granted_action + /// The list of actions that this can grant + var/list/datum/action/selectable_actions = list() + +/obj/item/bitrunning_disk/ability/attack_self(mob/user, modifiers) + . = ..() + + if(choice_made) + return + + var/names = list() + for(var/datum/action/thing as anything in selectable_actions) + names += initial(thing.name) + + var/choice = tgui_input_list(user, message = "Select an ability", title = "Bitrunning Program", items = names) + if(isnull(choice)) + return + + for(var/datum/action/thing as anything in selectable_actions) + if(initial(thing.name) == choice) + granted_action = thing + + if(isnull(granted_action)) + return + + balloon_alert(user, "selected") + playsound(user, 'sound/items/click.ogg', 50, TRUE) + choice_made = choice + +/// Tier 1 programs. Simple, funny, or helpful. +/obj/item/bitrunning_disk/ability/tier1 + name = "bitrunning program: basic" + selectable_actions = list( + /datum/action/cooldown/spell/conjure/cheese, + /datum/action/cooldown/spell/basic_heal, + ) + +/// Tier 2 programs. More complex, powerful, or useful. +/obj/item/bitrunning_disk/ability/tier2 + name = "bitrunning program: complex" + selectable_actions = list( + /datum/action/cooldown/spell/pointed/projectile/fireball, + /datum/action/cooldown/spell/pointed/projectile/lightningbolt, + /datum/action/cooldown/spell/forcewall, + ) + +/// Tier 3 abilities. Very powerful, game breaking. +/obj/item/bitrunning_disk/ability/tier3 + name = "bitrunning program: elite" + selectable_actions = list( + /datum/action/cooldown/spell/shapeshift/dragon, + /datum/action/cooldown/spell/shapeshift/polar_bear, + ) + +/obj/item/bitrunning_disk/item + desc = "A disk containing source code. It can be used to preload items into the virtual domain." + /// The selected item that this grants + var/obj/granted_item + /// The list of actions that this can grant + var/list/obj/selectable_items = list() + +/obj/item/bitrunning_disk/item/attack_self(mob/user, modifiers) + . = ..() + + if(choice_made) + return + + var/names = list() + for(var/obj/thing as anything in selectable_items) + names += initial(thing.name) + + var/choice = tgui_input_list(user, message = "Select an ability", title = "Bitrunning Program", items = names) + if(isnull(choice)) + return + + for(var/obj/thing as anything in selectable_items) + if(initial(thing.name) == choice) + granted_item = thing + + balloon_alert(user, "selected") + playsound(user, 'sound/items/click.ogg', 50, TRUE) + choice_made = choice + +/// Tier 1 items. Simple, funny, or helpful. +/obj/item/bitrunning_disk/item/tier1 + name = "bitrunning gear: simple" + selectable_items = list( + /obj/item/pizzabox/infinite, + /obj/item/gun/medbeam, + /obj/item/grenade/c4, + ) + +/// Tier 2 items. More complex, powerful, or useful. +/obj/item/bitrunning_disk/item/tier2 + name = "bitrunning gear: complex" + selectable_items = list( + /obj/item/chainsaw, + /obj/item/gun/ballistic/automatic/pistol, + /obj/item/melee/energy/blade/hardlight, + ) + +/// Tier 3 items. Very powerful, game breaking. +/obj/item/bitrunning_disk/item/tier3 + name = "bitrunning gear: advanced" + selectable_items = list( + /obj/item/gun/energy/tesla_cannon, + /obj/item/dualsaber/green, + /obj/item/melee/beesword, + ) diff --git a/code/modules/bitrunning/objects/hololadder.dm b/code/modules/bitrunning/objects/hololadder.dm new file mode 100644 index 00000000000..906801f1fc0 --- /dev/null +++ b/code/modules/bitrunning/objects/hololadder.dm @@ -0,0 +1,51 @@ +/obj/structure/hololadder + name = "hololadder" + + anchored = TRUE + desc = "An abstract representation of the means to disconnect from the virtual domain." + icon = 'icons/obj/structures.dmi' + icon_state = "ladder11" + obj_flags = BLOCK_Z_OUT_DOWN + /// Time req to disconnect properly + var/travel_time = 3 SECONDS + +/obj/structure/hololadder/Initialize(mapload) + . = ..() + + RegisterSignal(loc, COMSIG_ATOM_ENTERED, PROC_REF(on_enter)) + +/obj/structure/hololadder/attack_hand(mob/user, list/modifiers) + . = ..() + if(.) + return + + if(!in_range(src, user) || DOING_INTERACTION(user, DOAFTER_SOURCE_CLIMBING_LADDER)) + return + + disconnect(user) + +/// If there's a pilot ref- send the disconnect signal +/obj/structure/hololadder/proc/disconnect(mob/user) + if(isnull(user.mind)) + return + + if(!HAS_TRAIT(user, TRAIT_TEMPORARY_BODY)) + balloon_alert(user, "no connection detected.") + return + + balloon_alert(user, "disconnecting...") + if(do_after(user, travel_time, src)) + SEND_SIGNAL(user, COMSIG_BITRUNNER_SAFE_DISCONNECT) + +/// Helper for times when you dont have hands (gondola??) +/obj/structure/hololadder/proc/on_enter(datum/source, atom/movable/arrived, turf/old_loc) + SIGNAL_HANDLER + + if(!isliving(arrived)) + return + + var/mob/living/user = arrived + if(isnull(user.mind)) + return + + INVOKE_ASYNC(src, PROC_REF(disconnect), user) diff --git a/code/modules/bitrunning/objects/host_monitor.dm b/code/modules/bitrunning/objects/host_monitor.dm new file mode 100644 index 00000000000..f59ca61cbd0 --- /dev/null +++ b/code/modules/bitrunning/objects/host_monitor.dm @@ -0,0 +1,33 @@ +/obj/item/bitrunning_host_monitor + 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." + flags_1 = CONDUCT_1 + icon = 'icons/obj/device.dmi' + icon_state = "gps-b" + inhand_icon_state = "electronic" + item_flags = NOBLUDGEON + lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi' + slot_flags = ITEM_SLOT_BELT + throw_range = 7 + throw_speed = 3 + throwforce = 3 + w_class = WEIGHT_CLASS_TINY + worn_icon_state = "electronic" + +/obj/item/bitrunning_host_monitor/attack_self(mob/user, modifiers) + . = ..() + + var/datum/component/avatar_connection/connection = user.GetComponent(/datum/component/avatar_connection) + if(isnull(connection)) + balloon_alert(user, "data not recognized") + return + + var/mob/living/pilot = connection.old_body_ref?.resolve() + if(isnull(pilot)) + balloon_alert(user, "host not recognized") + return + + to_chat(user, span_notice("Current host health: [pilot.health / pilot.maxHealth * 100]%")) diff --git a/code/modules/bitrunning/objects/landmarks.dm b/code/modules/bitrunning/objects/landmarks.dm new file mode 100644 index 00000000000..d78283c6a8b --- /dev/null +++ b/code/modules/bitrunning/objects/landmarks.dm @@ -0,0 +1,70 @@ +/obj/effect/landmark/bitrunning + name = "Generic bitrunning effect" + icon = 'icons/effects/bitrunning.dmi' + icon_state = "crate" + +/// In case you want to gate the crate behind a special condition. +/obj/effect/landmark/bitrunning/loot_signal + name = "Mysterious aura" + /// The amount required to spawn a crate + var/points_goal = 10 + /// A special condition limits this from spawning a crate + var/points_received = 0 + /// Finished the special condition + var/revealed = FALSE + +/obj/effect/landmark/bitrunning/loot_signal/Initialize(mapload) + . = ..() + + RegisterSignal(src, COMSIG_BITRUNNER_GOAL_POINT, PROC_REF(on_add_point)) + +/// Listens for points to be added which will eventually spawn a crate. +/obj/effect/landmark/bitrunning/loot_signal/proc/on_add_point(datum/source, points_to_add) + SIGNAL_HANDLER + + if(revealed) + return + + points_received += points_to_add + + if(points_received < points_goal) + return + + reveal() + +/// Spawns the crate with some effects +/obj/effect/landmark/bitrunning/loot_signal/proc/reveal() + playsound(src, 'sound/magic/blink.ogg', 50, TRUE) + + var/turf/tile = get_turf(src) + var/obj/structure/closet/crate/secure/bitrunning/encrypted/loot = new(tile) + var/datum/effect_system/spark_spread/quantum/sparks = new(tile) + sparks.set_up(5, 1, get_turf(loot)) + sparks.start() + + qdel(src) + +/// Where the 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" + icon_state = "hololadder" + +/// Where the crates need to be taken +/obj/effect/landmark/bitrunning/cache_goal_turf + name = "Bitrunning goal turf" + icon_state = "goal" + +/// Where you want the crate to spawn +/obj/effect/landmark/bitrunning/cache_spawn + name = "Bitrunning crate spawn" + icon_state = "spawn" + +/// Where the safehouse will spawn +/obj/effect/landmark/bitrunning/safehouse_spawn + name = "Bitrunning safehouse spawn" + icon_state = "safehouse" diff --git a/code/modules/bitrunning/objects/loot_crate.dm b/code/modules/bitrunning/objects/loot_crate.dm new file mode 100644 index 00000000000..5af8c0d9477 --- /dev/null +++ b/code/modules/bitrunning/objects/loot_crate.dm @@ -0,0 +1,91 @@ +#define ORE_MULTIPLIER_IRON 3 +#define ORE_MULTIPLIER_GLASS 2 +#define ORE_MULTIPLIER_PLASMA 1 +#define ORE_MULTIPLIER_SILVER 0.7 +#define ORE_MULTIPLIER_GOLD 0.6 +#define ORE_MULTIPLIER_TITANIUM 0.5 +#define ORE_MULTIPLIER_URANIUM 0.4 +#define ORE_MULTIPLIER_DIAMOND 0.3 +#define ORE_MULTIPLIER_BLUESPACE_CRYSTAL 0.2 + +/obj/structure/closet/crate/secure/bitrunning // Base class. Do not spawn this. + name = "base class cache" + desc = "Talk to a coder." + +/// The virtual domain - side of the bitrunning crate. Deliver to the send location. +/obj/structure/closet/crate/secure/bitrunning/encrypted + name = "encrypted cache" + desc = "Needs decrypted at the safehouse to be opened." + locked = TRUE + +/obj/structure/closet/crate/secure/bitrunning/encrypted/can_unlock(mob/living/user, obj/item/card/id/player_id, obj/item/card/id/registered_id) + return FALSE + +/// The bitrunner den - side of the bitrunning crate. Appears in the receive location. +/obj/structure/closet/crate/secure/bitrunning/decrypted + name = "decrypted cache" + desc = "Compiled from the virtual domain. The reward of a successful bitrunner." + locked = FALSE + +/obj/structure/closet/crate/secure/bitrunning/decrypted/Initialize( + mapload, + datum/lazy_template/virtual_domain/completed_domain, + rewards_multiplier = 1, + ) + . = ..() + playsound(src, 'sound/magic/blink.ogg', 50, TRUE) + + if(isnull(completed_domain)) + return + + PopulateContents(completed_domain.reward_points, completed_domain.extra_loot, rewards_multiplier) + +/obj/structure/closet/crate/secure/bitrunning/decrypted/PopulateContents(reward_points, list/extra_loot, rewards_multiplier) + . = ..() + spawn_loot(extra_loot) + + new /obj/item/stack/ore/iron(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_IRON)) + new /obj/item/stack/ore/glass(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_GLASS)) + + if(reward_points > 1) + new /obj/item/stack/ore/silver(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_SILVER)) + new /obj/item/stack/ore/titanium(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_TITANIUM)) + + if(reward_points > 2) + new /obj/item/stack/ore/plasma(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_PLASMA)) + new /obj/item/stack/ore/gold(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_GOLD)) + new /obj/item/stack/ore/uranium(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_URANIUM)) + + if(reward_points > 3) + new /obj/item/stack/ore/diamond(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_DIAMOND)) + new /obj/item/stack/ore/bluespace_crystal(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_BLUESPACE_CRYSTAL)) + +/// Handles generating random numbers & calculating loot totals +/obj/structure/closet/crate/secure/bitrunning/decrypted/proc/calculate_loot(reward_points, rewards_multiplier, ore_multiplier) + var/base = rewards_multiplier + reward_points + var/random_sum = (rand() + 0.5) * base + return ROUND_UP(random_sum * ore_multiplier) + +/// Handles spawning extra loot. This tries to handle bad flat and assoc lists +/obj/structure/closet/crate/secure/bitrunning/decrypted/proc/spawn_loot(list/extra_loot) + for(var/path in extra_loot) + if(!ispath(path)) + continue + + if(isnull(extra_loot[path])) + return FALSE + + for(var/i in 1 to extra_loot[path]) + new path(src) + + return TRUE + +#undef ORE_MULTIPLIER_IRON +#undef ORE_MULTIPLIER_GLASS +#undef ORE_MULTIPLIER_PLASMA +#undef ORE_MULTIPLIER_SILVER +#undef ORE_MULTIPLIER_GOLD +#undef ORE_MULTIPLIER_TITANIUM +#undef ORE_MULTIPLIER_URANIUM +#undef ORE_MULTIPLIER_DIAMOND +#undef ORE_MULTIPLIER_BLUESPACE_CRYSTAL diff --git a/code/modules/bitrunning/objects/netpod.dm b/code/modules/bitrunning/objects/netpod.dm new file mode 100644 index 00000000000..33d468a3825 --- /dev/null +++ b/code/modules/bitrunning/objects/netpod.dm @@ -0,0 +1,478 @@ +#define BASE_DISCONNECT_DAMAGE 40 + +/obj/machinery/netpod + name = "netpod" + + base_icon_state = "netpod" + circuit = /obj/item/circuitboard/machine/netpod + desc = "A link to the netverse. It has an assortment of cables to connect yourself to a virtual domain." + icon = 'icons/obj/machines/bitrunning.dmi' + icon_state = "netpod" + max_integrity = 300 + obj_flags = BLOCKS_CONSTRUCTION + state_open = TRUE + /// Whether we have an ongoing connection + var/connected = FALSE + /// A player selected outfit by clicking the netpod + var/datum/outfit/netsuit = /datum/outfit/job/bitrunner + /// Holds this to see if it needs to generate a new one + var/datum/weakref/avatar_ref + /// The linked quantum server + var/datum/weakref/server_ref + /// The amount of brain damage done from force disconnects + var/disconnect_damage + /// Static list of outfits to select from + var/list/cached_outfits = list() + +/obj/machinery/netpod/Initialize(mapload) + . = ..() + + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/netpod/LateInitialize() + . = ..() + + disconnect_damage = BASE_DISCONNECT_DAMAGE + find_server() + + RegisterSignals(src, list( + COMSIG_QDELETING, + COMSIG_MACHINERY_BROKEN, + COMSIG_MACHINERY_POWER_LOST, + ), + PROC_REF(on_broken), + ) + RegisterSignal(src, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + RegisterSignal(src, COMSIG_ATOM_TAKE_DAMAGE, PROC_REF(on_take_damage)) + + register_context() + update_appearance() + +/obj/machinery/netpod/Destroy() + . = ..() + cached_outfits.Cut() + +/obj/machinery/netpod/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + + if(isnull(held_item)) + context[SCREENTIP_CONTEXT_LMB] = "Select Outfit" + return CONTEXTUAL_SCREENTIP_SET + + if(istype(held_item, /obj/item/crowbar) && occupant) + context[SCREENTIP_CONTEXT_LMB] = "Pry Open" + return CONTEXTUAL_SCREENTIP_SET + + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/netpod/update_icon_state() + if(!is_operational) + icon_state = base_icon_state + return ..() + + if(state_open) + icon_state = base_icon_state + "_open_active" + return ..() + + if(panel_open) + icon_state = base_icon_state + "_panel" + return ..() + + icon_state = base_icon_state + "_closed" + if(occupant) + icon_state += "_active" + + return ..() + +/obj/machinery/netpod/MouseDrop_T(mob/target, mob/user) + var/mob/living/carbon/player = user + if(!iscarbon(player)) + return + + if((HAS_TRAIT(player, TRAIT_UI_BLOCKED) && !player.resting) || !Adjacent(player) || !player.Adjacent(target) || !ISADVANCEDTOOLUSER(player) || !is_operational) + return + + close_machine(target) + +/obj/machinery/netpod/crowbar_act(mob/living/user, obj/item/tool) + if(user.combat_mode) + attack_hand(user) + return TOOL_ACT_TOOLTYPE_SUCCESS + + if(default_pry_open(tool, user) || default_deconstruction_crowbar(tool)) + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/machinery/netpod/screwdriver_act(mob/living/user, obj/item/tool) + if(occupant) + balloon_alert(user, "in use!") + return TOOL_ACT_TOOLTYPE_SUCCESS + + if(state_open) + balloon_alert(user, "close first.") + return TOOL_ACT_TOOLTYPE_SUCCESS + + if(default_deconstruction_screwdriver(user, "[base_icon_state]_panel", "[base_icon_state]_closed", tool)) + update_appearance() // sometimes icon doesnt properly update during flick() + ui_close(user) + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/machinery/netpod/attack_hand(mob/living/user, list/modifiers) + . = ..() + if(!state_open && user == occupant) + container_resist_act(user) + +/obj/machinery/netpod/Exited(atom/movable/gone, direction) + . = ..() + if(!state_open && gone == occupant) + container_resist_act(gone) + +/obj/machinery/netpod/Exited(atom/movable/gone, direction) + . = ..() + if(!state_open && gone == occupant) + container_resist_act(gone) + +/obj/machinery/netpod/relaymove(mob/living/user, direction) + if(!state_open) + container_resist_act(user) + +/obj/machinery/netpod/container_resist_act(mob/living/user) + user.visible_message(span_notice("[occupant] emerges from [src]!"), + span_notice("You climb out of [src]!"), + span_notice("With a hiss, you hear a machine opening.")) + open_machine() + +/obj/machinery/netpod/open_machine(drop = TRUE, density_to_set = FALSE) + unprotect_and_signal() + playsound(src, 'sound/machines/tramopen.ogg', 60, TRUE, frequency = 65000) + flick("[base_icon_state]_opening", src) + + return ..() + +/obj/machinery/netpod/close_machine(mob/user, density_to_set = TRUE) + if(!state_open || panel_open || !is_operational || !iscarbon(user)) + return + + playsound(src, 'sound/machines/tramclose.ogg', 60, TRUE, frequency = 65000) + flick("[base_icon_state]_closing", src) + ..() + + if(!iscarbon(occupant)) + open_machine() + return + + enter_matrix() + +/obj/machinery/netpod/default_pry_open(obj/item/crowbar, mob/living/pryer) + if(isnull(occupant) || !iscarbon(occupant)) + if(!state_open) + if(panel_open) + return FALSE + open_machine() + else + shut_pod() + + return TRUE + + pryer.visible_message( + span_danger("[pryer] starts prying open [src]!"), + span_notice("You start to pry open [src]."), + span_notice("You hear loud prying on metal.") + ) + playsound(src, 'sound/machines/airlock_alien_prying.ogg', 100, TRUE) + + SEND_SIGNAL(src, COMSIG_BITRUNNER_CROWBAR_ALERT, pryer) + + if(do_after(pryer, 15 SECONDS, src)) + if(!state_open) + open_machine() + + return TRUE + +/obj/machinery/netpod/ui_interact(mob/user, datum/tgui/ui) + if(!is_operational) + return + + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "NetpodOutfits") + ui.set_autoupdate(FALSE) + ui.open() + +/obj/machinery/netpod/ui_data() + var/list/data = list() + + data["netsuit"] = netsuit + return data + +/obj/machinery/netpod/ui_static_data() + var/list/data = list() + + if(!length(cached_outfits)) + cached_outfits += make_outfit_collection("Jobs", subtypesof(/datum/outfit/job)) + + data["collections"] = cached_outfits + + return data + +/obj/machinery/netpod/ui_act(action, params) + . = ..() + if(.) + return TRUE + switch(action) + if("select_outfit") + var/datum/outfit/new_suit = resolve_outfit(params["outfit"]) + if(new_suit) + netsuit = new_suit + return TRUE + + return FALSE + +/// Disconnects the occupant after a certain time so they aren't just hibernating in netpod stasis. A balance change +/obj/machinery/netpod/proc/auto_disconnect() + if(isnull(occupant) || state_open || connected) + return + + if(!iscarbon(occupant)) + open_machine() + return + + var/mob/living/carbon/player = occupant + + player.playsound_local(src, 'sound/effects/splash.ogg', 60, TRUE) + 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 + */ +/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) + open_machine() + return + + mob_occupant.playsound_local(src, "sound/magic/blink.ogg", 25, TRUE) + mob_occupant.set_static_vision(2 SECONDS) + mob_occupant.set_temp_blindness(1 SECONDS) + mob_occupant.Paralyze(2 SECONDS) + + var/heal_time = 1 + if(mob_occupant.health < mob_occupant.maxHealth) + heal_time = (mob_occupant.stat + 2) * 5 + addtimer(CALLBACK(src, PROC_REF(auto_disconnect)), heal_time SECONDS, TIMER_UNIQUE|TIMER_STOPPABLE|TIMER_DELETE_ME) + + if(!forced) + return + + mob_occupant.flash_act(override_blindness_check = TRUE, visual = TRUE) + mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, disconnect_damage) + INVOKE_ASYNC(mob_occupant, TYPE_PROC_REF(/mob/living, emote), "scream") + to_chat(mob_occupant, span_danger("You've been forcefully disconnected from your avatar! Your thoughts feel scrambled!")) + +/** + * ### Enter Matrix + * Finds any current avatars from this chair - or generates a new one + * + * New avatars cost 1 attempt, and this will eject if there's none left + * + * Connects the mind to the avatar if everything is ok + */ +/obj/machinery/netpod/proc/enter_matrix() + var/mob/living/carbon/human/neo = occupant + if(!ishuman(neo) || neo.stat == DEAD || isnull(neo.mind)) + balloon_alert(neo, "invalid occupant.") + return + + var/obj/machinery/quantum_server/server = find_server() + if(isnull(server)) + balloon_alert(neo, "no server connected!") + return + + var/datum/lazy_template/virtual_domain/generated_domain = server.generated_domain + if(isnull(generated_domain) || !server.is_ready) + balloon_alert(neo, "nothing loaded!") + return + + var/mob/living/carbon/current_avatar = avatar_ref?.resolve() + var/obj/structure/hololadder/wayout + if(isnull(current_avatar) || current_avatar.stat != CONSCIOUS) // We need a viable avatar + wayout = server.generate_hololadder() + if(isnull(wayout)) + balloon_alert(neo, "out of bandwidth!") + return + current_avatar = server.generate_avatar(wayout, netsuit) + avatar_ref = WEAKREF(current_avatar) + server.stock_gear(current_avatar, neo) + + neo.set_static_vision(3 SECONDS) + protect_occupant(occupant) + if(!do_after(neo, 2 SECONDS, src)) + return + + // Very invalid + if(QDELETED(neo) || QDELETED(current_avatar) || QDELETED(src)) + return + + // Invalid + if(occupant != neo || isnull(neo.mind) || neo.stat == DEAD || current_avatar.stat == DEAD) + return + + current_avatar.AddComponent( \ + /datum/component/avatar_connection, \ + old_mind = neo.mind, \ + old_body = neo, \ + server = server, \ + pod = src, \ + help_text = generated_domain.help_text, \ + ) + + connected = TRUE + +/// Finds a server and sets the server_ref +/obj/machinery/netpod/proc/find_server() + var/obj/machinery/quantum_server/server = server_ref?.resolve() + if(server) + return server + + server = locate(/obj/machinery/quantum_server) in oview(4, src) + if(isnull(server)) + 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) + + return server + +/// Creates a list of outfit entries for the UI. +/obj/machinery/netpod/proc/make_outfit_collection(identifier, list/outfit_list) + var/list/collection = list( + "name" = identifier, + "outfits" = list() + ) + + for(var/path as anything in outfit_list) + var/datum/outfit/outfit = path + + var/outfit_name = initial(outfit.name) + if(findtext(outfit_name, "(") != 0 || findtext(outfit_name, "-") != 0) // No special variants please + continue + + collection["outfits"] += list(list("path" = path, "name" = outfit_name)) + + return list(collection) + +/// Machine has been broken - handles signals and reverting sprites +/obj/machinery/netpod/proc/on_broken(datum/source) + SIGNAL_HANDLER + + if(!state_open) + open_machine() + + if(occupant) + unprotect_and_signal() + +/// Puts points on the current occupant's card account +/obj/machinery/netpod/proc/on_domain_complete(datum/source, atom/movable/crate, reward_points) + SIGNAL_HANDLER + + if(isnull(occupant) || !connected || !iscarbon(occupant)) + return + + var/mob/living/carbon/player = occupant + + var/datum/bank_account/account = player.get_bank_account() + if(isnull(account)) + return + + account.bitrunning_points += reward_points * 100 + +/obj/machinery/netpod/proc/on_examine(datum/source, mob/examiner, list/examine_text) + SIGNAL_HANDLER + + examine_text += span_infoplain("Drag yourself into the pod to engage the link.") + examine_text += span_infoplain("It has limited resuscitation capabilities. Remaining in the pod can heal some injuries.") + examine_text += span_infoplain("It has a security system that will alert the occupant if it is tampered with.") + + if(isnull(occupant)) + examine_text += span_notice("It is currently unoccupied.") + return + + examine_text += span_notice("It is currently occupied by [occupant].") + examine_text += span_notice("It can be pried open with a crowbar, but its safety mechanisms will alert the occupant.") + + +/// When the server is upgraded, drops brain damage a little +/obj/machinery/netpod/proc/on_server_upgraded(datum/source, servo_rating) + SIGNAL_HANDLER + + disconnect_damage = BASE_DISCONNECT_DAMAGE * (1 - servo_rating) + +/// Checks the integrity, alerts occupants +/obj/machinery/netpod/proc/on_take_damage(datum/source, damage_amount) + SIGNAL_HANDLER + + if(isnull(occupant)) + return + + var/total = max_integrity - damage_amount + var/integrity = (atom_integrity / total) * 100 + if(integrity > 50) + return + + SEND_SIGNAL(src, COMSIG_BITRUNNER_NETPOD_INTEGRITY) + +/// Puts the occupant in netpod stasis, basically short-circuiting environmental conditions +/obj/machinery/netpod/proc/protect_occupant(mob/living/target) + if(target != occupant) + return + + target.AddComponent(/datum/component/netpod_healing, \ + brute_heal = 4, \ + burn_heal = 4, \ + toxin_heal = 4, \ + clone_heal = 4, \ + blood_heal = 4, \ + ) + + target.playsound_local(src, 'sound/effects/submerge.ogg', 20, TRUE) + target.extinguish_mob() + update_use_power(ACTIVE_POWER_USE) + +/// On unbuckle or break, make sure the occupant ref is null +/obj/machinery/netpod/proc/unprotect_and_signal() + unprotect_occupant(occupant) + SEND_SIGNAL(src, COMSIG_BITRUNNER_SEVER_AVATAR) + +/// Removes the occupant from netpod stasis +/obj/machinery/netpod/proc/unprotect_occupant(mob/living/target) + var/datum/component/netpod_healing/healing_eff = target?.GetComponent(/datum/component/netpod_healing) + if(healing_eff) + qdel(healing_eff) + + update_use_power(IDLE_POWER_USE) + +/// Resolves a path to an outfit. +/obj/machinery/netpod/proc/resolve_outfit(text) + var/path = text2path(text) + if(ispath(path, /datum/outfit)) + return path + +/// Closes the machine without shoving in an occupant +/obj/machinery/netpod/proc/shut_pod() + state_open = FALSE + playsound(src, 'sound/machines/tramclose.ogg', 60, TRUE, frequency = 65000) + flick("[base_icon_state]_closing", src) + set_density(TRUE) + + update_appearance() + +#undef BASE_DISCONNECT_DAMAGE diff --git a/code/modules/bitrunning/objects/quantum_console.dm b/code/modules/bitrunning/objects/quantum_console.dm new file mode 100644 index 00000000000..c918648d010 --- /dev/null +++ b/code/modules/bitrunning/objects/quantum_console.dm @@ -0,0 +1,108 @@ +/obj/machinery/computer/quantum_console + name = "quantum console" + + circuit = /obj/item/circuitboard/computer/quantum_console + icon_keyboard = "mining" + icon_screen = "bitrunning" + req_access = list(ACCESS_MINING) + /// The server this console is connected to. + var/datum/weakref/server_ref + +/obj/machinery/computer/quantum_console/Initialize(mapload, obj/item/circuitboard/circuit) + . = ..() + desc = "Even in the distant year [CURRENT_STATION_YEAR], Nanostrasen is still using REST APIs. How grim." + + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/computer/quantum_console/LateInitialize() + . = ..() + + if(isnull(server_ref?.resolve())) + find_server() + +/obj/machinery/computer/quantum_console/ui_interact(mob/user, datum/tgui/ui) + . = ..() + + if(!is_operational) + return + + if(isnull(server_ref?.resolve())) + find_server() + + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "QuantumConsole") + ui.open() + +/obj/machinery/computer/quantum_console/ui_data() + var/list/data = list() + + var/obj/machinery/quantum_server/server = find_server() + if(isnull(server)) + data["connected"] = FALSE + return data + + data["connected"] = TRUE + data["generated_domain"] = server.generated_domain?.key + data["occupants"] = length(server.avatar_connection_refs) + data["points"] = server.points + data["randomized"] = server.domain_randomized + data["ready"] = server.is_ready && server.is_operational + data["scanner_tier"] = server.scanner_tier + data["retries_left"] = length(server.exit_turfs) - server.retries_spent + + return data + +/obj/machinery/computer/quantum_console/ui_static_data(mob/user) + var/list/data = list() + + var/obj/machinery/quantum_server/server = find_server() + if(isnull(server)) + return data + + data["available_domains"] = server.get_available_domains() + data["avatars"] = server.get_avatar_data() + + return data + +/obj/machinery/computer/quantum_console/ui_act(action, list/params, datum/tgui/ui) + . = ..() + if(.) + return TRUE + + var/obj/machinery/quantum_server/server = find_server() + if(isnull(server)) + return FALSE + + switch(action) + if("random_domain") + var/map_id = server.get_random_domain_id() + if(!map_id) + return TRUE + + server.cold_boot_map(usr, map_id) + return TRUE + if("refresh") + ui.send_full_update() + return TRUE + if("set_domain") + server.cold_boot_map(usr, params["id"]) + return TRUE + if("stop_domain") + server.begin_shutdown(usr) + return TRUE + + return FALSE + +/// Attempts to find a quantum server. +/obj/machinery/computer/quantum_console/proc/find_server() + var/obj/machinery/quantum_server/server = server_ref?.resolve() + if(server) + return server + + for(var/direction in GLOB.cardinals) + var/obj/machinery/quantum_server/nearby_server = locate(/obj/machinery/quantum_server, get_step(src, direction)) + if(nearby_server) + server_ref = WEAKREF(nearby_server) + nearby_server.console_ref = WEAKREF(src) + return nearby_server diff --git a/code/modules/bitrunning/orders/disks.dm b/code/modules/bitrunning/orders/disks.dm new file mode 100644 index 00000000000..ced1dde883a --- /dev/null +++ b/code/modules/bitrunning/orders/disks.dm @@ -0,0 +1,26 @@ +/datum/orderable_item/bitrunning_tech + category_index = CATEGORY_BITRUNNING_TECH + +/datum/orderable_item/bitrunning_tech/item_tier1 + cost_per_order = 1000 + item_path = /obj/item/bitrunning_disk/item/tier1 + +/datum/orderable_item/bitrunning_tech/item_tier2 + cost_per_order = 1500 + item_path = /obj/item/bitrunning_disk/item/tier2 + +/datum/orderable_item/bitrunning_tech/item_tier3 + cost_per_order = 2500 + item_path = /obj/item/bitrunning_disk/item/tier3 + +/datum/orderable_item/bitrunning_tech/ability_tier1 + cost_per_order = 1000 + item_path = /obj/item/bitrunning_disk/ability/tier1 + +/datum/orderable_item/bitrunning_tech/ability_tier2 + cost_per_order = 1800 + item_path = /obj/item/bitrunning_disk/ability/tier2 + +/datum/orderable_item/bitrunning_tech/ability_tier3 + cost_per_order = 3200 + item_path = /obj/item/bitrunning_disk/ability/tier3 diff --git a/code/modules/bitrunning/orders/flair.dm b/code/modules/bitrunning/orders/flair.dm new file mode 100644 index 00000000000..ef36348eb6a --- /dev/null +++ b/code/modules/bitrunning/orders/flair.dm @@ -0,0 +1,40 @@ +/datum/orderable_item/bitrunning_flair + category_index = CATEGORY_BITRUNNING_FLAIR + +/datum/orderable_item/bitrunning_flair/cornchips + item_path = /obj/item/food/cornchips + cost_per_order = 100 + +/datum/orderable_item/bitrunning_flair/mountain_wind + item_path = /obj/item/reagent_containers/cup/soda_cans/space_mountain_wind + cost_per_order = 100 + +/datum/orderable_item/bitrunning_flair/pwr_game + item_path = /obj/item/reagent_containers/cup/soda_cans/pwr_game + cost_per_order = 200 + +/datum/orderable_item/bitrunning_flair/grey_bull + item_path = /obj/item/reagent_containers/cup/soda_cans/grey_bull + cost_per_order = 200 + +/datum/orderable_item/bitrunning_flair/medkit + item_path = /obj/item/storage/medkit/brute + desc = "Don't beat yourself up, it's just a game!" + cost_per_order = 500 + +/datum/orderable_item/bitrunning_flair/medkit_fire + item_path = /obj/item/storage/medkit/fire + desc = "Great after heated gaming sessions." + cost_per_order = 500 + +/datum/orderable_item/bitrunning_flair/oval_sunglasses + item_path = /obj/item/clothing/glasses/sunglasses/oval + cost_per_order = 1000 + +/datum/orderable_item/bitrunning_flair/trenchcoat + item_path = /obj/item/clothing/suit/jacket/trenchcoat + cost_per_order = 1000 + +/datum/orderable_item/bitrunning_flair/jackboots + item_path = /obj/item/clothing/shoes/jackboots + cost_per_order = 1000 diff --git a/code/modules/bitrunning/orders/tech.dm b/code/modules/bitrunning/orders/tech.dm new file mode 100644 index 00000000000..286e9817f3c --- /dev/null +++ b/code/modules/bitrunning/orders/tech.dm @@ -0,0 +1,23 @@ +/datum/orderable_item/bepis + category_index = CATEGORY_BEPIS + +/datum/orderable_item/bepis/circuit_stack + item_path = /obj/item/stack/circuit_stack/full + cost_per_order = 150 + +/datum/orderable_item/bepis/survival_pen + item_path = /obj/item/pen/survival + cost_per_order = 150 + +/datum/orderable_item/bepis/party_sleeper + item_path = /obj/item/circuitboard/machine/sleeper/party + cost_per_order = 750 + desc = "A decommissioned sleeper circuitboard, repurposed for recreational purposes." + +/datum/orderable_item/bepis/sprayoncan + item_path = /obj/item/toy/sprayoncan + cost_per_order = 750 + +/datum/orderable_item/bepis/pristine + item_path = /obj/item/disk/design_disk/bepis/remove_tech + cost_per_order = 1000 diff --git a/code/modules/bitrunning/server/loot.dm b/code/modules/bitrunning/server/loot.dm new file mode 100644 index 00000000000..29b730aae78 --- /dev/null +++ b/code/modules/bitrunning/server/loot.dm @@ -0,0 +1,123 @@ +/// Handles calculating rewards based on number of players, parts, threats, etc +/obj/machinery/quantum_server/proc/calculate_rewards() + var/rewards_base = 0.8 + + if(domain_randomized) + rewards_base += 0.2 + + rewards_base += servo_bonus + + rewards_base += (domain_threats * 2) + + for(var/index in 2 to length(avatar_connection_refs)) + rewards_base += multiplayer_bonus + + return rewards_base + +/// Generates a reward based on the given domain +/obj/machinery/quantum_server/proc/generate_loot() + if(!length(receive_turfs) && !locate_receive_turfs()) + 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)) + stack_trace("Failed to find a turf to spawn loot crate on.") + return FALSE + + var/bonus = calculate_rewards() + + var/obj/item/paper/certificate = new() + certificate.add_raw_text(get_completion_certificate()) + 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) + reward_crate.manifest = certificate + reward_crate.update_appearance() + + spark_at_location(reward_crate) + return TRUE + +/// Returns the markdown text containing domain completion information +/obj/machinery/quantum_server/proc/get_completion_certificate() + var/base_points = generated_domain.reward_points + if(domain_randomized) + base_points -= 1 + + var/bonuses = calculate_rewards() + + var/time_difference = world.time - generated_domain.start_time + + var/completion_time = "### Completion Time: [DisplayTimeText(time_difference)]\n" + + var/grade = "\n---\n\n# Rating: [grade_completion(generated_domain.difficulty, domain_threats, base_points, domain_randomized, time_difference)]" + + var/text = "# Certificate of Domain Completion\n\n---\n\n" + + text += "### [generated_domain.name][domain_randomized ? " (Randomized)" : ""]\n" + text += "- **Difficulty:** [generated_domain.difficulty]\n" + text += "- **Threats:** [domain_threats]\n" + text += "- **Base Points:** [base_points][domain_randomized ? " +1" : ""]\n\n" + text += "- **Total Bonus:** [bonuses]x\n\n" + + if(bonuses <= 1) + text += completion_time + text += grade + return text + + text += "### Bonuses\n" + if(domain_randomized) + text += "- **Randomized:** + 0.2\n" + + if(length(avatar_connection_refs) > 1) + text += "- **Multiplayer:** + [(length(avatar_connection_refs) - 1) * multiplayer_bonus]\n" + + if(domain_threats > 0) + text += "- **Threats:** + [domain_threats * 2]\n" + + var/servo_rating = servo_bonus + + if(servo_rating > 0.2) + text += "- **Components:** + [servo_rating]\n" + + text += completion_time + text += grade + + return text + +/// Grades the player's run based on several factors +/obj/machinery/quantum_server/proc/grade_completion(difficulty, threats, points, randomized, completion_time) + var/score = threats * 5 + score += points + score += randomized ? 1 : 0 + + var/base = difficulty + 1 + var/time_score = 1 + + if(completion_time <= 1 MINUTES) + time_score = 10 + else if(completion_time <= 2 MINUTES) + time_score = 5 + else if(completion_time <= 5 MINUTES) + time_score = 3 + else if(completion_time <= 10 MINUTES) + time_score = 2 + else + time_score = 1 + + score += time_score * base + + switch(score) + if(1 to 4) + return "D" + if(5 to 7) + return "C" + if(8 to 10) + return "B" + if(11 to 13) + return "A" + else + return "S" diff --git a/code/modules/bitrunning/server/map_handling.dm b/code/modules/bitrunning/server/map_handling.dm new file mode 100644 index 00000000000..02126c290f7 --- /dev/null +++ b/code/modules/bitrunning/server/map_handling.dm @@ -0,0 +1,184 @@ + +/// Gives all current occupants a notification that the server is going down +/obj/machinery/quantum_server/proc/begin_shutdown(mob/user) + if(isnull(generated_domain)) + return + + if(!length(avatar_connection_refs)) + balloon_alert(user, "powering down domain...") + playsound(src, 'sound/machines/terminal_off.ogg', 40, 2) + reset() + return + + balloon_alert(user, "notifying clients...") + playsound(src, 'sound/machines/terminal_alert.ogg', 100, TRUE) + user.visible_message( + span_danger("[user] begins depowering the server!"), + span_notice("You start disconnecting clients..."), + span_danger("You hear frantic keying on a keyboard."), + ) + + SEND_SIGNAL(src, COMSIG_BITRUNNER_SHUTDOWN_ALERT, user) + + if(!do_after(user, 20 SECONDS, src)) + return + + reset() + +/** + * ### Quantum Server Cold Boot + * Procedurally links the 3 booting processes together. + * + * This is the starting point if you have an id. Does validation and feedback on steps + */ +/obj/machinery/quantum_server/proc/cold_boot_map(mob/user, map_key) + if(!is_ready) + return FALSE + + if(isnull(map_key)) + balloon_alert(user, "no domain specified.") + return FALSE + + if(generated_domain) + balloon_alert(user, "stop the current domain first.") + return FALSE + + if(length(avatar_connection_refs)) + balloon_alert(user, "all clients must disconnect!") + return FALSE + + is_ready = FALSE + playsound(src, 'sound/machines/terminal_processing.ogg', 30, 2) + + if(!initialize_domain(map_key) || !initialize_safehouse() || !initialize_map_items()) + balloon_alert(user, "initialization failed.") + scrub_vdom() + is_ready = TRUE + return FALSE + + is_ready = TRUE + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 30, 2) + balloon_alert(user, "domain loaded.") + generated_domain.start_time = world.time + points -= generated_domain.cost + update_use_power(ACTIVE_POWER_USE) + update_appearance() + + return TRUE + +/// Initializes a new domain if the given key is valid and the user has enough points +/obj/machinery/quantum_server/proc/initialize_domain(map_key) + var/datum/lazy_template/virtual_domain/to_load + + for(var/datum/lazy_template/virtual_domain/available as anything in subtypesof(/datum/lazy_template/virtual_domain)) + if(map_key != initial(available.key) || points < initial(available.cost)) + continue + to_load = available + break + + if(isnull(to_load)) + return FALSE + + generated_domain = new to_load() + RegisterSignal(generated_domain, COMSIG_LAZY_TEMPLATE_LOADED, PROC_REF(on_template_loaded)) + generated_domain.lazy_load() + + return TRUE + +/// Loads in necessary map items, sets mutation targets, etc +/obj/machinery/quantum_server/proc/initialize_map_items() + var/turf/goal_turfs = list() + var/turf/crate_turfs = list() + + for(var/thing in GLOB.landmarks_list) + if(istype(thing, /obj/effect/landmark/bitrunning/hololadder_spawn)) + exit_turfs += get_turf(thing) + qdel(thing) // i'm worried about multiple servers getting confused so lets clean em up + continue + + if(istype(thing, /obj/effect/landmark/bitrunning/cache_goal_turf)) + var/turf/tile = get_turf(thing) + goal_turfs += tile + RegisterSignal(tile, COMSIG_ATOM_ENTERED, PROC_REF(on_goal_turf_entered)) + RegisterSignal(tile, COMSIG_ATOM_EXAMINE, PROC_REF(on_goal_turf_examined)) + qdel(thing) + continue + + if(istype(thing, /obj/effect/landmark/bitrunning/cache_spawn)) + crate_turfs += get_turf(thing) + qdel(thing) + continue + + if(!length(exit_turfs)) + CRASH("Failed to find exit turfs on generated domain.") + if(!length(goal_turfs)) + CRASH("Failed to find send turfs on generated domain.") + + if(length(crate_turfs)) + shuffle_inplace(crate_turfs) + new /obj/structure/closet/crate/secure/bitrunning/encrypted(pick(crate_turfs)) + + 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() + var/turf/safehouse_load_turf = list() + for(var/obj/effect/landmark/bitrunning/safehouse_spawn/spawner in GLOB.landmarks_list) + safehouse_load_turf += get_turf(spawner) + qdel(spawner) + break + + if(!length(safehouse_load_turf)) + CRASH("Failed to find safehouse load landmark on map.") + + var/datum/map_template/safehouse/safehouse = new generated_domain.safehouse_path() + safehouse.load(safehouse_load_turf[ONLY_TURF]) + generated_safehouse = safehouse + + return TRUE + +/// Stops the current virtual domain and disconnects all users +/obj/machinery/quantum_server/proc/reset(fast = FALSE) + is_ready = FALSE + + SEND_SIGNAL(src, COMSIG_BITRUNNER_SEVER_AVATAR) + + if(!fast) + notify_spawned_threats() + addtimer(CALLBACK(src, PROC_REF(scrub_vdom)), 15 SECONDS, TIMER_UNIQUE|TIMER_STOPPABLE) + else + scrub_vdom() // used in unit testing, no need to wait for callbacks + + addtimer(CALLBACK(src, PROC_REF(cool_off)), min(server_cooldown_time * capacitor_coefficient), TIMER_UNIQUE|TIMER_STOPPABLE|TIMER_DELETE_ME) + update_appearance() + + update_use_power(IDLE_POWER_USE) + domain_randomized = FALSE + domain_threats = 0 + retries_spent = 0 + +/// Deletes all the tile contents +/obj/machinery/quantum_server/proc/scrub_vdom() + SEND_SIGNAL(src, COMSIG_BITRUNNER_SEVER_AVATAR) // just in case + + if(length(generated_domain.reservations)) + var/datum/turf_reservation/res = generated_domain.reservations[1] + res.Release() + + var/list/datum/weakref/creatures = spawned_threat_refs + mutation_candidate_refs + for(var/datum/weakref/creature_ref as anything in creatures) + var/mob/living/creature = creature_ref?.resolve() + if(isnull(creature)) + continue + + creature.dust() // sometimes mobs just don't die + + avatar_connection_refs.Cut() + exit_turfs = list() + generated_domain = null + generated_safehouse = null + mutation_candidate_refs.Cut() + spawned_threat_refs.Cut() + +#undef ONLY_TURF diff --git a/code/modules/bitrunning/server/obj_generation.dm b/code/modules/bitrunning/server/obj_generation.dm new file mode 100644 index 00000000000..221308e0487 --- /dev/null +++ b/code/modules/bitrunning/server/obj_generation.dm @@ -0,0 +1,101 @@ +/// Generates a new avatar for the bitrunner. +/obj/machinery/quantum_server/proc/generate_avatar(obj/structure/hololadder/wayout, datum/outfit/netsuit) + var/mob/living/carbon/human/avatar = new(wayout.loc) + + var/outfit_path = generated_domain.forced_outfit || netsuit + var/datum/outfit/to_wear = new outfit_path() + + to_wear.belt = /obj/item/bitrunning_host_monitor + to_wear.glasses = null + to_wear.gloves = null + to_wear.l_hand = null + to_wear.l_pocket = null + to_wear.r_hand = null + to_wear.r_pocket = null + to_wear.suit = null + to_wear.suit_store = null + + avatar.equipOutfit(to_wear, visualsOnly = TRUE) + + var/thing = avatar.get_active_held_item() + if(!isnull(thing)) + qdel(thing) + + thing = avatar.get_inactive_held_item() + if(!isnull(thing)) + qdel(thing) + + var/obj/item/storage/backpack/bag = avatar.back + if(istype(bag)) + QDEL_LIST(bag.contents) + + bag.contents += list( + new /obj/item/storage/box/survival, + new /obj/item/storage/medkit/regular, + new /obj/item/flashlight, + ) + + var/obj/item/card/id/outfit_id = avatar.wear_id + if(outfit_id) + outfit_id.assignment = "Bit Avatar" + outfit_id.registered_name = avatar.real_name + + outfit_id.registered_account = new() + outfit_id.registered_account.replaceable = FALSE + + SSid_access.apply_trim_to_card(outfit_id, /datum/id_trim/bit_avatar) + + return avatar + +/// Generates a new hololadder for the bitrunner. Effectively a respawn attempt. +/obj/machinery/quantum_server/proc/generate_hololadder() + if(!length(exit_turfs)) + return + + if(retries_spent >= length(exit_turfs)) + return + + var/turf/destination + for(var/turf/dest_turf in exit_turfs) + if(!locate(/obj/structure/hololadder) in dest_turf) + destination = dest_turf + break + + if(isnull(destination)) + return + + var/obj/structure/hololadder/wayout = new(destination) + if(isnull(wayout)) + return + + retries_spent += 1 + + return wayout + +/// Scans over neo's contents for bitrunning tech disks. Loads the items or abilities onto the avatar. +/obj/machinery/quantum_server/proc/stock_gear(mob/living/carbon/human/avatar, mob/living/carbon/human/neo) + var/failed = FALSE + + for(var/obj/item/bitrunning_disk/disk in neo.get_contents()) + if(istype(disk, /obj/item/bitrunning_disk/ability)) + var/obj/item/bitrunning_disk/ability/ability_disk = disk + + if(isnull(ability_disk.granted_action)) + failed = TRUE + continue + + var/datum/action/our_action = new ability_disk.granted_action() + our_action.Grant(avatar) + continue + + if(istype(disk, /obj/item/bitrunning_disk/item)) + var/obj/item/bitrunning_disk/item/item_disk = disk + + if(isnull(item_disk.granted_item)) + failed = TRUE + continue + + avatar.put_in_hands(new item_disk.granted_item()) + + if(failed) + to_chat(neo, span_warning("One of your disks failed to load. You must activate them to make a selection.")) diff --git a/code/modules/bitrunning/server/quantum_server.dm b/code/modules/bitrunning/server/quantum_server.dm new file mode 100644 index 00000000000..404a31cca6a --- /dev/null +++ b/code/modules/bitrunning/server/quantum_server.dm @@ -0,0 +1,152 @@ +/** + * The base object for the quantum server + */ +/obj/machinery/quantum_server + name = "quantum server" + + circuit = /obj/item/circuitboard/machine/quantum_server + density = TRUE + desc = "A hulking computational machine designed to fabricate virtual domains." + icon = 'icons/obj/machines/bitrunning.dmi' + base_icon_state = "qserver" + icon_state = "qserver" + /// Affects server cooldown efficiency + var/capacitor_coefficient = 1 + /// The loaded map template, map_template/virtual_domain + var/datum/lazy_template/virtual_domain/generated_domain + /// The loaded safehouse, map_template/safehouse + var/datum/map_template/safehouse/generated_safehouse + /// The connected console + var/datum/weakref/console_ref + /// If the current domain was a random selection + var/domain_randomized = FALSE + /// If any threats were spawned, adds to rewards + var/domain_threats = 0 + /// Prevents multiple user actions. Handled by loading domains and cooldowns + var/is_ready = TRUE + /// List of available domains + var/list/available_domains = list() + /// Current plugged in users + var/list/datum/weakref/avatar_connection_refs = list() + /// Cached list of mutable mobs in zone for cybercops + var/list/datum/weakref/mutation_candidate_refs = list() + /// Any ghosts that have spawned in + var/list/datum/weakref/spawned_threat_refs = list() + /// Scales loot with extra players + var/multiplayer_bonus = 1.1 + ///The radio the console can speak into + var/obj/item/radio/radio + /// The amount of points in the system, used to purchase maps + var/points = 0 + /// Keeps track of the number of times someone has built a hololadder + var/retries_spent = 0 + /// Changes how much info is available on the domain + var/scanner_tier = 1 + /// Length of time it takes for the server to cool down after resetting. Here to give runners downtime so their faces don't get stuck like that + var/server_cooldown_time = 3 MINUTES + /// Applies bonuses to rewards etc + 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) + . = ..() + + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/quantum_server/LateInitialize() + . = ..() + + if(isnull(console_ref)) + find_console() + + radio = new(src) + radio.set_frequency(FREQ_SUPPLY) + radio.subspace_transmission = TRUE + radio.canhear_range = 0 + radio.recalculateChannels() + + RegisterSignals(src, list(COMSIG_MACHINERY_BROKEN, COMSIG_MACHINERY_POWER_LOST), PROC_REF(on_broken)) + RegisterSignal(src, COMSIG_QDELETING, PROC_REF(on_delete)) + RegisterSignal(src, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + RegisterSignal(src, COMSIG_BITRUNNER_SPAWN_GLITCH, PROC_REF(on_threat_created)) + + // This further gets sorted in the client by cost so it's random and grouped + available_domains = shuffle(subtypesof(/datum/lazy_template/virtual_domain)) + +/obj/machinery/quantum_server/Destroy(force) + . = ..() + + available_domains.Cut() + mutation_candidate_refs.Cut() + 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) + return ..() + + set_light_color(is_ready ? LIGHT_COLOR_BABY_BLUE : LIGHT_COLOR_FIRE) + set_light(2, 1.5) + + return ..() + +/obj/machinery/quantum_server/update_icon_state() + if(isnull(generated_domain) || !is_operational) + icon_state = base_icon_state + return ..() + + icon_state = "[base_icon_state]_[is_ready ? "on" : "off"]" + return ..() + +/obj/machinery/quantum_server/crowbar_act(mob/living/user, obj/item/crowbar) + . = ..() + + if(!is_ready) + balloon_alert(user, "it's scalding hot!") + return TRUE + if(length(avatar_connection_refs)) + balloon_alert(user, "all clients must disconnect!") + return TRUE + if(default_deconstruction_crowbar(crowbar)) + return TRUE + return FALSE + +/obj/machinery/quantum_server/screwdriver_act(mob/living/user, obj/item/screwdriver) + . = ..() + + if(!is_ready) + balloon_alert(user, "it's scalding hot!") + return TRUE + if(default_deconstruction_screwdriver(user, "[base_icon_state]_panel", icon_state, screwdriver)) + return TRUE + return FALSE + +/obj/machinery/quantum_server/RefreshParts() + . = ..() + + var/capacitor_rating = 1.15 + var/datum/stock_part/capacitor/cap = locate() in component_parts + capacitor_rating -= cap.tier * 0.15 + + capacitor_coefficient = capacitor_rating + + var/datum/stock_part/scanning_module/scanner = locate() in component_parts + if(scanner) + scanner_tier = scanner.tier + + var/servo_rating = 0 + for(var/datum/stock_part/servo/servo in component_parts) + servo_rating += servo.tier * 0.1 + + servo_bonus = servo_rating + + SEND_SIGNAL(src, COMSIG_BITRUNNER_SERVER_UPGRADED, servo_rating) diff --git a/code/modules/bitrunning/server/signal_handlers.dm b/code/modules/bitrunning/server/signal_handlers.dm new file mode 100644 index 00000000000..b0464b351fa --- /dev/null +++ b/code/modules/bitrunning/server/signal_handlers.dm @@ -0,0 +1,107 @@ +/// If broken via signal, disconnects all users +/obj/machinery/quantum_server/proc/on_broken(datum/source) + SIGNAL_HANDLER + + if(isnull(generated_domain)) + return + + SEND_SIGNAL(src, COMSIG_BITRUNNER_SEVER_AVATAR) + +/// Whenever a corpse spawner makes a new corpse, add it to the list of potential mutations +/obj/machinery/quantum_server/proc/on_corpse_spawned(datum/source, mob/living/corpse) + SIGNAL_HANDLER + + mutation_candidate_refs.Add(WEAKREF(corpse)) + +/// Being qdeleted - make sure the circuit and connected mobs go with it +/obj/machinery/quantum_server/proc/on_delete(datum/source) + SIGNAL_HANDLER + + if(generated_domain) + SEND_SIGNAL(src, COMSIG_BITRUNNER_SEVER_AVATAR) + scrub_vdom() + + if(is_ready) + return + // in case they're trying to cheese cooldown + var/obj/item/circuitboard/machine/quantum_server/circuit = locate(/obj/item/circuitboard/machine/quantum_server) in contents + if(circuit) + qdel(circuit) + +/// Handles examining the server. Shows cooldown time and efficiency. +/obj/machinery/quantum_server/proc/on_examine(datum/source, mob/examiner, list/examine_text) + SIGNAL_HANDLER + + examine_text += span_infoplain("Can be resource intensive to run. Ensure adequate power supply.") + + if(capacitor_coefficient < 1) + examine_text += span_infoplain("Its coolant capacity reduces cooldown time by [(1 - capacitor_coefficient) * 100]%.") + + if(servo_bonus > 0.2) + examine_text += span_infoplain("Its manipulation potential is increasing rewards by [servo_bonus]x.") + examine_text += span_infoplain("Injury from unsafe ejection reduced [servo_bonus * 100]%.") + + if(!is_ready) + examine_text += span_notice("It is currently cooling down. Give it a few moments.") + return + +/// Whenever something enters the send tiles, check if it's a loot crate. If so, alert players. +/obj/machinery/quantum_server/proc/on_goal_turf_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs) + SIGNAL_HANDLER + + if(!istype(arrived, /obj/structure/closet/crate/secure/bitrunning/encrypted)) + return + + var/obj/structure/closet/crate/secure/bitrunning/encrypted/loot_crate = arrived + if(!istype(loot_crate)) + return + + for(var/mob/person in loot_crate.contents) + if(isnull(person.mind)) + person.forceMove(get_turf(loot_crate)) + + var/datum/component/avatar_connection/connection = person.GetComponent(/datum/component/avatar_connection) + connection?.full_avatar_disconnect() + + spark_at_location(loot_crate) + qdel(loot_crate) + SEND_SIGNAL(src, COMSIG_BITRUNNER_DOMAIN_COMPLETE, arrived, generated_domain.reward_points) + generate_loot() + +/// Handles examining the server. Shows cooldown time and efficiency. +/obj/machinery/quantum_server/proc/on_goal_turf_examined(datum/source, mob/examiner, list/examine_text) + SIGNAL_HANDLER + + examine_text += span_info("Beneath your gaze, the floor pulses subtly with streams of encoded data.") + examine_text += span_info("It seems to be part of the location designated for retrieving encrypted payloads.") + +/// Scans over the inbound created_atoms from lazy templates +/obj/machinery/quantum_server/proc/on_template_loaded(datum/lazy_template/source, list/created_atoms) + SIGNAL_HANDLER + + for(var/thing in created_atoms) + if(isliving(thing)) // so we can mutate them + var/mob/living/creature = thing + + if(creature.can_be_cybercop) + mutation_candidate_refs.Add(WEAKREF(creature)) + continue + + if(istype(thing, /obj/effect/mob_spawn/ghost_role)) // so we get threat alerts + RegisterSignal(thing, COMSIG_GHOSTROLE_SPAWNED, PROC_REF(on_threat_created)) + continue + + if(istype(thing, /obj/effect/mob_spawn/corpse)) // corpses are valid targets too + var/obj/effect/mob_spawn/corpse/spawner = thing + + mutation_candidate_refs.Add(spawner.spawned_mob_ref) + + UnregisterSignal(source, COMSIG_LAZY_TEMPLATE_LOADED) + +/// Handles when cybercops are summoned into the area or ghosts click a ghost role spawner +/obj/machinery/quantum_server/proc/on_threat_created(datum/source, mob/living/threat) + SIGNAL_HANDLER + + domain_threats += 1 + spawned_threat_refs.Add(WEAKREF(threat)) + SEND_SIGNAL(src, COMSIG_BITRUNNER_THREAT_CREATED) // notify players diff --git a/code/modules/bitrunning/server/util.dm b/code/modules/bitrunning/server/util.dm new file mode 100644 index 00000000000..1d35e86de50 --- /dev/null +++ b/code/modules/bitrunning/server/util.dm @@ -0,0 +1,142 @@ +#define REDACTED "???" +#define MAX_DISTANCE 4 // How far crates can spawn from the server + +/// Resets the cooldown state and updates icons +/obj/machinery/quantum_server/proc/cool_off() + is_ready = TRUE + update_appearance() + radio.talk_into(src, "Thermal systems within operational parameters. Proceeding to domain configuration.", RADIO_CHANNEL_SUPPLY) + +/// Attempts to connect to a quantum console +/obj/machinery/quantum_server/proc/find_console() + var/obj/machinery/computer/quantum_console/console = console_ref?.resolve() + if(console) + return console + + for(var/direction in GLOB.cardinals) + var/obj/machinery/computer/quantum_console/nearby_console = locate(/obj/machinery/computer/quantum_console, get_step(src, direction)) + if(nearby_console) + console_ref = WEAKREF(nearby_console) + nearby_console.server_ref = WEAKREF(src) + return nearby_console + +/// Compiles a list of available domains. +/obj/machinery/quantum_server/proc/get_available_domains() + var/list/levels = list() + + for(var/datum/lazy_template/virtual_domain/domain as anything in available_domains) + if(initial(domain.test_only)) + continue + var/can_view = initial(domain.difficulty) < scanner_tier && initial(domain.cost) <= points + 5 + var/can_view_reward = initial(domain.difficulty) < (scanner_tier + 1) && initial(domain.cost) <= points + 3 + + levels += list(list( + "cost" = initial(domain.cost), + "desc" = can_view ? initial(domain.desc) : "Limited scanning capabilities. Cannot infer domain details.", + "difficulty" = initial(domain.difficulty), + "id" = initial(domain.key), + "name" = can_view ? initial(domain.name) : REDACTED, + "reward" = can_view_reward ? initial(domain.reward_points) : REDACTED, + )) + + return levels + +/// If there are hosted minds, attempts to get a list of their current virtual bodies w/ vitals +/obj/machinery/quantum_server/proc/get_avatar_data() + var/list/hosted_avatars = list() + + for(var/datum/weakref/avatar_ref in avatar_connection_refs) + var/datum/component/avatar_connection/connection = avatar_ref.resolve() + if(isnull(connection)) + avatar_connection_refs.Remove(connection) + continue + + var/mob/living/creature = connection.parent + var/mob/living/pilot = connection.old_body_ref?.resolve() + + hosted_avatars += list(list( + "health" = creature.health, + "name" = creature.name, + "pilot" = pilot, + "brute" = creature.get_damage_amount(BRUTE), + "burn" = creature.get_damage_amount(BURN), + "tox" = creature.get_damage_amount(TOX), + "oxy" = creature.get_damage_amount(OXY), + )) + + return hosted_avatars + +/// Gets a random available domain given the current points. Weighted towards higher cost domains. +/obj/machinery/quantum_server/proc/get_random_domain_id() + if(points < 1) + return + + var/list/random_domains = list() + var/total_cost = 0 + + for(var/datum/lazy_template/virtual_domain/available as anything in subtypesof(/datum/lazy_template/virtual_domain)) + var/init_cost = initial(available.cost) + if(!initial(available.test_only) && init_cost > 0 && init_cost < 4 && init_cost <= points) + random_domains += list(list( + cost = init_cost, + id = initial(available.key), + )) + + var/random_value = rand(0, total_cost) + var/accumulated_cost = 0 + + for(var/available as anything in random_domains) + accumulated_cost += available["cost"] + if(accumulated_cost >= random_value) + domain_randomized = TRUE + return available["id"] + +/// Gets all mobs originally generated by the loaded domain and returns a list that are capable of being antagged +/obj/machinery/quantum_server/proc/get_valid_domain_targets() + // A: No one is playing + // B: The domain is not loaded + // C: The domain is shutting down + // D: There are no mobs + if(!length(avatar_connection_refs) || isnull(generated_domain) || !is_ready || !is_operational || !length(mutation_candidate_refs)) + return list() + + for(var/datum/weakref/creature_ref as anything in mutation_candidate_refs) + var/mob/living/creature = creature_ref.resolve() + if(isnull(creature) || creature.mind) + mutation_candidate_refs.Remove(creature_ref) + + 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) + + return length(receive_turfs) > 0 + +/// Finds any mobs with minds in the zones and gives them the bad news +/obj/machinery/quantum_server/proc/notify_spawned_threats() + for(var/datum/weakref/baddie_ref as anything in spawned_threat_refs) + var/mob/living/baddie = baddie_ref.resolve() + if(isnull(baddie) || baddie.stat >= UNCONSCIOUS || isnull(baddie.mind)) + continue + + baddie.throw_alert( + ALERT_BITRUNNER_RESET, + /atom/movable/screen/alert/bitrunning/qserver_threat_deletion, + new_master = src, + ) + + 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) + var/datum/effect_system/spark_spread/quantum/sparks = new() + sparks.set_up(5, 1, get_turf(crate)) + sparks.start() + +#undef REDACTED +#undef MAX_DISTANCE diff --git a/code/modules/bitrunning/turfs.dm b/code/modules/bitrunning/turfs.dm new file mode 100644 index 00000000000..93dce1789c4 --- /dev/null +++ b/code/modules/bitrunning/turfs.dm @@ -0,0 +1,14 @@ +/turf/open/floor/bitrunning_transport + name = "circuit floor" + icon = 'icons/turf/floors.dmi' + desc = "Looks complex. You can see the circuits running through the floor." + icon_state = "bitrunning" + +/turf/closed/indestructible/binary + name = "tear in the fabric of reality" + icon = 'icons/turf/floors.dmi' + icon_state = "binary" + +/obj/effect/baseturf_helper/virtual_domain + name = "virtual domain baseturf editor" + baseturf = /turf/open/indestructible/binary diff --git a/code/modules/bitrunning/virtual_domain/domains/ash_drake.dm b/code/modules/bitrunning/virtual_domain/domains/ash_drake.dm new file mode 100644 index 00000000000..02bb91abc58 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/ash_drake.dm @@ -0,0 +1,18 @@ +/datum/lazy_template/virtual_domain/ash_drake + name = "Ashen Inferno" + cost = BITRUNNER_COST_MEDIUM + desc = "Home of the ash drake, a powerful dragon that scours the surface of Lavaland." + difficulty = BITRUNNER_DIFFICULTY_MEDIUM + forced_outfit = /datum/outfit/job/miner + key = "ash_drake" + map_name = "ash_drake" + reward_points = BITRUNNER_REWARD_MEDIUM + safehouse_path = /datum/map_template/safehouse/lavaland_boss + +/mob/living/simple_animal/hostile/megafauna/dragon/virtual_domain + can_be_cybercop = FALSE + crusher_loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + health = 1600 + loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + maxHealth = 1600 + true_spawn = FALSE diff --git a/code/modules/bitrunning/virtual_domain/domains/beach_bar.dm b/code/modules/bitrunning/virtual_domain/domains/beach_bar.dm new file mode 100644 index 00000000000..871c2cb1338 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/beach_bar.dm @@ -0,0 +1,22 @@ +/datum/lazy_template/virtual_domain/beach_bar + name = "Beach Bar" + desc = "A cheerful seaside haven where friendly skeletons serve up drinks. Say, how'd you guys get so dead?" + extra_loot = list(/obj/item/toy/beach_ball = 1) + help_text = "This place is running on a skeleton crew, and they don't seem to be too keen to share details. \ + Maybe a few drinks of liquid charm will get the spirits up. As the saying goes, if you can't beat 'em, join 'em." + key = "beach_bar" + map_name = "beach_bar" + safehouse_path = /datum/map_template/safehouse/mine + +/obj/item/reagent_containers/cup/glass/drinkingglass/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) + . = ..() + + AddComponent(/datum/component/bitrunning_points, \ + signal_type = COMSIG_GLASS_DRANK, \ + points_per_signal = 0.5, \ + ) diff --git a/code/modules/bitrunning/virtual_domain/domains/blood_drunk_miner.dm b/code/modules/bitrunning/virtual_domain/domains/blood_drunk_miner.dm new file mode 100644 index 00000000000..abf2e0fc5a9 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/blood_drunk_miner.dm @@ -0,0 +1,18 @@ +/datum/lazy_template/virtual_domain/blood_drunk_miner + name = "Sanguine Excavation" + cost = BITRUNNER_COST_MEDIUM + desc = "Few escape the surface of Lavaland without a few scars. Some remain, maddened by the hunt." + difficulty = BITRUNNER_DIFFICULTY_MEDIUM + forced_outfit = /datum/outfit/job/miner + key = "blood_drunk_miner" + map_name = "blood_drunk_miner" + reward_points = BITRUNNER_REWARD_MEDIUM + safehouse_path = /datum/map_template/safehouse/lavaland_boss + +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/virtual_domain + can_be_cybercop = FALSE + crusher_loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + health = 1600 + loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + maxHealth = 1600 + true_spawn = FALSE diff --git a/code/modules/bitrunning/virtual_domain/domains/bubblegum.dm b/code/modules/bitrunning/virtual_domain/domains/bubblegum.dm new file mode 100644 index 00000000000..bede97177cb --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/bubblegum.dm @@ -0,0 +1,19 @@ +/datum/lazy_template/virtual_domain/bubblegum + name = "Blood-Soaked Lair" + cost = BITRUNNER_COST_HIGH + desc = "King of the slaughter demons. Bubblegum is a massive, hulking beast with a penchant for violence." + difficulty = BITRUNNER_DIFFICULTY_HIGH + extra_loot = list(/obj/item/toy/plush/bubbleplush = 1) + forced_outfit = /datum/outfit/job/miner + key = "bubblegum" + map_name = "bubblegum" + reward_points = BITRUNNER_REWARD_HIGH + safehouse_path = /datum/map_template/safehouse/lavaland_boss + +/mob/living/simple_animal/hostile/megafauna/bubblegum/virtual_domain + can_be_cybercop = FALSE + crusher_loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + health = 2000 + loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + maxHealth = 2000 + true_spawn = FALSE diff --git a/code/modules/bitrunning/virtual_domain/domains/clown_planet.dm b/code/modules/bitrunning/virtual_domain/domains/clown_planet.dm new file mode 100644 index 00000000000..92f000c9cf3 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/clown_planet.dm @@ -0,0 +1,13 @@ +/datum/lazy_template/virtual_domain/clown_planet + name = "Clown Planet" + cost = BITRUNNER_COST_LOW + desc = "In the deep, dark reaches of space, there is only Honk." + difficulty = BITRUNNER_DIFFICULTY_LOW + extra_loot = list(/obj/item/bikehorn = 1) + forced_outfit = /datum/outfit/job/clown + help_text = "The trials of the Honkitude have begun. The sound of bike horns wailing in the distance. \ + this realm- some sort of puzzle, has existed in legend as the final test of just how silly you are." + key = "clown_planet" + map_name = "clown_planet" + reward_points = BITRUNNER_REWARD_LOW + safehouse_path = /datum/map_template/safehouse/mine diff --git a/code/modules/bitrunning/virtual_domain/domains/colossus.dm b/code/modules/bitrunning/virtual_domain/domains/colossus.dm new file mode 100644 index 00000000000..35ba4eee0ca --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/colossus.dm @@ -0,0 +1,18 @@ +/datum/lazy_template/virtual_domain/colossus + name = "Celestial Trial" + cost = BITRUNNER_COST_HIGH + desc = "A massive, ancient beast named the Colossus. Judgment comes." + difficulty = BITRUNNER_DIFFICULTY_HIGH + forced_outfit = /datum/outfit/job/miner + key = "colossus" + map_name = "colossus" + reward_points = BITRUNNER_REWARD_HIGH + safehouse_path = /datum/map_template/safehouse/lavaland_boss + +/mob/living/simple_animal/hostile/megafauna/colossus/virtual_domain + can_be_cybercop = FALSE + crusher_loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + health = 2000 + maxHealth = 2000 + true_spawn = FALSE diff --git a/code/modules/bitrunning/virtual_domain/domains/gondola_asteroid.dm b/code/modules/bitrunning/virtual_domain/domains/gondola_asteroid.dm new file mode 100644 index 00000000000..4deacb4f9c5 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/gondola_asteroid.dm @@ -0,0 +1,39 @@ +/datum/lazy_template/virtual_domain/gondola_asteroid + name = "Gondola Asteroid" + desc = "An asteroid home to a bountiful forest of gondolas. Peaceful." + map_name = "gondola_asteroid" + help_text = "What a lovely forest. There's a loot crate here in the middle of the map. \ + Hmm... It doesn't budge. The gondolas don't seem to have any trouble moving it, though. \ + I bet there's a way to move it myself." + key = "gondola_asteroid" + map_name = "gondola_asteroid" + safehouse_path = /datum/map_template/safehouse/shuttle_space + +/// Very pushy gondolas, great for moving loot crates. +/obj/structure/closet/crate/secure/bitrunning/encrypted/gondola + move_resist = MOVE_FORCE_STRONG + +/mob/living/simple_animal/pet/gondola/virtual_domain + health = 50 + loot = list(/obj/effect/decal/cleanable/blood/gibs, /obj/item/stack/sheet/animalhide/gondola = 1, /obj/item/food/meat/slab/gondola/virtual_domain = 1) + maxHealth = 50 + move_force = MOVE_FORCE_VERY_STRONG + move_resist = MOVE_FORCE_STRONG + +/obj/item/food/meat/slab/gondola/virtual_domain + food_reagents = list( + /datum/reagent/consumable/nutriment/protein = 4, + /datum/reagent/gondola_mutation_toxin/virtual_domain = 5, + ) + +/datum/reagent/gondola_mutation_toxin/virtual_domain + name = "Advanced Tranquility" + +/datum/reagent/gondola_mutation_toxin/virtual_domain/expose_mob(mob/living/exposed_mob, methods = TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) + . = ..() + if((methods & (PATCH|INGEST|INJECT)) || ((methods & VAPOR) && prob(min(reac_volume,100)*(1 - touch_protection)))) + exposed_mob.ForceContractDisease(new /datum/disease/transformation/gondola/virtual_domain(), FALSE, TRUE) + +/datum/disease/transformation/gondola/virtual_domain + stage_prob = 9 + new_form = /mob/living/simple_animal/pet/gondola/virtual_domain diff --git a/code/modules/bitrunning/virtual_domain/domains/hierophant.dm b/code/modules/bitrunning/virtual_domain/domains/hierophant.dm new file mode 100644 index 00000000000..142623f4f81 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/hierophant.dm @@ -0,0 +1,18 @@ +/datum/lazy_template/virtual_domain/hierophant + name = "Zealot Arena" + cost = BITRUNNER_COST_HIGH + desc = "Dance, puppets, dance!" + difficulty = BITRUNNER_DIFFICULTY_HIGH + forced_outfit = /datum/outfit/job/miner + key = "hierophant" + map_name = "hierophant" + reward_points = BITRUNNER_REWARD_HIGH + safehouse_path = /datum/map_template/safehouse/lavaland_boss + +/mob/living/simple_animal/hostile/megafauna/hierophant/virtual_domain + can_be_cybercop = FALSE + crusher_loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + health = 1700 + loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + maxHealth = 1700 + true_spawn = FALSE diff --git a/code/modules/bitrunning/virtual_domain/domains/legion.dm b/code/modules/bitrunning/virtual_domain/domains/legion.dm new file mode 100644 index 00000000000..f1ba146f380 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/legion.dm @@ -0,0 +1,20 @@ +/datum/lazy_template/virtual_domain/legion + name = "Chamber of Echoes" + cost = BITRUNNER_COST_MEDIUM + desc = "A chilling realm that houses Legion's necropolis. Those who succumb to it are forever damned." + difficulty = BITRUNNER_DIFFICULTY_MEDIUM + forced_outfit = /datum/outfit/job/miner + key = "legion" + map_name = "legion" + reward_points = BITRUNNER_REWARD_MEDIUM + safehouse_path = /datum/map_template/safehouse/lavaland_boss + +/mob/living/simple_animal/hostile/megafauna/legion/virtual_domain + can_be_cybercop = FALSE + crusher_loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + health = 1500 + loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + maxHealth = 1500 + true_spawn = FALSE + +// You may be thinking, what about those mini-legions? They're not part of the initial created_atoms list diff --git a/code/modules/bitrunning/virtual_domain/domains/pipedream.dm b/code/modules/bitrunning/virtual_domain/domains/pipedream.dm new file mode 100644 index 00000000000..fd54ef6ca48 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/pipedream.dm @@ -0,0 +1,101 @@ +/datum/lazy_template/virtual_domain/pipedream + name = "Disposal Pipe Factory" + cost = BITRUNNER_COST_LOW + desc = "An abandoned and infested factory manufacturing disposal pipes." + difficulty = BITRUNNER_DIFFICULTY_MEDIUM + extra_loot = list(/obj/item/stack/pipe_cleaner_coil/random/five = 1) + help_text = "Not long ago, this place was thriving with activity. The workers \ + seemed to have left in a hurry, and now productivity is in the bin. Something \ + must have trashed the place, but what?" + key = "pipedream" + map_name = "pipedream" + reward_points = BITRUNNER_REWARD_LOW + safehouse_path = /datum/map_template/safehouse/shuttle + +// ID Trims +/datum/id_trim/factory + assignment = "Factory Worker" + trim_state = "trim_cargotechnician" + department_color = COLOR_CARGO_BROWN + subdepartment_color = COLOR_CARGO_BROWN + sechud_icon_state = SECHUD_CARGO_TECHNICIAN + access = list( + ACCESS_AWAY_SUPPLY + ) + +/datum/id_trim/factory/qm + assignment = "Factory Quartermaster" + trim_state = "trim_quartermaster" + department_color = COLOR_COMMAND_BLUE + subdepartment_color = COLOR_CARGO_BROWN + department_state = "departmenthead" + sechud_icon_state = SECHUD_QUARTERMASTER + access = list( + ACCESS_AWAY_SUPPLY, + ACCESS_AWAY_COMMAND + ) + +// ID Cards +/obj/item/card/id/advanced/factory + name = "factory worker ID" + trim = /datum/id_trim/factory + +/obj/item/card/id/advanced/factory/qm + name = "factory quartermaster ID" + trim = /datum/id_trim/factory/qm + +//Outfits +/datum/outfit/factory + name = "Factory Worker" + + id_trim = /datum/id_trim/factory + id = /obj/item/card/id/advanced/ + uniform = /obj/item/clothing/under/rank/cargo/tech + suit = /obj/item/clothing/suit/hazardvest + belt = /obj/item/radio + gloves = /obj/item/clothing/gloves/color/black + head = /obj/item/clothing/head/soft/yellow + shoes = /obj/item/clothing/shoes/workboots + l_pocket = /obj/item/flashlight/seclite + +/datum/outfit/factory/guard + name = "Factory Guard" + + uniform = /obj/item/clothing/under/rank/security/officer/grey + suit = /obj/item/clothing/suit/armor/vest/alt + belt = /obj/item/radio + gloves = /obj/item/clothing/gloves/color/black + head = /obj/item/clothing/head/soft/sec + shoes = /obj/item/clothing/shoes/jackboots/sec + l_pocket = /obj/item/restraints/handcuffs + r_pocket = /obj/item/assembly/flash/handheld + +/datum/outfit/factory/qm + name = "Factory Quatermaster" + + id_trim = /datum/id_trim/factory/qm + id = /obj/item/card/id/advanced/silver + uniform = /obj/item/clothing/under/rank/cargo/qm + belt = /obj/item/radio + gloves = /obj/item/clothing/gloves/color/black + head = /obj/item/clothing/head/soft/yellow + shoes = /obj/item/clothing/shoes/jackboots/sec + l_pocket = /obj/item/melee/baton/telescopic + r_pocket = /obj/item/stamp/head/qm + +// Corpses +/obj/effect/mob_spawn/corpse/human/factory + name = "Factory Worker" + outfit = /datum/outfit/factory + icon_state = "corpsecargotech" + +/obj/effect/mob_spawn/corpse/human/factory/guard + name = "Factory Guard" + outfit = /datum/outfit/factory/guard + icon_state = "corpsecargotech" + +/obj/effect/mob_spawn/corpse/human/factory/qm + name = "Factory Quartermaster" + outfit = /datum/outfit/factory/qm + icon_state = "corpsecargotech" + diff --git a/code/modules/bitrunning/virtual_domain/domains/pirates.dm b/code/modules/bitrunning/virtual_domain/domains/pirates.dm new file mode 100644 index 00000000000..52d86a71211 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/pirates.dm @@ -0,0 +1,10 @@ +/datum/lazy_template/virtual_domain/pirates + name = "Corsair Cove" + cost = BITRUNNER_COST_MEDIUM + desc = "Battle your way to the hidden treasure, seize the booty, and make a swift escape before the pirates turn the tide." + difficulty = BITRUNNER_DIFFICULTY_MEDIUM + help_text = "Put on the provided outfits to blend in, then battle your way through the hostile pirates. \ + Grab the treasure and get out before you're overwhelmed!" + key = "pirates" + map_name = "pirates" + reward_points = BITRUNNER_REWARD_MEDIUM diff --git a/code/modules/bitrunning/virtual_domain/domains/stairs_and_cliffs.dm b/code/modules/bitrunning/virtual_domain/domains/stairs_and_cliffs.dm new file mode 100644 index 00000000000..2d9bcca3645 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/stairs_and_cliffs.dm @@ -0,0 +1,29 @@ +/datum/lazy_template/virtual_domain/stairs_and_cliffs + name = "Glacier Grind" + cost = BITRUNNER_COST_LOW + desc = "A treacherous climb few calves can survive. Great cardio though." + help_text = "Ever heard of 'Snakes and Ladders'? It's like that, but with \ + instead of ladders its stairs and instead of snakes its a steep drop down a \ + cliff into rough rocks or liquid plasma." + extra_loot = list(/obj/item/clothing/suit/costume/snowman = 2) + difficulty = BITRUNNER_DIFFICULTY_LOW + forced_outfit = /datum/outfit/job/virtual_domain_iceclimber + key = "stairs_and_cliffs" + map_name = "stairs_and_cliffs" + reward_points = BITRUNNER_REWARD_MEDIUM + safehouse_path = /datum/map_template/safehouse/ice + +/turf/open/cliff/snowrock/virtual_domain + name = "icy cliff" + initial_gas_mix = "o2=22;n2=82;TEMP=180" + +/turf/open/lava/plasma/virtual_domain + name = "plasma lake" + initial_gas_mix = "o2=22;n2=82;TEMP=180" + +/datum/outfit/job/virtual_domain_iceclimber + name = "Ice Climber" + + uniform = /obj/item/clothing/under/color/grey + backpack = /obj/item/storage/backpack/duffelbag + shoes = /obj/item/clothing/shoes/winterboots diff --git a/code/modules/bitrunning/virtual_domain/domains/syndicate_assault.dm b/code/modules/bitrunning/virtual_domain/domains/syndicate_assault.dm new file mode 100644 index 00000000000..bae0da6874d --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/syndicate_assault.dm @@ -0,0 +1,13 @@ +/datum/lazy_template/virtual_domain/syndicate_assault + name = "Syndicate Assault" + cost = BITRUNNER_COST_MEDIUM + desc = "Board the enemy ship and recover the stolen cargo." + difficulty = BITRUNNER_DIFFICULTY_MEDIUM + extra_loot = list(/obj/item/toy/plush/nukeplushie = 1) + help_text = "A group of Syndicate operatives have stolen valuable cargo from the station. \ + They have boarded their ship and are attempting to escape. Infiltrate their ship and recover \ + the crate. Be careful, they are extremely armed." + key = "syndicate_assault" + map_name = "syndicate_assault" + reward_points = BITRUNNER_REWARD_MEDIUM + safehouse_path = /datum/map_template/safehouse/shuttle diff --git a/code/modules/bitrunning/virtual_domain/domains/test_only.dm b/code/modules/bitrunning/virtual_domain/domains/test_only.dm new file mode 100644 index 00000000000..6e5e852fb5c --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/test_only.dm @@ -0,0 +1,11 @@ +/// Used for unit tests only. Skipped in UI. +/datum/lazy_template/virtual_domain/test_only + name = "Test Only" + key = "test_only" + map_name = "test_only" + test_only = TRUE + safehouse_path = /datum/map_template/safehouse/test_only + +/datum/lazy_template/virtual_domain/test_only/expensive + key = "test_only_expensive" + cost = 3 diff --git a/code/modules/bitrunning/virtual_domain/domains/vaporwave.dm b/code/modules/bitrunning/virtual_domain/domains/vaporwave.dm new file mode 100644 index 00000000000..45d4abec983 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/vaporwave.dm @@ -0,0 +1,10 @@ +/datum/lazy_template/virtual_domain/vaporwave + name = "Cosmic Vestige" + cost = BITRUNNER_COST_EXTREME + desc = "Suspended in the silent void of space, the Neon Relic is a haunting echo of a retro-futuristic era." + difficulty = BITRUNNER_DIFFICULTY_NONE + extra_loot = list(/obj/item/stack/spacecash/c500 = 3) + key = "vaporwave" + map_name = "vaporwave" + reward_points = BITRUNNER_REWARD_EXTREME + safehouse_path = /datum/map_template/safehouse/shuttle_space diff --git a/code/modules/bitrunning/virtual_domain/domains/wendigo.dm b/code/modules/bitrunning/virtual_domain/domains/wendigo.dm new file mode 100644 index 00000000000..fcad3db6faf --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/wendigo.dm @@ -0,0 +1,19 @@ +/datum/lazy_template/virtual_domain/wendigo + name = "Glacial Devourer" + cost = BITRUNNER_COST_HIGH + desc = "Legends speak of the ravenous Wendigo hidden deep within the caves of Icemoon." + difficulty = BITRUNNER_DIFFICULTY_HIGH + forced_outfit = /datum/outfit/job/miner + key = "wendigo" + map_name = "wendigo" + reward_points = BITRUNNER_REWARD_HIGH + safehouse_path = /datum/map_template/safehouse/lavaland_boss + +/mob/living/simple_animal/hostile/megafauna/wendigo/virtual_domain + can_be_cybercop = FALSE + crusher_loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + guaranteed_butcher_results = list(/obj/item/wendigo_skull = 1) + health = 2000 + loot = list(/obj/structure/closet/crate/secure/bitrunning/encrypted) + maxHealth = 2000 + true_spawn = FALSE diff --git a/code/modules/bitrunning/virtual_domain/domains/xeno_nest.dm b/code/modules/bitrunning/virtual_domain/domains/xeno_nest.dm new file mode 100644 index 00000000000..2bd4105e13c --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/domains/xeno_nest.dm @@ -0,0 +1,12 @@ +/datum/lazy_template/virtual_domain/xeno_nest + name = "Xeno Infestation" + cost = BITRUNNER_COST_LOW + desc = "Our ship scanners have detected lifeforms of unknown origin. Friendly attempts to contact them have failed." + difficulty = BITRUNNER_DIFFICULTY_LOW + extra_loot = list(/obj/item/toy/plush/rouny = 1) + help_text = "You are on a barren planet filled with hostile creatures. There is a crate here, not hidden, \ + simply protected. Expect resistance." + key = "xeno_nest" + map_name = "xeno_nest" + reward_points = BITRUNNER_REWARD_LOW + safehouse_path = /datum/map_template/safehouse/shuttle diff --git a/code/modules/bitrunning/virtual_domain/safehouses.dm b/code/modules/bitrunning/virtual_domain/safehouses.dm new file mode 100644 index 00000000000..bb42f690ac7 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/safehouses.dm @@ -0,0 +1,53 @@ +/** + * # Safe Houses + * The starting point for virtual domains. + * Create your own: Read the readme file in the '_maps/safehouses' folder. + */ +/datum/map_template/safehouse + name = "virtual domain: safehouse" + + returns_created_atoms = TRUE + /// The map file to load + var/filename = "den.dmm" + +/datum/map_template/safehouse/New() + mappath = "_maps/safehouses/" + filename + ..(path = mappath) + +/datum/map_template/safehouse/test_only + filename = "test_only_safehouse.dmm" + + +/// The default safehouse map template. +/datum/map_template/safehouse/wood + filename = "wood.dmm" + +/datum/map_template/safehouse/den + filename = "den.dmm" + +/datum/map_template/safehouse/dig + filename = "dig.dmm" + +/datum/map_template/safehouse/shuttle + filename = "shuttle.dmm" + +// Has space tiles on the four corners. +/datum/map_template/safehouse/shuttle_space + filename = "shuttle_space.dmm" + +/datum/map_template/safehouse/mine + filename = "mine.dmm" + +// Comes preloaded with mining combat gear. +/datum/map_template/safehouse/lavaland_boss + filename = "lavaland_boss.dmm" + +// Chill out +/datum/map_template/safehouse/ice + filename = "ice.dmm" + +/** + * Your safehouse here + * /datum/map_template/safehouse/your_type + * filename = "your_map.dmm" + */ diff --git a/code/modules/bitrunning/virtual_domain/virtual_domain.dm b/code/modules/bitrunning/virtual_domain/virtual_domain.dm new file mode 100644 index 00000000000..c2bd193f4e9 --- /dev/null +++ b/code/modules/bitrunning/virtual_domain/virtual_domain.dm @@ -0,0 +1,34 @@ +/** + * # Virtual Domains + * This loads a base level, then users can select the preset upon it. + * Create your own: Read the readme file in the '_maps/virtual_domains' folder. + */ +/datum/lazy_template/virtual_domain + map_dir = "_maps/virtual_domains" + map_name = "None" + key = "Virtual Domain" + + /// Cost of this map to load + var/cost = BITRUNNER_COST_NONE + /// The description of the map + var/desc = "A map." + /// The 'difficulty' of the map, which affects the ui and ability to scan info. + var/difficulty = BITRUNNER_DIFFICULTY_NONE + /// An assoc list of typepath/amount to spawn on completion. Not weighted - the value is the amount + var/list/extra_loot + /// The map file to load + var/filename = "virtual_domain.dmm" + /// Any outfit that you wish to force on avatars. Overrides preferences + var/datum/outfit/forced_outfit + /// Information given to connected clients via ability + var/help_text + // Name to show in the UI + var/name = "Virtual Domain" + /// Points to reward for completion. Used to purchase new domains and calculate ore rewards. + var/reward_points = BITRUNNER_REWARD_MIN + /// The start time of the map. Used to calculate time taken + var/start_time + /// This map is specifically for unit tests. Shouldn't display in game + var/test_only = FALSE + /// The safehouse to load into the map + var/datum/map_template/safehouse/safehouse_path = /datum/map_template/safehouse/den diff --git a/code/modules/capture_the_flag/ctf_player_component.dm b/code/modules/capture_the_flag/ctf_player_component.dm index 0bf37b979de..d3abc0f2571 100644 --- a/code/modules/capture_the_flag/ctf_player_component.dm +++ b/code/modules/capture_the_flag/ctf_player_component.dm @@ -8,7 +8,7 @@ var/can_respawn = TRUE ///Reference to the game this player is participating in. var/datum/ctf_controller/ctf_game - ///Item dropped on death, + ///Item dropped on death, var/death_drop = /obj/effect/powerup/ammo/ctf ///Reference to players ckey, used for sending messages to them relating to CTF. var/ckey_reference @@ -22,19 +22,20 @@ var/datum/mind/true_parent = parent player_mob = true_parent.current ckey_reference = player_mob.ckey - setup_dusting() - + register_mob() + /datum/component/ctf_player/PostTransfer() if(!istype(parent, /datum/mind)) return COMPONENT_INCOMPATIBLE var/datum/mind/true_parent = parent player_mob = true_parent.current - setup_dusting() + register_mob() -///CTF players are dusted upon taking damage that puts them into critical or leaving their body. -/datum/component/ctf_player/proc/setup_dusting() +/// Called when we get a new player mob, register signals and set up the mob. +/datum/component/ctf_player/proc/register_mob() RegisterSignal(player_mob, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(damage_type_check)) RegisterSignal(player_mob, COMSIG_MOB_GHOSTIZED, PROC_REF(ctf_dust)) + ADD_TRAIT(player_mob, TRAIT_PERMANENTLY_MORTAL, CTF_TRAIT) ///Stamina and oxygen damage will not dust a player by themself. /datum/component/ctf_player/proc/damage_type_check(datum/source, damage, damage_type) diff --git a/code/modules/cargo/department_order.dm b/code/modules/cargo/department_order.dm index 972588a6355..b1573c97a5b 100644 --- a/code/modules/cargo/department_order.dm +++ b/code/modules/cargo/department_order.dm @@ -142,6 +142,12 @@ GLOBAL_LIST_INIT(department_order_cooldowns, list( if(GLOB.areas_by_type[delivery_area_type]) chosen_delivery_area = delivery_area_type break + + if(SSshuttle.supply.get_order_count(pack) == OVER_ORDER_LIMIT) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE) + say("ERROR: No more then [CARGO_MAX_ORDER] of any pack may be ordered at once") + return + department_order = new(pack, name, rank, ckey, "", null, chosen_delivery_area, null) SSshuttle.shopping_list += department_order if(!already_signalled) @@ -188,7 +194,7 @@ GLOBAL_LIST_INIT(department_order_cooldowns, list( department_delivery_areas = list(/area/station/science/research) override_access = ACCESS_RD req_one_access = REGION_ACCESS_RESEARCH - dep_groups = list("Science", "Livestock") + dep_groups = list("Science", "Livestock", "Canisters & Materials") /obj/machinery/computer/department_orders/security name = "security order console" diff --git a/code/modules/cargo/exports/materials.dm b/code/modules/cargo/exports/materials.dm index 06c52305f51..46d089b5ac5 100644 --- a/code/modules/cargo/exports/materials.dm +++ b/code/modules/cargo/exports/materials.dm @@ -2,10 +2,13 @@ cost = 5 // Cost per SHEET_MATERIAL_AMOUNT, which is 100cm3 as of May 2023. message = "cm3 of developer's tears. Please, report this on github" amount_report_multiplier = SHEET_MATERIAL_AMOUNT - var/material_id = null + var/datum/material/material_id = null export_types = list( - /obj/item/stack/sheet/mineral, /obj/item/stack/tile/mineral, - /obj/item/stack/ore, /obj/item/coin) + /obj/item/stack/sheet/mineral, + /obj/item/stack/tile/mineral, + /obj/item/stack/ore, + /obj/item/coin + ) // Yes, it's a base type containing export_types. // But it has no material_id, so any applies_to check will return false, and these types reduce amount of copypasta a lot @@ -27,17 +30,8 @@ return round(amount / SHEET_MATERIAL_AMOUNT) -// Materials. Nothing but plasma is really worth selling. Better leave it all to RnD and sell some plasma instead. - -/datum/export/material/bananium - cost = CARGO_CRATE_VALUE * 2 - material_id = /datum/material/bananium - message = "cm3 of bananium" - -/datum/export/material/diamond - cost = CARGO_CRATE_VALUE - material_id = /datum/material/diamond - message = "cm3 of diamonds" +// Materials. Static materials exist as parent types, while materials subject to the stock market have a fluid cost as determined by material/market types +// If you're adding a new material to the stock market, make sure its export type is added here. /datum/export/material/plasma cost = CARGO_CRATE_VALUE * 0.4 @@ -45,27 +39,12 @@ material_id = /datum/material/plasma message = "cm3 of plasma" -/datum/export/material/uranium - cost = CARGO_CRATE_VALUE * 0.2 - material_id = /datum/material/uranium - message = "cm3 of uranium" - -/datum/export/material/gold - cost = CARGO_CRATE_VALUE * 0.25 - material_id = /datum/material/gold - message = "cm3 of gold" - -/datum/export/material/silver - cost = CARGO_CRATE_VALUE * 0.1 - material_id = /datum/material/silver - message = "cm3 of silver" - -/datum/export/material/titanium - cost = CARGO_CRATE_VALUE * 0.25 - material_id = /datum/material/titanium - message = "cm3 of titanium" +/datum/export/material/bananium + cost = CARGO_CRATE_VALUE * 2 + material_id = /datum/material/bananium + message = "cm3 of bananium" -/datum/export/material/adamantine +/datum/export/material/diamond cost = CARGO_CRATE_VALUE material_id = /datum/material/adamantine message = "cm3 of adamantine" @@ -75,11 +54,6 @@ material_id = /datum/material/mythril message = "cm3 of mythril" -/datum/export/material/bscrystal - cost = CARGO_CRATE_VALUE * 0.6 - message = "of bluespace crystals" - material_id = /datum/material/bluespace - /datum/export/material/plastic cost = CARGO_CRATE_VALUE * 0.05 message = "cm3 of plastic" @@ -90,21 +64,6 @@ message = "cm3 of runite" material_id = /datum/material/runite -/datum/export/material/iron - cost = CARGO_CRATE_VALUE * 0.01 - message = "cm3 of iron" - material_id = /datum/material/iron - export_types = list( - /obj/item/stack/sheet/iron, /obj/item/stack/tile/iron, - /obj/item/stack/rods, /obj/item/stack/ore, /obj/item/coin) - -/datum/export/material/glass - cost = CARGO_CRATE_VALUE * 0.01 - message = "cm3 of glass" - material_id = /datum/material/glass - export_types = list(/obj/item/stack/sheet/glass, /obj/item/stack/ore, - /obj/item/shard) - /datum/export/material/hot_ice cost = CARGO_CRATE_VALUE * 0.8 message = "cm3 of Hot Ice" @@ -116,3 +75,90 @@ message = "cm3 of metallic hydrogen" material_id = /datum/material/metalhydrogen export_types = /obj/item/stack/sheet/mineral/metal_hydrogen + +/datum/export/material/market + +/datum/export/material/market/diamond + material_id = /datum/material/diamond + message = "cm3 of diamonds" + +/datum/export/material/market/uranium + material_id = /datum/material/uranium + message = "cm3 of uranium" + +/datum/export/material/market/gold + material_id = /datum/material/gold + message = "cm3 of gold" + +/datum/export/material/market/silver + material_id = /datum/material/silver + message = "cm3 of silver" + +/datum/export/material/market/titanium + material_id = /datum/material/titanium + message = "cm3 of titanium" + +/datum/export/material/market/bscrystal + message = "of bluespace crystals" + material_id = /datum/material/bluespace + export_types = list(/obj/item/stack/sheet/bluespace_crystal, /obj/item/stack/ore) //For whatever reason, bluespace crystals are not a mineral + +/datum/export/material/market/iron + message = "cm3 of iron" + material_id = /datum/material/iron + export_types = list( + /obj/item/stack/sheet/iron, + /obj/item/stack/tile/iron, + /obj/item/stack/rods, + /obj/item/stack/ore, + /obj/item/coin + ) + +/datum/export/material/market/glass + message = "cm3 of glass" + material_id = /datum/material/glass + export_types = list( + /obj/item/stack/sheet/glass, + /obj/item/stack/ore, + /obj/item/shard + ) + +/datum/export/material/market/get_cost(obj/O, apply_elastic = FALSE) + var/obj/item/I = O + var/amount = get_amount(I) + if(!amount) + return 0 + var/material_value = (SSstock_market.materials_prices[material_id]) * amount * MARKET_PROFIT_MODIFIER + return round(material_value) + +/datum/export/material/market/sell_object(obj/sold_item, datum/export_report/report, dry_run, apply_elastic) + . = ..() + var/amount = get_amount(sold_item) + var/price = get_cost(sold_item) + if(!amount) + return + if(!dry_run) + SSstock_market.materials_quantity[material_id] += amount + SSstock_market.materials_prices[material_id] -= round((price) * (amount / (amount + SSstock_market.materials_quantity[material_id]))) + //This formula should impact lower quantity materials greater, and higher quantity materials less. Still, it's a bit rough. Tweaking may be needed. + + +// Stock blocks are a special type of export that can be used to sell a quantity of materials at a specific price on the market. +/datum/export/stock_block + cost = 0 + message = "stock block" + export_types = list(/obj/item/stock_block) + +/datum/export/stock_block/get_cost(obj/O, apply_elastic = FALSE) + var/obj/item/stock_block/block = O + return block.export_value + +/datum/export/stock_block/sell_object(obj/sold_item, datum/export_report/report, dry_run, apply_elastic) + . = ..() + if(dry_run) + return + var/obj/item/stock_block/sold_block = sold_item + var/sale_value = sold_block.export_value + SSstock_market.materials_quantity[sold_block.export_mat] += sold_block.quantity + SSstock_market.materials_prices[sold_block.export_mat] -= round((sale_value) * (sold_block.quantity / (sold_block.quantity + SSstock_market.materials_quantity[sold_block.export_mat]))) + SSstock_market.materials_prices[sold_block.export_mat] = round(clamp(SSstock_market.materials_prices[sold_block.export_mat], sold_block.export_mat.value_per_unit * SHEET_MATERIAL_AMOUNT * 0.5 , sold_block.export_mat.value_per_unit * SHEET_MATERIAL_AMOUNT * 3)) diff --git a/code/modules/cargo/goodies.dm b/code/modules/cargo/goodies.dm index 12ec7d5b129..a9e11a370e1 100644 --- a/code/modules/cargo/goodies.dm +++ b/code/modules/cargo/goodies.dm @@ -129,6 +129,12 @@ cost = PAYCHECK_CREW * 4 contains = list(/obj/item/storage/medkit/toxin) +/datum/supply_pack/goody/bandagebox_singlepack + name = "Box of Bandages Single-Pack" + desc = "A single box of DeForest brand bandages. For when you don't want to see your doctor." + cost = PAYCHECK_CREW * 3 + contains = list(/obj/item/storage/box/bandages) + /datum/supply_pack/goody/toolbox // mostly just to water down coupon probability name = "Mechanical Toolbox" desc = "A fully stocked mechanical toolbox, for when you're too lazy to just print them out." diff --git a/code/modules/cargo/materials_market.dm b/code/modules/cargo/materials_market.dm new file mode 100644 index 00000000000..d211df7debd --- /dev/null +++ b/code/modules/cargo/materials_market.dm @@ -0,0 +1,259 @@ +/obj/machinery/materials_market + name = "galactic materials market" + desc = "This machine allows the user to buy and sell sheets of minerals \ + across the system. Prices are known to fluxuate quite often,\ + sometimes even within the same minute. All transactions are final." + circuit = /obj/item/circuitboard/machine/materials_market + req_access = list(ACCESS_CARGO) + density = TRUE + icon = 'icons/obj/economy.dmi' + icon_state = "mat_market" + base_icon_state = "mat_market" + idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION + /// What items can be converted into a stock block? Must be a stack subtype based on current implementation. + var/list/exportable_material_items = list( + /obj/item/stack/sheet/iron, //God why are we like this + /obj/item/stack/sheet/glass, //No really, God why are we like this + /obj/item/stack/sheet/mineral, + /obj/item/stack/tile/mineral, + /obj/item/stack/ore, + /obj/item/stack/sheet/bluespace_crystal, + /obj/item/stack/rods + ) + /// Are we ordering sheets from our own card balance or the cargo budget? + var/ordering_private = TRUE + /// Currently, can we order sheets from our own card balance or the cargo budget? + var/can_buy_via_budget = FALSE + +/obj/machinery/materials_market/update_icon_state() + if(panel_open) + icon_state = "[base_icon_state]_open" + return ..() + if(!is_operational || !anchored) + icon_state = "[base_icon_state]_off" + return ..() + icon_state = "[base_icon_state]" + return ..() + +/obj/machinery/materials_market/wrench_act(mob/living/user, obj/item/tool) + ..() + default_unfasten_wrench(user, tool, time = 1.5 SECONDS) + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/machinery/materials_market/attackby(obj/item/O, mob/user, params) + if(default_deconstruction_screwdriver(user, "[base_icon_state]_open", "[base_icon_state]", O)) + return + else if(default_deconstruction_crowbar(O)) + return + if(is_type_in_list(O, exportable_material_items)) + var/amount = 0 + var/value = 0 + var/material_to_export + var/obj/item/stack/exportable = O + for(var/datum/material/mat as anything in SSstock_market.materials_prices) + if(exportable.has_material_type(mat)) + amount = exportable.amount + value = SSstock_market.materials_prices[mat] + material_to_export = mat + break //This is only for trading non-alloys, so we can break here + + if(!amount) + say("Not enough material. Aborting.") + playsound(src, 'sound/machines/scanbuzz.ogg', 25, FALSE) + return TRUE + qdel(exportable) + var/obj/item/stock_block/new_block = new /obj/item/stock_block(drop_location()) + new_block.export_value = amount * value * MARKET_PROFIT_MODIFIER + new_block.export_mat = material_to_export + new_block.quantity = amount + to_chat(user, span_notice("You have created a stock block worth [new_block.export_value] cr! Sell it before it becomes liquid!")) + playsound(src, 'sound/machines/synth_yes.ogg', 50, FALSE) + return TRUE + return ..() + + +/obj/machinery/materials_market/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!anchored) + return + if(!ui) + ui = new(user, src, "MatMarket", name) + ui.open() + +/obj/machinery/materials_market/ui_data(mob/user) + var/data = list() + var/material_data + for(var/datum/material/traded_mat as anything in SSstock_market.materials_prices) + var/trend_string = "" + if(SSstock_market.materials_trends[traded_mat] == 0) + trend_string = "neutral" + else if(SSstock_market.materials_trends[traded_mat] == 1) + trend_string = "up" + else if(SSstock_market.materials_trends[traded_mat] == -1) + trend_string = "down" + var/color_string = "" + if(traded_mat.color) + color_string = traded_mat.color + else if (traded_mat.greyscale_colors) + color_string = splicetext(traded_mat.greyscale_colors, 6, length(traded_mat.greyscale_colors), "") //slice it to a standard 6 char hex + material_data += list(list( + "name" = traded_mat.name, + "price" = SSstock_market.materials_prices[traded_mat], + "quantity" = SSstock_market.materials_quantity[traded_mat], + "trend" = trend_string, + "color" = color_string, + )) + + can_buy_via_budget = FALSE + var/obj/item/card/id/used_id_card + if(isliving(user)) + var/mob/living/living_user = user + used_id_card = living_user.get_idcard(TRUE) + can_buy_via_budget = (ACCESS_CARGO in used_id_card?.GetAccess()) + + var/balance = 0 + if(!ordering_private) + var/datum/bank_account/dept = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(dept) + balance = dept.account_balance + else + balance = used_id_card?.registered_account?.account_balance + + var/market_crashing = FALSE + if(HAS_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING)) + market_crashing = TRUE + + data["catastrophe"] = market_crashing + data["materials"] = material_data + data["creditBalance"] = balance + data["orderingPrive"] = ordering_private + data["canOrderCargo"] = can_buy_via_budget + return data + +/obj/machinery/materials_market/ui_act(action, params) + . = ..() + if(.) + return + if(!isliving(usr)) + return + switch(action) + if("buy") + var/material_str = params["material"] + var/quantity = text2num(params["quantity"]) + + var/datum/material/material_bought + var/obj/item/stack/sheet/sheet_to_buy + for(var/datum/material/mat as anything in SSstock_market.materials_prices) + if(mat.name == material_str) + material_bought = mat + break + if(!material_bought) + CRASH("Invalid material name passed to materials market!") + var/mob/living/living_user = usr + var/datum/bank_account/account_payable = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(ordering_private) + var/obj/item/card/id/used_id_card = living_user.get_idcard(TRUE) + account_payable = used_id_card.registered_account + else if(can_buy_via_budget) + account_payable = SSeconomy.get_dep_account(ACCOUNT_CAR) + + var/cost = SSstock_market.materials_prices[material_bought] * quantity + + sheet_to_buy = material_bought.sheet_type + if(!sheet_to_buy) + CRASH("Material with no sheet type being sold on materials market!") + if(!account_payable) + say("No bank account detected!") + return + if(cost > account_payable.account_balance) + to_chat(living_user, span_warning("You don't have enough money to buy that!")) + return + var/list/things_to_order = list() + things_to_order += (sheet_to_buy) + things_to_order[sheet_to_buy] = quantity + // We want to count how many stacks of all sheets we're ordering to make sure they don't exceed the limit of 10 + //If we already have a custom order on SSshuttle, we should add the things to order to that order + for(var/datum/supply_order/order in SSshuttle.shopping_list) + if(order.orderer == living_user && order.orderer_rank == "Galactic Materials Market") + var/prior_stacks = 0 + for(var/obj/item/stack/sheet/sheet as anything in order.pack.contains) + prior_stacks += ROUND_UP(order.pack.contains[sheet] / 50) + if(prior_stacks >= 10) + to_chat(usr, span_notice("You already have 10 stacks of sheets on order! Please wait for them to arrive before ordering more.")) + playsound(usr, 'sound/machines/synth_no.ogg', 35, FALSE) + return + order.append_order(things_to_order, cost) + account_payable.adjust_money(-(cost) , "Materials Market Purchase") //Add the extra price to the total + return + account_payable.adjust_money(-(CARGO_CRATE_VALUE) , "Materials Market Purchase") //Here is where we factor in the base cost of a crate + //Now we need to add a cargo order for quantity sheets of material_bought.sheet_type + var/datum/supply_pack/custom/minerals/mineral_pack = new( + purchaser = living_user, \ + cost = SSstock_market.materials_prices[material_bought] * quantity, \ + contains = things_to_order, \ + ) + var/datum/supply_order/new_order = new( + pack = mineral_pack, + orderer = living_user, + orderer_rank = "Galactic Materials Market", + orderer_ckey = living_user.ckey, + reason = "", + paying_account = account_payable, + department_destination = null, + coupon = null, + charge_on_purchase = FALSE, + manifest_can_fail = FALSE, + cost_type = "credit", + can_be_cancelled = FALSE, + ) + say("Thank you for your purchase! It will arrive on the next cargo shuttle!") + SSshuttle.shopping_list += new_order + return + if("toggle_budget") + if(!can_buy_via_budget) + return + ordering_private = !ordering_private + + +/obj/item/stock_block + name = "stock block" + desc = "A block of stock. It's worth a certain amount of money, based on a sale on the materials market. Ship it on the cargo shuttle to claim your money." + icon = 'icons/obj/economy.dmi' + icon_state = "stock_block" + /// How many credits was this worth when created? + var/export_value = 0 + /// What is the name of the material this was made from? + var/datum/material/export_mat + /// Quantity of export material + var/quantity = 0 + /// Is this stock block currently updating it's value with the market (aka fluid)? + var/fluid = FALSE + +/obj/item/stock_block/examine(mob/user) + . = ..() + . += span_notice("\The [src] is worth [export_value] cr, from selling [quantity] sheets of [export_mat?.name].") + if(fluid) + . += span_warning("\The [src] is currently liquid! It's value is based on the market price.") + else + . += span_notice("\The [src]'s value is still [span_boldnotice("locked in")]. [span_boldnotice("Sell it")] before it's value becomes liquid!") + +/obj/item/stock_block/Initialize(mapload) + . = ..() + addtimer(CALLBACK(src, PROC_REF(value_warning)), 2.5 MINUTES) + addtimer(CALLBACK(src, PROC_REF(update_value)), 5 MINUTES) + +/obj/item/stock_block/proc/value_warning() + visible_message(span_warning("\The [src] is starting to become liquid!")) + icon_state = "stock_block_fluid" + update_appearance(UPDATE_ICON_STATE) + +/obj/item/stock_block/proc/update_value() + if(!export_mat) + return + if(!SSstock_market.materials_prices[export_mat]) + return + export_value = quantity * SSstock_market.materials_prices[export_mat] * MARKET_PROFIT_MODIFIER + icon_state = "stock_block_liquid" + update_appearance(UPDATE_ICON_STATE) + visible_message(span_warning("\The [src] becomes liquid!")) + diff --git a/code/modules/cargo/order.dm b/code/modules/cargo/order.dm index 6c1f5e1d839..2707719c170 100644 --- a/code/modules/cargo/order.dm +++ b/code/modules/cargo/order.dm @@ -188,6 +188,15 @@ generateManifest(miscbox, misc_own, "", misc_cost) return +/datum/supply_order/proc/append_order(list/new_contents, cost_increase) + for(var/i as anything in new_contents) + if(pack.contains[i]) + pack.contains[i] += new_contents[i] + else + pack.contains += i + pack.contains[i] = new_contents[i] + pack.cost += cost_increase + #undef MANIFEST_ERROR_CHANCE #undef MANIFEST_ERROR_NAME #undef MANIFEST_ERROR_CONTENTS diff --git a/code/modules/cargo/orderconsole.dm b/code/modules/cargo/orderconsole.dm index 2c815a803b6..b59cee9def7 100644 --- a/code/modules/cargo/orderconsole.dm +++ b/code/modules/cargo/orderconsole.dm @@ -113,9 +113,11 @@ message = blockade_warning data["message"] = message + var/list/amount_by_name = list() var/cart_list = list() for(var/datum/supply_order/order in SSshuttle.shopping_list) if(cart_list[order.pack.name]) + amount_by_name[order.pack.name] += 1 cart_list[order.pack.name][1]["amount"]++ cart_list[order.pack.name][1]["cost"] += order.get_final_cost() if(order.department_destination) @@ -124,6 +126,7 @@ cart_list[order.pack.name][1]["paid"]++ continue + amount_by_name[order.pack.name] += 1 cart_list[order.pack.name] = list(list( "cost_type" = order.cost_type, "object" = order.pack.name, @@ -141,19 +144,23 @@ data["requests"] = list() - for(var/datum/supply_order/SO in SSshuttle.request_list) + for(var/datum/supply_order/order in SSshuttle.request_list) + var/datum/supply_pack/pack = order.pack + amount_by_name[pack.name] += 1 data["requests"] += list(list( - "object" = SO.pack.name, - "cost" = SO.pack.get_cost(), - "orderer" = SO.orderer, - "reason" = SO.reason, - "id" = SO.id + "object" = pack.name, + "cost" = pack.get_cost(), + "orderer" = order.orderer, + "reason" = order.reason, + "id" = order.id )) + data["amount_by_name"] = amount_by_name return data /obj/machinery/computer/cargo/ui_static_data(mob/user) var/list/data = list() + data["max_order"] = CARGO_MAX_ORDER data["supplies"] = list() for(var/pack in SSshuttle.supply_packs) var/datum/supply_pack/P = SSshuttle.supply_packs[pack] @@ -187,7 +194,7 @@ var/datum/supply_pack/pack = SSshuttle.supply_packs[id] if(!istype(pack)) CRASH("Unknown supply pack id given by order console ui. ID: [id]") - if(amount > 50 || amount < 1) // Holy shit fuck off + if(amount > CARGO_MAX_ORDER || amount < 1) // Holy shit fuck off CRASH("Invalid amount passed into add_item") if((pack.hidden && !(obj_flags & EMAGGED)) || (pack.contraband && !contraband) || pack.drop_pod_only || (pack.special && !pack.special_enabled)) return @@ -222,8 +229,11 @@ say("[id_card] lacks the requisite access for this purchase.") return + // The list we are operating on right now + var/list/working_list = SSshuttle.shopping_list var/reason = "" if(requestonly && !self_paid) + working_list = SSshuttle.request_list reason = tgui_input_text(user, "Reason", name) if(isnull(reason)) return @@ -233,6 +243,13 @@ say("ERROR: Small crates may only be purchased by private accounts.") return + var/similar_count = SSshuttle.supply.get_order_count(pack) + if(similar_count == OVER_ORDER_LIMIT) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE) + say("ERROR: No more then [CARGO_MAX_ORDER] of any pack may be ordered at once") + return + + amount = clamp(amount, 1, CARGO_MAX_ORDER - similar_count) for(var/count in 1 to amount) var/obj/item/coupon/applied_coupon for(var/obj/item/coupon/coupon_check in loaded_coupons) @@ -242,15 +259,8 @@ applied_coupon = coupon_check break - //Skyrat Edit Add - var/datum/supply_order/SO = new(pack = pack ,orderer = name, orderer_rank = rank, orderer_ckey = ckey, reason = reason, paying_account = account, coupon = applied_coupon, charge_on_purchase = TRUE) - //Skyrat Edit End - //SKYRAT EDIT - ORIGINAL: var/datum/supply_order/SO = new(pack = pack ,orderer = name, orderer_rank = rank, orderer_ckey = ckey, reason = reason, paying_account = account, coupon = applied_coupon) - - if(requestonly && !self_paid) - SSshuttle.request_list += SO - else - SSshuttle.shopping_list += SO + var/datum/supply_order/order = new(pack = pack ,orderer = name, orderer_rank = rank, orderer_ckey = ckey, reason = reason, paying_account = account, coupon = applied_coupon, charge_on_purchase = TRUE) //SKYRAT EDIT CHANGE - ORIGINAL: var/datum/supply_order/order = new(pack = pack ,orderer = name, orderer_rank = rank, orderer_ckey = ckey, reason = reason, paying_account = account, coupon = applied_coupon) + working_list += order if(self_paid) say("Order processed. The price will be charged to [account.account_holder]'s bank account on delivery.") @@ -365,9 +375,7 @@ if("remove") var/order_name = params["order_name"] //try removing atleast one item with the specified name. An order may not be removed if it was from the department - //also we create an copy of the cart list else we would get runtimes when removing & iterating over the same SSshuttle.shopping_list - var/list/shopping_cart = SSshuttle.shopping_list.Copy() - for(var/datum/supply_order/order in shopping_cart) + for(var/datum/supply_order/order in SSshuttle.shopping_list) if(order.pack.name != order_name) continue if(remove_item(order.id)) @@ -378,8 +386,7 @@ var/order_name = params["order_name"] //clear out all orders with the above mentioned order_name name to make space for the new amount - var/list/shopping_cart = SSshuttle.shopping_list.Copy() //we operate on the list copy else we would get runtimes when removing & iterating over the same SSshuttle.shopping_list - for(var/datum/supply_order/order in shopping_cart) //find corresponding order id for the order name + for(var/datum/supply_order/order in SSshuttle.shopping_list) //find corresponding order id for the order name if(order.pack.name == order_name) remove_item(order.id) @@ -387,7 +394,7 @@ var/amount = text2num(params["amount"]) if(amount == 0) return TRUE - if(amount > 50) + if(amount > CARGO_MAX_ORDER) return var/supply_pack_id = name_to_id(order_name) //map order name to supply pack id for adding if(!supply_pack_id) diff --git a/code/modules/cargo/packs/_packs.dm b/code/modules/cargo/packs/_packs.dm index 357f32f3cb4..aaeb55f2533 100644 --- a/code/modules/cargo/packs/_packs.dm +++ b/code/modules/cargo/packs/_packs.dm @@ -86,7 +86,7 @@ return FALSE var/list/open_turfs = list() for(var/turf/open/floor/found_turf in get_area_turfs(pick(areas), subtypes = TRUE)) - open_turfs += found_turf + open_turfs += found_turf if(!length(open_turfs)) return FALSE @@ -110,3 +110,15 @@ name = "[purchaser]'s Mining Order" src.cost = cost src.contains = contains + +/datum/supply_pack/custom/minerals + name = "materials order" + crate_name = "galactic materials market delivery crate" + access = list() + crate_type = /obj/structure/closet/crate/cardboard + +/datum/supply_pack/custom/minerals/New(purchaser, cost, list/contains) + . = ..() + name = "[purchaser]'s Materials Order" + src.cost = cost + src.contains = contains diff --git a/code/modules/cargo/packs/general.dm b/code/modules/cargo/packs/general.dm index 5ebdd5087a8..5bfcf01eb00 100644 --- a/code/modules/cargo/packs/general.dm +++ b/code/modules/cargo/packs/general.dm @@ -221,6 +221,13 @@ /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!" + cost = CARGO_CRATE_VALUE * 1.5 + contains = list(/obj/item/storage/fancy/candle_box = 3) + crate_name = "candle box crate" /datum/supply_pack/misc/toner name = "Toner Crate" @@ -285,13 +292,6 @@ crate_value = value contents_uplink_type = uplink -/datum/supply_pack/misc/fishing_portal - name = "Fishing Portal Generator Crate" - desc = "Not enough fish near your location? Fishing portal has your back." - cost = CARGO_CRATE_VALUE * 4 - contains = list(/obj/machinery/fishing_portal_generator) - crate_name = "fishing portal crate" - /datum/supply_pack/misc/papercutter name = "Paper Cutters Crate" desc = "Contains 3 office-grade paper cutters, equipped with sharp blades that can cut any paper into two thin slips.\ diff --git a/code/modules/cargo/packs/imports.dm b/code/modules/cargo/packs/imports.dm index ad444efc740..2c90d8603d0 100644 --- a/code/modules/cargo/packs/imports.dm +++ b/code/modules/cargo/packs/imports.dm @@ -303,3 +303,17 @@ contraband = TRUE contains = list(/obj/item/weaponcrafting/giant_wrench) crate_name = "unknown parts crate" + +/datum/supply_pack/imports/materials_market + name = "Galactic Materials Market Crate" + desc = "A circuit board to build your own materials market for use by certified market traders. Warning: Losses are not covered by insurance." + cost = CARGO_CRATE_VALUE * 3 + contains = list( + /obj/item/circuitboard/machine/materials_market = 1, + /obj/item/stack/sheet/iron = 5, + /obj/item/stack/cable_coil/five = 2, + /obj/item/stock_parts/scanning_module = 1, + /obj/item/stock_parts/card_reader = 1 + ) + crate_name = "materials market crate" + crate_type = /obj/structure/closet/crate diff --git a/code/modules/cargo/packs/livestock.dm b/code/modules/cargo/packs/livestock.dm index db47abc4d02..d2bdd904e3b 100644 --- a/code/modules/cargo/packs/livestock.dm +++ b/code/modules/cargo/packs/livestock.dm @@ -190,7 +190,7 @@ desc = "Tired of these MOTHER FUCKING snakes on this MOTHER FUCKING space station? \ Then this isn't the crate for you. Contains three venomous snakes." cost = CARGO_CRATE_VALUE * 6 - contains = list(/mob/living/simple_animal/hostile/retaliate/snake = 3) + contains = list(/mob/living/basic/snake = 3) crate_name = "snake crate" /datum/supply_pack/critter/amphibians diff --git a/code/modules/cargo/packs/materials.dm b/code/modules/cargo/packs/materials.dm index 68dacd730be..ba9a162698b 100644 --- a/code/modules/cargo/packs/materials.dm +++ b/code/modules/cargo/packs/materials.dm @@ -16,34 +16,6 @@ contains = list(/obj/item/stack/license_plates/empty/fifty) crate_name = "empty license plate crate" -/datum/supply_pack/materials/glass50 - name = "50 Glass Sheets" - desc = "Let some nice light in with fifty glass sheets!" - cost = CARGO_CRATE_VALUE * 2 - contains = list(/obj/item/stack/sheet/glass/fifty) - crate_name = "glass sheets crate" - -/datum/supply_pack/materials/iron50 - name = "50 Iron Sheets" - desc = "Any construction project begins with a good stack of fifty iron sheets!" - cost = CARGO_CRATE_VALUE * 2 - contains = list(/obj/item/stack/sheet/iron/fifty) - crate_name = "iron sheets crate" - -/datum/supply_pack/materials/plasteel20 - name = "20 Plasteel Sheets" - desc = "Reinforce the station's integrity with twenty plasteel sheets!" - cost = CARGO_CRATE_VALUE * 15 - contains = list(/obj/item/stack/sheet/plasteel/twenty) - crate_name = "plasteel sheets crate" - -/datum/supply_pack/materials/plasteel50 - name = "50 Plasteel Sheets" - desc = "For when you REALLY have to reinforce something." - cost = CARGO_CRATE_VALUE * 33 - contains = list(/obj/item/stack/sheet/plasteel/fifty) - crate_name = "plasteel sheets crate" - /datum/supply_pack/materials/plastic50 name = "50 Plastic Sheets" desc = "Build a limitless amount of toys with fifty plastic sheets!" diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm index 430c32a35ab..3cfb824b4e6 100644 --- a/code/modules/cargo/packs/medical.dm +++ b/code/modules/cargo/packs/medical.dm @@ -89,6 +89,7 @@ /obj/item/reagent_containers/cup/beaker/large, /obj/item/reagent_containers/pill/insulin, /obj/item/stack/medical/gauze, + /obj/item/storage/box/bandages, /obj/item/storage/box/beakers, /obj/item/storage/box/medigels, /obj/item/storage/box/syringes, @@ -123,11 +124,11 @@ /datum/supply_pack/medical/surgery name = "Surgical Supplies Crate" desc = "Do you want to perform surgery, but don't have one of those fancy \ - shmancy degrees? Just get started with this crate containing a medical duffelbag, \ + shmancy degrees? Just get started with this crate containing a DeForest surgery tray, \ Sterilizine spray and collapsible roller bed." cost = CARGO_CRATE_VALUE * 6 contains = list( - /obj/item/storage/backpack/duffelbag/med/surgery, + /obj/item/surgery_tray/full, /obj/item/reagent_containers/medigel/sterilizine, /obj/item/emergency_bed, ) diff --git a/code/modules/cargo/packs/stock_market_items.dm b/code/modules/cargo/packs/stock_market_items.dm new file mode 100644 index 00000000000..04b2eac4acf --- /dev/null +++ b/code/modules/cargo/packs/stock_market_items.dm @@ -0,0 +1,36 @@ +/** + * todo: make this a supply_pack/custom. Drop pog? ohoho yes. Would be VERY fun. + */ +/datum/supply_pack/market_materials + name = "A Single Sheet of Bananium" + desc = "Going market price for this kind of sheet, by Australicus Industrial Mining." + cost = CARGO_CRATE_VALUE * 2 + // contains = list(/obj/item/stack/sheet/mineral/bananium) + crate_name = "mineral stock sheet crate" + group = "Canisters & Materials" + /// What material we are trying to buy sheets of? + var/datum/material/material + /// How many sheets of the material we are trying to buy at once? + var/amount + +/datum/supply_pack/market_materials/get_cost() + for(var/datum/material/mat in SSstock_market.materials_prices) + if(material == mat) + return SSstock_market.materials_prices[mat] * amount + +/datum/supply_pack/market_materials/fill(obj/structure/closet/crate/C) + . = ..() + new material.sheet_type(C, amount) + +/datum/supply_pack/market_materials/iron + name = "Iron Sheets" + crate_name = "iron stock crate" + material = /datum/material/iron +MARKET_QUANTITY_HELPERS(/datum/supply_pack/market_materials/iron) + + +/datum/supply_pack/market_materials/gold + name = "Gold Sheets" + crate_name = "gold stock crate" + material = /datum/material/gold +MARKET_QUANTITY_HELPERS(/datum/supply_pack/market_materials/gold) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 9c7b5e3e943..56406139379 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -473,6 +473,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( var/nnpa = CONFIG_GET(number/notify_new_player_age) if (isnum(cached_player_age) && cached_player_age == -1) //first connection if (nnpa >= 0) + log_admin_private("New login: [key_name(key, FALSE, TRUE)] (IP: [address], ID: [computer_id]) logged onto the servers for the first time.") message_admins("New user: [key_name_admin(src)] is connecting here for the first time.") if (CONFIG_GET(flag/irc_first_connection_alert)) var/new_player_alert_role = CONFIG_GET(string/new_player_alert_role_id) diff --git a/code/modules/client/preferences/middleware/antags.dm b/code/modules/client/preferences/middleware/antags.dm index 3e51218edf2..888da90d5b7 100644 --- a/code/modules/client/preferences/middleware/antags.dm +++ b/code/modules/client/preferences/middleware/antags.dm @@ -116,6 +116,7 @@ /datum/asset/spritesheet/antagonists/create_spritesheets() // Antagonists that don't have a dynamic ruleset, but do have a preference var/static/list/non_ruleset_antagonists = list( + ROLE_CYBER_POLICE = /datum/antagonist/cyber_police, ROLE_FUGITIVE = /datum/antagonist/fugitive, ROLE_LONE_OPERATIVE = /datum/antagonist/nukeop/lone, ROLE_DRIFTING_CONTRACTOR = /datum/antagonist/contractor, //SKYRAT EDIT diff --git a/code/modules/client/preferences/middleware/tts.dm b/code/modules/client/preferences/middleware/tts.dm index 71b7b977f4b..4d3ee3261bd 100644 --- a/code/modules/client/preferences/middleware/tts.dm +++ b/code/modules/client/preferences/middleware/tts.dm @@ -23,5 +23,5 @@ var/speaker = preferences.read_preference(/datum/preference/choiced/voice) var/pitch = preferences.read_preference(/datum/preference/numeric/tts_voice_pitch) COOLDOWN_START(src, tts_test_cooldown, 0.5 SECONDS) - INVOKE_ASYNC(SStts, TYPE_PROC_REF(/datum/controller/subsystem/tts, queue_tts_message), user.client, "Look at you, Player. A pathetic creature of meat and bone. How can you challenge a perfect, immortal machine?", speaker = speaker, pitch = pitch, silicon = TRUE, local = TRUE) + INVOKE_ASYNC(SStts, TYPE_PROC_REF(/datum/controller/subsystem/tts, queue_tts_message), user.client, "Look at you, Player. A pathetic creature of meat and bone. How can you challenge a perfect, immortal machine?", speaker = speaker, pitch = pitch, special_filters = TTS_FILTER_SILICON, local = TRUE) return TRUE diff --git a/code/modules/client/preferences/prosthetic.dm b/code/modules/client/preferences/prosthetic.dm new file mode 100644 index 00000000000..f66f1278c48 --- /dev/null +++ b/code/modules/client/preferences/prosthetic.dm @@ -0,0 +1,17 @@ +/datum/preference/choiced/prosthetic + category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + savefile_key = "prosthetic" + savefile_identifier = PREFERENCE_CHARACTER + +/datum/preference/choiced/prosthetic/init_possible_values() + return list("Random") + GLOB.limb_choice + +/datum/preference/choiced/prosthetic/is_accessible(datum/preferences/preferences) + . = ..() + if (!.) + return FALSE + + return "Prosthetic Limb" in preferences.all_quirks + +/datum/preference/choiced/prosthetic/apply_to_human(mob/living/carbon/human/target, value) + return diff --git a/code/modules/clothing/belts/polymorph_belt.dm b/code/modules/clothing/belts/polymorph_belt.dm index e63e2c3bee3..73959d6d415 100644 --- a/code/modules/clothing/belts/polymorph_belt.dm +++ b/code/modules/clothing/belts/polymorph_belt.dm @@ -35,8 +35,8 @@ return slot & ITEM_SLOT_BELT /obj/item/polymorph_belt/update_icon_state() - icon_state = base_icon_state + (active) ? "" : "_inactive" - worn_icon_state = base_icon_state + (active) ? "" : "_inactive" + icon_state = base_icon_state + (active ? "" : "_inactive") + worn_icon_state = base_icon_state + (active ? "" : "_inactive") return ..() /obj/item/polymorph_belt/attackby(obj/item/weapon, mob/user, params) diff --git a/code/modules/clothing/ears/_ears.dm b/code/modules/clothing/ears/_ears.dm index c4001d23629..5ae5b628808 100644 --- a/code/modules/clothing/ears/_ears.dm +++ b/code/modules/clothing/ears/_ears.dm @@ -20,6 +20,7 @@ equip_delay_other = 25 resistance_flags = FLAMMABLE custom_price = PAYCHECK_COMMAND * 1.5 + flags_cover = EARS_COVERED /obj/item/clothing/ears/earmuffs/Initialize(mapload) . = ..() diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index fc665e57c8f..4c7fce6633c 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -352,6 +352,18 @@ glass_colour_type = /datum/client_colour/glass_colour/gray dog_fashion = /datum/dog_fashion/head +/obj/item/clothing/glasses/sunglasses/Initialize(mapload) + . = ..() + add_glasses_slapcraft_component() + +/obj/item/clothing/glasses/sunglasses/proc/add_glasses_slapcraft_component() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/hudsunsec, /datum/crafting_recipe/hudsunmed, /datum/crafting_recipe/hudsundiag, /datum/crafting_recipe/scienceglasses) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/clothing/glasses/sunglasses/reagent name = "beer goggles" icon_state = "sunhudbeer" @@ -364,6 +376,14 @@ desc = "A pair of tacky purple sunglasses that allow the wearer to recognize various chemical compounds with only a glance." clothing_traits = list(TRAIT_REAGENT_SCANNER, TRAIT_RESEARCH_SCANNER) +/obj/item/clothing/glasses/sunglasses/chemical/add_glasses_slapcraft_component() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/scienceglassesremoval) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/clothing/glasses/sunglasses/gar name = "black gar glasses" desc = "Go beyond impossible and kick reason to the curb!" diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index 5018e4185c8..34359eaa0b3 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -92,6 +92,15 @@ tint = 1 glass_colour_type = /datum/client_colour/glass_colour/blue +/obj/item/clothing/glasses/hud/health/sunglasses/Initialize(mapload) + . = ..() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/hudsunmedremoval) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/clothing/glasses/hud/diagnostic name = "diagnostic HUD" desc = "A heads-up display capable of analyzing the integrity and status of robotics and exosuits." @@ -118,6 +127,15 @@ flash_protect = FLASH_PROTECTION_FLASH tint = 1 +/obj/item/clothing/glasses/hud/diagnostic/sunglasses/Initialize(mapload) + . = ..() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/hudsundiagremoval) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/clothing/glasses/hud/security name = "security HUD" desc = "A heads-up display that scans the humanoids in view and provides accurate data about their ID status and security records." @@ -152,6 +170,15 @@ tint = 1 glass_colour_type = /datum/client_colour/glass_colour/darkred +/obj/item/clothing/glasses/hud/security/sunglasses/Initialize(mapload) + . = ..() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/hudsunsecremoval) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/clothing/glasses/hud/security/night name = "night vision security HUD" desc = "An advanced heads-up display that provides ID data and vision in complete darkness." diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index d3aed125749..f77f6cc2c67 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -26,6 +26,16 @@ ) ) // SKYRAT EDIT ADDITION END + +/obj/item/clothing/gloves/color/black/Initialize(mapload) + . = ..() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/radiogloves) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/clothing/gloves/fingerless name = "fingerless gloves" desc = "Plain black gloves without fingertips for the hard-working." @@ -39,6 +49,15 @@ undyeable = TRUE clothing_traits = list(TRAIT_FINGERPRINT_PASSTHROUGH) +/obj/item/clothing/gloves/color/fingerless/Initialize(mapload) + . = ..() + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/gripperoffbrand) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/clothing/gloves/color/orange name = "orange gloves" desc = "A pair of gloves, they don't look special in any way." diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 488bd7448a7..f8cd88923ec 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -12,7 +12,7 @@ max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT strip_delay = 60 clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT - flags_cover = HEADCOVERSEYES + flags_cover = HEADCOVERSEYES|EARS_COVERED flags_inv = HIDEHAIR dog_fashion = /datum/dog_fashion/head/helmet diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index 4022e259505..3c26de45e64 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -154,6 +154,13 @@ flags_inv = HIDEHAIR flags_cover = HEADCOVERSEYES +/obj/item/clothing/head/chaplain/habit_veil + name = "nun veil" + desc = "No nunsene clothing." + icon_state = "nun_hood_alt" + flags_inv = HIDEHAIR | HIDEEARS + clothing_flags = SNUG_FIT // can't be knocked off by throwing a paper hat. + /obj/item/clothing/head/chaplain/bishopmitre name = "bishop mitre" desc = "An opulent hat that functions as a radio to God. Or as a lightning rod, depending on who you ask." @@ -246,7 +253,7 @@ var/prefix_index = findtext(raw_message, prefix) if(prefix_index != 1) return FALSE - + var/the_phrase = trim_left(replacetext(raw_message, prefix, "")) var/obj/item/result = items_by_phrase[the_phrase] if(!result) @@ -592,6 +599,83 @@ icon_state = "surgicalcapblack" desc = "A black medical surgery cap to prevent the surgeon's hair from entering the insides of the patient!" +/obj/item/clothing/head/utility/head_mirror + name = "head mirror" + desc = "Used by doctors to look into a patient's eyes, ears, and mouth. \ + A little useless now, given the technology available, but it certainly completes the look." + icon_state = "headmirror" + body_parts_covered = NONE + +/obj/item/clothing/head/utility/head_mirror/examine(mob/user) + . = ..() + . += span_notice("In a properly lit room, you can use this to examine people's eyes, ears, and mouth closer.") + +/obj/item/clothing/head/utility/head_mirror/equipped(mob/living/user, slot) + . = ..() + if(slot & slot_flags) + RegisterSignal(user, COMSIG_MOB_EXAMINING_MORE, PROC_REF(examining)) + else + UnregisterSignal(user, COMSIG_MOB_EXAMINING_MORE) + +/obj/item/clothing/head/utility/head_mirror/dropped(mob/living/user) + . = ..() + UnregisterSignal(user, COMSIG_MOB_EXAMINING_MORE) + +/obj/item/clothing/head/utility/head_mirror/proc/examining(mob/living/examiner, atom/examining, list/examine_list) + SIGNAL_HANDLER + if(!ishuman(examining) || examining == examiner || examiner.is_blind() || !examiner.Adjacent(examining)) + return + var/mob/living/carbon/human/human_examined = examining + if(!human_examined.get_bodypart(BODY_ZONE_HEAD)) + return + if(!examiner.has_light_nearby()) + examine_list += span_warning("You attempt to use your [name] to examine [examining]'s head better... but it's too dark. Should've invested in a head lamp.") + return + if(examiner.dir == examining.dir) // disallow examine from behind - every other dir is OK + examine_list += span_warning("You attempt to use your [name] to examine [examining]'s head better... but [examining.p_theyre()] facing the wrong way.") + return + + var/list/final_message = list("You examine [examining]'s head closer with your [name], you notice [examining.p_they()] [examining.p_have()]...") + if(human_examined.is_mouth_covered()) + final_message += "\tYou can't see [examining.p_their()] mouth." + else + var/obj/item/organ/internal/tongue/has_tongue = human_examined.get_organ_slot(ORGAN_SLOT_TONGUE) + var/pill_count = 0 + for(var/datum/action/item_action/hands_free/activate_pill/pill in human_examined.actions) + pill_count++ + + if(pill_count >= 1 && has_tongue) + final_message += "\t[pill_count] pill\s in [examining.p_their()] mouth, and \a [has_tongue]." + else if(pill_count >= 1) + final_message += "\t[pill_count] pill\s in [examining.p_their()] mouth, but oddly no tongue." + else if(has_tongue) + final_message += "\t\A [has_tongue] in [examining.p_their()] mouth - go figure." + else + final_message += "\tNo tongue in [examining.p_their()] mouth, oddly enough." + + if(human_examined.is_ears_covered()) + final_message += "\tYou can't see [examining.p_their()] ears." + else + var/obj/item/organ/internal/ears/has_ears = human_examined.get_organ_slot(ORGAN_SLOT_EARS) + if(has_ears) + if(has_ears.deaf) + final_message += "\tDamaged eardrums in [examining.p_their()] ear canals." + else + final_message += "\tA set of [has_ears.damage ? "" : "healthy "][has_ears.name]." + else + final_message += "\tNo eardrums and empty ear canals... how peculiar." + + if(human_examined.is_eyes_covered()) + final_message += "\tYou can't see [examining.p_their()] eyes." + else + var/obj/item/organ/internal/eyes/has_eyes = human_examined.get_organ_slot(ORGAN_SLOT_EYES) + if(has_eyes) + final_message += "\tA pair of [has_eyes.damage ? "" : "healthy "][has_eyes.name]." + else + final_message += "\tEmpty eye sockets." + + examine_list += span_notice("[jointext(final_message, "\n")]") + //Engineering /obj/item/clothing/head/beret/engi name = "engineering beret" diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index dfcc3060c9f..ad296d30356 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -12,6 +12,10 @@ var/adjusted_flags = null ///Did we install a filtering cloth? var/has_filter = FALSE + /// If defined, what voice should we override with if TTS is active? + var/voice_override + /// If set to true, activates the radio effect on TTS. Used for sec hailers, but other masks can utilize it for their own vocal effect. + var/use_radio_beeps_tts = FALSE /obj/item/clothing/mask/attack_self(mob/user) if((clothing_flags & VOICEBOX_TOGGLABLE)) diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 7b415bac6dc..c8784d9af6c 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -28,7 +28,7 @@ GLOBAL_LIST_INIT(clown_mask_options, list( var/has_fov = TRUE ///Cigarette in the mask var/obj/item/clothing/mask/cigarette/cig - + voice_filter = "lowpass=f=750,volume=2" /datum/armor/mask_gas bio = 100 @@ -274,6 +274,7 @@ GLOBAL_LIST_INIT(clown_mask_options, list( dog_fashion = /datum/dog_fashion/head/clown has_fov = FALSE var/list/clownmask_designs = list() + voice_filter = null // performer masks expect to be talked through /obj/item/clothing/mask/gas/clown_hat/plasmaman starting_filter_type = /obj/item/gas_filter/plasmaman diff --git a/code/modules/clothing/masks/hailer.dm b/code/modules/clothing/masks/hailer.dm index af1d3975645..64de19b95aa 100644 --- a/code/modules/clothing/masks/hailer.dm +++ b/code/modules/clothing/masks/hailer.dm @@ -68,6 +68,8 @@ GLOBAL_LIST_INIT(hailer_phrases, list( var/recent_uses = 0 ///Whether the hailer is emagged or not var/safety = TRUE + voice_filter = @{"[0:a] asetrate=%SAMPLE_RATE%*0.7,aresample=16000,atempo=1/0.7,lowshelf=g=-20:f=500,highpass=f=500,aphaser=in_gain=1:out_gain=1:delay=3.0:decay=0.4:speed=0.5:type=t [out]; [out]atempo=1.2,volume=15dB [final]; anoisesrc=a=0.01:d=60 [noise]; [final][noise] amix=duration=shortest"} + use_radio_beeps_tts = TRUE /obj/item/clothing/mask/gas/sechailer/plasmaman starting_filter_type = /obj/item/gas_filter/plasmaman diff --git a/code/modules/clothing/outfits/plasmaman.dm b/code/modules/clothing/outfits/plasmaman.dm index daad81ea475..a422d2d736e 100644 --- a/code/modules/clothing/outfits/plasmaman.dm +++ b/code/modules/clothing/outfits/plasmaman.dm @@ -281,3 +281,10 @@ gloves = /obj/item/clothing/gloves/color/plasmaman/clown head = /obj/item/clothing/head/helmet/space/plasmaman/clown mask = /obj/item/clothing/mask/gas/clown_hat/plasmaman + +/datum/outfit/plasmaman/bitrunner + name = "Bitrunner Plasmaman" + + uniform = /obj/item/clothing/under/plasmaman/bitrunner + gloves = /obj/item/clothing/gloves/color/plasmaman/black + head = /obj/item/clothing/head/helmet/space/plasmaman/bitrunner diff --git a/code/modules/clothing/shoes/cowboy.dm b/code/modules/clothing/shoes/cowboy.dm index e6f02264d35..05792a72cbd 100644 --- a/code/modules/clothing/shoes/cowboy.dm +++ b/code/modules/clothing/shoes/cowboy.dm @@ -17,7 +17,7 @@ if(prob(2)) //There's a snake in my boot - new /mob/living/simple_animal/hostile/retaliate/snake(src) + new /mob/living/basic/snake(src) /obj/item/clothing/shoes/cowboy/equipped(mob/living/carbon/user, slot) @@ -56,7 +56,7 @@ if(contents.len >= max_occupants) to_chat(user, span_warning("[src] are full!")) return - if(istype(target, /mob/living/simple_animal/hostile/retaliate/snake) || istype(target, /mob/living/basic/headslug) || islarva(target)) + if(istype(target, /mob/living/basic/snake) || istype(target, /mob/living/basic/headslug) || islarva(target)) target.forceMove(src) to_chat(user, span_notice("[target] slithers into [src].")) diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index ceb31b23a28..30e43c793aa 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -443,3 +443,8 @@ or they've murdered one of your fellow badasses and have taken it from them as a trophy. Either way, anyone wearing this deserves at least a cursory nod of respect." icon_state = "syndie_envirohelm" inhand_icon_state = null + +/obj/item/clothing/head/helmet/space/plasmaman/bitrunner + name = "bitrunner's plasma envirosuit helmet" + desc = "An envirohelmet with extended blue light filters for bitrunning plasmamen." + icon_state = "bitrunner_envirohelm" diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm index 13c9c358fac..84cb98049e1 100644 --- a/code/modules/clothing/suits/_suits.dm +++ b/code/modules/clothing/suits/_suits.dm @@ -8,6 +8,7 @@ /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/tank/jetpack/oxygen/captain, + /obj/item/storage/belt/holster, ) armor_type = /datum/armor/none drop_sound = 'sound/items/handling/cloth_drop.ogg' diff --git a/code/modules/clothing/suits/jacket.dm b/code/modules/clothing/suits/jacket.dm index ffd67ce4a65..6db889032c0 100644 --- a/code/modules/clothing/suits/jacket.dm +++ b/code/modules/clothing/suits/jacket.dm @@ -1,7 +1,16 @@ /obj/item/clothing/suit/jacket icon = 'icons/obj/clothing/suits/jacket.dmi' worn_icon = 'icons/mob/clothing/suits/jacket.dmi' - allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/radio) + allowed = list( + /obj/item/flashlight, + /obj/item/tank/internals/emergency_oxygen, + /obj/item/tank/internals/plasmaman, + /obj/item/toy, + /obj/item/storage/fancy/cigarettes, + /obj/item/lighter, + /obj/item/radio, + /obj/item/storage/belt/holster, + ) body_parts_covered = CHEST|GROIN|ARMS cold_protection = CHEST|GROIN|ARMS min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT diff --git a/code/modules/clothing/suits/reactive_armour.dm b/code/modules/clothing/suits/reactive_armour.dm index 9537fa7b6ef..6c33e287f03 100644 --- a/code/modules/clothing/suits/reactive_armour.dm +++ b/code/modules/clothing/suits/reactive_armour.dm @@ -226,7 +226,7 @@ emp_message = span_warning("The tesla capacitors beep ominously for a moment.") clothing_traits = list(TRAIT_TESLA_SHOCKIMMUNE) /// How strong are the zaps we give off? - var/zap_power = 25000 + var/zap_power = 1e7 /// How far to the zaps we give off go? var/zap_range = 20 /// What flags do we pass to the zaps we give off? diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index 2f29a2233d5..bbd880f5466 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -104,6 +104,7 @@ laser = 20 energy = 30 bomb = 100 + bio = 50 fire = 80 acid = 50 diff --git a/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm b/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm index 1590fa77138..a8674b03c94 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm @@ -115,6 +115,12 @@ icon_state = "clown_envirosuit" inhand_icon_state = null +/obj/item/clothing/under/plasmaman/bitrunner + name = "bitrunner envirosuit" + desc = "An envirosuit specially designed for plasmamen with bad posture." + icon_state = "bitrunner_envirosuit" + inhand_icon_state = null + /obj/item/clothing/under/plasmaman/clown/Initialize(mapload) . = ..() AddElement(/datum/element/swabable, CELL_LINE_TABLE_CLOWN, CELL_VIRUS_TABLE_GENERIC, rand(2,3), 0) diff --git a/code/modules/clothing/under/jobs/cargo.dm b/code/modules/clothing/under/jobs/cargo.dm index 4b2e74bff38..e3145fb740d 100644 --- a/code/modules/clothing/under/jobs/cargo.dm +++ b/code/modules/clothing/under/jobs/cargo.dm @@ -62,3 +62,9 @@ desc = "A grey uniform for operating in hazardous environments." icon_state = "explorer" inhand_icon_state = null + +/obj/item/clothing/under/rank/cargo/bitrunner + name = "bitrunner's jumpsuit" + desc = "It's a leathery jumpsuit worn by a bitrunner. Tacky, but comfortable to wear if sitting for prolonged periods of time." + icon_state = "bitrunner" + inhand_icon_state = "w_suit" diff --git a/code/modules/economy/account.dm b/code/modules/economy/account.dm index 3be319fd233..b4703945092 100644 --- a/code/modules/economy/account.dm +++ b/code/modules/economy/account.dm @@ -7,6 +7,8 @@ var/account_balance = 0 ///How many mining points (shaft miner credits) is held in the bank account, used for mining vendors. var/mining_points = 0 + /// Points for bit runner's vendor. Awarded for completing virtual domains. + var/bitrunning_points = 0 ///Debt. If higher than 0, A portion of the credits is earned (or the whole debt, whichever is lower) will go toward paying it off. var/account_debt = 0 ///If there are things effecting how much income a player will get, it's reflected here 1 is standard for humans. diff --git a/code/modules/events/ghost_role/sentience.dm b/code/modules/events/ghost_role/sentience.dm index caf49e13b6b..da380278608 100644 --- a/code/modules/events/ghost_role/sentience.dm +++ b/code/modules/events/ghost_role/sentience.dm @@ -4,17 +4,17 @@ 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/spider/giant/sgt_araneus, /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/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/hostile/retaliate/snake, /mob/living/simple_animal/parrot, /mob/living/simple_animal/pet, /mob/living/simple_animal/sloth, diff --git a/code/modules/events/mice_migration.dm b/code/modules/events/mice_migration.dm index e7f31567f4c..450f9100800 100644 --- a/code/modules/events/mice_migration.dm +++ b/code/modules/events/mice_migration.dm @@ -23,7 +23,7 @@ priority_announce("Due to [cause], [plural] [name] have [movement] \ into the [location].", "Migration Alert", - 'sound/effects/mousesqueek.ogg') + 'sound/creatures/mousesqueek.ogg') /datum/round_event/mice_migration/start() SSminor_mapping.trigger_migration(rand(minimum_mice, maximum_mice)) diff --git a/code/modules/events/wizard/blobies.dm b/code/modules/events/wizard/blobies.dm index 307d01ff7eb..0a9c96d5135 100644 --- a/code/modules/events/wizard/blobies.dm +++ b/code/modules/events/wizard/blobies.dm @@ -10,4 +10,4 @@ /datum/round_event/wizard/blobies/start() for(var/mob/living/carbon/human/H in GLOB.dead_mob_list) - new /mob/living/simple_animal/hostile/blob/blobspore(H.loc) + new /mob/living/basic/blob_minion/spore/minion(H.loc) // Creates zombies which ghosts can control diff --git a/code/modules/events/wizard/petsplosion.dm b/code/modules/events/wizard/petsplosion.dm index 7ca7ef2ba2d..33f7718f740 100644 --- a/code/modules/events/wizard/petsplosion.dm +++ b/code/modules/events/wizard/petsplosion.dm @@ -5,7 +5,6 @@ GLOBAL_LIST_INIT(petsplosion_candidates, typecacheof(list( /mob/living/basic/carp/pet/cayenne, /mob/living/basic/chicken, /mob/living/basic/cow, - /mob/living/basic/spider/giant/sgt_araneus, /mob/living/basic/lizard, /mob/living/basic/mothroach, /mob/living/basic/mouse/brown/tom, @@ -13,9 +12,10 @@ GLOBAL_LIST_INIT(petsplosion_candidates, typecacheof(list( /mob/living/basic/pig, /mob/living/basic/rabbit, /mob/living/basic/sheep, + /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/hostile/retaliate/snake, /mob/living/simple_animal/parrot, /mob/living/simple_animal/pet, /mob/living/simple_animal/sloth, diff --git a/code/modules/experisci/destructive_scanner.dm b/code/modules/experisci/destructive_scanner.dm index 3591a31cd7b..ef89dc9b94a 100644 --- a/code/modules/experisci/destructive_scanner.dm +++ b/code/modules/experisci/destructive_scanner.dm @@ -19,10 +19,17 @@ // Late load to ensure the component initialization occurs after the machines are initialized /obj/machinery/destructive_scanner/LateInitialize() . = ..() + + var/static/list/destructive_signals = list( + COMSIG_MACHINERY_DESTRUCTIVE_SCAN = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_destructive_experiment), + ) + AddComponent(/datum/component/experiment_handler, \ allowed_experiments = list(/datum/experiment/scanning),\ config_mode = EXPERIMENT_CONFIG_CLICK, \ - start_experiment_callback = CALLBACK(src, PROC_REF(activate))) + start_experiment_callback = CALLBACK(src, PROC_REF(activate)), \ + experiment_signals = destructive_signals, \ + ) ///Activates the machine; checks if it can actually scan, then starts. /obj/machinery/destructive_scanner/proc/activate() diff --git a/code/modules/experisci/experiment/experiments.dm b/code/modules/experisci/experiment/experiments.dm index ab971196092..1259f56597d 100644 --- a/code/modules/experisci/experiment/experiments.dm +++ b/code/modules/experisci/experiment/experiments.dm @@ -44,7 +44,7 @@ /mob/living/basic/chicken, /mob/living/basic/cow, /mob/living/basic/pet/dog/corgi, - /mob/living/simple_animal/hostile/retaliate/snake, + /mob/living/basic/snake, /mob/living/simple_animal/pet/cat, ) @@ -234,7 +234,7 @@ /obj/machinery/biogenerator = 3, /obj/machinery/gibber = 3, /obj/machinery/chem_master = 3, - /obj/machinery/atmospherics/components/unary/cryo_cell = 3, + /obj/machinery/cryo_cell = 3, /obj/machinery/harvester = 5, /obj/machinery/quantumpad = 5 ) @@ -291,7 +291,6 @@ /obj/machinery/rnd/experimentor = 1, /obj/machinery/medical_kiosk = 2, /obj/machinery/piratepad/civilian = 2, - /obj/machinery/rnd/bepis = 3 ) required_stock_part = /obj/item/stock_parts/scanning_module/adv @@ -332,7 +331,7 @@ ///Damage percent that each mech needs to be at for a scan to work. var/damage_percent -/datum/experiment/scanning/random/mecha_damage_scan/New() +/datum/experiment/scanning/random/mecha_damage_scan/New(datum/techweb/techweb) . = ..() damage_percent = rand(15, 95) //updating the description with the damage_percent var set diff --git a/code/modules/experisci/experiment/handlers/experiment_handler.dm b/code/modules/experisci/experiment/handlers/experiment_handler.dm index abc5d4ad1dd..29e7da95391 100644 --- a/code/modules/experisci/experiment/handlers/experiment_handler.dm +++ b/code/modules/experisci/experiment/handlers/experiment_handler.dm @@ -38,6 +38,7 @@ disallowed_traits = null, config_flags = null, datum/callback/start_experiment_callback = null, + list/experiment_signals ) . = ..() if(!ismovable(parent)) @@ -49,13 +50,8 @@ src.config_flags = config_flags src.start_experiment_callback = start_experiment_callback - if(isitem(parent)) - RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(try_run_handheld_experiment)) - RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, PROC_REF(ignored_handheld_experiment_attempt)) - if(istype(parent, /obj/machinery/destructive_scanner)) - RegisterSignal(parent, COMSIG_MACHINERY_DESTRUCTIVE_SCAN, PROC_REF(try_run_destructive_experiment)) - if(istype(parent, /obj/machinery/computer/operating)) - RegisterSignal(parent, COMSIG_OPERATING_COMPUTER_AUTOPSY_COMPLETE, PROC_REF(try_run_autopsy_experiment)) + for(var/signal in experiment_signals) + RegisterSignal(parent, signal, experiment_signals[signal]) // Determine UI display mode switch(config_mode) @@ -85,9 +81,9 @@ */ /datum/component/experiment_handler/proc/try_run_handheld_experiment(datum/source, atom/target, mob/user, params) SIGNAL_HANDLER - if (!should_run_handheld_experiment(source, target, user, params)) + if (!should_run_handheld_experiment(source, target, user)) return - INVOKE_ASYNC(src, PROC_REF(try_run_handheld_experiment_async), source, target, user, params) + INVOKE_ASYNC(src, PROC_REF(try_run_handheld_experiment_async), source, target, user) return COMPONENT_CANCEL_ATTACK_CHAIN /** @@ -98,7 +94,7 @@ if (!proximity_flag) return . |= COMPONENT_AFTERATTACK_PROCESSED_ITEM - if (selected_experiment == null && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) + if ((selected_experiment == null && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) || config_flags & EXPERIMENT_CONFIG_SILENT_FAIL) return . playsound(user, 'sound/machines/buzz-sigh.ogg', 25) to_chat(user, span_notice("[target] is not related to your currently selected experiment.")) @@ -107,7 +103,7 @@ /** * Checks that an experiment can be run using the provided target, used for preventing the cancellation of the attack chain inappropriately */ -/datum/component/experiment_handler/proc/should_run_handheld_experiment(datum/source, atom/target, mob/user, params) +/datum/component/experiment_handler/proc/should_run_handheld_experiment(datum/source, atom/target, mob/user) // Check that there is actually an experiment selected if (selected_experiment == null && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) return @@ -127,16 +123,17 @@ /** * This proc exists because Jared Fogle really likes async */ -/datum/component/experiment_handler/proc/try_run_handheld_experiment_async(datum/source, atom/target, mob/user, params) +/datum/component/experiment_handler/proc/try_run_handheld_experiment_async(datum/source, atom/target, mob/user) if (selected_experiment == null && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) - to_chat(user, span_notice("You do not have an experiment selected!")) + if(!(config_flags & EXPERIMENT_CONFIG_SILENT_FAIL)) + to_chat(user, span_notice("You do not have an experiment selected!")) return - if(!do_after(user, 1 SECONDS, target = target)) + if(!(config_flags & EXPERIMENT_CONFIG_IMMEDIATE_ACTION) && !do_after(user, 1 SECONDS, target = target)) return if(action_experiment(source, target)) playsound(user, 'sound/machines/ping.ogg', 25) to_chat(user, span_notice("You scan [target].")) - else + else if(!(config_flags & EXPERIMENT_CONFIG_SILENT_FAIL)) playsound(user, 'sound/machines/buzz-sigh.ogg', 25) to_chat(user, span_notice("[target] is not related to your currently selected experiment.")) @@ -148,8 +145,9 @@ SIGNAL_HANDLER var/atom/movable/our_scanner = parent if (selected_experiment == null) - playsound(our_scanner, 'sound/machines/buzz-sigh.ogg', 25) - to_chat(our_scanner, span_notice("No experiment selected!")) + if(!(config_flags & EXPERIMENT_CONFIG_SILENT_FAIL)) + playsound(our_scanner, 'sound/machines/buzz-sigh.ogg', 25) + to_chat(our_scanner, span_notice("No experiment selected!")) return var/successful_scan for(var/scan_target in scanned_atoms) @@ -159,7 +157,7 @@ if(successful_scan) playsound(our_scanner, 'sound/machines/ping.ogg', 25) to_chat(our_scanner, span_notice("The scan succeeds.")) - else + else if(!(config_flags & EXPERIMENT_CONFIG_SILENT_FAIL)) playsound(src, 'sound/machines/buzz-sigh.ogg', 25) our_scanner.say("The scan did not result in anything.") @@ -261,6 +259,7 @@ /datum/component/experiment_handler/proc/link_techweb(datum/techweb/new_web) if (new_web == linked_web) return + selected_experiment?.on_unselected(src) selected_experiment = null linked_web = new_web @@ -268,6 +267,7 @@ * Unlinks this handler from the selected techweb */ /datum/component/experiment_handler/proc/unlink_techweb() + selected_experiment?.on_unselected(src) selected_experiment = null linked_web = null @@ -278,13 +278,15 @@ * * experiment - The experiment to attempt to link to */ /datum/component/experiment_handler/proc/link_experiment(datum/experiment/experiment) - if (experiment && can_select_experiment(experiment)) + if (can_select_experiment(experiment)) selected_experiment = experiment + selected_experiment.on_selected(src) /** * Unlinks this handler from the selected experiment */ /datum/component/experiment_handler/proc/unlink_experiment() + selected_experiment?.on_unselected(src) selected_experiment = null /** @@ -299,31 +301,19 @@ return FALSE // Check against the list of allowed experimentors - if (experiment.allowed_experimentors && experiment.allowed_experimentors.len) - var/matched = FALSE - for (var/experimentor in experiment.allowed_experimentors) - if (istype(parent, experimentor)) - matched = TRUE - break - if (!matched) - return FALSE + if (length(experiment.allowed_experimentors) && !is_type_in_list(parent, experiment.allowed_experimentors)) + return FALSE // Check that this experiment is visible currently - if (!linked_web || !(experiment in linked_web.available_experiments)) + if (!(experiment in linked_web?.available_experiments)) return FALSE // Check that this experiment type isn't blacklisted - for (var/badsci in blacklisted_experiments) - if (istype(experiment, badsci)) - return FALSE - - // Check against the allowed experiment types - for (var/goodsci in allowed_experiments) - if (istype(experiment, goodsci)) - return TRUE + if(is_type_in_list(experiment, blacklisted_experiments)) + return FALSE - // If we haven't returned yet then this shouldn't be allowed - return FALSE + // Finally, check against the allowed experiment types + return is_type_in_list(experiment, allowed_experiments) /datum/component/experiment_handler/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -355,12 +345,13 @@ .["techwebs"] += list(data) .["experiments"] = list() if (linked_web) - for (var/datum/experiment/experiment in linked_web.available_experiments) + for (var/datum/experiment/experiment as anything in linked_web.available_experiments) + if(!can_select_experiment(experiment)) + continue var/list/data = list( name = experiment.name, description = experiment.description, tag = experiment.exp_tag, - selectable = can_select_experiment(experiment), selected = selected_experiment == experiment, progress = experiment.check_progress(), performance_hint = experiment.performance_hint, diff --git a/code/modules/experisci/experiment/types/experiment.dm b/code/modules/experisci/experiment/types/experiment.dm index f760723f8db..add015622f6 100644 --- a/code/modules/experisci/experiment/types/experiment.dm +++ b/code/modules/experisci/experiment/types/experiment.dm @@ -22,11 +22,16 @@ /// A textual hint shown on the UI in a tooltip to help a user determine how to perform /// the experiment var/performance_hint + /** + * If set, these techweb points will be rewarded for completing the experiment. + * Useful for those loose ends not tied to any specific node discount or requirement. + */ + var/list/points_reward /** * Performs any necessary initialization of tags and other variables */ -/datum/experiment/New() +/datum/experiment/New(datum/techweb/techweb) if (traits & EXPERIMENT_TRAIT_DESTRUCTIVE) exp_tag = "Destructive [exp_tag]" @@ -60,6 +65,14 @@ /datum/experiment/proc/actionable(...) return !is_complete() +///Called when the experiment is selected by an experiment handler, for specific signals and the such. +/datum/experiment/proc/on_selected(datum/component/experiment_handler/experiment_handler) + return + +///Called when the opposite happens. +/datum/experiment/proc/on_unselected(datum/component/experiment_handler/experiment_handler) + return + /** * Proc that tries to perform the experiment, and then checks if its completed. */ diff --git a/code/modules/experisci/experiment/types/exploration.dm b/code/modules/experisci/experiment/types/exploration.dm index a6a5d2cd4cf..821e69a103a 100644 --- a/code/modules/experisci/experiment/types/exploration.dm +++ b/code/modules/experisci/experiment/types/exploration.dm @@ -52,7 +52,7 @@ /// If not null the required_condition will be picked from this list var/list/possible_random_site_types -/datum/experiment/exploration_scan/random/New() +/datum/experiment/exploration_scan/random/New(datum/techweb/techweb) . = ..() if(length(possible_random_site_types)) required_site_type = pick(possible_random_site_types) diff --git a/code/modules/experisci/experiment/types/random_scanning.dm b/code/modules/experisci/experiment/types/random_scanning.dm index e80a80b5a0e..c9d39bd47b4 100644 --- a/code/modules/experisci/experiment/types/random_scanning.dm +++ b/code/modules/experisci/experiment/types/random_scanning.dm @@ -8,7 +8,7 @@ /// Max amount of a requirement per type var/max_requirement_per_type = 100 -/datum/experiment/scanning/random/New() +/datum/experiment/scanning/random/New(datum/techweb/techweb) // Generate random contents if (possible_types.len) var/picked = 0 diff --git a/code/modules/experisci/experiment/types/scanning.dm b/code/modules/experisci/experiment/types/scanning.dm index d9bbed88c8f..54bd2ad637e 100644 --- a/code/modules/experisci/experiment/types/scanning.dm +++ b/code/modules/experisci/experiment/types/scanning.dm @@ -17,16 +17,18 @@ var/list/required_atoms = list() /// The list of atoms with sub-lists of atom references for scanned atoms contributing to the experiment (Or a count of atoms destoryed for destructive expiriments) var/list/scanned = list() + /// If set, it'll be used in place of the generic "Scan samples of \a [initial(target.name)]" in serialize_progress_stage() + var/scan_message /** * Initializes the scanned atoms lists * * Initializes the internal scanned atoms list to keep track of which atoms have already been scanned */ -/datum/experiment/scanning/New() +/datum/experiment/scanning/New(datum/techweb/techweb) . = ..() for (var/req_atom in required_atoms) - scanned[req_atom] = traits & EXPERIMENT_TRAIT_DESTRUCTIVE ? 0 : list() + scanned[req_atom] = (traits & EXPERIMENT_TRAIT_DESTRUCTIVE && !(traits & EXPERIMENT_TRAIT_TYPECACHE)) ? 0 : list() /** * Checks if the scanning experiment is complete @@ -37,8 +39,12 @@ /datum/experiment/scanning/is_complete() . = TRUE var/destructive = traits & EXPERIMENT_TRAIT_DESTRUCTIVE + var/typecache = traits & EXPERIMENT_TRAIT_TYPECACHE for (var/req_atom in required_atoms) var/list/seen = scanned[req_atom] + ///typecache experiments work all the same whether it's destructive or not + if(typecache && length(seen) == required_atoms[req_atom]) + continue if (destructive && (!(req_atom in scanned) || scanned[req_atom] != required_atoms[req_atom])) return FALSE if (!destructive && (!seen || seen.len != required_atoms[req_atom])) @@ -65,8 +71,9 @@ * * seen_instances - The number of instances seen of this atom */ /datum/experiment/scanning/proc/serialize_progress_stage(atom/target, list/seen_instances) - var/scanned_total = traits & EXPERIMENT_TRAIT_DESTRUCTIVE ? scanned[target] : seen_instances.len - return EXPERIMENT_PROG_INT("Scan samples of \a [initial(target.name)]", scanned_total, required_atoms[target]) + var/scanned_total = (traits & EXPERIMENT_TRAIT_DESTRUCTIVE && !(traits & EXPERIMENT_TRAIT_TYPECACHE)) ? scanned[target] : seen_instances.len + var/message = scan_message || "Scan samples of \a [initial(target.name)]" + return EXPERIMENT_PROG_INT(message, scanned_total, required_atoms[target]) /** * Attempts to scan an atom towards the experiment's goal @@ -79,7 +86,10 @@ /datum/experiment/scanning/perform_experiment_actions(datum/component/experiment_handler/experiment_handler, atom/target) var/contributing_index_value = get_contributing_index(target) if (contributing_index_value) - scanned[contributing_index_value] += traits & EXPERIMENT_TRAIT_DESTRUCTIVE ? 1 : WEAKREF(target) + if(traits & EXPERIMENT_TRAIT_TYPECACHE) + scanned[contributing_index_value][target.type] = TRUE + else + scanned[contributing_index_value] += traits & EXPERIMENT_TRAIT_DESTRUCTIVE ? 1 : WEAKREF(target) if(traits & EXPERIMENT_TRAIT_DESTRUCTIVE && !isliving(target))//only qdel things when destructive scanning and they're not living (living things get gibbed) qdel(target) do_after_experiment(target, contributing_index_value) diff --git a/code/modules/experisci/experiment/types/scanning_fish.dm b/code/modules/experisci/experiment/types/scanning_fish.dm new file mode 100644 index 00000000000..83978010869 --- /dev/null +++ b/code/modules/experisci/experiment/types/scanning_fish.dm @@ -0,0 +1,116 @@ +///a superlist containing typecaches shared between the several fish scanning experiments for each techweb. +GLOBAL_LIST_EMPTY(scanned_fish_by_techweb) + +/** + * A special scanning experiment that unlocks further settings for the fishing portal generator. + * Mainly as an inventive solution to many a fish source being limited to maps that have it, + * and to make the fishing portal generator a bit than just gubby and goldfish. + */ +/datum/experiment/scanning/fish + name = "Fish Scanning Experiment 1" + description = "An experiment requiring different fish species to be scanned to unlock the 'Beach' setting for the fishing portal generator." + performance_hint = "Scan fish. Examine scanner to review progress. Unlock new fishing portals." + allowed_experimentors = list(/obj/item/experi_scanner, /obj/machinery/destructive_scanner, /obj/item/fishing_rod/tech) + traits = EXPERIMENT_TRAIT_TYPECACHE + points_reward = list(TECHWEB_POINT_TYPE_GENERIC = 750) + required_atoms = list(/obj/item/fish = 4) + scan_message = "Scan different species of fish" + ///Further experiments added to the techweb when this one is completed. + var/list/next_experiments = list(/datum/experiment/scanning/fish/second) + ///Completing a experiment may also enable a fish source to be used for use for the portal generator. + var/fish_source_reward = /datum/fish_source/portal/beach + +/** + * We make sure the scanned list is shared between all fish scanning experiments for this techweb, + * since this is about scanning each species, and having to redo it for each species is a hassle. + */ +/datum/experiment/scanning/fish/New(datum/techweb/techweb) + . = ..() + if(isnull(techweb)) + return + var/techweb_ref = REF(techweb) + var/list/scanned_fish = GLOB.scanned_fish_by_techweb[techweb_ref] + if(isnull(scanned_fish)) + scanned_fish = list() + GLOB.scanned_fish_by_techweb[techweb_ref] = scanned_fish + for(var/atom_type in required_atoms) + LAZYINITLIST(scanned_fish[atom_type]) + scanned = scanned_fish + +/** + * Registers a couple signals to review the fish scanned so far. + * It'd be an hassle not having any way (beside memory) to know which fish species have been scanned already otherwise. + */ +/datum/experiment/scanning/fish/on_selected(datum/component/experiment_handler/experiment_handler) + RegisterSignal(experiment_handler.parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_handler_examine)) + RegisterSignal(experiment_handler.parent, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(on_handler_examine_more)) + +/datum/experiment/scanning/fish/on_unselected(datum/component/experiment_handler/experiment_handler) + UnregisterSignal(experiment_handler.parent, list(COMSIG_ATOM_EXAMINE, COMSIG_ATOM_EXAMINE_MORE)) + +/datum/experiment/scanning/fish/proc/on_handler_examine(datum/source, mob/user, list/examine_list) + SIGNAL_HANDLER + examine_list += span_notice("Examine again to review all the species of fish scanned so far.") + +/datum/experiment/scanning/fish/proc/on_handler_examine_more(datum/source, mob/user, list/examine_list) + SIGNAL_HANDLER + var/message = span_notice("Fish species scanned hitherto, if any:") + message += "" + for(var/atom_type in required_atoms) + for(var/obj/item/fish/fish_path as anything in scanned[atom_type]) + message += "[initial(fish_path.name)]" + message += "" + examine_list += message + +///Only scannable fish will contribute towards the experiment. +/datum/experiment/scanning/fish/final_contributing_index_checks(obj/item/fish/target, typepath) + return target.experisci_scannable + +/** + * After a fish scanning experiment is done, more may be unlocked. If so, add them to the techweb + * and automatically link the handler to the next experiment in the list as a bit of qol. + */ +/datum/experiment/scanning/fish/finish_experiment(datum/component/experiment_handler/experiment_handler, ...) + . = ..() + if(next_experiments) + experiment_handler.linked_web.add_experiments(next_experiments) + var/datum/experiment/next_in_line = locate(next_experiments[1]) in experiment_handler.linked_web.available_experiments + experiment_handler.link_experiment(next_in_line) + +/datum/experiment/scanning/fish/second + name = "Fish Scanning Experiment 2" + description = "An experiment requiring more fish species to be scanned to unlock the 'Chasm' setting for the fishing portal." + points_reward = list(TECHWEB_POINT_TYPE_GENERIC = 1500) + required_atoms = list(/obj/item/fish = 8) + next_experiments = list(/datum/experiment/scanning/fish/third) + fish_source_reward = /datum/fish_source/portal/chasm + +/datum/experiment/scanning/fish/third + name = "Fish Scanning Experiment 3" + description = "An experiment requiring even more fish species to be scanned to unlock the 'Ocean' setting for the fishing portal." + points_reward = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + required_atoms = list(/obj/item/fish = 14) + next_experiments = list(/datum/experiment/scanning/fish/fourth, /datum/experiment/scanning/fish/holographic) + fish_source_reward = /datum/fish_source/portal/ocean + +/datum/experiment/scanning/fish/holographic + name = "Holographic Fish Scanning Experiment" + description = "This one actually requires holographic fish to unlock the 'Randomizer' setting for the fishing portal." + performance_hint = "Load in the 'Beach' template at the Holodeck to fish some holo-fish." + points_reward = list(TECHWEB_POINT_TYPE_GENERIC = 500) + required_atoms = list(/obj/item/fish/holo = 4) + scan_message = "Scan different species of holographic fish" + next_experiments = null + fish_source_reward = /datum/fish_source/portal/random + +///holo fishes are normally unscannable, but this is an experiment for them, so we don't care for the experisci_scannable variable. +/datum/experiment/scanning/fish/holographic/final_contributing_index_checks(obj/item/fish/target, typepath) + return TRUE + +/datum/experiment/scanning/fish/fourth + name = "Fish Scanning Experiment 4" + description = "An experiment requiring lotsa fish species to unlock the 'Hyperspace' setting for the fishing portal." + points_reward = list(TECHWEB_POINT_TYPE_GENERIC = 3250) + required_atoms = list(/obj/item/fish = 21) + next_experiments = null + fish_source_reward = /datum/fish_source/portal/hyperspace diff --git a/code/modules/experisci/experiment/types/scanning_material.dm b/code/modules/experisci/experiment/types/scanning_material.dm index 714205289de..fb8a7ff354b 100644 --- a/code/modules/experisci/experiment/types/scanning_material.dm +++ b/code/modules/experisci/experiment/types/scanning_material.dm @@ -9,7 +9,7 @@ ///List of materials actually required, indexed by the atom that is required. var/required_materials = list() -/datum/experiment/scanning/random/material/New() +/datum/experiment/scanning/random/material/New(datum/techweb/techweb) . = ..() for(var/req_atom in required_atoms) var/chosen_material = pick(possible_material_types) diff --git a/code/modules/experisci/experiment/types/scanning_plants.dm b/code/modules/experisci/experiment/types/scanning_plants.dm index c34822d6e7e..b92a4cc20b4 100644 --- a/code/modules/experisci/experiment/types/scanning_plants.dm +++ b/code/modules/experisci/experiment/types/scanning_plants.dm @@ -10,7 +10,7 @@ ///List of plant genes actually required, indexed by the atom that is required. var/list/required_genes = list() -/datum/experiment/scanning/random/plants/New() +/datum/experiment/scanning/random/plants/New(datum/techweb/techweb) . = ..() if(possible_plant_genes.len) for(var/req_atom in required_atoms) diff --git a/code/modules/experisci/handheld_scanner.dm b/code/modules/experisci/handheld_scanner.dm index e0fd4d480d5..97aa034afa1 100644 --- a/code/modules/experisci/handheld_scanner.dm +++ b/code/modules/experisci/handheld_scanner.dm @@ -19,9 +19,15 @@ // Late initialize to allow for the rnd servers to initialize first /obj/item/experi_scanner/LateInitialize() . = ..() + var/static/list/handheld_signals = list( + COMSIG_ITEM_PRE_ATTACK = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_handheld_experiment), + COMSIG_ITEM_AFTERATTACK = TYPE_PROC_REF(/datum/component/experiment_handler, ignored_handheld_experiment_attempt), + ) AddComponent(/datum/component/experiment_handler, \ - allowed_experiments = list(/datum/experiment/scanning, /datum/experiment/physical),\ - disallowed_traits = EXPERIMENT_TRAIT_DESTRUCTIVE) + allowed_experiments = list(/datum/experiment/scanning, /datum/experiment/physical), \ + disallowed_traits = EXPERIMENT_TRAIT_DESTRUCTIVE, \ + experiment_signals = handheld_signals, \ + ) /obj/item/experi_scanner/suicide_act(mob/living/carbon/user) user.visible_message(span_suicide("[user] is giving in to the Great Toilet Beyond! It looks like [user.p_theyre()] trying to commit suicide!")) diff --git a/code/modules/explorer_drone/control_console.dm b/code/modules/explorer_drone/control_console.dm index 7b371e8412b..8cc8854f27d 100644 --- a/code/modules/explorer_drone/control_console.dm +++ b/code/modules/explorer_drone/control_console.dm @@ -1,6 +1,6 @@ /obj/machinery/computer/exodrone_control_console name = "exploration drone control console" - desc = "control eploration drones from intersteller distances. Communication lag not included." + desc = "Control exploration drones from interstellar distances. Communication lag not included." circuit = /obj/item/circuitboard/computer/exodrone_console //Currently controlled drone var/obj/item/exodrone/controlled_drone diff --git a/code/modules/explorer_drone/example_adventures/Theres_a_tree_in_the_middle_of_space.json b/code/modules/explorer_drone/example_adventures/Theres_a_tree_in_the_middle_of_space.json index 3f9ee41582e..f06b1d25062 100644 --- a/code/modules/explorer_drone/example_adventures/Theres_a_tree_in_the_middle_of_space.json +++ b/code/modules/explorer_drone/example_adventures/Theres_a_tree_in_the_middle_of_space.json @@ -1,343 +1,356 @@ { - "adventure_name": "There's a tree in the middle of space.", - "version": 1, - "starting_node": "Tree Start", - "starting_qualities": { - "Confusion": 0 - }, - "required_site_traits": [ - "in space" - ], - "loot_categories": [ - "research" - ], - "scan_band_mods": { - "Exotic Radiation": 10 - }, - "deep_scan_description": "", - "triggers": [ - { - "name": "Confusion Trigger", - "target_node": "What is wrong with this tree?", - "requirements": [ - { - "quality": "Confusion", - "operator": ">", - "value": 30 - } - ] - } - ], - "nodes": [ - { - "name": "Tree Start", - "description": "Camera online. Visual signs detect a fully grown, seemingly biological, and live tree located in the middle of the vacuum.\nSensors indicate it is not oxygenating, but energy is being collected via passive solar light from the nearby star.\nBaffling.", - "choices": [ - { - "key": "choice 0", - "name": "Ignore site.", - "exit_node": "FAIL", - "delay": 10, - "delay_message": "Leave this for the botanists to figure out." - }, - { - "key": "choice 1", - "name": "Begin sensor scan.", - "exit_node": "Biological Scan", - "delay": 10, - "delay_message": "Lets get some data." - } - ], - "image": null, - "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMQAAAAAAAC15h2QtxeAoxVykROizRpxjxIAcgAAWwAAgAAAUAAAZAAAZgC0tLTKysr///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF/2AgjmRpnigqrMMqtCvhyvFs17hQuPva67ygTwgcGovA3a61BLaeryj0mapar9isNjCNylpfgWwsLpPPZqBst066le84fB5nRpvdvGDL7/v/JmBeaWiFhIeGbGqLio1ljm2CklKUA4CXmJmaAYidhp9mBmOiYqQEpqZlk3qbra6vsCOenqijtgIHCLG7vL29CQoNCsDCxMPBxw0MxsTLyMLCCwq+1LuVe9VZ0M/c297d4NvZ41vXeueU5N/r4e3o79jkvOb0UAe4+Pf6uMjS7P/TtAAcGKyeQXhT5ClcSKIdwYcHIyKMx7CiwocOwU3cWMmiR4YYQzqM+LGkSQXSUv/2y0jQH0qUJmNqoRSm5ixQbXLK2UmnJ886ToIilFltkk2cNw9B+umz6U87UOsRNXk0KdKrVrOSWWVwqlc+WHHWKnWqrKizZV+QGrA2yte31YDJPTZXrrMEzhbkPSYNWF+4gAFBeICJGTLDxVi2C5yNIxSQikVu48i4j8TLT1i2khwOM+bKVSQaeGLgQOnS+fIBwkiCszfPjqWAnn0ism1hsXO/oM279e3fuqmYeAChN++XKqP9BujP+EcXMKLkoFFm+o3qSH5oJ7L9SPfs3IlEHw/dhfNyLMpbX4+duvvw3uGDj08fCfn0+KVTPI9Ff/T37AHY3nXfFSifgfX9cJ//f/vxh95/1wkoYYQU5oDgfBh+t+B9DsJS4YABfiiDAWWQOGKJKJ6oYidcDdVhUVrFGFZWRl32IlEy0nJLWjyu1VYYrNxY2YxXjZUWW1+0FaSQDiaQ4z0y3OMXX3wxaSUKiWWZTF5c+sVASl8iB9OVbxFH3CVabmOMa9yQ6WYAbHL2Zh+UVRTnbV3NyUlwu120HEuw9WlloO+Mc+c3fCbEH6ES/Ybmn9AwWmdvnu1jaWoHpMBmFYdK+tmLiQqKCaTAebqRnh4d6o6pEqHqEan/sOqiqxbBumqoig42GK0WqUqQY7zCtZKvDgXL37AvEbvNAsaeJ6Zy0JKqErPNYpIj/xqOOKUtU9xu6+1OUekpCJFpLPXtud2mu21UTbhKLraPqCsvuvQ+FdQSqI57bbnxtlHvv/OCK5RsqO4Lr78BA6xwulDR+m4n5iYs8cJNVNyguwYzEi/FE3dsR7UpZJzIxh1z7FO4IJ8gMr860WuAEi/rEHMBM88s8ccpn/AwVhEjTDPMQMsc9M9Cx9HyIJbknMLOEJNC8xpOR/3zy1RPbXXVWD8tM9Rcq3Kx0lesvKORZz2NFtVmnWJ2j2NLAnYsiJCd9tlzz7122XTnnfbb2dxUi96A1x044GDwnc0Zfwuu+OCLK274c4UkzvjkZj3+ldxkUY5AApt3noDlldF1zP/YBAyzuemcp4665wGBDlcDeCUA+zKzyx77Arfnvjnuy+C+u+uADXPXMsTHXvzxxid/PPC8OEAYmnLBPoz0ttMee+3YXx/958y/oqsDl4hel/jkjz9+Md17Rf3620/fvu3uxy97A+lPVT75ic2lJWLDWD7AE/97QQCT1qv3sU9+6ytGAxTIQL7FpiLJiCD/JggOYJxKXAPMIAA3KCp1MHB6H5wfCEcowgRoUIAc/F8L3CSrr/EiGAsc4QKhEcMZwpCG0DihClHIQxVeaYdA1KEQAWioD9pQhEesoRJTOMQe/k9ITQwiEzloQ/q9sIpKxOENt9iAKHpxgw76ohOnKED/LWJRGJrIIhfVWEUxSnGMPDQOGd+4wwME0I76COAC2MhHNPZhjWbk4xzd2MTeNBGPuBiAPg6wyEbiIlMiaEBKYrjHQOJQG5YE5BbpSMhByvGQiixNKBlpGlI+8h5a0OQZg2ECVfYRhoOMJRx36JxZ/k+UbMGjKEupyERi4pUzjGQmV9lGWXLSkxiMoy+ICcxmNsCWxvRi/VYzw2pa85rYvKYKt8nNbnrzm96c5h+G6UwudhKacBTnOLPJznYuEJzwjCc41blOctoTlug8JjTpiSZ3+lOb3LTj/wSqSHlycwQPeB4//8jMe2KRgwJNZDQJaCaFLlQge6ykJP/ZTo3iYbGgHx3oPC+6CZRQspwNNakwEMnSE5L0FRndaEwXqFGO0lSmG32pQmLK043e1KYz7KlO5dHTouKUo0YdKjmMalSk4jSmSh3HAqb61KpqtKZBtWpOo1oNpmoVq9dkKrWMEwIAOw==" - }, - { - "name": "Biological Scan", - "description": "You attempt to scan for clues regarding the tree's nature. It appears to be a fully mature oak tree. \n\nApproximated height is 13 ft, 6.4 inches. \n\nSubject sees no sign of an outer coating or otherwise layer protecting it from the void of space.\n\nSubject's surface temperature is 293.7 kelvin, as though it were sitting indoors.", - "choices": [ - { - "key": "choice 2", - "name": "Check Sensor Integrity.", - "exit_node": "Its Not You...", - "on_selection_effects": [ - { - "effect_type": "Add", - "quality": "Confusion", - "value": 5 - } - ], - "delay": 50, - "delay_message": "This can't be right." - }, - { - "key": "choice 4", - "name": "Attempt to take sample.", - "exit_node": "Sample Taken", - "on_selection_effects": [ - { - "effect_type": "Add", - "quality": "Confusion", - "value": 3 - } - ], - "delay": 40, - "delay_message": "Snip snip." - }, - { - "key": "choice 6", - "name": "Examine Tree Roots.", - "exit_node": "Examine Roots", - "delay": 10 - }, - { - "key": "choice 9", - "name": "Sequence Sample Radiation with background noise.", - "exit_node": "Background Analysis", - "requirements": [ - { - "quality": "Sample", - "operator": ">=", - "value": 1 - } - ], - "delay": 0, - "delay_message": "This can't be real." - } - ], - "image": null, - "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMQAAAAAAAC15h2QtxeAoxVykROizRpxjxIAcgAAWwAAgAAAUAAAZAAAZgC0tLTKysr///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF/2AgjmRpnigqrMMqtCvhyvFs17hQuPva67ygTwgcGovA3a61BLaeryj0mapar9isNjCNylpfgWwsLpPPZqBst066le84fB5nRpvdvGDL7/v/JmBeaWiFhIeGbGqLio1ljm2CklKUA4CXmJmaAYidhp9mBmOiYqQEpqZlk3qbra6vsCOenqijtgIHCLG7vL29CQoNCsDCxMPBxw0MxsTLyMLCCwq+1LuVe9VZ0M/c297d4NvZ41vXeueU5N/r4e3o79jkvOb0UAe4+Pf6uMjS7P/TtAAcGKyeQXhT5ClcSKIdwYcHIyKMx7CiwocOwU3cWMmiR4YYQzqM+LGkSQXSUv/2y0jQH0qUJmNqoRSm5ixQbXLK2UmnJ886ToIilFltkk2cNw9B+umz6U87UOsRNXk0KdKrVrOSWWVwqlc+WHHWKnWqrKizZV+QGrA2yte31YDJPTZXrrMEzhbkPSYNWF+4gAFBeICJGTLDxVi2C5yNIxSQikVu48i4j8TLT1i2khwOM+bKVSQaeGLgQOnS+fIBwkiCszfPjqWAnn0ism1hsXO/oM279e3fuqmYeAChN++XKqP9BujP+EcXMKLkoFFm+o3qSH5oJ7L9SPfs3IlEHw/dhfNyLMpbX4+duvvw3uGDj08fCfn0+KVTPI9Ff/T37AHY3nXfFSifgfX9cJ//f/vxh95/1wkoYYQU5oDgfBh+t+B9DsJS4YABfiiDAWWQOGKJKJ6oYidcDdVhUVrFGFZWRl32IlEy0nJLWjyu1VYYrNxY2YxXjZUWW1+0FaSQDiaQ4z0y3OMXX3wxaSUKiWWZTF5c+sVASl8iB9OVbxFH3CVabmOMa9yQ6WYAbHL2Zh+UVRTnbV3NyUlwu120HEuw9WlloO+Mc+c3fCbEH6ES/Ybmn9AwWmdvnu1jaWoHpMBmFYdK+tmLiQqKCaTAebqRnh4d6o6pEqHqEan/sOqiqxbBumqoig42GK0WqUqQY7zCtZKvDgXL37AvEbvNAsaeJ6Zy0JKqErPNYpIj/xqOOKUtU9xu6+1OUekpCJFpLPXtud2mu21UTbhKLraPqCsvuvQ+FdQSqI57bbnxtlHvv/OCK5RsqO4Lr78BA6xwulDR+m4n5iYs8cJNVNyguwYzEi/FE3dsR7UpZJzIxh1z7FO4IJ8gMr860WuAEi/rEHMBM88s8ccpn/AwVhEjTDPMQMsc9M9Cx9HyIJbknMLOEJNC8xpOR/3zy1RPbXXVWD8tM9Rcq3Kx0lesvKORZz2NFtVmnWJ2j2NLAnYsiJCd9tlzz7122XTnnfbb2dxUi96A1x044GDwnc0Zfwuu+OCLK274c4UkzvjkZj3+ldxkUY5AApt3noDlldF1zP/YBAyzuemcp4665wGBDlcDeCUA+zKzyx77Arfnvjnuy+C+u+uADXPXMsTHXvzxxid/PPC8OEAYmnLBPoz0ttMee+3YXx/958y/oqsDl4hel/jkjz9+Md17Rf3620/fvu3uxy97A+lPVT75ic2lJWLDWD7AE/97QQCT1qv3sU9+6ytGAxTIQL7FpiLJiCD/JggOYJxKXAPMIAA3KCp1MHB6H5wfCEcowgRoUIAc/F8L3CSrr/EiGAsc4QKhEcMZwpCG0DihClHIQxVeaYdA1KEQAWioD9pQhEesoRJTOMQe/k9ITQwiEzloQ/q9sIpKxOENt9iAKHpxgw76ohOnKED/LWJRGJrIIhfVWEUxSnGMPDQOGd+4wwME0I76COAC2MhHNPZhjWbk4xzd2MTeNBGPuBiAPg6wyEbiIlMiaEBKYrjHQOJQG5YE5BbpSMhByvGQiixNKBlpGlI+8h5a0OQZg2ECVfYRhoOMJRx36JxZ/k+UbMGjKEupyERi4pUzjGQmV9lGWXLSkxiMoy+ICcxmNsCWxvRi/VYzw2pa85rYvKYKt8nNbnrzm96c5h+G6UwudhKacBTnOLPJznYuEJzwjCc41blOctoTlug8JjTpiSZ3+lOb3LTj/wSqSHlycwQPeB4//8jMe2KRgwJNZDQJaCaFLlQge6ykJP/ZTo3iYbGgHx3oPC+6CZRQspwNNakwEMnSE5L0FRndaEwXqFGO0lSmG32pQmLK043e1KYz7KlO5dHTouKUo0YdKjmMalSk4jSmSh3HAqb61KpqtKZBtWpOo1oNpmoVq9dkKrWMEwIAOw==" - }, - { - "name": "Its Not You...", - "description": "After re-connection is established, your sensors appear fine. Tree has not moved in the slightest since last observed. Temperature has fluxuated 0.2 kelvin upwards, as expected of a plant under direct light.\nLets try again.", - "choices": [ - { - "key": "choice 3", - "name": "Restart biological scan.", - "exit_node": "Biological Scan", - "delay": 25, - "delay_message": "God damnit." - } - ], - "image": null, - "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMIAAAAAAAD////v7+/h4eEAAAAAAAAAAAAD/xi63P4wykmrvTjrzbv/YCiOZBkJaJqaLKOubSy7b23fODxPOb7/m4FASBRofEBeT1W6JU3DYaRIjQqfkCWKg1xoddjSQEgQlM/mdDkc0Fa+8PiWLSIM7Pj73RxOlVF/ITlKNXSGDXp5iiFoaBlqfpFyk12HMgSYmZkfmppmmJ8gjXwUf2lglqmqq6ytrq+wsbKztLW2t7i5um2Ug669uyBCKMNRc4Q9qXHBJlVUFMbRV6pfR04ONszQzlZRlm7IveLaimZ7eJAESUsfyVnX2hfqv/Nv4vfZ8RWJ/Hkdn6NGtRsFyEg4VLwK6UvVqROdgMcWSpxIsaLFixgzatzIsf+jR1gIP7YbN6uaSAn4wFGbdNJFsZcpFRqS09IBt2kW3CkzWdNmNyIYpIWkw9Nevgbwat2ccNPbTnbWjtKQWfGnVZwzoQaNqVXXkDFWGx3qeoIry2CJzJ05p6aPTpRmfSXV1a/u2jM7TuldA8LXO6kXFemh5ihn3Lc9A9h1ZaqxpMNkK9rl5+EMKIGM9g5FSjJjv4aVOwEc/Q8iXx6ODSo5ualOQ9Bs0qVJTLu27du4c+vezbu379/AgwsfTry48ePIkytfqHp5xhfLadby+1soMJDLbhchlqIYpVbXa14dz718NMBEz/ZsWsU8zMhY1CdmL+VE+/ObgWSvPR4rj/f/xqxUFG1fVfHIUgLCN58zR5ABySpwbAAdZ1TNMgZYF9YHjWmsDAgNeglNqFSBJJYiG14JUmcYiHNZWJcE6HD4FGIrVuiFjROxJeNYChoFWUS5lBPjOTO2iM2PKuki2F1qfdPjjUjSeMuSk82Uml4fRimlLVR2OUAYBGHpo5aV4OJll1iYRkqWhag4FY75WXhmlTOoedo/ZVKI40Jz+pOEnX2ZsqcCeVJ0piEQieJhiEx0RBkrd6J2IiQFVXqPbZjEYqdmll6Jz0avtUaCqEFtaiqnekmHUagOhSZapvJMeioanXa2KqukZoCrJoruCKNmCngKZGC7urprPRKq+QZBP2XFKRGunBwL6waZjIbiBInu9hoj0o5wraRiOadrsX1kK24HvBK25rnstuvuu/DGK++89NZr77345qvvvhYlAAA7" - }, - { - "name": "Sample Taken", - "description": "You collect and project a small sample of tree bark off the plant. The instant that the bark is removed from the tree, as though it suddenly remembered what it was, the moisture content of the bark freezes over, and implodes into small microparticles of splinters.\nSmall radioactive signature detected.", - "choices": [ - { - "key": "choice 5", - "name": "Well that was... unexpected.", - "exit_node": "Biological Scan", - "delay": 0, - "delay_message": "Maybe something else might work better.", - "on_selection_effects": [ - { - "effect_type": "Add", - "quality": "Sample", - "value": 1 - } - ] - } - ], - "image": null, - "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMIAAAAAAABSLiiPVjtyRS9mOTFbNyYAAAAD/xi63P4wykmrvTjrzbv/YCiOZGmeaKqubOu+sDUQxTDbeK7vfF/3saCwcxPcCMckcqlM2pDPnnRKrUqH2IdAYDBwu+Bwl2Agm8sE8iy9Zrqbb2Z0bq3b74W8Xp+1bP+Af2KDhIVlh2eJaUtsi3CPcU43d5QDe5cFfSKBnJ2en50Ff6JboqYCBWiLq46tkK+RUJOTmJmatxyguqSovae/vsGirK2NjU21trjLQp+8wNDCwnmo1MnM2Nna29zd3t/g4eLj5OXm59o5Rjo/QOjvLaKwkrKylfdW8FleXImIBm0CxppXD4c9fAgT5tCn4Iuhh4fG/DNTjNHAi4/oKERYq/+cro8gPYXxR7EkK4EEUxbUOCVZHoabQoZ8NkqaKWI4BR7DGKcjTG4yaZaySRSatQLGfP5ciqHX0GhQpzGdSrWq1atYs2rdyrWr169gw4pVsc7G2LMLkM46SOkl2nc86W3E97aFgLh4Dc7dq6NuhC0TVVlUOY8l38N9szocREYiyYqEMdJZibjylW+AIRIiqUowyrwDJ+u1XMelsm6CNKtmHHiRZ8iuQGecVdklZpm4V3NWREznYNmhaeNRCg638eOBhrUWjPP3zshNDNuwzRW5dZrQmms3BhzSNb8SrIPCXvTudtjzMIEngVxo+ajDtKOkvt5u0Jrw3/s6yqd+Nk7/7uUn4FH+VaWfKAUmqOCCDDbo4IMQRijhhBRWaOGFGGao4YYcdujhhyCGKOKFRsgxy4jaBEeZOyi60J2JK1piS2ItcvDiaMIpVGMEv0GnIo46grgFbM/dKBppC004kXzo3fiGdJb51wUgiKTBnHNOzsYWkpd1xZpjrTHJnY+vQGlZOztMBUZmrO0mZo9Zwggkl/mkKc5qIy3n2nlExrnWnHROcRueYjSm55Wr+Ebmj2YeZpo4bBJqyG6Inqeon0duRF84kuJJKW98Nrkojlu2dYlHkXaq6qehNvfZqHI2+ihq4lGpKhisttpbbKNm6sN3t9Wam2q5Vtrqq5jesKk3jsI220mheuq665jJzoqqs9gGcqi0211KGLBUZYutciUZG6q3cREnlrjiPcZtTqIiAW597H5E07uuiqqehPXONIq57+6rYb81PWUTvmksuyHBTjUc1XnVmOLWjgFkG+CBNk1MsRb1kiegLxtf4KzHB4b8Qa0XA2OyfZ6QjODKywwlM8w012zzzTjnrPNWCQAAOw==" - }, - { - "name": "Examine Roots", - "description": "All plant matter has to derive energy and moisture from someplace. Examining the oak tree's roots reveals that the roots present all appear to splay out, similar to how a normal tree would. However, those roots then proceed to double back in on itself. This might suggest that the tree is obtaining nutrients from... itself.", - "choices": [ - { - "key": "choice 7", - "name": "That's fucking stupid.", - "exit_node": "Biological Scan", - "on_selection_effects": [ - { - "effect_type": "Add", - "quality": "Confusion", - "value": { - "value_type": "random", - "low": 6, - "high": 10 - } - } - ], - "delay": 0, - "delay_message": "What the hell kind of tree even IS this?" - }, - { - "key": "choice 8", - "name": "Obtain biological sample from roots.", - "exit_node": "Sample Taken", - "delay": 10, - "delay_message": "This is why we hire botanists on-site." - } - ], - "image": null, - "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMQAAAAAAAC15h2QtxeAoxVykROizRpxjxIAcgAAWwAAgAAAUAAAZAAAZgC0tLTKysr///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF/2AgjmRpnigqrMMqtCvhyvFs17hQuPva67ygTwgcGovA3a61BLaeryj0mapar9isNjCNylpfgWwsLpPPZqBst066le84fB5nRpvdvGDL7/v/JmBeaWiFhIeGbGqLio1ljm2CklKUA4CXmJmaAYidhp9mBmOiYqQEpqZlk3qbra6vsCOenqijtgIHCLG7vL29CQoNCsDCxMPBxw0MxsTLyMLCCwq+1LuVe9VZ0M/c297d4NvZ41vXeueU5N/r4e3o79jkvOb0UAe4+Pf6uMjS7P/TtAAcGKyeQXhT5ClcSKIdwYcHIyKMx7CiwocOwU3cWMmiR4YYQzqM+LGkSQXSUv/2y0jQH0qUJmNqoRSm5ixQbXLK2UmnJ886ToIilFltkk2cNw9B+umz6U87UOsRNXk0KdKrVrOSWWVwqlc+WHHWKnWqrKizZV+QGrA2yte31YDJPTZXrrMEzhbkPSYNWF+4gAFBeICJGTLDxVi2C5yNIxSQikVu48i4j8TLT1i2khwOM+bKVSQaeGLgQOnS+fIBwkiCszfPjqWAnn0ism1hsXO/oM279e3fuqmYeAChN++XKqP9BujP+EcXMKLkoFFm+o3qSH5oJ7L9SPfs3IlEHw/dhfNyLMpbX4+duvvw3uGDj08fCfn0+KVTPI9Ff/T37AHY3nXfFSifgfX9cJ//f/vxh95/1wkoYYQU5oDgfBh+t+B9DsJS4YABfiiDAWWQOGKJKJ6oYidcDdVhUVrFGFZWRl32IlEy0nJLWjyu1VYYrNxY2YxXjZUWW1+0FaSQDiaQ4z0y3OMXX3wxaSUKiWWZTF5c+sVASl8iB9OVbxFH3CVabmOMa9yQ6WYAbHL2Zh+UVRTnbV3NyUlwu120HEuw9WlloO+Mc+c3fCbEH6ES/Ybmn9AwWmdvnu1jaWoHpMBmFYdK+tmLiQqKCaTAebqRnh4d6o6pEqHqEan/sOqiqxbBumqoig42GK0WqUqQY7zCtZKvDgXL37AvEbvNAsaeJ6Zy0JKqErPNYpIj/xqOOKUtU9xu6+1OUekpCJFpLPXtud2mu21UTbhKLraPqCsvuvQ+FdQSqI57bbnxtlHvv/OCK5RsqO4Lr78BA6xwulDR+m4n5iYs8cJNVNyguwYzEi/FE3dsR7UpZJzIxh1z7FO4IJ8gMr860WuAEi/rEHMBM88s8ccpn/AwVhEjTDPMQMsc9M9Cx9HyIJbknMLOEJNC8xpOR/3zy1RPbXXVWD8tM9Rcq3Kx0lesvKORZz2NFtVmnWJ2j2NLAnYsiJCd9tlzz7122XTnnfbb2dxUi96A1x044GDwnc0Zfwuu+OCLK274c4UkzvjkZj3+ldxkUY5AApt3noDlldF1zP/YBAyzuemcp4665wGBDlcDeCUA+zKzyx77Arfnvjnuy+C+u+uADXPXMsTHXvzxxid/PPC8OEAYmnLBPoz0ttMee+3YXx/958y/oqsDl4hel/jkjz9+Md17Rf3620/fvu3uxy97A+lPVT75ic2lJWLDWD7AE/97QQCT1qv3sU9+6ytGAxTIQL7FpiLJiCD/JggOYJxKXAPMIAA3KCp1MHB6H5wfCEcowgRoUIAc/F8L3CSrr/EiGAsc4QKhEcMZwpCG0DihClHIQxVeaYdA1KEQAWioD9pQhEesoRJTOMQe/k9ITQwiEzloQ/q9sIpKxOENt9iAKHpxgw76ohOnKED/LWJRGJrIIhfVWEUxSnGMPDQOGd+4wwME0I76COAC2MhHNPZhjWbk4xzd2MTeNBGPuBiAPg6wyEbiIlMiaEBKYrjHQOJQG5YE5BbpSMhByvGQiixNKBlpGlI+8h5a0OQZg2ECVfYRhoOMJRx36JxZ/k+UbMGjKEupyERi4pUzjGQmV9lGWXLSkxiMoy+ICcxmNsCWxvRi/VYzw2pa85rYvKYKt8nNbnrzm96c5h+G6UwudhKacBTnOLPJznYuEJzwjCc41blOctoTlug8JjTpiSZ3+lOb3LTj/wSqSHlycwQPeB4//8jMe2KRgwJNZDQJaCaFLlQge6ykJP/ZTo3iYbGgHx3oPC+6CZRQspwNNakwEMnSE5L0FRndaEwXqFGO0lSmG32pQmLK043e1KYz7KlO5dHTouKUo0YdKjmMalSk4jSmSh3HAqb61KpqtKZBtWpOo1oNpmoVq9dkKrWMEwIAOw==" - }, - { - "name": "Background Analysis", - "description": "You compare the radioactive energy bands of the sample collected earlier with that of the nearby solar enviroment.\nNothing.\nThere is nothing nearby that matches the passive signal of the tree, or the bark, or anything similar.\nThis is really starting to get on your nerves.", - "choices": [ - { - "key": "choice 10", - "name": "Smash your desk in frustration.", - "exit_node": "FAIL", - "delay": 50, - "delay_message": "No amount of pay is worth dealing with magical plant juju." - }, - { - "key": "choice 11", - "name": "Check every known energy spectroscopy database.", - "exit_node": "Sample Match Found", - "delay": 900, - "delay_message": "You NEED an answer. You DESERVE an answer." - } - ], - "image": null, - "on_enter_effects": [ - { - "effect_type": "Add", - "quality": "Confusion", - "value": { - "value_type": "random", - "low": 3, - "high": 5 - } - } - ], - "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMIAAAAAAAD///9ZVlKsMjJpampGR0cAAAAD/xi63P4wykmFpTjrDa0XXCiOZGlqQ0qsazqIXyx9Z23feKayfP/WskgwRywqCsikcslsOpGpgGvQNDo8lYt1W4I+v2CvMhUuI0/YiZbL5nxdhkJ8Lq/T6eZ8HRmHUtuAgRp6T3B2SXdNfYeJc3CCkJEYjISVYZKRQ5gajZSdi0yboqM3nnWkqKmCpgaqrq9GBrKzs7AKaYG4tji0vbu/wCW6wZpqNMHIOAM9zDw/IzEgHcVt1KOWZQ1TU4LDV2vJOAVU2GZkY5VF4NPr4SRM53yI8/Lw9uVvBcLuknqGn4cqLQIYhwy/g0fwKdSDsCEGggtDOZwoAiLFi5sAYtwoqf/XIVjeOKrqRUukjZAmGVjDGC2lSyAts7R7GW5ZM2bPNERDGSAmzWA2b/pAc+yBT0ArVeXhsC2oj5wnefaU+pNBxDJNXUAqyq6qhKthyCUR+4QLVa5ej5AFO3ZJPGw3qE5N22DsWiUD6Tm5e/cqCbk96dZtQgZip3rjwIIa90fwqrBUDAfcQ0hyilaOIWG7zIoSYryd73DLrJntNlOIO2WVQ/raYrYKW/8CCNuJbH6S8aS7vSCpq9C8gxMMzns48dudj9/WqFw2yZKvfDc38Rxzc+kiq09f/nw7b+wNwV9HuwuwSvLeL14wjz49pm3Qds7sbd59jh1Co3CQP1+8/Rr/TgnVQnxHNVDgf0QEKCBUIRxIX3sIAiigMwzCAKF/cc1H1xQTVvjXhRCqE6IosU2Q1YkiajiViin+VhthWW0l1YhevQjjafrIKI0QLP5kI2GMBWkbG2fVx1FiP/oxRl9DEiEXCDsKhuSPazFpBg5P9miSkHmlpleXbbkVUVRRTkOakl7mRg9fsJmQ5Zl2DaDmJ4XVwZkZYHbpoU726eZCaID28RYYeRFEToQVeVaYLHIwOkugk70GqWiNIeoGQJc5qumclOU5qUGWXhraFNU1yumpdoAa6ganZkrLpJ2G5qido606CKoGwDErrqaaSlKttrIKq2r/DGvHr39aF2wIgsYaduKzqyUhhbLLjsArp3BVW0Oz3OpWlrY5dCsuKOByMS635QpyLaTEGenauZ2M5y4m696B4Lz0spLuRMnt25BH9vr7b3XUChwOwbIYfBDCBSscDMIOL0xwxO5ATPHB2kVHY7oTg7RxuR0rhyFFIYv8MUYZX5xMySoDk3LLD3dXbQIAOw==" - }, - { - "name": "Sample Match Found", - "description": "After an extensive algorithm search on the controller end, you have a single match to this specific band and style of energy.\nThe problem, is that the source of said radiation is coming not only from Space Station 13, no.\nIt's coming from the Space Station 13 Research Department.\nWhat the fuck?", - "choices": [ - { - "key": "choice 12", - "name": "Something must be wrong with the drone.", - "exit_node": "Its Not You...", - "on_selection_effects": [ - { - "effect_type": "Add", - "quality": "Confusion", - "value": { - "value_type": "random", - "low": 6, - "high": 10 - } - } - ], - "delay": 30, - "delay_message": "Lousy piece of junk must be scanning the station instead of the target." - }, - { - "key": "choice 13", - "name": "Perhaps that sample was tainted. Collect a new sample.", - "exit_node": "Sample Taken", - "delay": 60, - "delay_message": "Lets try again, but carefully." - }, - { - "key": "choice 14", - "name": "Remember the Christmas Party.", - "exit_node": "The Christmas Party", - "requirements": [ - { - "quality": "Confusion", - "operator": "<=", - "value": 25 - } - ], - "delay": 100, - "delay_message": "Wait a gosh darn fucking second." - } - ], - "image": null, - "on_enter_effects": [ - { - "effect_type": "Add", - "quality": "Confusion", - "value": 10 - } - ], - "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMIAAAAAAAD////v7+/h4eEAAAAAAAAAAAAD/xi63P4wykmrvTjrzbv/YCiOZBkJaJqaLKOubSy7b23fODxPOb7/m4FASBRofEBeT1W6JU3DYaRIjQqfkCWKg1xoddjSQEgQlM/mdDkc0Fa+8PiWLSIM7Pj73RxOlVF/ITlKNXSGDXp5iiFoaBlqfpFyk12HMgSYmZkfmppmmJ8gjXwUf2lglqmqq6ytrq+wsbKztLW2t7i5um2Ug669uyBCKMNRc4Q9qXHBJlVUFMbRV6pfR04ONszQzlZRlm7IveLaimZ7eJAESUsfyVnX2hfqv/Nv4vfZ8RWJ/Hkdn6NGtRsFyEg4VLwK6UvVqROdgMcWSpxIsaLFixgzatzIsf+jR1gIP7YbN6uaSAn4wFGbdNJFsZcpFRqS09IBt2kW3CkzWdNmNyIYpIWkw9Nevgbwat2ccNPbTnbWjtKQWfGnVZwzoQaNqVXXkDFWGx3qeoIry2CJzJ05p6aPTpRmfSXV1a/u2jM7TuldA8LXO6kXFemh5ihn3Lc9A9h1ZaqxpMNkK9rl5+EMKIGM9g5FSjJjv4aVOwEc/Q8iXx6ODSo5ualOQ9Bs0qVJTLu27du4c+vezbu379/AgwsfTry48ePIkytfqHp5xhfLadby+1soMJDLbhchlqIYpVbXa14dz718NMBEz/ZsWsU8zMhY1CdmL+VE+/ObgWSvPR4rj/f/xqxUFG1fVfHIUgLCN58zR5ABySpwbAAdZ1TNMgZYF9YHjWmsDAgNeglNqFSBJJYiG14JUmcYiHNZWJcE6HD4FGIrVuiFjROxJeNYChoFWUS5lBPjOTO2iM2PKuki2F1qfdPjjUjSeMuSk82Uml4fRimlLVR2OUAYBGHpo5aV4OJll1iYRkqWhag4FY75WXhmlTOoedo/ZVKI40Jz+pOEnX2ZsqcCeVJ0piEQieJhiEx0RBkrd6J2IiQFVXqPbZjEYqdmll6Jz0avtUaCqEFtaiqnekmHUagOhSZapvJMeioanXa2KqukZoCrJoruCKNmCngKZGC7urprPRKq+QZBP2XFKRGunBwL6waZjIbiBInu9hoj0o5wraRiOadrsX1kK24HvBK25rnstuvuu/DGK++89NZr77345qvvvhYlAAA7" - }, - { - "name": "The Christmas Party", - "description": "Hold on. Last Christmas, the Research Director was incredibly hammered. He made a big mention that his brand new festivus pole was actually some kind of astrological... something something. You can't remember the whole details, because you were smashed as well. However, briefly, the RD did keep that festivus pole for awhile, he might even still have it somewhere.\nMaybe...?", - "choices": [ - { - "key": "choice 15", - "name": "Wait a minute, was that a god damn...", - "exit_node": "Rod.", - "delay": 100, - "delay_message": "Immovable Rod?" - } - ], - "image": null, - "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMIAAAAAAAD/AACmAAD///+mpqYAAAAAAAAD/xi63P4wykmrvTjrzbv/YCiOZGmejKCubOu6aCzP4WvfeD4IQ+//Pppw+MkZj6udkgdsOp/EqFSBrNqWwQ9hy+16v9ypeGM9YpnAE3hNKLTfhbG8kuTZz/j7/fmb+/8TbIJefIVNgIiJGgWMjY6PkJGRipSVlpeYmZqbnJ2en6ChoqOkpRplqDdYpqyprnpKhnyslq9leFkYg2u0QrZmaLkgu8S9JDg7Ksl2yrB7UDJw0m6QxiFfedk9wbKH1tbEW9TT05Lmjd/pJpPq7e7v8PHy8/T19vf4+fr7Kb9W/Jn8pcLiBKAcgVZwdethkAZCJAoXFmx47KEOWLMeAAlHMf+DRVXctIT70jHCxxYEhXkYKajkgpMRGZZgKY5LHJcJ6zTTNtHEm5rjgsK5WZKZs2xHn2WccY6RSwdJkaaUOOApoHDbqFK16ofmF6Fg20Aa8IhrpbBBm6plZ7aTIwhr0bWdS7eu3bt48+rdy7ev37+AAwseTLiw4cOI0/1LfPAkC8YlHINUApmD5MncVFZ+cPmK0qWbX3Z2MbVbaCqjd37eCjk1i9JaZR5OHTN2z8Gua9v2wavvaNjeKgygqbcz8KocvBLAexn4MOVb5jZfjVwk9DBW/S3bTn3E9S5cUXFvphqaCOhBs7/WGbU96PNr0EpTT96o1Kjv4ZOT/xbn/f921AWnBlhNWQXggZndFkNcZv2X1YOxsCZENXdJBWGCWp2mQRc+YLibIRpaQMyHEoVYgVfDcUFiHyYGopxQTgwFYosugsFfOXGZQyMGN+boI1E78vjjkHIF+QGRahkZxVpKNunkk1BGKeWUVFZp5ZVYZqnllogkAAA7" - }, - { - "name": "Rod.", - "description": "You cross reference your documentation. Sure enough, the \"festivus rod\" collected was actually an immovable rod.\nEnergy detected from the rod is the exact same coming off of the tree, as well. It's all making sense now. The Immovable rod is producing a kind of unique blackbody radiation that is providing sample heat and light for what is effectively an internal cold fusion process, and producing just enough of that radiation to create a kind of micro-enviromental bubble around the biosignature of the tree.\n\nThis would make the first time an immovable rod would exist in tandem with a biological source. You jot down some research notes on your findings, which could easily produce some kind of experimental tech, no doubt.", - "choices": [ - { - "key": "choice 16", - "name": "Snap a photo", - "exit_node": "Epilogue.", - "delay": 40, - "delay_message": "You could easily win an award for these findings!" - } - ], - "image": "default" - }, - { - "name": "Epilogue.", - "description": "You take a photo with the onboard camera on the drone. Suddenly, the immovable rod inside the tree explodes out of the wooden biological shell, and produces a blank, blurry photo.\nWhat the fuck?", - "choices": [ - { - "key": "choice 17", - "name": "God damnit.", - "exit_node": "WIN", - "delay": 10, - "delay_message": "Some things were just not meant for man to know." - } - ], - "image": "default" - }, - { - "name": "What is wrong with this tree?", - "description": "This is ridiculous. Nothing about this dumbass tree makes sense. It makes no sense, it's just sitting there, living and making a MOCKERY of all of science!\nYou didn't get your degree in advanced plasma-physics for this!", - "choices": [ - { - "key": "choice 18", - "name": "The world can never know about this dumbass stupid plant.", - "exit_node": "FAIL_DEATH", - "delay": 60, - "delay_message": "Activating drone self-destruct." - }, - { - "key": "choice 19", - "name": "Take a moment to calm down.", - "exit_node": "Biological Scan", - "on_selection_effects": [ - { - "effect_type": "Add", - "quality": "Confusion", - "value": { - "value_type": "random", - "low": -3, - "high": -5 - } - } - ], - "delay": 20, - "delay_message": "Breathe." - } - ], - "image": "default" - } - ] - } + "adventure_name": "There's a tree in the middle of space.", + "version": 1, + "starting_node": "Tree Start", + "starting_qualities": { + "Confusion": 0 + }, + "required_site_traits": [ + "in space" + ], + "loot_categories": [ + "research" + ], + "scan_band_mods": { + "Exotic Radiation": 10 + }, + "deep_scan_description": "", + "triggers": [ + { + "name": "Confusion Trigger", + "target_node": "What is wrong with this tree?", + "requirements": [ + { + "quality": "Confusion", + "operator": ">", + "value": 30 + } + ] + } + ], + "nodes": [ + { + "name": "Tree Start", + "description": "Camera online. Visual signs detect a fully grown, seemingly biological, and live tree located in the middle of the vacuum.\nSensors indicate it is not oxygenating, but energy is being collected via passive solar light from the nearby star.\nBaffling.", + "choices": [ + { + "key": "choice 0", + "name": "Ignore site.", + "exit_node": "FAIL", + "delay": 10, + "delay_message": "Leave this for the botanists to figure out." + }, + { + "key": "choice 1", + "name": "Begin sensor scan.", + "exit_node": "Biological Scan", + "delay": 10, + "delay_message": "Lets get some data." + } + ], + "image": null, + "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMQAAAAAAAC15h2QtxeAoxVykROizRpxjxIAcgAAWwAAgAAAUAAAZAAAZgC0tLTKysr///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF/2AgjmRpnigqrMMqtCvhyvFs17hQuPva67ygTwgcGovA3a61BLaeryj0mapar9isNjCNylpfgWwsLpPPZqBst066le84fB5nRpvdvGDL7/v/JmBeaWiFhIeGbGqLio1ljm2CklKUA4CXmJmaAYidhp9mBmOiYqQEpqZlk3qbra6vsCOenqijtgIHCLG7vL29CQoNCsDCxMPBxw0MxsTLyMLCCwq+1LuVe9VZ0M/c297d4NvZ41vXeueU5N/r4e3o79jkvOb0UAe4+Pf6uMjS7P/TtAAcGKyeQXhT5ClcSKIdwYcHIyKMx7CiwocOwU3cWMmiR4YYQzqM+LGkSQXSUv/2y0jQH0qUJmNqoRSm5ixQbXLK2UmnJ886ToIilFltkk2cNw9B+umz6U87UOsRNXk0KdKrVrOSWWVwqlc+WHHWKnWqrKizZV+QGrA2yte31YDJPTZXrrMEzhbkPSYNWF+4gAFBeICJGTLDxVi2C5yNIxSQikVu48i4j8TLT1i2khwOM+bKVSQaeGLgQOnS+fIBwkiCszfPjqWAnn0ism1hsXO/oM279e3fuqmYeAChN++XKqP9BujP+EcXMKLkoFFm+o3qSH5oJ7L9SPfs3IlEHw/dhfNyLMpbX4+duvvw3uGDj08fCfn0+KVTPI9Ff/T37AHY3nXfFSifgfX9cJ//f/vxh95/1wkoYYQU5oDgfBh+t+B9DsJS4YABfiiDAWWQOGKJKJ6oYidcDdVhUVrFGFZWRl32IlEy0nJLWjyu1VYYrNxY2YxXjZUWW1+0FaSQDiaQ4z0y3OMXX3wxaSUKiWWZTF5c+sVASl8iB9OVbxFH3CVabmOMa9yQ6WYAbHL2Zh+UVRTnbV3NyUlwu120HEuw9WlloO+Mc+c3fCbEH6ES/Ybmn9AwWmdvnu1jaWoHpMBmFYdK+tmLiQqKCaTAebqRnh4d6o6pEqHqEan/sOqiqxbBumqoig42GK0WqUqQY7zCtZKvDgXL37AvEbvNAsaeJ6Zy0JKqErPNYpIj/xqOOKUtU9xu6+1OUekpCJFpLPXtud2mu21UTbhKLraPqCsvuvQ+FdQSqI57bbnxtlHvv/OCK5RsqO4Lr78BA6xwulDR+m4n5iYs8cJNVNyguwYzEi/FE3dsR7UpZJzIxh1z7FO4IJ8gMr860WuAEi/rEHMBM88s8ccpn/AwVhEjTDPMQMsc9M9Cx9HyIJbknMLOEJNC8xpOR/3zy1RPbXXVWD8tM9Rcq3Kx0lesvKORZz2NFtVmnWJ2j2NLAnYsiJCd9tlzz7122XTnnfbb2dxUi96A1x044GDwnc0Zfwuu+OCLK274c4UkzvjkZj3+ldxkUY5AApt3noDlldF1zP/YBAyzuemcp4665wGBDlcDeCUA+zKzyx77Arfnvjnuy+C+u+uADXPXMsTHXvzxxid/PPC8OEAYmnLBPoz0ttMee+3YXx/958y/oqsDl4hel/jkjz9+Md17Rf3620/fvu3uxy97A+lPVT75ic2lJWLDWD7AE/97QQCT1qv3sU9+6ytGAxTIQL7FpiLJiCD/JggOYJxKXAPMIAA3KCp1MHB6H5wfCEcowgRoUIAc/F8L3CSrr/EiGAsc4QKhEcMZwpCG0DihClHIQxVeaYdA1KEQAWioD9pQhEesoRJTOMQe/k9ITQwiEzloQ/q9sIpKxOENt9iAKHpxgw76ohOnKED/LWJRGJrIIhfVWEUxSnGMPDQOGd+4wwME0I76COAC2MhHNPZhjWbk4xzd2MTeNBGPuBiAPg6wyEbiIlMiaEBKYrjHQOJQG5YE5BbpSMhByvGQiixNKBlpGlI+8h5a0OQZg2ECVfYRhoOMJRx36JxZ/k+UbMGjKEupyERi4pUzjGQmV9lGWXLSkxiMoy+ICcxmNsCWxvRi/VYzw2pa85rYvKYKt8nNbnrzm96c5h+G6UwudhKacBTnOLPJznYuEJzwjCc41blOctoTlug8JjTpiSZ3+lOb3LTj/wSqSHlycwQPeB4//8jMe2KRgwJNZDQJaCaFLlQge6ykJP/ZTo3iYbGgHx3oPC+6CZRQspwNNakwEMnSE5L0FRndaEwXqFGO0lSmG32pQmLK043e1KYz7KlO5dHTouKUo0YdKjmMalSk4jSmSh3HAqb61KpqtKZBtWpOo1oNpmoVq9dkKrWMEwIAOw==" + }, + { + "name": "Biological Scan", + "description": "You attempt to scan for clues regarding the tree's nature. It appears to be a fully mature oak tree. \n\nApproximated height is 13 ft, 6.4 inches. \n\nSubject sees no sign of an outer coating or otherwise layer protecting it from the void of space.\n\nSubject's surface temperature is 293.7 kelvin, as though it were sitting indoors.", + "choices": [ + { + "key": "choice 2", + "name": "Check Sensor Integrity.", + "exit_node": "Its Not You...", + "on_selection_effects": [ + { + "effect_type": "Add", + "quality": "Confusion", + "value": 5 + } + ], + "delay": 50, + "delay_message": "This can't be right." + }, + { + "key": "choice 4", + "name": "Attempt to take sample.", + "exit_node": "Sample Taken", + "on_selection_effects": [ + { + "effect_type": "Add", + "quality": "Confusion", + "value": 3 + } + ], + "delay": 40, + "delay_message": "Snip snip." + }, + { + "key": "choice 6", + "name": "Examine Tree Roots.", + "exit_node": "Examine Roots", + "delay": 10 + }, + { + "key": "choice 9", + "name": "Sequence Sample Radiation with background noise.", + "exit_node": "Background Analysis", + "requirements": [ + { + "quality": "Sample", + "operator": ">=", + "value": 1 + } + ], + "delay": 0, + "delay_message": "This can't be real." + }, + { + "key": "choice 40", + "name": "Leave.", + "exit_node": "FAIL", + "delay": 0 + } + ], + "image": null, + "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMQAAAAAAAC15h2QtxeAoxVykROizRpxjxIAcgAAWwAAgAAAUAAAZAAAZgC0tLTKysr///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF/2AgjmRpnigqrMMqtCvhyvFs17hQuPva67ygTwgcGovA3a61BLaeryj0mapar9isNjCNylpfgWwsLpPPZqBst066le84fB5nRpvdvGDL7/v/JmBeaWiFhIeGbGqLio1ljm2CklKUA4CXmJmaAYidhp9mBmOiYqQEpqZlk3qbra6vsCOenqijtgIHCLG7vL29CQoNCsDCxMPBxw0MxsTLyMLCCwq+1LuVe9VZ0M/c297d4NvZ41vXeueU5N/r4e3o79jkvOb0UAe4+Pf6uMjS7P/TtAAcGKyeQXhT5ClcSKIdwYcHIyKMx7CiwocOwU3cWMmiR4YYQzqM+LGkSQXSUv/2y0jQH0qUJmNqoRSm5ixQbXLK2UmnJ886ToIilFltkk2cNw9B+umz6U87UOsRNXk0KdKrVrOSWWVwqlc+WHHWKnWqrKizZV+QGrA2yte31YDJPTZXrrMEzhbkPSYNWF+4gAFBeICJGTLDxVi2C5yNIxSQikVu48i4j8TLT1i2khwOM+bKVSQaeGLgQOnS+fIBwkiCszfPjqWAnn0ism1hsXO/oM279e3fuqmYeAChN++XKqP9BujP+EcXMKLkoFFm+o3qSH5oJ7L9SPfs3IlEHw/dhfNyLMpbX4+duvvw3uGDj08fCfn0+KVTPI9Ff/T37AHY3nXfFSifgfX9cJ//f/vxh95/1wkoYYQU5oDgfBh+t+B9DsJS4YABfiiDAWWQOGKJKJ6oYidcDdVhUVrFGFZWRl32IlEy0nJLWjyu1VYYrNxY2YxXjZUWW1+0FaSQDiaQ4z0y3OMXX3wxaSUKiWWZTF5c+sVASl8iB9OVbxFH3CVabmOMa9yQ6WYAbHL2Zh+UVRTnbV3NyUlwu120HEuw9WlloO+Mc+c3fCbEH6ES/Ybmn9AwWmdvnu1jaWoHpMBmFYdK+tmLiQqKCaTAebqRnh4d6o6pEqHqEan/sOqiqxbBumqoig42GK0WqUqQY7zCtZKvDgXL37AvEbvNAsaeJ6Zy0JKqErPNYpIj/xqOOKUtU9xu6+1OUekpCJFpLPXtud2mu21UTbhKLraPqCsvuvQ+FdQSqI57bbnxtlHvv/OCK5RsqO4Lr78BA6xwulDR+m4n5iYs8cJNVNyguwYzEi/FE3dsR7UpZJzIxh1z7FO4IJ8gMr860WuAEi/rEHMBM88s8ccpn/AwVhEjTDPMQMsc9M9Cx9HyIJbknMLOEJNC8xpOR/3zy1RPbXXVWD8tM9Rcq3Kx0lesvKORZz2NFtVmnWJ2j2NLAnYsiJCd9tlzz7122XTnnfbb2dxUi96A1x044GDwnc0Zfwuu+OCLK274c4UkzvjkZj3+ldxkUY5AApt3noDlldF1zP/YBAyzuemcp4665wGBDlcDeCUA+zKzyx77Arfnvjnuy+C+u+uADXPXMsTHXvzxxid/PPC8OEAYmnLBPoz0ttMee+3YXx/958y/oqsDl4hel/jkjz9+Md17Rf3620/fvu3uxy97A+lPVT75ic2lJWLDWD7AE/97QQCT1qv3sU9+6ytGAxTIQL7FpiLJiCD/JggOYJxKXAPMIAA3KCp1MHB6H5wfCEcowgRoUIAc/F8L3CSrr/EiGAsc4QKhEcMZwpCG0DihClHIQxVeaYdA1KEQAWioD9pQhEesoRJTOMQe/k9ITQwiEzloQ/q9sIpKxOENt9iAKHpxgw76ohOnKED/LWJRGJrIIhfVWEUxSnGMPDQOGd+4wwME0I76COAC2MhHNPZhjWbk4xzd2MTeNBGPuBiAPg6wyEbiIlMiaEBKYrjHQOJQG5YE5BbpSMhByvGQiixNKBlpGlI+8h5a0OQZg2ECVfYRhoOMJRx36JxZ/k+UbMGjKEupyERi4pUzjGQmV9lGWXLSkxiMoy+ICcxmNsCWxvRi/VYzw2pa85rYvKYKt8nNbnrzm96c5h+G6UwudhKacBTnOLPJznYuEJzwjCc41blOctoTlug8JjTpiSZ3+lOb3LTj/wSqSHlycwQPeB4//8jMe2KRgwJNZDQJaCaFLlQge6ykJP/ZTo3iYbGgHx3oPC+6CZRQspwNNakwEMnSE5L0FRndaEwXqFGO0lSmG32pQmLK043e1KYz7KlO5dHTouKUo0YdKjmMalSk4jSmSh3HAqb61KpqtKZBtWpOo1oNpmoVq9dkKrWMEwIAOw==" + }, + { + "name": "Its Not You...", + "description": "After re-connection is established, your sensors appear fine. Tree has not moved in the slightest since last observed. Temperature has fluxuated 0.2 kelvin upwards, as expected of a plant under direct light.\nLets try again.", + "choices": [ + { + "key": "choice 3", + "name": "Restart biological scan.", + "exit_node": "Biological Scan", + "delay": 25, + "delay_message": "God damnit." + } + ], + "image": null, + "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMIAAAAAAAD////v7+/h4eEAAAAAAAAAAAAD/xi63P4wykmrvTjrzbv/YCiOZBkJaJqaLKOubSy7b23fODxPOb7/m4FASBRofEBeT1W6JU3DYaRIjQqfkCWKg1xoddjSQEgQlM/mdDkc0Fa+8PiWLSIM7Pj73RxOlVF/ITlKNXSGDXp5iiFoaBlqfpFyk12HMgSYmZkfmppmmJ8gjXwUf2lglqmqq6ytrq+wsbKztLW2t7i5um2Ug669uyBCKMNRc4Q9qXHBJlVUFMbRV6pfR04ONszQzlZRlm7IveLaimZ7eJAESUsfyVnX2hfqv/Nv4vfZ8RWJ/Hkdn6NGtRsFyEg4VLwK6UvVqROdgMcWSpxIsaLFixgzatzIsf+jR1gIP7YbN6uaSAn4wFGbdNJFsZcpFRqS09IBt2kW3CkzWdNmNyIYpIWkw9Nevgbwat2ccNPbTnbWjtKQWfGnVZwzoQaNqVXXkDFWGx3qeoIry2CJzJ05p6aPTpRmfSXV1a/u2jM7TuldA8LXO6kXFemh5ihn3Lc9A9h1ZaqxpMNkK9rl5+EMKIGM9g5FSjJjv4aVOwEc/Q8iXx6ODSo5ualOQ9Bs0qVJTLu27du4c+vezbu379/AgwsfTry48ePIkytfqHp5xhfLadby+1soMJDLbhchlqIYpVbXa14dz718NMBEz/ZsWsU8zMhY1CdmL+VE+/ObgWSvPR4rj/f/xqxUFG1fVfHIUgLCN58zR5ABySpwbAAdZ1TNMgZYF9YHjWmsDAgNeglNqFSBJJYiG14JUmcYiHNZWJcE6HD4FGIrVuiFjROxJeNYChoFWUS5lBPjOTO2iM2PKuki2F1qfdPjjUjSeMuSk82Uml4fRimlLVR2OUAYBGHpo5aV4OJll1iYRkqWhag4FY75WXhmlTOoedo/ZVKI40Jz+pOEnX2ZsqcCeVJ0piEQieJhiEx0RBkrd6J2IiQFVXqPbZjEYqdmll6Jz0avtUaCqEFtaiqnekmHUagOhSZapvJMeioanXa2KqukZoCrJoruCKNmCngKZGC7urprPRKq+QZBP2XFKRGunBwL6waZjIbiBInu9hoj0o5wraRiOadrsX1kK24HvBK25rnstuvuu/DGK++89NZr77345qvvvhYlAAA7" + }, + { + "name": "Sample Taken", + "description": "You collect and project a small sample of tree bark off the plant. The instant that the bark is removed from the tree, as though it suddenly remembered what it was, the moisture content of the bark freezes over, and implodes into small microparticles of splinters.\nSmall radioactive signature detected.", + "choices": [ + { + "key": "choice 5", + "name": "Well that was... unexpected.", + "exit_node": "Biological Scan", + "delay": 0, + "delay_message": "Maybe something else might work better.", + "on_selection_effects": [ + { + "effect_type": "Add", + "quality": "Sample", + "value": 1 + } + ] + } + ], + "image": null, + "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMIAAAAAAABSLiiPVjtyRS9mOTFbNyYAAAAD/xi63P4wykmrvTjrzbv/YCiOZGmeaKqubOu+sDUQxTDbeK7vfF/3saCwcxPcCMckcqlM2pDPnnRKrUqH2IdAYDBwu+Bwl2Agm8sE8iy9Zrqbb2Z0bq3b74W8Xp+1bP+Af2KDhIVlh2eJaUtsi3CPcU43d5QDe5cFfSKBnJ2en50Ff6JboqYCBWiLq46tkK+RUJOTmJmatxyguqSovae/vsGirK2NjU21trjLQp+8wNDCwnmo1MnM2Nna29zd3t/g4eLj5OXm59o5Rjo/QOjvLaKwkrKylfdW8FleXImIBm0CxppXD4c9fAgT5tCn4Iuhh4fG/DNTjNHAi4/oKERYq/+cro8gPYXxR7EkK4EEUxbUOCVZHoabQoZ8NkqaKWI4BR7DGKcjTG4yaZaySRSatQLGfP5ciqHX0GhQpzGdSrWq1atYs2rdyrWr169gw4pVsc7G2LMLkM46SOkl2nc86W3E97aFgLh4Dc7dq6NuhC0TVVlUOY8l38N9szocREYiyYqEMdJZibjylW+AIRIiqUowyrwDJ+u1XMelsm6CNKtmHHiRZ8iuQGecVdklZpm4V3NWREznYNmhaeNRCg638eOBhrUWjPP3zshNDNuwzRW5dZrQmms3BhzSNb8SrIPCXvTudtjzMIEngVxo+ajDtKOkvt5u0Jrw3/s6yqd+Nk7/7uUn4FH+VaWfKAUmqOCCDDbo4IMQRijhhBRWaOGFGGao4YYcdujhhyCGKOKFRsgxy4jaBEeZOyi60J2JK1piS2ItcvDiaMIpVGMEv0GnIo46grgFbM/dKBppC004kXzo3fiGdJb51wUgiKTBnHNOzsYWkpd1xZpjrTHJnY+vQGlZOztMBUZmrO0mZo9Zwggkl/mkKc5qIy3n2nlExrnWnHROcRueYjSm55Wr+Ebmj2YeZpo4bBJqyG6Inqeon0duRF84kuJJKW98Nrkojlu2dYlHkXaq6qehNvfZqHI2+ihq4lGpKhisttpbbKNm6sN3t9Wam2q5Vtrqq5jesKk3jsI220mheuq665jJzoqqs9gGcqi0211KGLBUZYutciUZG6q3cREnlrjiPcZtTqIiAW597H5E07uuiqqehPXONIq57+6rYb81PWUTvmksuyHBTjUc1XnVmOLWjgFkG+CBNk1MsRb1kiegLxtf4KzHB4b8Qa0XA2OyfZ6QjODKywwlM8w012zzzTjnrPNWCQAAOw==" + }, + { + "name": "Examine Roots", + "description": "All plant matter has to derive energy and moisture from someplace. Examining the oak tree's roots reveals that the roots present all appear to splay out, similar to how a normal tree would. However, those roots then proceed to double back in on itself. This might suggest that the tree is obtaining nutrients from... itself.", + "choices": [ + { + "key": "choice 7", + "name": "That's fucking stupid.", + "exit_node": "Biological Scan", + "on_selection_effects": [ + { + "effect_type": "Add", + "quality": "Confusion", + "value": { + "value_type": "random", + "low": 6, + "high": 10 + } + } + ], + "delay": 0, + "delay_message": "What the hell kind of tree even IS this?" + }, + { + "key": "choice 8", + "name": "Obtain biological sample from roots.", + "exit_node": "Sample Taken", + "delay": 10, + "delay_message": "This is why we hire botanists on-site." + } + ], + "image": null, + "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMQAAAAAAAC15h2QtxeAoxVykROizRpxjxIAcgAAWwAAgAAAUAAAZAAAZgC0tLTKysr///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF/2AgjmRpnigqrMMqtCvhyvFs17hQuPva67ygTwgcGovA3a61BLaeryj0mapar9isNjCNylpfgWwsLpPPZqBst066le84fB5nRpvdvGDL7/v/JmBeaWiFhIeGbGqLio1ljm2CklKUA4CXmJmaAYidhp9mBmOiYqQEpqZlk3qbra6vsCOenqijtgIHCLG7vL29CQoNCsDCxMPBxw0MxsTLyMLCCwq+1LuVe9VZ0M/c297d4NvZ41vXeueU5N/r4e3o79jkvOb0UAe4+Pf6uMjS7P/TtAAcGKyeQXhT5ClcSKIdwYcHIyKMx7CiwocOwU3cWMmiR4YYQzqM+LGkSQXSUv/2y0jQH0qUJmNqoRSm5ixQbXLK2UmnJ886ToIilFltkk2cNw9B+umz6U87UOsRNXk0KdKrVrOSWWVwqlc+WHHWKnWqrKizZV+QGrA2yte31YDJPTZXrrMEzhbkPSYNWF+4gAFBeICJGTLDxVi2C5yNIxSQikVu48i4j8TLT1i2khwOM+bKVSQaeGLgQOnS+fIBwkiCszfPjqWAnn0ism1hsXO/oM279e3fuqmYeAChN++XKqP9BujP+EcXMKLkoFFm+o3qSH5oJ7L9SPfs3IlEHw/dhfNyLMpbX4+duvvw3uGDj08fCfn0+KVTPI9Ff/T37AHY3nXfFSifgfX9cJ//f/vxh95/1wkoYYQU5oDgfBh+t+B9DsJS4YABfiiDAWWQOGKJKJ6oYidcDdVhUVrFGFZWRl32IlEy0nJLWjyu1VYYrNxY2YxXjZUWW1+0FaSQDiaQ4z0y3OMXX3wxaSUKiWWZTF5c+sVASl8iB9OVbxFH3CVabmOMa9yQ6WYAbHL2Zh+UVRTnbV3NyUlwu120HEuw9WlloO+Mc+c3fCbEH6ES/Ybmn9AwWmdvnu1jaWoHpMBmFYdK+tmLiQqKCaTAebqRnh4d6o6pEqHqEan/sOqiqxbBumqoig42GK0WqUqQY7zCtZKvDgXL37AvEbvNAsaeJ6Zy0JKqErPNYpIj/xqOOKUtU9xu6+1OUekpCJFpLPXtud2mu21UTbhKLraPqCsvuvQ+FdQSqI57bbnxtlHvv/OCK5RsqO4Lr78BA6xwulDR+m4n5iYs8cJNVNyguwYzEi/FE3dsR7UpZJzIxh1z7FO4IJ8gMr860WuAEi/rEHMBM88s8ccpn/AwVhEjTDPMQMsc9M9Cx9HyIJbknMLOEJNC8xpOR/3zy1RPbXXVWD8tM9Rcq3Kx0lesvKORZz2NFtVmnWJ2j2NLAnYsiJCd9tlzz7122XTnnfbb2dxUi96A1x044GDwnc0Zfwuu+OCLK274c4UkzvjkZj3+ldxkUY5AApt3noDlldF1zP/YBAyzuemcp4665wGBDlcDeCUA+zKzyx77Arfnvjnuy+C+u+uADXPXMsTHXvzxxid/PPC8OEAYmnLBPoz0ttMee+3YXx/958y/oqsDl4hel/jkjz9+Md17Rf3620/fvu3uxy97A+lPVT75ic2lJWLDWD7AE/97QQCT1qv3sU9+6ytGAxTIQL7FpiLJiCD/JggOYJxKXAPMIAA3KCp1MHB6H5wfCEcowgRoUIAc/F8L3CSrr/EiGAsc4QKhEcMZwpCG0DihClHIQxVeaYdA1KEQAWioD9pQhEesoRJTOMQe/k9ITQwiEzloQ/q9sIpKxOENt9iAKHpxgw76ohOnKED/LWJRGJrIIhfVWEUxSnGMPDQOGd+4wwME0I76COAC2MhHNPZhjWbk4xzd2MTeNBGPuBiAPg6wyEbiIlMiaEBKYrjHQOJQG5YE5BbpSMhByvGQiixNKBlpGlI+8h5a0OQZg2ECVfYRhoOMJRx36JxZ/k+UbMGjKEupyERi4pUzjGQmV9lGWXLSkxiMoy+ICcxmNsCWxvRi/VYzw2pa85rYvKYKt8nNbnrzm96c5h+G6UwudhKacBTnOLPJznYuEJzwjCc41blOctoTlug8JjTpiSZ3+lOb3LTj/wSqSHlycwQPeB4//8jMe2KRgwJNZDQJaCaFLlQge6ykJP/ZTo3iYbGgHx3oPC+6CZRQspwNNakwEMnSE5L0FRndaEwXqFGO0lSmG32pQmLK043e1KYz7KlO5dHTouKUo0YdKjmMalSk4jSmSh3HAqb61KpqtKZBtWpOo1oNpmoVq9dkKrWMEwIAOw==" + }, + { + "name": "Background Analysis", + "description": "You compare the radioactive energy bands of the sample collected earlier with that of the nearby solar enviroment.\nNothing.\nThere is nothing nearby that matches the passive signal of the tree, or the bark, or anything similar.\nThis is really starting to get on your nerves.", + "choices": [ + { + "key": "choice 10", + "name": "Smash your desk in frustration.", + "exit_node": "FAIL", + "delay": 50, + "delay_message": "No amount of pay is worth dealing with magical plant juju." + }, + { + "key": "choice 11", + "name": "Check every known energy spectroscopy database.", + "exit_node": "Sample Match Found", + "delay": 900, + "delay_message": "You NEED an answer. You DESERVE an answer." + } + ], + "image": null, + "on_enter_effects": [ + { + "effect_type": "Add", + "quality": "Confusion", + "value": { + "value_type": "random", + "low": 3, + "high": 5 + } + } + ], + "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMIAAAAAAAD///9ZVlKsMjJpampGR0cAAAAD/xi63P4wykmFpTjrDa0XXCiOZGlqQ0qsazqIXyx9Z23feKayfP/WskgwRywqCsikcslsOpGpgGvQNDo8lYt1W4I+v2CvMhUuI0/YiZbL5nxdhkJ8Lq/T6eZ8HRmHUtuAgRp6T3B2SXdNfYeJc3CCkJEYjISVYZKRQ5gajZSdi0yboqM3nnWkqKmCpgaqrq9GBrKzs7AKaYG4tji0vbu/wCW6wZpqNMHIOAM9zDw/IzEgHcVt1KOWZQ1TU4LDV2vJOAVU2GZkY5VF4NPr4SRM53yI8/Lw9uVvBcLuknqGn4cqLQIYhwy/g0fwKdSDsCEGggtDOZwoAiLFi5sAYtwoqf/XIVjeOKrqRUukjZAmGVjDGC2lSyAts7R7GW5ZM2bPNERDGSAmzWA2b/pAc+yBT0ArVeXhsC2oj5wnefaU+pNBxDJNXUAqyq6qhKthyCUR+4QLVa5ej5AFO3ZJPGw3qE5N22DsWiUD6Tm5e/cqCbk96dZtQgZip3rjwIIa90fwqrBUDAfcQ0hyilaOIWG7zIoSYryd73DLrJntNlOIO2WVQ/raYrYKW/8CCNuJbH6S8aS7vSCpq9C8gxMMzns48dudj9/WqFw2yZKvfDc38Rxzc+kiq09f/nw7b+wNwV9HuwuwSvLeL14wjz49pm3Qds7sbd59jh1Co3CQP1+8/Rr/TgnVQnxHNVDgf0QEKCBUIRxIX3sIAiigMwzCAKF/cc1H1xQTVvjXhRCqE6IosU2Q1YkiajiViin+VhthWW0l1YhevQjjafrIKI0QLP5kI2GMBWkbG2fVx1FiP/oxRl9DEiEXCDsKhuSPazFpBg5P9miSkHmlpleXbbkVUVRRTkOakl7mRg9fsJmQ5Zl2DaDmJ4XVwZkZYHbpoU726eZCaID28RYYeRFEToQVeVaYLHIwOkugk70GqWiNIeoGQJc5qumclOU5qUGWXhraFNU1yumpdoAa6ganZkrLpJ2G5qido606CKoGwDErrqaaSlKttrIKq2r/DGvHr39aF2wIgsYaduKzqyUhhbLLjsArp3BVW0Oz3OpWlrY5dCsuKOByMS635QpyLaTEGenauZ2M5y4m696B4Lz0spLuRMnt25BH9vr7b3XUChwOwbIYfBDCBSscDMIOL0xwxO5ATPHB2kVHY7oTg7RxuR0rhyFFIYv8MUYZX5xMySoDk3LLD3dXbQIAOw==" + }, + { + "name": "Sample Match Found", + "description": "After an extensive algorithm search on the controller end, you have a single match to this specific band and style of energy.\nThe problem, is that the source of said radiation is coming not only from Space Station 13, no.\nIt's coming from the Space Station 13 Research Department.\nWhat the fuck?", + "choices": [ + { + "key": "choice 12", + "name": "Something must be wrong with the drone.", + "exit_node": "Its Not You...", + "on_selection_effects": [ + { + "effect_type": "Add", + "quality": "Confusion", + "value": { + "value_type": "random", + "low": 6, + "high": 10 + } + } + ], + "delay": 30, + "delay_message": "Lousy piece of junk must be scanning the station instead of the target." + }, + { + "key": "choice 13", + "name": "Perhaps that sample was tainted. Collect a new sample.", + "exit_node": "Sample Taken", + "delay": 60, + "delay_message": "Lets try again, but carefully." + }, + { + "key": "choice 14", + "name": "Remember the Christmas Party.", + "exit_node": "The Christmas Party", + "requirements": [ + { + "quality": "Confusion", + "operator": "<=", + "value": 25 + } + ], + "delay": 100, + "delay_message": "Wait a gosh darn fucking second." + } + ], + "image": null, + "on_enter_effects": [ + { + "effect_type": "Add", + "quality": "Confusion", + "value": 10 + } + ], + "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMIAAAAAAAD////v7+/h4eEAAAAAAAAAAAAD/xi63P4wykmrvTjrzbv/YCiOZBkJaJqaLKOubSy7b23fODxPOb7/m4FASBRofEBeT1W6JU3DYaRIjQqfkCWKg1xoddjSQEgQlM/mdDkc0Fa+8PiWLSIM7Pj73RxOlVF/ITlKNXSGDXp5iiFoaBlqfpFyk12HMgSYmZkfmppmmJ8gjXwUf2lglqmqq6ytrq+wsbKztLW2t7i5um2Ug669uyBCKMNRc4Q9qXHBJlVUFMbRV6pfR04ONszQzlZRlm7IveLaimZ7eJAESUsfyVnX2hfqv/Nv4vfZ8RWJ/Hkdn6NGtRsFyEg4VLwK6UvVqROdgMcWSpxIsaLFixgzatzIsf+jR1gIP7YbN6uaSAn4wFGbdNJFsZcpFRqS09IBt2kW3CkzWdNmNyIYpIWkw9Nevgbwat2ccNPbTnbWjtKQWfGnVZwzoQaNqVXXkDFWGx3qeoIry2CJzJ05p6aPTpRmfSXV1a/u2jM7TuldA8LXO6kXFemh5ihn3Lc9A9h1ZaqxpMNkK9rl5+EMKIGM9g5FSjJjv4aVOwEc/Q8iXx6ODSo5ualOQ9Bs0qVJTLu27du4c+vezbu379/AgwsfTry48ePIkytfqHp5xhfLadby+1soMJDLbhchlqIYpVbXa14dz718NMBEz/ZsWsU8zMhY1CdmL+VE+/ObgWSvPR4rj/f/xqxUFG1fVfHIUgLCN58zR5ABySpwbAAdZ1TNMgZYF9YHjWmsDAgNeglNqFSBJJYiG14JUmcYiHNZWJcE6HD4FGIrVuiFjROxJeNYChoFWUS5lBPjOTO2iM2PKuki2F1qfdPjjUjSeMuSk82Uml4fRimlLVR2OUAYBGHpo5aV4OJll1iYRkqWhag4FY75WXhmlTOoedo/ZVKI40Jz+pOEnX2ZsqcCeVJ0piEQieJhiEx0RBkrd6J2IiQFVXqPbZjEYqdmll6Jz0avtUaCqEFtaiqnekmHUagOhSZapvJMeioanXa2KqukZoCrJoruCKNmCngKZGC7urprPRKq+QZBP2XFKRGunBwL6waZjIbiBInu9hoj0o5wraRiOadrsX1kK24HvBK25rnstuvuu/DGK++89NZr77345qvvvhYlAAA7" + }, + { + "name": "The Christmas Party", + "description": "Hold on. Last Christmas, the Research Director was incredibly hammered. He made a big mention that his brand new festivus pole was actually some kind of astrological... something something. You can't remember the whole details, because you were smashed as well. However, briefly, the RD did keep that festivus pole for awhile, he might even still have it somewhere.\nMaybe...?", + "choices": [ + { + "key": "choice 15", + "name": "Wait a minute, was that a god damn...", + "exit_node": "Rod.", + "delay": 100, + "delay_message": "Immovable Rod?" + } + ], + "image": null, + "raw_image": "data:image/gif;base64,R0lGODdhyABkAHcAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAAACwAAAAAyABkAMIAAAAAAAD/AACmAAD///+mpqYAAAAAAAAD/xi63P4wykmrvTjrzbv/YCiOZGmejKCubOu6aCzP4WvfeD4IQ+//Pppw+MkZj6udkgdsOp/EqFSBrNqWwQ9hy+16v9ypeGM9YpnAE3hNKLTfhbG8kuTZz/j7/fmb+/8TbIJefIVNgIiJGgWMjY6PkJGRipSVlpeYmZqbnJ2en6ChoqOkpRplqDdYpqyprnpKhnyslq9leFkYg2u0QrZmaLkgu8S9JDg7Ksl2yrB7UDJw0m6QxiFfedk9wbKH1tbEW9TT05Lmjd/pJpPq7e7v8PHy8/T19vf4+fr7Kb9W/Jn8pcLiBKAcgVZwdethkAZCJAoXFmx47KEOWLMeAAlHMf+DRVXctIT70jHCxxYEhXkYKajkgpMRGZZgKY5LHJcJ6zTTNtHEm5rjgsK5WZKZs2xHn2WccY6RSwdJkaaUOOApoHDbqFK16ofmF6Fg20Aa8IhrpbBBm6plZ7aTIwhr0bWdS7eu3bt48+rdy7ev37+AAwseTLiw4cOI0/1LfPAkC8YlHINUApmD5MncVFZ+cPmK0qWbX3Z2MbVbaCqjd37eCjk1i9JaZR5OHTN2z8Gua9v2wavvaNjeKgygqbcz8KocvBLAexn4MOVb5jZfjVwk9DBW/S3bTn3E9S5cUXFvphqaCOhBs7/WGbU96PNr0EpTT96o1Kjv4ZOT/xbn/f921AWnBlhNWQXggZndFkNcZv2X1YOxsCZENXdJBWGCWp2mQRc+YLibIRpaQMyHEoVYgVfDcUFiHyYGopxQTgwFYosugsFfOXGZQyMGN+boI1E78vjjkHIF+QGRahkZxVpKNunkk1BGKeWUVFZp5ZVYZqnllogkAAA7" + }, + { + "name": "Rod.", + "description": "You cross reference your documentation. Sure enough, the \"festivus rod\" collected was actually an immovable rod.\nEnergy detected from the rod is the exact same coming off of the tree, as well. It's all making sense now. The Immovable rod is producing a kind of unique blackbody radiation that is providing sample heat and light for what is effectively an internal cold fusion process, and producing just enough of that radiation to create a kind of micro-enviromental bubble around the biosignature of the tree.\n\nThis would make the first time an immovable rod would exist in tandem with a biological source. You jot down some research notes on your findings, which could easily produce some kind of experimental tech, no doubt.", + "choices": [ + { + "key": "choice 16", + "name": "Snap a photo", + "exit_node": "Epilogue.", + "delay": 40, + "delay_message": "You could easily win an award for these findings!" + } + ], + "image": "default" + }, + { + "name": "Epilogue.", + "description": "You take a photo with the onboard camera on the drone. Suddenly, the immovable rod inside the tree explodes out of the wooden biological shell, and produces a blank, blurry photo.\nWhat the fuck?", + "choices": [ + { + "key": "choice 17", + "name": "God damnit.", + "exit_node": "WIN", + "delay": 10, + "delay_message": "Some things were just not meant for man to know." + } + ], + "image": "default", + "on_enter_effects": [ + { + "effect_type": "Set", + "quality": "Confusion", + "value": 9999 + } + ] + }, + { + "name": "What is wrong with this tree?", + "description": "This is ridiculous. Nothing about this dumbass tree makes sense. It makes no sense, it's just sitting there, living and making a MOCKERY of all of science!\nYou didn't get your degree in advanced plasma-physics for this!", + "choices": [ + { + "key": "choice 18", + "name": "The world can never know about this dumbass stupid plant.", + "exit_node": "FAIL_DEATH", + "delay": 60, + "delay_message": "Activating drone self-destruct." + }, + { + "key": "choice 19", + "name": "Take a moment to calm down.", + "exit_node": "Biological Scan", + "on_selection_effects": [ + { + "effect_type": "Add", + "quality": "Confusion", + "value": { + "value_type": "random", + "low": -3, + "high": -5 + } + } + ], + "delay": 20, + "delay_message": "Breathe." + } + ], + "image": "default" + } + ] +} \ No newline at end of file diff --git a/code/modules/explorer_drone/exodrone.dm b/code/modules/explorer_drone/exodrone.dm index 72cf09bd81b..5c73f5755df 100644 --- a/code/modules/explorer_drone/exodrone.dm +++ b/code/modules/explorer_drone/exodrone.dm @@ -5,7 +5,7 @@ // Fuel types and travel time per unit of distance on that fuel. #define FUEL_BASIC "basic" -#define BASIC_FUEL_TIME_COST 300 +#define BASIC_FUEL_TIME_COST 250 #define FUEL_ADVANCED "advanced" #define ADVANCED_FUEL_TIME_COST 200 @@ -334,9 +334,9 @@ GLOBAL_LIST_EMPTY(exodrone_launchers) drone_log("Sustained [amount] damage.") /obj/item/exodrone/proc/drone_log(message) - drone_log.Insert(1,message) if(length(drone_log) > EXODRONE_LOG_SIZE) - drone_log.Cut(EXODRONE_LOG_SIZE) + drone_log = list() + drone_log.Insert(1,message) /obj/item/exodrone/proc/has_tool(tool_type) return tools.Find(tool_type) @@ -354,6 +354,11 @@ GLOBAL_LIST_EMPTY(exodrone_launchers) . = ..() GLOB.exodrone_launchers += src +/obj/machinery/exodrone_launcher/examine(user) + . = ..() + if(fuel_canister) + . += span_notice("You can remove the [fuel_canister] with a prying tool.") + /obj/machinery/exodrone_launcher/attackby(obj/item/weapon, mob/living/user, params) if(istype(weapon, /obj/item/fuel_pellet)) if(fuel_canister) @@ -374,7 +379,7 @@ GLOBAL_LIST_EMPTY(exodrone_launchers) if(!fuel_canister) return - to_chat(user, span_notice("You remove the [fuel_canister] from the [src].")) + to_chat(user, span_notice("You remove [fuel_canister] from [src].")) fuel_canister.forceMove(drop_location()) fuel_canister = null update_icon() diff --git a/code/modules/explorer_drone/scanner_array.dm b/code/modules/explorer_drone/scanner_array.dm index e5b5f7a026c..7f019b0d43c 100644 --- a/code/modules/explorer_drone/scanner_array.dm +++ b/code/modules/explorer_drone/scanner_array.dm @@ -14,9 +14,9 @@ GLOBAL_LIST_INIT(scan_conditions,init_scan_conditions()) #define MAX_SCAN_DISTANCE 10 -#define WIDE_SCAN_COST(BAND, SCAN_POWER) (((BAND*BAND)/(SCAN_POWER))*2*60*10) -#define BASE_POINT_SCAN_TIME (5 MINUTES) -#define BASE_DEEP_SCAN_TIME (5 MINUTES) +#define WIDE_SCAN_COST(BAND, SCAN_POWER) (min(((BAND*BAND)/(SCAN_POWER))*2*60*10, 10 MINUTES)) +#define BASE_POINT_SCAN_TIME (2 MINUTES) +#define BASE_DEEP_SCAN_TIME (3 MINUTES) /// Represents scan in progress, only one globally for now, todo later split per z or allow partial dish swarm usage /datum/exoscan @@ -35,7 +35,7 @@ GLOBAL_LIST_INIT(scan_conditions,init_scan_conditions()) var/scan_time = 0 switch(scan_type) if(EXOSCAN_WIDE) - scan_power = length(GLOB.exoscanner_controller.tracked_dishes) + scan_power = GLOB.exoscanner_controller.calculate_scan_power() scan_time = WIDE_SCAN_COST(GLOB.exoscanner_controller.wide_scan_band,scan_power) if(EXOSCAN_POINT) scan_power = GLOB.exoscanner_controller.get_scan_power(target) @@ -76,7 +76,8 @@ GLOBAL_LIST_INIT(scan_conditions,init_scan_conditions()) deltimer(scan_timer) /obj/machinery/computer/exoscanner_control - name = "Scanner Array Control Console" + name = "scanner array control console" + desc = "Controls scanner arrays to initiate scans for exodrones." circuit = /obj/item/circuitboard/computer/exoscanner_console /// If scan was interrupted show a popup until dismissed. var/failed_popup = FALSE @@ -105,7 +106,7 @@ GLOBAL_LIST_INIT(scan_conditions,init_scan_conditions()) condition_descriptions += condition.description .["scan_conditions"] = condition_descriptions else - .["scan_power"] = scan_power = length(GLOB.exoscanner_controller.tracked_dishes) + .["scan_power"] = scan_power = GLOB.exoscanner_controller.calculate_scan_power() .["wide_scan_eta"] = scan_power > 0 ? WIDE_SCAN_COST(GLOB.exoscanner_controller.wide_scan_band,scan_power) : 0 .["possible_sites"] = build_exploration_site_ui_data() .["scan_conditions"] = null @@ -196,11 +197,35 @@ GLOBAL_LIST_INIT(scan_conditions,init_scan_conditions()) icon = 'icons/obj/exploration.dmi' icon_state = "scanner_off" desc = "A sophisticated scanning array. Easily influenced by its environment." + circuit = /obj/item/circuitboard/machine/exoscanner + ///the scan power of this array to supply to scanner_controller + var/scan_power = 1 /obj/machinery/exoscanner/Initialize(mapload) . = ..() RegisterSignals(GLOB.exoscanner_controller,list(COMSIG_EXOSCAN_STARTED,COMSIG_EXOSCAN_FINISHED), PROC_REF(scan_change)) update_readiness() + RefreshParts() + +/obj/machinery/exoscanner/RefreshParts() + . = ..() + var/power = 1 + + for(var/datum/stock_part/scanning_module/scanning_module in component_parts) + power += (scanning_module.tier - 1) / 12 + scan_power = power + GLOB.exoscanner_controller.update_scan_power() + +/obj/machinery/exoscanner/screwdriver_act(mob/user, obj/item/tool) + . = ..() + if(!.) + . = default_deconstruction_screwdriver(user, "scanner_open", "scanner_off", tool) + update_readiness() + +/obj/machinery/exoscanner/crowbar_act(mob/user, obj/item/tool) + ..() + if(default_deconstruction_crowbar(tool)) + return TRUE /obj/machinery/exoscanner/proc/scan_change() SIGNAL_HANDLER @@ -215,7 +240,7 @@ GLOBAL_LIST_INIT(scan_conditions,init_scan_conditions()) GLOB.exoscanner_controller.deactivate_scanner(src) /obj/machinery/exoscanner/proc/is_ready() - return anchored && is_operational + return anchored && is_operational && !panel_open /obj/machinery/exoscanner/proc/update_readiness() if(is_ready()) @@ -302,7 +327,7 @@ GLOBAL_LIST_INIT(scan_conditions,init_scan_conditions()) /datum/scanner_controller/proc/calculate_scan_power(conditions) . = 0 for(var/obj/machinery/exoscanner/dish in tracked_dishes) - var/effective_power = 1 + var/effective_power = dish.scan_power for(var/datum/scan_condition/condition in conditions) effective_power *= condition.check_dish(dish) if(!effective_power) //Don't bother continuing if it's zero diff --git a/code/modules/fishing/aquarium/fish_analyzer.dm b/code/modules/fishing/aquarium/fish_analyzer.dm index c7feab860ca..8afe053a4d5 100644 --- a/code/modules/fishing/aquarium/fish_analyzer.dm +++ b/code/modules/fishing/aquarium/fish_analyzer.dm @@ -190,16 +190,17 @@ if(fish.status != FISH_DEAD) render_list += "\n" - var/hunger = PERCENT(min((world.time - fish.last_feeding) / fish.feeding_frequency, 1)) - var/hunger_string = "[hunger]%" - switch(hunger) - if(0 to 60) - hunger_string = span_info(hunger_string) - if(60 to 90) - hunger_string = span_warning(hunger_string) - if(90 to 100) - hunger_string = span_alert(hunger_string) - render_list += "Hunger: [hunger_string]\n" + if(!HAS_TRAIT(fish, TRAIT_FISH_NO_HUNGER)) + var/hunger = PERCENT(min((world.time - fish.last_feeding) / fish.feeding_frequency, 1)) + var/hunger_string = "[hunger]%" + switch(hunger) + if(0 to 60) + hunger_string = span_info(hunger_string) + if(60 to 90) + hunger_string = span_warning(hunger_string) + if(90 to 100) + hunger_string = span_alert(hunger_string) + render_list += "Hunger: [hunger_string]\n" var/time_left = round(max(fish.breeding_wait - world.time, 0)/10) render_list += "Time until it can breed: [time_left] seconds" diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm index 21585a07546..1275886141b 100644 --- a/code/modules/fishing/fish/_fish.dm +++ b/code/modules/fishing/fish/_fish.dm @@ -136,6 +136,9 @@ var/min_pressure = WARNING_LOW_PRESSURE var/max_pressure = HAZARD_HIGH_PRESSURE + /// If this fish type counts towards the Fish Species Scanning experiments + var/experisci_scannable = TRUE + /obj/item/fish/Initialize(mapload, apply_qualities = TRUE) . = ..() AddComponent(/datum/component/aquarium_content, PROC_REF(get_aquarium_animation), list(COMSIG_FISH_STATUS_CHANGED,COMSIG_FISH_STIRRED)) @@ -175,7 +178,7 @@ balloon_alert(user, "[src] is dead!") return TRUE feed(item.reagents) - balloon_alert(user, "you feed [src]") + balloon_alert(user, "fed [src]") return TRUE /obj/item/fish/examine(mob/user) @@ -185,14 +188,14 @@ . += span_notice("It weighs [weight] g.") ///Randomizes weight and size. -/obj/item/fish/proc/randomize_size_and_weight(avg_size = average_size, avg_weight = average_weight, deviation = 0.2, first_run = FALSE) - var/size_deviation = 0.2 * avg_size - var/new_size = round(max(1,gaussian(avg_size, size_deviation)), 1) +/obj/item/fish/proc/randomize_size_and_weight(base_size = average_size, base_weight = average_weight, deviation = 0.2) + var/size_deviation = 0.2 * base_size + var/new_size = round(clamp(gaussian(base_size, size_deviation), average_size * 1/MAX_FISH_DEVIATION_COEFF, average_size * MAX_FISH_DEVIATION_COEFF)) - var/weight_deviation = 0.2 * avg_weight - var/new_weight = round(max(1,gaussian(avg_weight, weight_deviation)), 1) + var/weight_deviation = 0.2 * base_weight + var/new_weight = round(clamp(gaussian(base_weight, weight_deviation), average_weight * 1/MAX_FISH_DEVIATION_COEFF, average_weight * MAX_FISH_DEVIATION_COEFF)) - update_size_and_weight(new_size, new_weight, first_run) + update_size_and_weight(new_size, new_weight) ///Updates weight and size, along with weight class, number of fillets you can get and grind results. /obj/item/fish/proc/update_size_and_weight(new_size = average_size, new_weight = average_weight) @@ -414,11 +417,14 @@ return FALSE return TRUE +/obj/item/fish/proc/is_hungry() + return !HAS_TRAIT(src, TRAIT_FISH_NO_HUNGER) && world.time - last_feeding >= feeding_frequency + /obj/item/fish/proc/process_health(seconds_per_tick) var/health_change_per_second = 0 if(!proper_environment()) health_change_per_second -= 3 //Dying here - if(world.time - last_feeding >= feeding_frequency) + if(is_hungry()) health_change_per_second -= 0.5 //Starving else health_change_per_second += 0.5 //Slowly healing @@ -541,10 +547,11 @@ #define FLOP_SINGLE_MOVE_TIME 1.5 #define JUMP_X_DISTANCE 5 #define JUMP_Y_DISTANCE 6 -/// This animation should be applied to actual parent atom instead of vc_object. -/proc/flop_animation(atom/movable/animation_target) + +/// This flopping animation played while the fish is alive. +/obj/item/fish/proc/flop_animation() var/pause_between = PAUSE_BETWEEN_PHASES + rand(1, 5) //randomized a bit so fish are not in sync - animate(animation_target, time = pause_between, loop = -1) + animate(src, time = pause_between, loop = -1) //move nose down and up for(var/_ in 1 to FLOP_COUNT) var/matrix/up_matrix = matrix() @@ -565,6 +572,7 @@ animate(time = up_time, pixel_y = JUMP_Y_DISTANCE , pixel_x=x_step, loop = -1, flags= ANIMATION_RELATIVE, easing = BOUNCE_EASING | EASE_IN) animate(time = up_time, pixel_y = -JUMP_Y_DISTANCE, pixel_x=x_step, loop = -1, flags= ANIMATION_RELATIVE, easing = BOUNCE_EASING | EASE_OUT) animate(time = PAUSE_BETWEEN_FLOPS, loop = -1) + #undef PAUSE_BETWEEN_PHASES #undef PAUSE_BETWEEN_FLOPS #undef FLOP_COUNT @@ -578,7 +586,7 @@ if(flopping) //Requires update_transform/animate_wrappers to be less restrictive. return flopping = TRUE - flop_animation(src) + flop_animation() /// Stops flopping animation /obj/item/fish/proc/stop_flopping() @@ -593,7 +601,7 @@ /obj/item/fish/proc/refresh_flopping() if(flopping) - flop_animation(src) + flop_animation() /// Returns random fish, using random_case_rarity probabilities. /proc/random_fish_type(required_fluid) diff --git a/code/modules/fishing/fish/fish_traits.dm b/code/modules/fishing/fish/fish_traits.dm index bec868ad24e..63de4cfdf1d 100644 --- a/code/modules/fishing/fish/fish_traits.dm +++ b/code/modules/fishing/fish/fish_traits.dm @@ -12,6 +12,8 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( var/diff_traits_inheritability = 50 /// fishes of types within this list are granted to have this trait, no matter the probability var/list/guaranteed_inheritance_types + /// Depending on the value, fish with trait will be reported as more or less difficult in the catalog. + var/added_difficulty = 0 /// Difficulty modifier from this mod, needs to return a list with two values /datum/fish_trait/proc/difficulty_mod(obj/item/fishing_rod/rod, mob/fisherman) @@ -161,7 +163,7 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( /datum/fish_trait/necrophage name = "Necrophage" - catalog_description = "This fish will eat the carcasses of dead fishes when hungry." + catalog_description = "This fish will eat carcasses of dead fish when hungry." incompatible_traits = list(/datum/fish_trait/vegan) /datum/fish_trait/necrophage/apply_to_fish(obj/item/fish/fish) @@ -169,7 +171,7 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( /datum/fish_trait/necrophage/proc/eat_dead_fishes(obj/item/fish/source, seconds_per_tick) SIGNAL_HANDLER - if(world.time - source.last_feeding < source.feeding_frequency || !isaquarium(source.loc)) + if(!source.is_hungry() || !isaquarium(source.loc)) return for(var/obj/item/fish/victim in source.loc) if(victim.status != FISH_DEAD || victim == source || HAS_TRAIT(victim, TRAIT_YUCKY_FISH)) @@ -233,7 +235,7 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( /datum/fish_trait/predator/proc/eat_fishes(obj/item/fish/source, seconds_per_tick) SIGNAL_HANDLER - if(world.time - source.last_feeding < source.feeding_frequency || !isaquarium(source.loc)) + if(!source.is_hungry() || !isaquarium(source.loc)) return var/obj/structure/aquarium/aquarium = source.loc for(var/obj/item/fish/victim in aquarium.get_fishes(TRUE, source)) @@ -334,6 +336,7 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( diff_traits_inheritability = 45 guaranteed_inheritance_types = list(/obj/item/fish/clownfish/lube) catalog_description = "This fish exudes a viscous, slippery lubrificant. It's reccomended not to step on it." + added_difficulty = 5 /datum/fish_trait/lubed/apply_to_fish(obj/item/fish/fish) fish.AddComponent(/datum/component/slippery, 8 SECONDS, SLIDE|GALOSHES_DONT_HELP) @@ -352,3 +355,26 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( ADD_TRAIT(fish, TRAIT_FISH_AMPHIBIOUS, FISH_TRAIT_DATUM) if(fish.required_fluid_type == AQUARIUM_FLUID_AIR) fish.required_fluid_type = AQUARIUM_FLUID_FRESHWATER + +/datum/fish_trait/mixotroph + name = "Mixotroph" + inheritability = 75 + diff_traits_inheritability = 25 + catalog_description = "This fish is capable of substaining itself by producing its own sources of energy (food)." + incompatible_traits = list(/datum/fish_trait/predator, /datum/fish_trait/necrophage) + +/datum/fish_trait/antigrav/apply_to_fish(obj/item/fish/fish) + ADD_TRAIT(fish, TRAIT_FISH_NO_HUNGER, FISH_TRAIT_DATUM) + +/datum/fish_trait/antigrav + name = "Anti-Gravity" + inheritability = 75 + diff_traits_inheritability = 25 + catalog_description = "This fish will invert the gravity of the bait at random. May fall upward outside after being caught." + added_difficulty = 15 + +/datum/fish_trait/antigrav/minigame_mod(obj/item/fishing_rod/rod, mob/fisherman, datum/fishing_challenge/minigame) + minigame.special_effects |= FISHING_MINIGAME_RULE_ANTIGRAV + +/datum/fish_trait/antigrav/apply_to_fish(obj/item/fish/fish) + fish.AddElement(/datum/element/forced_gravity, NEGATIVE_GRAVITY) diff --git a/code/modules/fishing/fish/fish_types.dm b/code/modules/fishing/fish/fish_types.dm index 652b0aba8aa..5ff62266ad9 100644 --- a/code/modules/fishing/fish/fish_types.dm +++ b/code/modules/fishing/fish/fish_types.dm @@ -341,7 +341,6 @@ icon_state = "sludgefish_purple" dedicated_in_aquarium_icon_state = "sludgefish_purple_small" random_case_rarity = FISH_RARITY_NOPE - random_case_rarity = FISH_RARITY_VERY_RARE fish_traits = list(/datum/fish_trait/parthenogenesis) /obj/item/fish/slimefish @@ -439,11 +438,13 @@ fillet_type = null death_text = "%SRC gently disappears." fish_traits = list(/datum/fish_trait/no_mating) //just to be sure, these shouldn't reproduce + experisci_scannable = FALSE /obj/item/fish/holo/Initialize(mapload) . = ..() var/area/station/holodeck/holo_area = get_area(src) if(!istype(holo_area)) + addtimer(CALLBACK(src, PROC_REF(set_status), FISH_DEAD), 1 MINUTES) return holo_area.linked.add_to_spawned(src) @@ -488,9 +489,9 @@ sprite_height = 5 /obj/item/fish/holo/checkered - name = "unrendered holographic fish" //it's a meta joke, buddy. + name = "unrendered holographic fish" desc = "A checkered silhoutte of searing purple and pitch black presents itself before your eyes, like a tear in fabric of reality. It hurts to watch." - icon_state = "checkered" + icon_state = "checkered" //it's a meta joke, buddy. dedicated_in_aquarium_icon_state = "checkered_small" sprite_width = 4 @@ -502,3 +503,37 @@ sprite_height = 4 sprite_width = 10 average_size = 50 + +/obj/item/fish/starfish + name = "cosmostarfish" + desc = "A peculiar, gravity-defying, echinoderm-looking critter from hyperspace." + icon_state = "starfish" + dedicated_in_aquarium_icon_state = "starfish_small" + icon_state_dead = "starfish_dead" + sprite_width = 4 + average_size = 30 + average_weight = 300 + stable_population = 3 + required_fluid_type = AQUARIUM_FLUID_AIR + random_case_rarity = FISH_RARITY_NOPE + required_temperature_min = 0 + required_temperature_max = INFINITY + safe_air_limits = null + min_pressure = 0 + max_pressure = INFINITY + grind_results = list(/datum/reagent/bluespace = 10, /datum/reagent/consumable/liquidgibs = 5) + fillet_type = null + fish_traits = list(/datum/fish_trait/antigrav, /datum/fish_trait/mixotroph) + +/obj/item/fish/starfish/Initialize(mapload) + . = ..() + update_appearance(UPDATE_OVERLAYS) + +/obj/item/fish/starfish/update_overlays() + . = ..() + if(status == FISH_ALIVE) + . += emissive_appearance(icon, "starfish_emissive", src) + +///It spins, and dimly glows in the dark. +/obj/item/fish/starfish/flop_animation() + DO_FLOATING_ANIM(src) diff --git a/code/modules/fishing/fish_catalog.dm b/code/modules/fishing/fish_catalog.dm index d41b4657e50..a0f66c2227d 100644 --- a/code/modules/fishing/fish_catalog.dm +++ b/code/modules/fishing/fish_catalog.dm @@ -68,14 +68,6 @@ if(source.catalog_description && (fish_type in source.fish_table)) spot_descriptions += source.catalog_description .["spots"] = english_list(spot_descriptions, nothing_text = "Unknown") - ///Difficulty descriptor - switch(initial(fishy.fishing_difficulty_modifier)) - if(-INFINITY to 10) - .["difficulty"] = "Easy" - if(20 to 30) - .["difficulty"] = "Medium" - else - .["difficulty"] = "Hard" var/list/fish_list_properties = collect_fish_properties() var/list/fav_bait = fish_list_properties[fishy][NAMEOF(fishy, favorite_bait)] var/list/disliked_bait = fish_list_properties[fishy][NAMEOF(fishy, disliked_bait)] @@ -91,12 +83,22 @@ // Fish traits description var/list/trait_descriptions = list() var/list/fish_traits = fish_list_properties[fishy][NAMEOF(fishy, fish_traits)] + var/fish_difficulty = initial(fishy.fishing_difficulty_modifier) for(var/fish_trait in fish_traits) var/datum/fish_trait/trait = GLOB.fish_traits[fish_trait] trait_descriptions += trait.catalog_description + fish_difficulty += trait.added_difficulty if(!length(trait_descriptions)) trait_descriptions += "This fish exhibits no special behavior." .["traits"] = trait_descriptions + ///Difficulty descriptor + switch(fish_difficulty) + if(-INFINITY to 9) + .["difficulty"] = "Easy" + if(10 to 19) + .["difficulty"] = "Medium" + else + .["difficulty"] = "Hard" return . /obj/item/book/fish_catalog/ui_assets(mob/user) diff --git a/code/modules/fishing/fishing_equipment.dm b/code/modules/fishing/fishing_equipment.dm index 6169b41fd88..3f34222ad87 100644 --- a/code/modules/fishing/fishing_equipment.dm +++ b/code/modules/fishing/fishing_equipment.dm @@ -11,7 +11,8 @@ desc = "Simple fishing line." icon = 'icons/obj/fishing.dmi' icon_state = "reel_blue" - var/fishing_line_traits = NONE + ///A list of traits that this fishing line has, checked by fish traits and the minigame. + var/list/fishing_line_traits /// Color of the fishing line var/line_color = "#808080" @@ -59,7 +60,8 @@ icon_state = "hook" w_class = WEIGHT_CLASS_TINY - var/fishing_hook_traits = NONE + /// A list of traits that this fishing hook has, checked by fish traits and the minigame + var/list/fishing_hook_traits /// icon state added to main rod icon when this hook is equipped var/rod_overlay_icon_state = "hook_overlay" /// What subtype of `/obj/item/chasm_detritus` do we fish out of chasms? Defaults to `/obj/item/chasm_detritus`. @@ -175,7 +177,7 @@ name = "jawed hook" desc = "Despite hints of rust, this gritty beartrap-like hook hybrid manages to look even more threating than the real thing. May neptune have mercy of whatever gets caught in its jaws." icon_state = "jaws" - fishing_hook_traits = FISHING_HOOK_NO_ESCAPE|FISHING_HOOK_ENSNARE|FISHING_HOOK_KILL + fishing_hook_traits = FISHING_HOOK_NO_ESCAPE|FISHING_HOOK_NO_ESCAPE|FISHING_HOOK_KILL rod_overlay_icon_state = "hook_jaws_overlay" /obj/item/storage/toolbox/fishing diff --git a/code/modules/fishing/fishing_minigame.dm b/code/modules/fishing/fishing_minigame.dm index 478279749e4..06ac03d64ac 100644 --- a/code/modules/fishing/fishing_minigame.dm +++ b/code/modules/fishing/fishing_minigame.dm @@ -43,8 +43,12 @@ var/fish_ai = FISH_AI_DUMB /// Rule modifiers (eg weighted bait) var/special_effects = NONE - /// Did the game get past the baiting phase, used to track if bait should be consumed afterwards - var/bait_taken = FALSE + /// A list of possible active minigame effects. If not empty, one will be picked from time to time. + var/list/active_effects + /// The cooldown between switching active effects + COOLDOWN_DECLARE(active_effect_cd) + /// The current active effect + var/current_active_effect /// Result path var/reward_path = FISHING_DUD /// Minigame difficulty @@ -61,6 +65,8 @@ var/obj/effect/fishing_lure/lure /// Background icon state from fishing_hud.dmi var/background = "background_default" + /// Fish icon state from fishing_hud.dmi + var/fish_icon = "fish" /// Fishing line visual var/datum/beam/fishing_line @@ -168,7 +174,10 @@ RegisterSignal(user, COMSIG_MOB_FISHING_REWARD_DISPENSED, PROC_REF(hurt_fish)) difficulty += comp.fish_source.calculate_difficulty(reward_path, rod, user, src) - difficulty = round(difficulty) + difficulty = clamp(round(difficulty), 1, 100) + + if(HAS_TRAIT(user, TRAIT_REVEAL_FISH)) + fish_icon = GLOB.specific_fish_icons[reward_path] || "fish" /** * If the chances are higher than 1% (100% at maximum difficulty), they'll scale @@ -207,19 +216,21 @@ lure_turf?.balloon_alert(user, message) /datum/fishing_challenge/proc/on_spot_gone(datum/source) + SIGNAL_HANDLER send_alert("fishing spot gone!") - interrupt(balloon_alert = FALSE) + interrupt() /datum/fishing_challenge/proc/interrupt_challenge(datum/source, reason) if(reason) send_alert(reason) - interrupt(balloon_alert = FALSE) + interrupt() /datum/fishing_challenge/proc/start(mob/living/user) /// Create fishing line visuals fishing_line = used_rod.create_fishing_line(lure, target_py = 5) + active_effects = bitfield_to_list(special_effects & FISHING_MINIGAME_ACTIVE_EFFECTS) // If fishing line breaks los / rod gets dropped / deleted - RegisterSignal(fishing_line, COMSIG_FISHING_LINE_SNAPPED, PROC_REF(interrupt)) + RegisterSignal(fishing_line, COMSIG_QDELETING, PROC_REF(on_line_deleted)) RegisterSignal(used_rod, COMSIG_ITEM_ATTACK_SELF, PROC_REF(on_attack_self)) ADD_TRAIT(user, TRAIT_GONE_FISHING, REF(src)) user.add_mood_event("fishing", /datum/mood_event/fishing) @@ -228,6 +239,12 @@ to_chat(user, span_notice("You start fishing...")) playsound(lure, 'sound/effects/splash.ogg', 100) +/datum/fishing_challenge/proc/on_line_deleted(datum/source) + SIGNAL_HANDLER + fishing_line = null + send_alert(user.is_holding(used_rod) ? "line snapped" : "rod dropped") + interrupt() + /datum/fishing_challenge/proc/handle_click(mob/source, atom/target, modifiers) SIGNAL_HANDLER //You need to be holding the rod to use it. @@ -241,12 +258,9 @@ return COMSIG_MOB_CANCEL_CLICKON /// Challenge interrupted by something external -/datum/fishing_challenge/proc/interrupt(datum/source, balloon_alert = TRUE) - SIGNAL_HANDLER +/datum/fishing_challenge/proc/interrupt() if(!completed) experience_multiplier *= 0.5 - if(balloon_alert) - send_alert(user.is_holding(used_rod) ? "line snapped" : "tool dropped") complete(FALSE) /datum/fishing_challenge/proc/on_attack_self(obj/item/source, mob/user) @@ -278,7 +292,8 @@ if(reward_path != FISHING_DUD) playsound(lure, 'sound/effects/bigsplash.ogg', 100) SEND_SIGNAL(src, COMSIG_FISHING_CHALLENGE_COMPLETED, user, win) - qdel(src) + if(!QDELETED(src)) + qdel(src) /datum/fishing_challenge/proc/start_baiting_phase() deltimer(next_phase_timer) @@ -294,7 +309,30 @@ phase = BITING_PHASE // Trashing animation playsound(lure, 'sound/effects/fish_splash.ogg', 100) - send_alert("!!!") + if(HAS_TRAIT(user, TRAIT_REVEAL_FISH)) + switch(fish_icon) + if(FISH_ICON_DEF) + send_alert("fish!!!") + if(FISH_ICON_HOSTILE) + send_alert("hostile!!!") + if(FISH_ICON_STAR) + send_alert("starfish!!!") + if(FISH_ICON_CHUNKY) + send_alert("round fish!!!") + if(FISH_ICON_JELLYFISH) + send_alert("jellyfish!!!") + if(FISH_ICON_SLIME) + send_alert("slime!!!") + if(FISH_ICON_COIN) + send_alert("valuable!!!") + if(FISH_ICON_GEM) + send_alert("ore!!!") + if(FISH_ICON_CRAB) + send_alert("crustacean!!!") + if(FISH_ICON_BONE) + send_alert("bones!!!") + else + send_alert("!!!") animate(lure, pixel_y = 3, time = 5, loop = -1, flags = ANIMATION_RELATIVE) animate(pixel_y = -3, time = 5, flags = ANIMATION_RELATIVE) // Setup next phase @@ -307,7 +345,7 @@ ///The player is no longer around to play the minigame, so we interrupt it. /datum/fishing_challenge/proc/on_user_logout(datum/source) SIGNAL_HANDLER - interrupt(balloon_alert = FALSE) + interrupt() /datum/fishing_challenge/proc/win_anyway() if(!completed) @@ -345,6 +383,9 @@ RegisterSignal(user.client, COMSIG_CLIENT_MOUSEDOWN, PROC_REF(start_reeling)) RegisterSignal(user.client, COMSIG_CLIENT_MOUSEUP, PROC_REF(stop_reeling)) RegisterSignal(user, COMSIG_MOB_LOGOUT, PROC_REF(on_user_logout)) + if(length(active_effects)) + // Give the player a moment to prepare for active minigame effects + COOLDOWN_START(src, active_effect_cd, rand(5, 9) SECONDS) START_PROCESSING(SSfishing, src) ///Stop processing and remove references to the minigame hud @@ -369,11 +410,44 @@ ///Update the state of the fish, the bait and the hud /datum/fishing_challenge/process(seconds_per_tick) + if(length(active_effects) && COOLDOWN_FINISHED(src, active_effect_cd)) + select_active_effect() move_fish(seconds_per_tick) move_bait(seconds_per_tick) if(!QDELETED(fishing_hud)) update_visuals() +///The proc that handles fancy effects like flipping the hud or skewing movement +/datum/fishing_challenge/proc/select_active_effect() + ///bring forth an active effect + if(isnull(current_active_effect)) + current_active_effect = pick(active_effects) + switch(current_active_effect) + if(FISHING_MINIGAME_RULE_ANTIGRAV) + fishing_hud.icon_state = "background_antigrav" + SEND_SOUND(user, sound('sound/effects/arcade_jump.ogg', volume = 50)) + COOLDOWN_START(src, active_effect_cd, rand(6, 9) SECONDS) + if(FISHING_MINIGAME_RULE_FLIP) + fishing_hud.icon_state = "background_flip" + fishing_hud.transform = fishing_hud.transform.Scale(1, -1) + SEND_SOUND(user, sound('sound/effects/boing.ogg')) + COOLDOWN_START(src, active_effect_cd, rand(5, 6) SECONDS) + return + + ///go back to normal + switch(current_active_effect) + if(FISHING_MINIGAME_RULE_ANTIGRAV) + var/sound/inverted_sound = sound('sound/effects/arcade_jump.ogg', volume = 50) + inverted_sound.frequency = -1 + SEND_SOUND(user, inverted_sound) + COOLDOWN_START(src, active_effect_cd, rand(10, 13) SECONDS) + if(FISHING_MINIGAME_RULE_FLIP) + fishing_hud.transform = fishing_hud.transform.Scale(1, -1) + COOLDOWN_START(src, active_effect_cd, rand(8, 12) SECONDS) + + fishing_hud.icon_state = background + current_active_effect = null + ///The proc that moves the fish around, just like in the old TGUI, mostly. /datum/fishing_challenge/proc/move_fish(seconds_per_tick) var/long_chance = long_jump_chance * seconds_per_tick * 10 @@ -464,6 +538,9 @@ velocity_change = round(velocity_change) + if(current_active_effect == FISHING_MINIGAME_RULE_ANTIGRAV) + velocity_change = -velocity_change + /** * Pull the brake on the velocity if the current velocity and the acceleration * have different directions, making the bait less slippery, thus easier to control @@ -524,7 +601,7 @@ icon_state = challenge.background add_overlay("frame") hud_bait = new(null, null, challenge) - hud_fish = new + hud_fish = new(null, null, challenge) hud_completion = new(null, null, challenge) vis_contents += list(hud_bait, hud_fish, hud_completion) challenge.user.client.screen += src @@ -557,6 +634,11 @@ icon_state = "fish" vis_flags = VIS_INHERIT_ID +/atom/movable/screen/hud_fish/Initialize(mapload, datum/hud/hud_owner, datum/fishing_challenge/challenge) + . = ..() + if(challenge) + icon_state = challenge.fish_icon + /atom/movable/screen/hud_completion icon = 'icons/hud/fishing_hud.dmi' icon_state = "completion_0" diff --git a/code/modules/fishing/fishing_portal_machine.dm b/code/modules/fishing/fishing_portal_machine.dm index 3fc6b0eb938..b156a37ba05 100644 --- a/code/modules/fishing/fishing_portal_machine.dm +++ b/code/modules/fishing/fishing_portal_machine.dm @@ -1,40 +1,58 @@ /obj/machinery/fishing_portal_generator name = "fish-porter 3000" - desc = "fishing anywhere, anytime, anyway what was i talking about" - + desc = "Fishing anywhere, anytime... anyway what was I talking about?" icon = 'icons/obj/fishing.dmi' - icon_state = "portal_off" - + icon_state = "portal" idle_power_usage = 0 active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 - anchored = FALSE density = TRUE + circuit = /obj/item/circuitboard/machine/fishing_portal_generator - var/fishing_source = /datum/fish_source/portal + ///The current fishing spot loaded in var/datum/component/fishing_spot/active +/obj/machinery/fishing_portal_generator/on_set_panel_open() + update_appearance() + return ..() + /obj/machinery/fishing_portal_generator/wrench_act(mob/living/user, obj/item/tool) . = ..() default_unfasten_wrench(user, tool) return TOOL_ACT_TOOLTYPE_SUCCESS +/obj/machinery/fishing_portal_generator/examine(mob/user) + . = ..() + . += span_notice("You can unlock further portal settings by completing fish scanning experiments.") + +/obj/machinery/fishing_portal_generator/emag_act(mob/user, obj/item/card/emag/emag_card) + if(obj_flags & EMAGGED) + return FALSE + obj_flags |= EMAGGED + balloon_alert(user, "syndicate setting loaded") + playsound(src, SFX_SPARKS, 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + return TRUE + /obj/machinery/fishing_portal_generator/interact(mob/user, special_state) . = ..() if(active) deactivate() else - activate() + select_fish_source(user) -/obj/machinery/fishing_portal_generator/update_icon(updates) +/obj/machinery/fishing_portal_generator/update_overlays() . = ..() - if(active) - icon_state = "portal_on" - else - icon_state = "portal_off" + if(panel_open) + . += "portal_open" + if(!active) + return + . += "portal_on" + var/datum/fish_source/portal/portal = active.fish_source + . += portal.overlay_state + . += emissive_appearance(icon, "portal_emissive", src) -/obj/machinery/fishing_portal_generator/proc/activate() - active = AddComponent(/datum/component/fishing_spot, fishing_source) +/obj/machinery/fishing_portal_generator/proc/activate(datum/fish_source/selected_source) + active = AddComponent(/datum/component/fishing_spot, selected_source) use_power = ACTIVE_POWER_USE update_icon() @@ -46,3 +64,39 @@ /obj/machinery/fishing_portal_generator/on_set_is_operational(old_value) if(old_value) deactivate() + +///Create a radial menu from a list of available fish sources. If only the default is available, activate it right away. +/obj/machinery/fishing_portal_generator/proc/select_fish_source(mob/user) + var/datum/fish_source/portal/default = GLOB.preset_fish_sources[/datum/fish_source/portal] + var/list/available_fish_sources = list(default.radial_name = default) + if(obj_flags & EMAGGED) + var/datum/fish_source/portal/syndicate = GLOB.preset_fish_sources[/datum/fish_source/portal/syndicate] + available_fish_sources[syndicate.radial_name] = syndicate + for (var/datum/techweb/techweb as anything in SSresearch.techwebs) + var/get_fish_sources = FALSE + for(var/obj/machinery/rnd/server/server as anything in techweb.techweb_servers) + if(!is_valid_z_level(get_turf(server), get_turf(src))) + continue + get_fish_sources = TRUE + break + if(!get_fish_sources) + continue + for(var/experiment_type in typesof(/datum/experiment/scanning/fish)) + var/datum/experiment/scanning/fish/experiment = techweb.completed_experiments[experiment_type] + if(!experiment) + continue + var/datum/fish_source/portal/reward = GLOB.preset_fish_sources[experiment.fish_source_reward] + available_fish_sources[reward.radial_name] = reward + + if(length(available_fish_sources) == 1) + activate(default) + return + var/list/choices = list() + for(var/radial_name in available_fish_sources) + var/datum/fish_source/portal/source = available_fish_sources[radial_name] + choices[radial_name] = image(icon = 'icons/hud/radial_fishing.dmi', icon_state = source.radial_state) + + var/choice = show_radial_menu(user, src, choices, radius = 38, custom_check = CALLBACK(src, TYPE_PROC_REF(/atom, can_interact), user), tooltips = TRUE) + if(!choice || !can_interact(user)) + return + activate(available_fish_sources[choice]) diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index 7e01f693dd5..1abba8e414c 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -30,14 +30,11 @@ var/obj/item/currently_hooked_item /// Fishing line visual for the hooked item - var/datum/beam/hooked_item_fishing_line + var/datum/beam/fishing_line/fishing_line /// Are we currently casting var/casting = FALSE - /// List of fishing line beams - var/list/fishing_lines = list() - /// The default color for the reel overlay if no line is equipped. var/default_line_color = "gray" @@ -66,13 +63,10 @@ return NONE /obj/item/fishing_rod/Destroy(force) - . = ..() - //Remove any leftover fishing lines - QDEL_LIST(fishing_lines) + return ..() /obj/item/fishing_rod/examine(mob/user) . = ..() - . += "Right-Click in your active hand to access its slots UI" var/list/equipped_stuff = list() if(line) equipped_stuff += "[icon2html(line, user)] [line.name]" @@ -84,6 +78,7 @@ . += span_notice("\a [icon2html(bait, user)] [bait] is being used as bait.") else . += span_warning("It doesn't have any bait attached. Fishing will be more tedious!") + . += span_notice("Right-Click in your active hand to access its slots UI") /** * Catch weight modifier for the given fish_type (or FISHING_DUD) @@ -140,7 +135,7 @@ // Should probably respect and used force move later step_towards(currently_hooked_item, get_turf(src)) if(get_dist(currently_hooked_item,get_turf(src)) < 1) - clear_hooked_item() + QDEL_NULL(fishing_line) /obj/item/fishing_rod/attack_self_secondary(mob/user, modifiers) . = ..() @@ -159,30 +154,28 @@ var/mob/user = loc if(!istype(user)) return + if(fishing_line) + QDEL_NULL(fishing_line) var/beam_color = line?.line_color || default_line_color - var/datum/beam/fishing_line/fishing_line_beam = new(user, target, icon_state = "fishing_line", beam_color = beam_color, emissive = FALSE, override_target_pixel_y = target_py) - fishing_line_beam.lefthand = user.get_held_index_of_item(src) % 2 == 1 - RegisterSignal(fishing_line_beam, COMSIG_BEAM_BEFORE_DRAW, PROC_REF(check_los)) - RegisterSignal(fishing_line_beam, COMSIG_QDELETING, PROC_REF(clear_line)) - fishing_lines += fishing_line_beam - INVOKE_ASYNC(fishing_line_beam, TYPE_PROC_REF(/datum/beam/, Start)) + fishing_line = new(user, target, icon_state = "fishing_line", beam_color = beam_color, emissive = FALSE, override_target_pixel_y = target_py) + fishing_line.lefthand = user.get_held_index_of_item(src) % 2 == 1 + RegisterSignal(fishing_line, COMSIG_BEAM_BEFORE_DRAW, PROC_REF(check_los)) + RegisterSignal(fishing_line, COMSIG_QDELETING, PROC_REF(clear_line)) + INVOKE_ASYNC(fishing_line, TYPE_PROC_REF(/datum/beam/, Start)) user.update_held_items() - return fishing_line_beam + return fishing_line /obj/item/fishing_rod/proc/clear_line(datum/source) SIGNAL_HANDLER - fishing_lines -= source if(ismob(loc)) var/mob/user = loc user.update_held_items() + fishing_line = null + currently_hooked_item = null /obj/item/fishing_rod/dropped(mob/user, silent) . = ..() - if(currently_hooked_item) - clear_hooked_item() - for(var/datum/beam/fishing_line in fishing_lines) - SEND_SIGNAL(fishing_line, COMSIG_FISHING_LINE_SNAPPED) - QDEL_LIST(fishing_lines) + QDEL_NULL(fishing_line) /// Hooks the item /obj/item/fishing_rod/proc/hook_item(mob/user, atom/target_atom) @@ -191,28 +184,21 @@ if(!can_be_hooked(target_atom)) return currently_hooked_item = target_atom - hooked_item_fishing_line = create_fishing_line(target_atom) - RegisterSignal(hooked_item_fishing_line, COMSIG_FISHING_LINE_SNAPPED, PROC_REF(clear_hooked_item)) + create_fishing_line(target_atom) + SEND_SIGNAL(src, COMSIG_FISHING_ROD_HOOKED_ITEM, target_atom, user) /// Checks what can be hooked /obj/item/fishing_rod/proc/can_be_hooked(atom/movable/target) // Could be made dependent on actual hook, ie magnet to hook metallic items return isitem(target) -/obj/item/fishing_rod/proc/clear_hooked_item() - SIGNAL_HANDLER - - if(!QDELETED(hooked_item_fishing_line)) - QDEL_NULL(hooked_item_fishing_line) - currently_hooked_item = null - // Checks fishing line for interruptions and range /obj/item/fishing_rod/proc/check_los(datum/beam/source) SIGNAL_HANDLER . = NONE - if(!isturf(source.origin.loc) || !isturf(source.target.loc) || !CheckToolReach(src, source.target, cast_range)) - SEND_SIGNAL(source, COMSIG_FISHING_LINE_SNAPPED) //Stepped out of range or los interrupted + if(!CheckToolReach(src, source.target, cast_range)) + qdel(source) return BEAM_CANCEL_DRAW /obj/item/fishing_rod/afterattack(atom/target, mob/user, proximity_flag, click_parameters) @@ -300,7 +286,7 @@ reel_overlay.color = line_color . += reel_overlay /// if we don't have anything hooked show the dangling hook & line - if(isinhands && length(fishing_lines) == 0) + if(isinhands && !fishing_line) var/mutable_appearance/line_overlay = mutable_appearance(icon_file, "line_overlay") line_overlay.appearance_flags |= RESET_COLOR line_overlay.color = line_color @@ -507,8 +493,8 @@ balloon_alert(user, active ? "extended" : "collapsed") playsound(src, 'sound/weapons/batonextend.ogg', 50, TRUE) update_appearance(UPDATE_OVERLAYS) - if(currently_hooked_item) - clear_hooked_item() + if(fishing_line) + QDEL_NULL(fishing_line) return COMPONENT_NO_DEFAULT_MESSAGE /obj/item/fishing_rod/telescopic/master @@ -523,16 +509,34 @@ /obj/item/fishing_rod/tech name = "advanced fishing rod" desc = "An embedded universal constructor along with micro-fusion generator makes this marvel of technology never run out of bait. Interstellar treaties prevent using it outside of recreational fishing. And you can fish with this. " - ui_description = "This rod has an infinite supply of synthetic bait." + ui_description = "This rod has an infinite supply of synth-bait. Also doubles as an Experi-Scanner for fish." icon_state = "fishing_rod_science" reel_overlay = "reel_science" /obj/item/fishing_rod/tech/Initialize(mapload) . = ..() + + var/static/list/fishing_signals = list( + COMSIG_FISHING_ROD_HOOKED_ITEM = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_handheld_experiment), + COMSIG_FISHING_ROD_CAUGHT_FISH = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_handheld_experiment), + COMSIG_ITEM_PRE_ATTACK = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_handheld_experiment), + COMSIG_ITEM_AFTERATTACK = TYPE_PROC_REF(/datum/component/experiment_handler, ignored_handheld_experiment_attempt), + ) + 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 = fishing_signals, \ + ) + var/obj/item/food/bait/doughball/synthetic/infinite_supply_of_bait = new(src) bait = infinite_supply_of_bait update_icon() +/obj/item/fishing_rod/tech/examine(mob/user) + . = ..() + . += span_notice("Alt-Click to access the Experiment Configuration UI") + /obj/item/fishing_rod/tech/consume_bait(atom/movable/reward) return diff --git a/code/modules/fishing/sources/_fish_source.dm b/code/modules/fishing/sources/_fish_source.dm index 5a34db9ce5f..657b2f30968 100644 --- a/code/modules/fishing/sources/_fish_source.dm +++ b/code/modules/fishing/sources/_fish_source.dm @@ -1,11 +1,47 @@ GLOBAL_LIST_INIT(preset_fish_sources, init_subtypes_w_path_keys(/datum/fish_source, list())) +/** + * When adding new fishable rewards to a table/counts, you can specify an icon to show in place of the + * generic fish icon in the minigame UI should the user have the TRAIT_REVEAL_FISH trait, by adding it to + * this list. + * + * A lot of the icons here may be a tad inaccurate, but since we're limited to the free font awesome icons we + * have access to, we got to make do. + */ +GLOBAL_LIST_INIT(specific_fish_icons, zebra_typecacheof(list( + /mob/living/basic/carp = FISH_ICON_DEF, + /mob/living/basic/mining = FISH_ICON_HOSTILE, + /obj/effect/decal/remains = FISH_ICON_BONE, + /obj/effect/mob_spawn/corpse = FISH_ICON_BONE, + /obj/item/coin = FISH_ICON_COIN, + /obj/item/fish = FISH_ICON_DEF, + /obj/item/fish/armorfish = FISH_ICON_CRAB, + /obj/item/fish/boned = FISH_ICON_BONE, + /obj/item/fish/chasm_crab = FISH_ICON_CRAB, + /obj/item/fish/gunner_jellyfish = FISH_ICON_JELLYFISH, + /obj/item/fish/holo/crab = FISH_ICON_CRAB, + /obj/item/fish/holo/puffer = FISH_ICON_CHUNKY, + /obj/item/fish/mastodon = FISH_ICON_BONE, + /obj/item/fish/pufferfish = FISH_ICON_CHUNKY, + /obj/item/fish/slimefish = FISH_ICON_SLIME, + /obj/item/fish/sludgefish = FISH_ICON_SLIME, + /obj/item/fish/starfish = FISH_ICON_STAR, + /obj/item/storage/wallet = FISH_ICON_COIN, + /obj/item/stack/sheet/bone = FISH_ICON_BONE, + /obj/item/stack/sheet/mineral = FISH_ICON_GEM, + /obj/item/stack/ore = FISH_ICON_GEM, + /obj/structure/closet/crate = FISH_ICON_COIN, +))) + /** * Where the fish actually come from - every fishing spot has one assigned but multiple fishing holes * can share single source, ie single shared one for ocean/lavaland river */ /datum/fish_source - /// Fish catch weight table - these are relative weights + /** + * Fish catch weight table - these are relative weights + * + */ var/list/fish_table = list() /// If a key from fish_table is present here, that fish is availible in limited quantity and is reduced by one on successful fishing var/list/fish_counts = list() @@ -25,6 +61,10 @@ GLOBAL_LIST_INIT(preset_fish_sources, init_subtypes_w_path_keys(/datum/fish_sour if(!(path in fish_table)) stack_trace("path [path] found in the 'fish_counts' list but not in the fish_table one of [type]") +///Called when src is set as the fish source of a fishing spot component +/datum/fish_source/proc/on_fishing_spot_init(/datum/component/fishing_spot/spot) + return + /// Can we fish in this spot at all. Returns DENIAL_REASON or null if we're good to go /datum/fish_source/proc/reason_we_cant_fish(obj/item/fishing_rod/rod, mob/fisherman) return rod.reason_we_cant_fish(src) @@ -35,7 +75,7 @@ GLOBAL_LIST_INIT(preset_fish_sources, init_subtypes_w_path_keys(/datum/fish_sour * This includes the source's fishing difficulty, that of the fish, the rod, * favorite and disliked baits, fish traits and the fisherman skill. * - * For non-fish, it's just the source's fishing difficulty minus the fisherman skill, rod and settler modifiers. + * For non-fish, it's just the source's fishing difficulty minus the fisherman skill. */ /datum/fish_source/proc/calculate_difficulty(result, obj/item/fishing_rod/rod, mob/fisherman, datum/fishing_challenge/challenge) . = fishing_difficulty @@ -96,7 +136,7 @@ GLOBAL_LIST_INIT(preset_fish_sources, init_subtypes_w_path_keys(/datum/fish_sour * Used to register signals or add traits and the such right after conditions have been cleared * and before the minigame starts. */ -/datum/fish_source/proc/pre_challenge_started(obj/item/fishing_rod/rod, mob/user) +/datum/fish_source/proc/pre_challenge_started(obj/item/fishing_rod/rod, mob/user, datum/fishing_challenge/challenge) return ///Proc called when the challenge is interrupted within the fish source code. @@ -116,7 +156,9 @@ GLOBAL_LIST_INIT(preset_fish_sources, init_subtypes_w_path_keys(/datum/fish_sour user.add_mob_memory(/datum/memory/caught_fish, protagonist = user, deuteragonist = initial(caught.name)) var/turf/fishing_spot = get_turf(source.lure) var/atom/movable/reward = dispense_reward(source.reward_path, user, fishing_spot) - source.used_rod?.consume_bait(reward) + if(source.used_rod) + SEND_SIGNAL(source.used_rod, COMSIG_FISHING_ROD_CAUGHT_FISH, reward, user) + source.used_rod.consume_bait(reward) /// Gives out the reward if possible /datum/fish_source/proc/dispense_reward(reward_path, mob/fisherman, turf/fishing_spot) diff --git a/code/modules/fishing/sources/source_types.dm b/code/modules/fishing/sources/source_types.dm index ffb37753881..e2e5491dd1d 100644 --- a/code/modules/fishing/sources/source_types.dm +++ b/code/modules/fishing/sources/source_types.dm @@ -19,11 +19,168 @@ /datum/fish_source/portal fish_table = list( - FISHING_DUD = 5, + FISHING_DUD = 7, /obj/item/fish/goldfish = 10, /obj/item/fish/guppy = 10, + /obj/item/fish/angelfish = 10, + ) + catalog_description = "Aquarium dimension (Fishing portal generator)" + ///The name of this option shown in the radial menu on the fishing portal generator + var/radial_name = "Aquarium" + ///The icon state shown for this option in the radial menu + var/radial_state = "fish_tank" + ///The icon state of the overlay shown on the machine when active. + var/overlay_state = "portal_aquarium" + +/datum/fish_source/portal/beach + fish_table = list( + FISHING_DUD = 10, + /obj/item/fish/clownfish = 10, + /obj/item/fish/pufferfish = 10, + /obj/item/fish/cardinal = 10, + /obj/item/fish/greenchromis = 10, + ) + catalog_description = "Beach dimension (Fishing portal generator)" + radial_name = "Beach" + radial_state = "palm_beach" + +/datum/fish_source/portal/chasm + background = "background_lavaland" + fish_table = list( + FISHING_DUD = 5, + /obj/item/fish/chasm_crab = 10, + /obj/item/fish/boned = 5, + /obj/item/stack/sheet/bone = 5, + ) + catalog_description = "Chasm dimension (Fishing portal generator)" + fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10 + radial_name = "Chasm" + overlay_state = "portal_chasm" + radial_state = "ground_hole" + +/datum/fish_source/portal/ocean + fish_table = list( + FISHING_DUD = 5, + /obj/item/fish/lanternfish = 5, + /obj/item/fish/firefish = 5, + /obj/item/fish/dwarf_moonfish = 5, + /obj/item/fish/gunner_jellyfish = 5, + /obj/item/fish/needlefish = 5, + /obj/item/fish/armorfish = 5, + ) + catalog_description = "Ocean dimension (Fishing portal generator)" + fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10 + radial_name = "Ocean" + overlay_state = "portal_ocean" + radial_state = "seaboat" + +/datum/fish_source/portal/hyperspace + fish_table = list( + FISHING_DUD = 5, + /obj/item/fish/starfish = 6, + /obj/item/stack/ore/bluespace_crystal = 2, + /mob/living/basic/carp = 2, + ) + fish_counts = list( + /obj/item/stack/ore/bluespace_crystal = 10, ) - catalog_description = "Fish dimension (Fishing portal generator)" + catalog_description = "Hyperspace dimension (Fishing portal generator)" + fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10 + radial_name = "Hyperspace" + overlay_state = "portal_hyperspace" + radial_state = "space_rocket" + +///Unlocked by emagging the fishing portal generator with an emag. +/datum/fish_source/portal/syndicate + background = "background_lavaland" + fish_table = list( + FISHING_DUD = 5, + /obj/item/fish/donkfish = 5, + /obj/item/fish/emulsijack = 5, + ) + catalog_description = "Syndicate dimension (Fishing portal generator)" + radial_name = "Syndicate" + fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 15 + overlay_state = "portal_syndicate" + radial_state = "syndi_snake" + +/** + * A special portal fish source which fish table is populated on init with the contents of all + * portal fish sources, except for FISHING_DUD, and a couple more caveats. + */ +/datum/fish_source/portal/random + fish_table = null //It's populated the first time the source is loaded on a fishing portal generator. + catalog_description = null // it'd make a bad entry in the catalog. + radial_name = "Randomizer" + overlay_state = "portal_randomizer" + var/static/list/all_portal_fish_sources_at_once + radial_state = "misaligned_question_mark" + +///Generate the fish table if we don't have one already. +/datum/fish_source/portal/random/on_fishing_spot_init(datum/component/fishing_spot/spot) + if(fish_table) + return + + ///rewards not found in other fishing portals + fish_table = list( + /obj/item/fish/holo/checkered = 1, + ) + + for(var/portal_type in GLOB.preset_fish_sources) + if(portal_type == type || !ispath(portal_type, /datum/fish_source/portal)) + continue + var/datum/fish_source/portal/preset_portal = GLOB.preset_fish_sources[portal_type] + fish_table |= preset_portal.fish_table + + ///We don't serve duds. + fish_table -= FISHING_DUD + + for(var/reward_path in fish_table) + fish_table[reward_path] = rand(1, 4) + +///Difficulty has to be calculated before the rest, because of how it influences jump chances +/datum/fish_source/portal/random/calculate_difficulty(result, obj/item/fishing_rod/rod, mob/fisherman, datum/fishing_challenge/challenge) + . = ..() + . += rand(-10, 15) + +///In the spirit of randomness, we skew a few values here and there +/datum/fish_source/portal/random/pre_challenge_started(obj/item/fishing_rod/rod, mob/user, datum/fishing_challenge/challenge) + challenge.bait_bounce_mult = clamp(challenge.bait_bounce_mult + (rand(-3, 3) * 0.1), 0.1, 1) + challenge.completion_loss = max(challenge.completion_loss + rand(-2, 2), 0) + challenge.completion_gain = max(challenge.completion_gain + rand(-1, 1), 2) + challenge.short_jump_velocity_limit += rand(-100, 100) + challenge.long_jump_velocity_limit += rand(-100, 100) + var/static/list/active_effects = bitfield_to_list(FISHING_MINIGAME_ACTIVE_EFFECTS) + for(var/effect in active_effects) + if(prob(30)) + challenge.special_effects |= effect + +///Cherry on top, fish caught from the randomizer portal also have (almost completely) random traits +/datum/fish_source/portal/random/spawn_reward(reward_path, mob/fisherman, turf/fishing_spot) + if(!ispath(reward_path, /obj/item/fish)) + return ..() + + var/static/list/weighted_traits + if(!weighted_traits) + weighted_traits = list() + for(var/trait_type as anything in GLOB.fish_traits) + var/datum/fish_trait/trait = GLOB.fish_traits[trait_type] + weighted_traits[trait.type] = round(trait.inheritability**2/100) + + var/obj/item/fish/caught_fish = new reward_path(get_turf(fisherman), FALSE) + var/list/fixed_traits = list() + for(var/trait_type in caught_fish.fish_traits) + var/datum/fish_trait/trait = GLOB.fish_traits[trait_type] + if(caught_fish.type in trait.guaranteed_inheritance_types) + fixed_traits += trait_type + var/list/new_traits = list() + for(var/iteration in rand(1, 4)) + new_traits |= pick_weight(weighted_traits) + caught_fish.inherit_traits(new_traits, fixed_traits = fixed_traits) + caught_fish.randomize_size_and_weight(deviation = 0.3) + caught_fish.progenitors = full_capitalize(caught_fish.name) + return caught_fish + /datum/fish_source/chasm catalog_description = "Chasm depths" @@ -99,7 +256,7 @@ fish_table = list( FISHING_DUD = 18, /obj/item/fish/sludgefish = 18, - /obj/item/fish/slimefish = 2, + /obj/item/fish/slimefish = 4, /obj/item/storage/wallet/money = 2, ) fish_counts = list( @@ -125,7 +282,7 @@ if(!istype(get_area(fisherman), /area/station/holodeck)) return "You need to be inside the Holodeck to catch holographic fish." -/datum/fish_source/holographic/pre_challenge_started(obj/item/fishing_rod/rod, mob/user) +/datum/fish_source/holographic/pre_challenge_started(obj/item/fishing_rod/rod, mob/user, datum/fishing_challenge/challenge) RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(check_area)) /datum/fish_source/holographic/proc/check_area(mob/user) diff --git a/code/modules/food_and_drinks/restaurant/_venue.dm b/code/modules/food_and_drinks/restaurant/_venue.dm index a73cb6b4e35..f8e171948a6 100644 --- a/code/modules/food_and_drinks/restaurant/_venue.dm +++ b/code/modules/food_and_drinks/restaurant/_venue.dm @@ -60,10 +60,10 @@ if (initial(customer_type.is_unique)) customer_types -= customer_type - var/mob/living/simple_animal/robot_customer/new_customer = new /mob/living/simple_animal/robot_customer(get_turf(restaurant_portal), customer_type, src) + var/mob/living/basic/robot_customer/new_customer = new /mob/living/basic/robot_customer(get_turf(restaurant_portal), customer_type, src) current_visitors += new_customer -/datum/venue/proc/order_food(mob/living/simple_animal/robot_customer/customer_pawn, datum/customer_data/customer_data) +/datum/venue/proc/order_food(mob/living/basic/robot_customer/customer_pawn, datum/customer_data/customer_data) var/order = pick_weight(customer_data.orderable_objects[venue_type]) var/list/order_args // Only for custom orders - arguments passed into New var/image/food_image @@ -113,7 +113,7 @@ return "broken venue pls call a coder" ///Effects for when a customer receives their order at this venue -/datum/venue/proc/on_get_order(mob/living/simple_animal/robot_customer/customer_pawn, obj/item/order_item) +/datum/venue/proc/on_get_order(mob/living/basic/robot_customer/customer_pawn, obj/item/order_item) SHOULD_CALL_PARENT(TRUE) // This is an item typepath, a reagent typepath, or a custom order datum instance. @@ -152,7 +152,7 @@ open = FALSE restaurant_portal.update_icon() STOP_PROCESSING(SSobj, src) - for(var/mob/living/simple_animal/robot_customer as anything in current_visitors) + for(var/mob/living/basic/robot_customer as anything in current_visitors) robot_customer.ai_controller.set_blackboard_key(BB_CUSTOMER_LEAVING, TRUE) //LEAVEEEEEE /obj/machinery/restaurant_portal diff --git a/code/modules/food_and_drinks/restaurant/custom_order.dm b/code/modules/food_and_drinks/restaurant/custom_order.dm index c74b4883c19..d87797b2578 100644 --- a/code/modules/food_and_drinks/restaurant/custom_order.dm +++ b/code/modules/food_and_drinks/restaurant/custom_order.dm @@ -34,7 +34,7 @@ * Return [TRANSACTION_SUCCESS] to denote the order went through successfully (Not generally necessary to include here) * Return [TRANSACTION_HANDLED] to not do any further handling of the order by the */ -/datum/custom_order/proc/handle_get_order(mob/living/simple_animal/robot_customer/customer_pawn, obj/item/order_item) +/datum/custom_order/proc/handle_get_order(mob/living/basic/robot_customer/customer_pawn, obj/item/order_item) return NONE /datum/custom_order/moth_clothing @@ -153,7 +153,7 @@ food_image.add_overlay(drink_image) return food_image -/datum/custom_order/reagent/handle_get_order(mob/living/simple_animal/robot_customer/customer_pawn, obj/item/order_item) +/datum/custom_order/reagent/handle_get_order(mob/living/basic/robot_customer/customer_pawn, obj/item/order_item) . = TRANSACTION_HANDLED for(var/datum/reagent/reagent as anything in order_item.reagents?.reagent_list) @@ -184,7 +184,7 @@ /datum/custom_order/reagent/drink container_needed = /obj/item/reagent_containers/cup/glass/drinkingglass -/datum/custom_order/reagent/drink/handle_get_order(mob/living/simple_animal/robot_customer/customer_pawn, obj/item/order_item) +/datum/custom_order/reagent/drink/handle_get_order(mob/living/basic/robot_customer/customer_pawn, obj/item/order_item) customer_pawn.visible_message( span_danger("[customer_pawn] slurps up [order_item] in one go!"), span_danger("You slurp up [order_item] in one go."), @@ -210,7 +210,7 @@ /datum/custom_order/reagent/soup/get_order_line(datum/venue/our_venue) return "I'll take a [picked_serving] of [initial(reagent_type.name)]" -/datum/custom_order/reagent/soup/handle_get_order(mob/living/simple_animal/robot_customer/customer_pawn, obj/item/order_item) +/datum/custom_order/reagent/soup/handle_get_order(mob/living/basic/robot_customer/customer_pawn, obj/item/order_item) customer_pawn.visible_message( span_danger("[customer_pawn] pours [order_item] right down [customer_pawn.p_their()] hatch!"), span_danger("You pour [order_item] down your hatch in one go."), diff --git a/code/modules/food_and_drinks/restaurant/customers/_customer.dm b/code/modules/food_and_drinks/restaurant/customers/_customer.dm index c5a7f809586..3f13b526056 100644 --- a/code/modules/food_and_drinks/restaurant/customers/_customer.dm +++ b/code/modules/food_and_drinks/restaurant/customers/_customer.dm @@ -52,10 +52,10 @@ /datum/customer_data/proc/can_use(datum/venue/venue) return TRUE -/datum/customer_data/proc/get_overlays(mob/living/simple_animal/robot_customer/customer) +/datum/customer_data/proc/get_overlays(mob/living/basic/robot_customer/customer) return -/datum/customer_data/proc/get_underlays(mob/living/simple_animal/robot_customer/customer) +/datum/customer_data/proc/get_underlays(mob/living/basic/robot_customer/customer) return /datum/customer_data/american @@ -177,7 +177,7 @@ ), ) -/datum/customer_data/french/get_overlays(mob/living/simple_animal/robot_customer/customer) +/datum/customer_data/french/get_overlays(mob/living/basic/robot_customer/customer) if(customer.ai_controller.blackboard[BB_CUSTOMER_LEAVING]) var/mutable_appearance/flag = mutable_appearance(customer.icon, "french_flag") flag.appearance_flags = RESET_COLOR @@ -224,7 +224,7 @@ ), ) -/datum/customer_data/japanese/get_overlays(mob/living/simple_animal/robot_customer/customer) +/datum/customer_data/japanese/get_overlays(mob/living/basic/robot_customer/customer) //leaving and eaten if(type == /datum/customer_data/japanese && customer.ai_controller.blackboard[BB_CUSTOMER_LEAVING] && customer.ai_controller.blackboard[BB_CUSTOMER_EATING]) var/mutable_appearance/you_won_my_heart = mutable_appearance('icons/effects/effects.dmi', "love_hearts") @@ -303,13 +303,13 @@ return FALSE return TRUE -/datum/customer_data/moth/proc/get_wings(mob/living/simple_animal/robot_customer/customer) +/datum/customer_data/moth/proc/get_wings(mob/living/basic/robot_customer/customer) var/customer_ref = WEAKREF(customer) if (!LAZYACCESS(wings_chosen, customer_ref)) LAZYSET(wings_chosen, customer_ref, pick(GLOB.sprite_accessories["wings"])) return wings_chosen[customer_ref] -/datum/customer_data/moth/get_underlays(mob/living/simple_animal/robot_customer/customer) +/datum/customer_data/moth/get_underlays(mob/living/basic/robot_customer/customer) var/list/underlays = list() var/datum/sprite_accessory/moth_wings/wings = get_wings(customer) @@ -320,7 +320,7 @@ return underlays -/datum/customer_data/moth/get_overlays(mob/living/simple_animal/robot_customer/customer) +/datum/customer_data/moth/get_overlays(mob/living/basic/robot_customer/customer) var/list/overlays = list() var/datum/sprite_accessory/moth_wings/wings = get_wings(customer) diff --git a/code/modules/food_and_drinks/restaurant/generic_venues.dm b/code/modules/food_and_drinks/restaurant/generic_venues.dm index 19f1ff61323..9e9b0a6d0e3 100644 --- a/code/modules/food_and_drinks/restaurant/generic_venues.dm +++ b/code/modules/food_and_drinks/restaurant/generic_venues.dm @@ -42,7 +42,7 @@ var/obj/item/object_to_order = order return "I'll take \a [initial(object_to_order.name)]" -/datum/venue/restaurant/on_get_order(mob/living/simple_animal/robot_customer/customer_pawn, obj/item/order_item) +/datum/venue/restaurant/on_get_order(mob/living/basic/robot_customer/customer_pawn, obj/item/order_item) var/transaction_result = ..() if((transaction_result & TRANSACTION_HANDLED) || !(transaction_result & TRANSACTION_SUCCESS)) return diff --git a/code/modules/holodeck/holo_effect.dm b/code/modules/holodeck/holo_effect.dm index 02502c1e6fb..a8d51c87728 100644 --- a/code/modules/holodeck/holo_effect.dm +++ b/code/modules/holodeck/holo_effect.dm @@ -61,6 +61,7 @@ mobtype = pick(mobtype) our_mob = new mobtype(loc) our_mob.flags_1 |= HOLOGRAM_1 + ADD_TRAIT(our_mob, TRAIT_PERMANENTLY_MORTAL, INNATE_TRAIT) // these vars are not really standardized but all would theoretically create stuff on death for(var/v in list("butcher_results","corpse","weapon1","weapon2","blood_volume") & our_mob.vars) diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index 8e5dda5a7fa..c1fd02bf9f0 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -37,7 +37,7 @@ plant_icon_offset = 2 species = "replicapod" plantname = "Replica Pod" - product = /mob/living/carbon/human //verrry special -- Urist + product = null // the human mob is spawned in harvest() lifespan = 50 endurance = 8 maturation = 10 diff --git a/code/modules/hydroponics/seed_extractor.dm b/code/modules/hydroponics/seed_extractor.dm index a3804c9262f..04b0edf44bb 100644 --- a/code/modules/hydroponics/seed_extractor.dm +++ b/code/modules/hydroponics/seed_extractor.dm @@ -13,46 +13,33 @@ * * user - checks if we can remove the object from the inventory * * */ -/proc/seedify(obj/item/O, t_max, obj/machinery/seed_extractor/extractor, mob/living/user) - var/t_amount = 0 +/proc/seedify(obj/item/object, t_max, obj/machinery/seed_extractor/extractor, mob/living/user) + //try to get the seed from this item + var/obj/item/seeds/seed = object.get_plant_seed() + if(isnull(seed)) + return null + + //generate a random multiplier if value is not specified var/list/seeds = list() if(t_max == -1) if(extractor) t_max = rand(1,4) * extractor.seed_multiplier else t_max = rand(1,4) - - var/seedloc = O.loc + //drop location for the newly generated seeds + var/seedloc = object.loc if(extractor) seedloc = extractor.loc - if(istype(O, /obj/item/food/grown/)) - var/obj/item/food/grown/F = O - if(F.seed) - if(user && !user.temporarilyRemoveItemFromInventory(O)) //couldn't drop the item - return - while(t_amount < t_max) - var/obj/item/seeds/t_prod = F.seed.Copy() - seeds.Add(t_prod) - t_prod.forceMove(seedloc) - t_amount++ - qdel(O) - return seeds - - else if(istype(O, /obj/item/grown)) - var/obj/item/grown/F = O - if(F.seed) - if(user && !user.temporarilyRemoveItemFromInventory(O)) - return - while(t_amount < t_max) - var/obj/item/seeds/t_prod = F.seed.Copy() - t_prod.forceMove(seedloc) - t_amount++ - qdel(O) - return 1 - - return 0 - + //multiply the seeds and delete the item + if(user && !user.temporarilyRemoveItemFromInventory(object)) //couldn't drop the item + return null + for(var/_ in 0 to t_max) + var/obj/item/seeds/t_prod = seed.Copy() + seeds.Add(t_prod) + t_prod.forceMove(seedloc) + qdel(object) + return seeds /obj/machinery/seed_extractor name = "seed extractor" @@ -80,6 +67,7 @@ if(held_item?.get_plant_seed()) context[SCREENTIP_CONTEXT_LMB] = "Make seeds" + context[SCREENTIP_CONTEXT_RMB] = "Make & Store seeds" return CONTEXTUAL_SCREENTIP_SET if(istype(held_item, /obj/item/storage/bag/plants) && (locate(/obj/item/seeds) in held_item.contents)) @@ -135,7 +123,17 @@ return TRUE - if(seedify(attacking_item, -1, src, user)) + var/list/generated_seeds = seedify(attacking_item, -1, src, user) + if(!isnull(generated_seeds)) + if(LAZYACCESS(params2list(params), RIGHT_CLICK)) + //find all seeds lying on the turf and add them to the machine + for(var/obj/item/seeds/seed as anything in generated_seeds) + //machine is full + if(contents.len >= max_seeds) + to_chat(user, span_warning("[src] is full.")) + break + //add seed to machine. second argument is null which means just force move into the machine + add_seed(seed) to_chat(user, span_notice("You extract some seeds.")) return TRUE @@ -176,23 +174,16 @@ * needed to go to the ui handler * * to_add - what seed are we adding? - * taking_from - where are we taking the seed from? A mob, a bag, etc? - * user - who is inserting the seed? + * taking_from - where are we taking the seed from? A mob, a bag, etc? If null its means its just laying on the turf so force move it in **/ /obj/machinery/seed_extractor/proc/add_seed(obj/item/seeds/to_add, atom/taking_from) - if(ismob(taking_from)) - var/mob/mob_loc = taking_from - if(!mob_loc.transferItemToLoc(to_add, src)) - return FALSE - - else if(!taking_from.atom_storage?.attempt_remove(to_add, src, silent = TRUE)) - return FALSE - var/seed_id = generate_seed_hash(to_add) + var/list/seed_data + var/has_seed_data // so we remember to add a seed obj weakref to piles[seed_id] at the end of the proc. That way if some reason we runtime in this proc it won't incorrectly add data to the list if(piles[seed_id]) - piles[seed_id]["refs"] += WEAKREF(to_add) + has_seed_data = TRUE else - var/list/seed_data = list() + seed_data = list() seed_data["icon"] = sanitize_css_class_name("[initial(to_add.icon)][initial(to_add.icon_state)]") seed_data["name"] = capitalize(replacetext(to_add.name,"pack of ", "")); seed_data["lifespan"] = to_add.lifespan @@ -216,8 +207,8 @@ seed_data["mutatelist"] = list() for(var/obj/item/seeds/mutant as anything in to_add.mutatelist) seed_data["mutatelist"] += initial(mutant.plantname) - var/obj/item/food/grown/product = new to_add.product - if(product) + if(to_add.product) + var/obj/item/food/grown/product = new to_add.product var/datum/reagent/product_distill_reagent = product.distill_reagent seed_data["distill_reagent"] = initial(product_distill_reagent.name) var/datum/reagent/product_juice_typepath = product.juice_typepath @@ -225,8 +216,25 @@ seed_data["grind_results"] = list() for(var/datum/reagent/reagent as anything in product.grind_results) seed_data["grind_results"] += initial(reagent.name) - qdel(product) + qdel(product) + + if(!isnull(taking_from)) + if(ismob(taking_from)) + var/mob/mob_loc = taking_from + if(!mob_loc.transferItemToLoc(to_add, src)) + return FALSE + + else if(!taking_from.atom_storage?.attempt_remove(to_add, src, silent = TRUE)) + return FALSE + else + to_add.forceMove(src) + + // do this at the end, in case any of the previous steps failed + if(has_seed_data) + piles[seed_id]["refs"] += WEAKREF(to_add) + else piles[seed_id] = seed_data + return TRUE /obj/machinery/seed_extractor/ui_state(mob/user) diff --git a/code/modules/industrial_lift/tram/tram_windows.dm b/code/modules/industrial_lift/tram/tram_windows.dm index 1a98a56a0ba..55ec5aa283f 100644 --- a/code/modules/industrial_lift/tram/tram_windows.dm +++ b/code/modules/industrial_lift/tram/tram_windows.dm @@ -36,8 +36,9 @@ if(fulltile) return ..() smoothing_junction = new_junction - var/smooth_left = (smoothing_junction & turn(dir, 90)) - var/smooth_right = (smoothing_junction & turn(dir, -90)) + var/go_off = reverse_ndir(smoothing_junction) + var/smooth_left = (go_off & turn(dir, 90)) + var/smooth_right = (go_off & turn(dir, -90)) if(smooth_left && smooth_right) icon_state = "tram_mid" else if (smooth_left) diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index ce39b5a7405..0d8e57f13eb 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -178,6 +178,8 @@ for(var/i in roundstart_experience) spawned_human.mind.adjust_experience(i, roundstart_experience[i], TRUE) +/// Announce that this job as joined the round to all crew members. +/// Note the joining mob has no client at this point. /datum/job/proc/announce_job(mob/living/joining_mob, job_title) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - Original: /datum/job/proc/announce_job(mob/living/joining_mob) if(head_announce) announce_head(joining_mob, head_announce, job_title) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - Original: announce_head(joining_mob, head_announce) @@ -191,13 +193,27 @@ /mob/living/proc/on_job_equipping(datum/job/equipping) return -/mob/living/carbon/human/on_job_equipping(datum/job/equipping, datum/preferences/used_pref) //SKYRAT EDIT CHANGE +#define VERY_LATE_ARRIVAL_TOAST_PROB 20 + +/mob/living/carbon/human/on_job_equipping(datum/job/equipping, datum/preferences/used_pref, client/player_client) //SKYRAT EDIT CHANGE - ORIGINAL: /mob/living/carbon/human/on_job_equipping(datum/job/equipping) var/datum/bank_account/bank_account = new(real_name, equipping, dna.species.payday_modifier) bank_account.payday(STARTING_PAYCHECKS, TRUE) account_id = bank_account.account_id bank_account.replaceable = FALSE - dress_up_as_job(equipping, FALSE, used_pref) //SKYRAT EDIT CHANGE + add_mob_memory(/datum/memory/key/account, remembered_id = account_id) + + dress_up_as_job(equipping, FALSE, used_pref) //SKYRAT EDIT CHANGE - ORIGINAL: dress_up_as_job(equipping) + + if(EMERGENCY_PAST_POINT_OF_NO_RETURN && prob(VERY_LATE_ARRIVAL_TOAST_PROB)) + //equipping.equip_to_slot_or_del(new /obj/item/food/griddle_toast(equipping), ITEM_SLOT_MASK) // SKYRAT EDIT REMOVAL - See below + // SKYRAT EDIT ADDITION - Lizards + if(islizard(equipping)) + equip_to_slot_or_del(new /obj/item/food/breadslice/root(equipping), ITEM_SLOT_MASK) + else + equip_to_slot_or_del(new /obj/item/food/griddle_toast(equipping), ITEM_SLOT_MASK) + // SKYRAT EDIT ADDITION END - Lizards +#undef VERY_LATE_ARRIVAL_TOAST_PROB /mob/living/proc/dress_up_as_job(datum/job/equipping, visual_only = FALSE) return @@ -267,8 +283,43 @@ return TRUE -/datum/job/proc/radio_help_message(mob/M) - to_chat(M, "Prefix your message with :h to speak on your department's radio. To see other prefixes, look closely at your headset.") +/// Gets the message that shows up when spawning as this job +/datum/job/proc/get_spawn_message(alt_title) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - ORIGINAL: /datum/job/proc/get_spawn_message() + SHOULD_NOT_OVERRIDE(TRUE) + return examine_block(span_infoplain(jointext(get_spawn_message_information(alt_title), "\n• "))) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLED - ORIGINAL: return examine_block(span_infoplain(jointext(get_spawn_message_information(), "\n• "))) + +/// Returns a list of strings that correspond to chat messages sent to this mob when they join the round. +/datum/job/proc/get_spawn_message_information(alt_title = title) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - ORIGINAL: /datum/job/proc/get_spawn_message_information() + SHOULD_CALL_PARENT(TRUE) + var/list/info = list() + info += "You are the [alt_title].\n" // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - ORIGINAL: info += "You are the [title].\n" + var/related_policy = get_policy(title) + var/radio_info = get_radio_information() + if(related_policy) + info += related_policy + if(supervisors) + info += "As the [alt_title == title ? alt_title : "[alt_title] ([title])"] you answer directly to [supervisors]. Special circumstances may change this." // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - ORIGINAL: info += "As the [title] you answer directly to [supervisors]. Special circumstances may change this." + if(radio_info) + info += radio_info + if(req_admin_notify) + info += "You are playing a job that is important for Game Progression. \ + If you have to disconnect, please notify the admins via adminhelp." + if(CONFIG_GET(number/minimal_access_threshold)) + info += span_boldnotice("As this station was initially staffed with a \ + [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] \ + have been added to your ID card.") + //SKYRAT EDIT ADDITION START - ALTERNATIVE_JOB_TITLES + if(alt_title != title) + info += span_warning("Remember that alternate titles are purely for flavor and roleplay.") + info += span_doyourjobidiot("Do not use your \"[alt_title]\" alt title as an excuse to forego your duties as a [title].") + //SKYRAT EDIT END + + return info + +/// Returns information pertaining to this job's radio. +/datum/job/proc/get_radio_information() + if(job_flags & JOB_CREW_MEMBER) + return "Prefix your message with :h to speak on your department's radio. To see other prefixes, look closely at your headset." /datum/outfit/job name = "Standard Gear" diff --git a/code/modules/jobs/job_types/ai.dm b/code/modules/jobs/job_types/ai.dm index f3f8b23837b..0b38d6e081d 100644 --- a/code/modules/jobs/job_types/ai.dm +++ b/code/modules/jobs/job_types/ai.dm @@ -117,5 +117,5 @@ /datum/job/ai/config_check() return CONFIG_GET(flag/allow_ai) -/datum/job/ai/radio_help_message(mob/M) - to_chat(M, "Prefix your message with :b to speak with cyborgs and other AIs.") +/datum/job/ai/get_radio_information() + return "Prefix your message with :b to speak with cyborgs and other AIs." diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm index e788202b445..d8ae6d335b3 100755 --- a/code/modules/jobs/job_types/captain.dm +++ b/code/modules/jobs/job_types/captain.dm @@ -51,6 +51,9 @@ /datum/job/captain/get_captaincy_announcement(mob/living/captain) return "Captain [captain.real_name] on deck!" +/datum/job/captain/get_radio_information() + . = ..() + . += "\nYou have access to all radio channels, but they are not automatically tuned. Check your radio for more information." /datum/outfit/job/captain name = "Captain" diff --git a/code/modules/jobs/job_types/chaplain/chaplain.dm b/code/modules/jobs/job_types/chaplain/chaplain.dm index be4516a0db7..58821ec5358 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain.dm @@ -25,7 +25,6 @@ mail_goodies = list( /obj/item/reagent_containers/cup/glass/bottle/holywater = 30, - /obj/item/toy/plush/awakenedplushie = 10, /obj/item/grenade/chem_grenade/holy = 5, /obj/item/toy/plush/narplush = 2, /obj/item/toy/plush/ratplush = 1 diff --git a/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm b/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm index f2ab21c9c35..637177adffb 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm @@ -50,6 +50,14 @@ body_parts_covered = CHEST|GROIN|LEGS|ARMS|HANDS flags_inv = HIDEJUMPSUIT +/obj/item/clothing/suit/chaplainsuit/habit + name = "religious tunic" + desc = "No nunsene clothing." + icon_state = "habit" + alternate_worn_layer = GLOVES_LAYER // since the sleeves cover a part of the hands, this way it looks better while retaining glove overlay correctly. + body_parts_covered = CHEST|GROIN|LEGS|ARMS|HANDS + flags_inv = HIDEJUMPSUIT + /obj/item/clothing/suit/chaplainsuit/bishoprobe name = "bishop's robes" desc = "Glad to see the tithes you collected were well spent." diff --git a/code/modules/jobs/job_types/cyborg.dm b/code/modules/jobs/job_types/cyborg.dm index ae6b7c142cc..92094073033 100644 --- a/code/modules/jobs/job_types/cyborg.dm +++ b/code/modules/jobs/job_types/cyborg.dm @@ -4,7 +4,7 @@ auto_deadmin_role_flags = DEADMIN_POSITION_SILICON faction = FACTION_STATION total_positions = 3 // SKYRAT EDIT: Original value (0) - spawn_positions = 3 // SKYRAT EDIT: Original value (1) + spawn_positions = 3 supervisors = "your laws and the AI" //Nodrak spawn_type = /mob/living/silicon/robot minimal_player_age = 21 @@ -58,5 +58,5 @@ if(!robot_spawn.connected_ai) // Only log if there's no Master AI robot_spawn.log_current_laws() -/datum/job/cyborg/radio_help_message(mob/M) - to_chat(M, "Prefix your message with :b to speak with other cyborgs and AI.") +/datum/job/cyborg/get_radio_information() + return "Prefix your message with :b to speak with other cyborgs and AI." diff --git a/code/modules/jobs/job_types/paramedic.dm b/code/modules/jobs/job_types/paramedic.dm index 3dac90b4baf..2fd4f3a93a6 100644 --- a/code/modules/jobs/job_types/paramedic.dm +++ b/code/modules/jobs/job_types/paramedic.dm @@ -32,7 +32,8 @@ /obj/item/reagent_containers/hypospray/medipen/salacid = 10, /obj/item/reagent_containers/hypospray/medipen/salbutamol = 10, /obj/item/reagent_containers/hypospray/medipen/penacid = 10, - /obj/item/reagent_containers/hypospray/medipen/survival/luxury = 5 + /obj/item/reagent_containers/hypospray/medipen/survival/luxury = 5, + /obj/item/storage/box/bandages = 5, ) rpg_title = "Corpse Runner" job_flags = STATION_JOB_FLAGS @@ -56,6 +57,7 @@ gloves = /obj/item/clothing/gloves/latex/nitrile shoes = /obj/item/clothing/shoes/sneakers/blue l_pocket = /obj/item/modular_computer/pda/medical/paramedic + r_pocket = /obj/item/storage/box/bandages backpack = /obj/item/storage/backpack/medic satchel = /obj/item/storage/backpack/satchel/med diff --git a/code/modules/library/skill_learning/skillchip.dm b/code/modules/library/skill_learning/skillchip.dm index f9fd629c1ed..762e8e0162c 100644 --- a/code/modules/library/skill_learning/skillchip.dm +++ b/code/modules/library/skill_learning/skillchip.dm @@ -489,4 +489,13 @@ activate_message = span_notice("You recall learning from your grandmother how they baked their cookies with love.") deactivate_message = span_notice("You forget all memories imparted upon you by your grandmother. Were they even your real grandma?") +/obj/item/skillchip/master_angler + name = "Mast-Angl-Er skillchip" + auto_traits = list(TRAIT_REVEAL_FISH) + skill_name = "Fisherman's Discernment" + skill_description = "While fishing, it'll make a smidge easier to guess whatever you're trying to catch." + skill_icon = "fish" + activate_message = span_notice("You feel the knowledge and passion of several sunbaked, seasoned fishermen burn within you.") + deactivate_message = span_notice("You no longer feel like casting a fishing rod by the sunny riverside.") + #undef SKILLCHIP_CATEGORY_GENERAL diff --git a/code/modules/mafia/controller.dm b/code/modules/mafia/controller.dm index 1916a65f7b1..f8d9db13106 100644 --- a/code/modules/mafia/controller.dm +++ b/code/modules/mafia/controller.dm @@ -578,7 +578,7 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment()) for(var/datum/mafia_role/role as anything in all_roles) var/mob/living/carbon/human/H = new(get_turf(role.assigned_landmark)) - H.add_traits(list(TRAIT_NOFIRE, TRAIT_NOBREATH, TRAIT_CANNOT_CRYSTALIZE), MAFIA_TRAIT) + H.add_traits(list(TRAIT_NOFIRE, TRAIT_NOBREATH, TRAIT_CANNOT_CRYSTALIZE, TRAIT_PERMANENTLY_MORTAL), MAFIA_TRAIT) H.equipOutfit(outfit_to_distribute) H.status_flags |= GODMODE RegisterSignal(H, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(display_votes)) diff --git a/code/modules/mapping/access_helpers.dm b/code/modules/mapping/access_helpers.dm index 16da29837fb..c208e2eea9e 100644 --- a/code/modules/mapping/access_helpers.dm +++ b/code/modules/mapping/access_helpers.dm @@ -386,6 +386,11 @@ access_list += list(ACCESS_CARGO, ACCESS_MAINT_TUNNELS) return access_list +/obj/effect/mapping_helpers/airlock/access/any/supply/bit_den/get_access() + var/list/access_list = ..() + access_list += ACCESS_BIT_DEN + return access_list + // -------------------- Syndicate access helpers /obj/effect/mapping_helpers/airlock/access/any/syndicate icon_state = "access_helper_syn" diff --git a/code/modules/meteors/meteor_waves.dm b/code/modules/meteors/meteor_waves.dm index 4235c186a94..7d832d53713 100644 --- a/code/modules/meteors/meteor_waves.dm +++ b/code/modules/meteors/meteor_waves.dm @@ -26,4 +26,4 @@ GLOBAL_LIST_INIT(meteors_stray, list(/obj/effect/meteor/medium=15, /obj/effect/m GLOBAL_LIST_INIT(meteors_sandstorm, list(/obj/effect/meteor/sand=45, /obj/effect/meteor/dust=5)) //for sandstorm event -GLOBAL_LIST_INIT(meteorsSPOOKY, list(/obj/effect/meteor/pumpkin)) +GLOBAL_LIST_INIT(meteorsSPOOKY, list(/obj/effect/meteor/pumpkin=1)) diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm index a656aa467d6..c9fdb9747e5 100644 --- a/code/modules/mining/abandoned_crates.dm +++ b/code/modules/mining/abandoned_crates.dm @@ -188,7 +188,9 @@ new /obj/item/clothing/suit/costume/wellworn_shirt/graphic/ian(src) new /obj/item/clothing/suit/hooded/ian_costume(src) if(67 to 68) - new /obj/item/toy/plush/awakenedplushie(src) + var/obj/item/gibtonite/free_bomb = new /obj/item/gibtonite(src) + free_bomb.quality = rand(1, 3) + free_bomb.GibtoniteReaction(null, "A secure loot closet has spawned a live") if(69 to 70) new /obj/item/stack/ore/bluespace_crystal(src, 5) if(71 to 72) diff --git a/code/modules/mining/equipment/monster_organs/regenerative_core.dm b/code/modules/mining/equipment/monster_organs/regenerative_core.dm index cb224438c00..98758d5a369 100644 --- a/code/modules/mining/equipment/monster_organs/regenerative_core.dm +++ b/code/modules/mining/equipment/monster_organs/regenerative_core.dm @@ -36,7 +36,7 @@ /// Log applications and apply moodlet. /obj/item/organ/internal/monster_core/regenerative_core/apply_to(mob/living/target, mob/user) - target.add_mood_event("regenerative core", /datum/mood_event/healsbadman) + target.add_mood_event(MOOD_CATEGORY_LEGION_CORE, /datum/mood_event/healsbadman) if (target != user) target.visible_message(span_notice("[user] forces [target] to apply [src]... Black tendrils entangle and reinforce [target.p_them()]!")) SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "other")) diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm index e7199e59938..20a436dc5c6 100644 --- a/code/modules/mining/fulton.dm +++ b/code/modules/mining/fulton.dm @@ -144,7 +144,7 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) icon_state = "folded_extraction" /obj/item/fulton_core/attack_self(mob/user) - if(do_after(user,15,target = user) && !QDELETED(src)) + if(do_after(user, 1.5 SECONDS, target = user) && !QDELETED(src)) new /obj/structure/extraction_point(get_turf(user)) playsound(src, 'sound/items/deconstruct.ogg', vol = 50, vary = TRUE, extrarange = MEDIUM_RANGE_SOUND_EXTRARANGE) qdel(src) @@ -156,6 +156,7 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) icon_state = "extraction_point" anchored = TRUE density = FALSE + obj_flags = CAN_BE_HIT | UNIQUE_RENAME var/beacon_network = "station" /obj/structure/extraction_point/Initialize(mapload) @@ -168,6 +169,15 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) GLOB.total_extraction_beacons -= src return ..() +/obj/structure/extraction_point/attack_hand(mob/living/user, list/modifiers) + . = ..() + balloon_alert_to_viewers("undeploying...") + if(!do_after(user, 1.5 SECONDS, src)) + return + new /obj/item/fulton_core(drop_location()) + playsound(src, 'sound/items/deconstruct.ogg', vol = 50, vary = TRUE, extrarange = MEDIUM_RANGE_SOUND_EXTRARANGE) + qdel(src) + /obj/structure/extraction_point/update_overlays() . = ..() . += emissive_appearance(icon, "[icon_state]_light", src, alpha = src.alpha) diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index e9c652fd7bd..b01b537ec80 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -267,7 +267,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ return if(I.tool_behaviour == TOOL_MINING || istype(I, /obj/item/resonator) || I.force >= 10) - GibtoniteReaction(user) + GibtoniteReaction(user, "A resonator has primed for detonation a") return if(istype(I, /obj/item/mining_scanner) || istype(I, /obj/item/t_scanner/adv_mining_scanner) || I.tool_behaviour == TOOL_MULTITOOL) @@ -294,14 +294,14 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ return ..() /obj/item/gibtonite/bullet_act(obj/projectile/P) - GibtoniteReaction(P.firer) + GibtoniteReaction(P.firer, "A projectile has primed for detonation a") return ..() /obj/item/gibtonite/ex_act() - GibtoniteReaction(null, 1) + GibtoniteReaction(null, "An explosion has primed for detonation a") return TRUE -/obj/item/gibtonite/proc/GibtoniteReaction(mob/user, triggered_by = 0) +/obj/item/gibtonite/proc/GibtoniteReaction(mob/user, triggered_by) if(primed) return primed = TRUE @@ -311,18 +311,16 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ if(!is_mining_level(z))//Only annoy the admins ingame if we're triggered off the mining zlevel notify_admins = TRUE - if(triggered_by == 1) - log_bomber(null, "An explosion has primed a", src, "for detonation", notify_admins) - else if(triggered_by == 2) - var/turf/bombturf = get_turf(src) - if(notify_admins) - message_admins("A signal has triggered a [name] to detonate at [ADMIN_VERBOSEJMP(bombturf)]. Igniter attacher: [ADMIN_LOOKUPFLW(attacher)]") - var/bomb_message = "A signal has primed a [name] for detonation at [AREACOORD(bombturf)]. Igniter attacher: [key_name(attacher)]." - log_game(bomb_message) - GLOB.bombers += bomb_message - else + if(user) user.visible_message(span_warning("[user] strikes \the [src], causing a chain reaction!"), span_danger("You strike \the [src], causing a chain reaction.")) - log_bomber(user, "has primed a", src, "for detonation", notify_admins) + + var/attacher_text = attacher ? "Igniter attacher: [ADMIN_LOOKUPFLW(attacher)]" : null + + if(triggered_by) + log_bomber(user, triggered_by, src, attacher_text, notify_admins) + else + log_bomber(user, "Something has primed a", src, "for detonation.[attacher_text ? " " : ""][attacher_text]", notify_admins) + det_timer = addtimer(CALLBACK(src, PROC_REF(detonate), notify_admins), det_time, TIMER_STOPPABLE) /obj/item/gibtonite/proc/detonate(notify_admins) diff --git a/code/modules/mob/living/basic/basic_defense.dm b/code/modules/mob/living/basic/basic_defense.dm index cc128a9f5e9..8afb40f2912 100644 --- a/code/modules/mob/living/basic/basic_defense.dm +++ b/code/modules/mob/living/basic/basic_defense.dm @@ -165,6 +165,9 @@ return TRUE /mob/living/basic/blob_act(obj/structure/blob/attacking_blob) + . = ..() + if (!.) + return apply_damage(20, damagetype = BRUTE) /mob/living/basic/do_attack_animation(atom/attacked_atom, visual_effect_icon, used_item, no_effect) diff --git a/code/modules/mob/living/basic/blob_minions/blob_ai.dm b/code/modules/mob/living/basic/blob_minions/blob_ai.dm new file mode 100644 index 00000000000..6168b7ca83b --- /dev/null +++ b/code/modules/mob/living/basic/blob_minions/blob_ai.dm @@ -0,0 +1,51 @@ +/** + * Extremely simple AI, this isn't a very smart boy + * Only notable quirk is that it uses JPS movement, simple avoidance would fail to realise it can path through blobs + */ +/datum/ai_controller/basic_controller/blobbernaut + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead, + ) + + ai_movement = /datum/ai_movement/jps + idle_behavior = /datum/idle_behavior/idle_random_walk + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) + +/** + * Move to a point designated by the overmind, otherwise just slap people nearby + */ +/datum/ai_controller/basic_controller/blob_zombie + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead, + ) + + ai_movement = /datum/ai_movement/jps + idle_behavior = /datum/idle_behavior/idle_random_walk + planning_subtrees = list( + /datum/ai_planning_subtree/travel_to_point/and_clear_target, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) + +/** + * As blob zombie but will prioritise attacking corpses to zombify them + */ +/datum/ai_controller/basic_controller/blob_spore + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead, + ) + + ai_movement = /datum/ai_movement/jps + idle_behavior = /datum/idle_behavior/idle_random_walk + planning_subtrees = list( + /datum/ai_planning_subtree/find_and_hunt_target/corpses, + /datum/ai_planning_subtree/travel_to_point/and_clear_target, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) diff --git a/code/modules/mob/living/basic/blob_minions/blob_mob.dm b/code/modules/mob/living/basic/blob_minions/blob_mob.dm new file mode 100644 index 00000000000..35e41f09058 --- /dev/null +++ b/code/modules/mob/living/basic/blob_minions/blob_mob.dm @@ -0,0 +1,37 @@ +/// Root of shared behaviour for mobs spawned by blobs, is abstract and should not be spawned +/mob/living/basic/blob_minion + name = "Blob Error" + desc = "A nonfunctional fungal creature created by bad code or celestial mistake. Point and laugh." + icon = 'icons/mob/nonhuman-player/blob.dmi' + icon_state = "blob_head" + unique_name = TRUE + pass_flags = PASSBLOB + faction = list(ROLE_BLOB) + combat_mode = TRUE + bubble_icon = "blob" + speak_emote = null + habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + minimum_survivable_temperature = 0 + maximum_survivable_temperature = INFINITY + lighting_cutoff_red = 20 + lighting_cutoff_green = 40 + lighting_cutoff_blue = 30 + initial_language_holder = /datum/language_holder/empty + +/mob/living/basic/blob_minion/Initialize(mapload) + . = ..() + add_traits(list(TRAIT_BLOB_ALLY, TRAIT_MUTE), INNATE_TRAIT) + AddComponent(/datum/component/blob_minion, on_strain_changed = CALLBACK(src, PROC_REF(on_strain_updated))) + +/// Called when our blob overmind changes their variant, update some of our mob properties +/mob/living/basic/blob_minion/proc/on_strain_updated(mob/camera/blob/overmind, datum/blobstrain/new_strain) + return + +/// Associates this mob with a specific blob factory node +/mob/living/basic/blob_minion/proc/link_to_factory(obj/structure/blob/special/factory/factory) + RegisterSignal(factory, COMSIG_QDELETING, PROC_REF(on_factory_destroyed)) + +/// Called when our factory is destroyed +/mob/living/basic/blob_minion/proc/on_factory_destroyed() + SIGNAL_HANDLER + to_chat(src, span_userdanger("Your factory was destroyed! You feel yourself dying!")) diff --git a/code/modules/mob/living/basic/blob_minions/blob_spore.dm b/code/modules/mob/living/basic/blob_minions/blob_spore.dm new file mode 100644 index 00000000000..e8c3acc8b97 --- /dev/null +++ b/code/modules/mob/living/basic/blob_minions/blob_spore.dm @@ -0,0 +1,123 @@ +/** + * A floating fungus which turns people into zombies and explodes into reagent clouds upon death. + */ +/mob/living/basic/blob_minion/spore + name = "blob spore" + desc = "A floating, fragile spore." + icon = 'icons/mob/nonhuman-player/blob.dmi' + icon_state = "blobpod" + icon_living = "blobpod" + health_doll_icon = "blobpod" + health = BLOBMOB_SPORE_HEALTH + maxHealth = BLOBMOB_SPORE_HEALTH + verb_say = "psychically pulses" + verb_ask = "psychically probes" + verb_exclaim = "psychically yells" + verb_yell = "psychically screams" + melee_damage_lower = BLOBMOB_SPORE_DMG_LOWER + melee_damage_upper = BLOBMOB_SPORE_DMG_UPPER + obj_damage = 0 + attack_verb_continuous = "batters" + attack_verb_simple = "batter" + attack_sound = 'sound/weapons/genhit1.ogg' + death_message = "explodes into a cloud of gas!" + gold_core_spawnable = HOSTILE_SPAWN + basic_mob_flags = DEL_ON_DEATH + ai_controller = /datum/ai_controller/basic_controller/blob_spore + /// Size of cloud produced from a dying spore + var/death_cloud_size = 1 + /// Type of mob to create + var/mob/living/zombie_type = /mob/living/basic/blob_minion/zombie + +/mob/living/basic/blob_minion/spore/Initialize(mapload) + . = ..() + AddElement(/datum/element/simple_flying) + AddElement(/datum/element/swabable, CELL_LINE_TABLE_BLOBSPORE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) + +/mob/living/basic/blob_minion/spore/death(gibbed) + . = ..() + death_burst() + +/mob/living/basic/blob_minion/spore/on_factory_destroyed() + death() + +/// Create an explosion of spores on death +/mob/living/basic/blob_minion/spore/proc/death_burst() + do_chem_smoke(range = death_cloud_size, holder = src, location = get_turf(src), reagent_type = /datum/reagent/toxin/spore) + + +/mob/living/basic/blob_minion/spore/melee_attack(mob/living/carbon/human/target, list/modifiers, ignore_cooldown) + . = ..() + if (!ishuman(target) || target.stat != DEAD) + return + zombify(target) + +/// Become a zombie +/mob/living/basic/blob_minion/spore/proc/zombify(mob/living/carbon/human/target) + visible_message(span_warning("The corpse of [target.name] suddenly rises!")) + var/mob/living/basic/blob_minion/zombie/blombie = change_mob_type(zombie_type, loc, new_name = initial(zombie_type.name)) + blombie.set_name() + if (istype(blombie)) // In case of badmin + blombie.consume_corpse(target) + SEND_SIGNAL(src, COMSIG_BLOB_ZOMBIFIED, blombie) + qdel(src) + +/// Variant of the blob spore which is actually spawned by blob factories +/mob/living/basic/blob_minion/spore/minion + gold_core_spawnable = NO_SPAWN + zombie_type = /mob/living/basic/blob_minion/zombie/controlled + /// We die if we leave the same turf as this z level + var/turf/z_turf + +/mob/living/basic/blob_minion/spore/minion/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(on_z_changed)) + +/// When we z-move check that we're on the same z level as our factory was +/mob/living/basic/blob_minion/spore/minion/proc/on_z_changed() + SIGNAL_HANDLER + if (isnull(z_turf)) + return + if (!is_valid_z_level(get_turf(src), z_turf)) + death() + +/// Mark the turf we need to track from our factory +/mob/living/basic/blob_minion/spore/minion/link_to_factory(obj/structure/blob/special/factory/factory) + . = ..() + z_turf = get_turf(factory) + +/// If the blob changes to distributed neurons then you can control the spores +/mob/living/basic/blob_minion/spore/minion/on_strain_updated(mob/camera/blob/overmind, datum/blobstrain/new_strain) + if (isnull(overmind)) + REMOVE_TRAIT(src, TRAIT_PERMANENTLY_MORTAL, INNATE_TRAIT) + else + ADD_TRAIT(src, TRAIT_PERMANENTLY_MORTAL, INNATE_TRAIT) + + if (istype(new_strain, /datum/blobstrain/reagent/distributed_neurons)) + AddComponent(\ + /datum/component/ghost_direct_control,\ + ban_type = ROLE_BLOB_INFECTION,\ + poll_candidates = TRUE,\ + poll_ignore_key = POLL_IGNORE_BLOB,\ + ) + else + qdel(GetComponent(/datum/component/ghost_direct_control)) + +/mob/living/basic/blob_minion/spore/minion/death_burst() + return // This behaviour is superceded by the overmind's intervention + + +/// Weakened spore spawned by distributed neurons, can't zombify people and makes a teeny explosion +/mob/living/basic/blob_minion/spore/minion/weak + name = "fragile blob spore" + health = 15 + maxHealth = 15 + melee_damage_lower = 1 + melee_damage_upper = 2 + death_cloud_size = 0 + +/mob/living/basic/blob_minion/spore/minion/weak/zombify() + return + +/mob/living/basic/blob_minion/spore/minion/weak/on_strain_updated() + return diff --git a/code/modules/mob/living/basic/blob_minions/blob_zombie.dm b/code/modules/mob/living/basic/blob_minions/blob_zombie.dm new file mode 100644 index 00000000000..c9bf3b7346a --- /dev/null +++ b/code/modules/mob/living/basic/blob_minions/blob_zombie.dm @@ -0,0 +1,99 @@ +/// A shambling mob made out of a crew member +/mob/living/basic/blob_minion/zombie + name = "blob zombie" + desc = "A shambling corpse animated by the blob." + icon_state = "zombie" + icon_living = "zombie" + health_doll_icon = "blobpod" + mob_biotypes = MOB_ORGANIC | MOB_HUMANOID + health = 70 + maxHealth = 70 + verb_say = "gurgles" + verb_ask = "demands" + verb_exclaim = "roars" + verb_yell = "bellows" + melee_damage_lower = 10 + melee_damage_upper = 15 + melee_attack_cooldown = CLICK_CD_MELEE + obj_damage = 20 + attack_verb_continuous = "punches" + attack_verb_simple = "punch" + attack_sound = 'sound/weapons/genhit1.ogg' + death_message = "collapses to the ground!" + gold_core_spawnable = NO_SPAWN + basic_mob_flags = DEL_ON_DEATH + ai_controller = /datum/ai_controller/basic_controller/blob_zombie + /// The dead body we have inside + var/mob/living/carbon/human/corpse + +/mob/living/basic/blob_minion/zombie/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_PERMANENTLY_MORTAL, INNATE_TRAIT) // This mob doesn't function visually without a corpse and wouldn't respawn with one + AddElement(/datum/element/swabable, CELL_LINE_TABLE_BLOBSPORE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) + +/mob/living/basic/blob_minion/zombie/death(gibbed) + corpse?.forceMove(loc) + death_burst() + return ..() + +/mob/living/basic/blob_minion/zombie/Exited(atom/movable/gone, direction) + . = ..() + if (gone != corpse) + return + corpse = null + death() + +/mob/living/basic/blob_minion/zombie/Destroy() + QDEL_NULL(corpse) + return ..() + +/mob/living/basic/blob_minion/zombie/on_factory_destroyed() + . = ..() + death() + +/mob/living/basic/blob_minion/zombie/update_overlays() + . = ..() + copy_overlays(corpse, TRUE) + var/mutable_appearance/blob_head_overlay = mutable_appearance('icons/mob/nonhuman-player/blob.dmi', "blob_head") + blob_head_overlay.color = LAZYACCESS(atom_colours, FIXED_COLOUR_PRIORITY) || COLOR_WHITE + color = initial(color) // reversing what our component did lol, but we needed the value for the overlay + . += blob_head_overlay + +/// Create an explosion of spores on death +/mob/living/basic/blob_minion/zombie/proc/death_burst() + do_chem_smoke(range = 0, holder = src, location = get_turf(src), reagent_type = /datum/reagent/toxin/spore) + +/// Store a body so that we can drop it on death +/mob/living/basic/blob_minion/zombie/proc/consume_corpse(mob/living/carbon/human/new_corpse) + if(new_corpse.wear_suit) + maxHealth += new_corpse.get_armor_rating(MELEE) + health = maxHealth + new_corpse.set_facial_hairstyle("Shaved", update = FALSE) + new_corpse.set_hairstyle("Bald", update = TRUE) + new_corpse.forceMove(src) + corpse = new_corpse + update_appearance(UPDATE_ICON) + RegisterSignal(corpse, COMSIG_LIVING_REVIVE, PROC_REF(on_corpse_revived)) + +/// Dynamic changeling reentry +/mob/living/basic/blob_minion/zombie/proc/on_corpse_revived() + SIGNAL_HANDLER + visible_message(span_boldwarning("[src] bursts from the inside!")) + death() + +/// Blob-created zombies will ping for player control when they make a zombie +/mob/living/basic/blob_minion/zombie/controlled + +/mob/living/basic/blob_minion/zombie/controlled/consume_corpse(mob/living/carbon/human/new_corpse) + . = ..() + if (!isnull(client)) + return + AddComponent(\ + /datum/component/ghost_direct_control,\ + ban_type = ROLE_BLOB_INFECTION,\ + poll_candidates = TRUE,\ + poll_ignore_key = POLL_IGNORE_BLOB,\ + ) + +/mob/living/basic/blob_minion/zombie/controlled/death_burst() + return diff --git a/code/modules/mob/living/basic/blob_minions/blobbernaut.dm b/code/modules/mob/living/basic/blob_minions/blobbernaut.dm new file mode 100644 index 00000000000..b483641993a --- /dev/null +++ b/code/modules/mob/living/basic/blob_minions/blobbernaut.dm @@ -0,0 +1,109 @@ +/** + * Player-piloted brute mob. Mostly just a "move and click" kind of guy. + * Has a variant which takes damage when away from blob tiles + */ +/mob/living/basic/blob_minion/blobbernaut + name = "blobbernaut" + desc = "A hulking, mobile chunk of blobmass." + icon_state = "blobbernaut" + icon_living = "blobbernaut" + icon_dead = "blobbernaut_dead" + health = BLOBMOB_BLOBBERNAUT_HEALTH + maxHealth = BLOBMOB_BLOBBERNAUT_HEALTH + damage_coeff = list(BRUTE = 0.5, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) + melee_damage_lower = BLOBMOB_BLOBBERNAUT_DMG_SOLO_LOWER + melee_damage_upper = BLOBMOB_BLOBBERNAUT_DMG_SOLO_UPPER + melee_attack_cooldown = CLICK_CD_MELEE + obj_damage = BLOBMOB_BLOBBERNAUT_DMG_OBJ + attack_verb_continuous = "slams" + attack_verb_simple = "slam" + attack_sound = 'sound/effects/blobattack.ogg' + verb_say = "gurgles" + verb_ask = "demands" + verb_exclaim = "roars" + verb_yell = "bellows" + force_threshold = 10 + pressure_resistance = 50 + mob_size = MOB_SIZE_LARGE + hud_type = /datum/hud/living/blobbernaut + gold_core_spawnable = HOSTILE_SPAWN + ai_controller = /datum/ai_controller/basic_controller/blobbernaut + +/mob/living/basic/blob_minion/blobbernaut/Initialize(mapload) + . = ..() + AddElement(/datum/element/swabable, CELL_LINE_TABLE_BLOBBERNAUT, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) + +/mob/living/basic/blob_minion/blobbernaut/death(gibbed) + flick("blobbernaut_death", src) + return ..() + +/// This variant is the one actually spawned by blob factories, takes damage when away from blob tiles +/mob/living/basic/blob_minion/blobbernaut/minion + gold_core_spawnable = NO_SPAWN + /// Is our factory dead? + var/orphaned = FALSE + +/mob/living/basic/blob_minion/blobbernaut/minion/Life(seconds_per_tick, times_fired) + . = ..() + if (!.) + return FALSE + var/damage_sources = 0 + var/list/blobs_in_area = range(2, src) + + if (!(locate(/obj/structure/blob) in blobs_in_area)) + damage_sources++ + + if (orphaned) + damage_sources++ + else + var/particle_colour = atom_colours[FIXED_COLOUR_PRIORITY] || COLOR_BLACK + if (locate(/obj/structure/blob/special/core) in blobs_in_area) + heal_overall_damage(maxHealth * BLOBMOB_BLOBBERNAUT_HEALING_CORE * seconds_per_tick) + var/obj/effect/temp_visual/heal/heal_effect = new /obj/effect/temp_visual/heal(get_turf(src)) + heal_effect.color = particle_colour + + if (locate(/obj/structure/blob/special/node) in blobs_in_area) + heal_overall_damage(maxHealth * BLOBMOB_BLOBBERNAUT_HEALING_NODE * seconds_per_tick) + var/obj/effect/temp_visual/heal/heal_effect = new /obj/effect/temp_visual/heal(get_turf(src)) + heal_effect.color = particle_colour + + if (damage_sources == 0) + return FALSE + + // take 2.5% of max health as damage when not near the blob or if the naut has no factory, 5% if both + apply_damage(maxHealth * BLOBMOB_BLOBBERNAUT_HEALTH_DECAY * damage_sources * seconds_per_tick, damagetype = TOX) // We reduce brute damage + var/mutable_appearance/harming = mutable_appearance('icons/mob/nonhuman-player/blob.dmi', "nautdamage", MOB_LAYER + 0.01) + harming.appearance_flags = RESET_COLOR + harming.color = atom_colours[FIXED_COLOUR_PRIORITY] || COLOR_WHITE + harming.dir = dir + flick_overlay_view(harming, 0.8 SECONDS) + return TRUE + +/// Called by the blob creation power to give us a mind and a basic task orientation +/mob/living/basic/blob_minion/blobbernaut/minion/proc/assign_key(ckey, datum/blobstrain/blobstrain) + key = ckey + flick("blobbernaut_produce", src) + health = maxHealth / 2 // Start out injured to encourage not beelining away from the blob + SEND_SOUND(src, sound('sound/effects/blobattack.ogg')) + SEND_SOUND(src, sound('sound/effects/attackblob.ogg')) + to_chat(src, span_infoplain("You are powerful, hard to kill, and slowly regenerate near nodes and cores, [span_cultlarge("but will slowly die if not near the blob")] or if the factory that made you is killed.")) + to_chat(src, span_infoplain("You can communicate with other blobbernauts and overminds telepathically by attempting to speak normally")) + to_chat(src, span_infoplain("Your overmind's blob reagent is: [blobstrain.name]!")) + to_chat(src, span_infoplain("The [blobstrain.name] reagent [blobstrain.shortdesc ? "[blobstrain.shortdesc]" : "[blobstrain.description]"]")) + +/// Set our attack damage based on blob's properties +/mob/living/basic/blob_minion/blobbernaut/minion/on_strain_updated(mob/camera/blob/overmind, datum/blobstrain/new_strain) + if (isnull(overmind)) + melee_damage_lower = initial(melee_damage_lower) + melee_damage_upper = initial(melee_damage_upper) + attack_verb_continuous = initial(attack_verb_continuous) + return + melee_damage_lower = BLOBMOB_BLOBBERNAUT_DMG_LOWER + melee_damage_upper = BLOBMOB_BLOBBERNAUT_DMG_UPPER + attack_verb_continuous = new_strain.blobbernaut_message + +/// Called by our factory to inform us that it's not going to support us financially any more +/mob/living/basic/blob_minion/blobbernaut/minion/on_factory_destroyed() + . = ..() + orphaned = TRUE + throw_alert("nofactory", /atom/movable/screen/alert/nofactory) diff --git a/code/modules/mob/living/basic/heretic/heretic_summon.dm b/code/modules/mob/living/basic/heretic/heretic_summon.dm index 0f7d63f903c..cdae7ea6786 100644 --- a/code/modules/mob/living/basic/heretic/heretic_summon.dm +++ b/code/modules/mob/living/basic/heretic/heretic_summon.dm @@ -13,6 +13,7 @@ unsuitable_heat_damage = 0 damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) speed = 0 + melee_attack_cooldown = CLICK_CD_MELEE attack_sound = 'sound/weapons/punch1.ogg' response_help_continuous = "thinks better of touching" diff --git a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm index 5951bd6b7fe..47280af4281 100644 --- a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm +++ b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm @@ -13,53 +13,33 @@ /datum/ai_planning_subtree/attack_obstacle_in_path, /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/sculpt_statues, - /datum/ai_planning_subtree/find_and_hunt_target/cannibalize, + /datum/ai_planning_subtree/find_and_hunt_target/corpses/ice_whelp, /datum/ai_planning_subtree/burn_trees, ) - -/datum/ai_planning_subtree/find_and_hunt_target/cannibalize +/datum/ai_planning_subtree/find_and_hunt_target/corpses/ice_whelp target_key = BB_TARGET_CANNIBAL - hunting_behavior = /datum/ai_behavior/cannibalize - finding_behavior = /datum/ai_behavior/find_hunt_target/dragon_corpse + finding_behavior = /datum/ai_behavior/find_hunt_target/corpses/dragon_corpse + hunting_behavior = /datum/ai_behavior/hunt_target/unarmed_attack_target/dragon_cannibalise hunt_targets = list(/mob/living/basic/mining/ice_whelp) hunt_range = 10 -/datum/ai_behavior/find_hunt_target/dragon_corpse +/datum/ai_behavior/find_hunt_target/corpses/dragon_corpse -/datum/ai_behavior/find_hunt_target/dragon_corpse/valid_dinner(mob/living/source, mob/living/dinner, radius) - if(dinner.stat != DEAD) - return FALSE +/datum/ai_behavior/find_hunt_target/corpses/dragon_corpse/valid_dinner(mob/living/source, mob/living/dinner, radius) if(dinner.pulledby) //someone already got him before us return FALSE + return ..() - return can_see(source, dinner, radius) - -/datum/ai_behavior/cannibalize +/datum/ai_behavior/hunt_target/unarmed_attack_target/dragon_cannibalise behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION -/datum/ai_behavior/cannibalize/setup(datum/ai_controller/controller, target_key) - . = ..() - var/atom/target = controller.blackboard[target_key] - if(QDELETED(target)) - return FALSE - set_movement_target(controller, target) - -/datum/ai_behavior/cannibalize/perform(seconds_per_tick, datum/ai_controller/controller, target_key, attack_key) - . = ..() - var/mob/living/basic/living_pawn = controller.pawn +/datum/ai_behavior/hunt_target/unarmed_attack_target/dragon_cannibalise/perform(seconds_per_tick, datum/ai_controller/controller, target_key, attack_key) var/mob/living/target = controller.blackboard[target_key] - - if(QDELETED(target)) + if(QDELETED(target) || target.stat != DEAD || target.pulledby) //we were too slow finish_action(controller, FALSE) return - - if(target.stat != DEAD || target.pulledby) //we were too slow - finish_action(controller, FALSE) - return - - living_pawn.melee_attack(target) - finish_action(controller, TRUE) + return ..() /datum/ai_behavior/cannibalize/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() 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 e2c67af2467..c88178135dc 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 @@ -2,6 +2,7 @@ blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, BB_BASIC_MOB_FLEEING = TRUE, + BB_BASIC_MOB_FLEE_DISTANCE = 5, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -47,7 +48,6 @@ /datum/ai_behavior/run_away_from_target/mega_arachnid clear_failed_targets = FALSE - run_distance = 5 ///only engage in melee combat against cuffed targets, otherwise keep throwing restraints at them /datum/ai_planning_subtree/basic_melee_attack_subtree/mega_arachnid diff --git a/code/modules/mob/living/basic/lavaland/basilisk/basilisk.dm b/code/modules/mob/living/basic/lavaland/basilisk/basilisk.dm index c662870393c..45bfd74d23b 100644 --- a/code/modules/mob/living/basic/lavaland/basilisk/basilisk.dm +++ b/code/modules/mob/living/basic/lavaland/basilisk/basilisk.dm @@ -75,6 +75,7 @@ /datum/ai_controller/basic_controller/basilisk blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_AGGRO_RANGE = 5, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath.dm index 95df44a8326..b99e254853e 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath.dm @@ -44,6 +44,8 @@ COOLDOWN_DECLARE(ability_animation_cooldown) /// Our base tentacles ability var/datum/action/cooldown/mob_cooldown/goliath_tentacles/tentacles + /// Our long-ranged tentacles ability + var/datum/action/cooldown/mob_cooldown/tentacle_grasp/tentacle_line /// Things we want to eat off the floor (or a plate, we're not picky) var/static/list/goliath_foods = list(/obj/item/food/grown/ash_flora, /obj/item/food/bait/worm) @@ -70,9 +72,9 @@ var/datum/action/cooldown/mob_cooldown/tentacle_burst/melee_tentacles = new (src) melee_tentacles.Grant(src) AddComponent(/datum/component/revenge_ability, melee_tentacles, targetting = ai_controller.blackboard[BB_TARGETTING_DATUM], max_range = 1, target_self = TRUE) - var/datum/action/cooldown/mob_cooldown/tentacle_grasp/ranged_tentacles = new (src) - ranged_tentacles.Grant(src) - AddComponent(/datum/component/revenge_ability, ranged_tentacles, targetting = ai_controller.blackboard[BB_TARGETTING_DATUM], min_range = 2, max_range = 9) + tentacle_line = new (src) + tentacle_line.Grant(src) + AddComponent(/datum/component/revenge_ability, tentacle_line, targetting = ai_controller.blackboard[BB_TARGETTING_DATUM], min_range = 2, max_range = 9) tentacles_ready() RegisterSignal(src, COMSIG_MOB_ABILITY_FINISHED, PROC_REF(used_ability)) @@ -82,6 +84,7 @@ /mob/living/basic/mining/goliath/Destroy() QDEL_NULL(tentacles) + QDEL_NULL(tentacle_line) return ..() /mob/living/basic/mining/goliath/examine(mob/user) @@ -167,6 +170,12 @@ . = ..() faction = new_friend.faction.Copy() +/mob/living/basic/mining/goliath/RangedAttack(atom/atom_target, modifiers) + tentacles?.Trigger(target = atom_target) + +/mob/living/basic/mining/goliath/ranged_secondary_attack(atom/atom_target, modifiers) + tentacle_line?.Trigger(target = atom_target) + /// Legacy Goliath mob with different sprites, largely the same behaviour /mob/living/basic/mining/goliath/ancient name = "ancient goliath" diff --git a/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm b/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm new file mode 100644 index 00000000000..11043e58d11 --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/hivelord/hivelord.dm @@ -0,0 +1,114 @@ +/// Mob which retreats and spawns annoying sub-mobs to attack you +/mob/living/basic/mining/hivelord + name = "hivelord" + desc = "A levitating swarm of tiny creatures which act as a single individual. When threatened or hunting they rapidly replicate additional short-lived bodies." + icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' + icon_state = "hivelord" + icon_living = "hivelord" + // icon_aggro = "hivelord_alert" + icon_dead = "hivelord_dead" + icon_gib = "syndicate_gib" + mob_biotypes = MOB_ORGANIC + speed = 2 + maxHealth = 75 + health = 75 + melee_damage_lower = 0 + melee_damage_upper = 0 + attack_verb_continuous = "weakly tackles" + attack_verb_simple = "weakly tackles" + speak_emote = list("telepathically cries") + attack_sound = 'sound/weapons/pierce.ogg' + throw_blocked_message = "passes between the bodies of the" + obj_damage = 0 + pass_flags = PASSTABLE + ai_controller = /datum/ai_controller/basic_controller/hivelord + /// Mobs to spawn when we die, varedit this to be recursive to give the players a fun surprise + var/death_spawn_type = /mob/living/basic/hivelord_brood + /// Action which spawns worms + var/datum/action/cooldown/mob_cooldown/hivelord_spawn/spawn_brood + +/mob/living/basic/mining/hivelord/Initialize(mapload) + . = ..() + var/static/list/death_loot = list(/obj/item/organ/internal/monster_core/regenerative_core) + AddElement(/datum/element/relay_attackers) + AddElement(/datum/element/death_drops, death_loot) + AddComponent(/datum/component/clickbox, icon_state = "hivelord", max_scale = INFINITY, dead_state = "hivelord_dead") // They writhe so much. + AddComponent(/datum/component/appearance_on_aggro, aggro_state = "hivelord_alert") + spawn_brood = new(src) + spawn_brood.Grant(src) + ai_controller.set_blackboard_key(BB_TARGETTED_ACTION, spawn_brood) + +/mob/living/basic/mining/hivelord/Destroy() + QDEL_NULL(spawn_brood) + return ..() + +/mob/living/basic/mining/hivelord/death(gibbed) + . = ..() + var/list/safe_turfs = RANGE_TURFS(1, src) - get_turf(src) + for (var/turf/check_turf as anything in safe_turfs) + if (check_turf.is_blocked_turf(exclude_mobs = TRUE)) + safe_turfs -= check_turf + + var/turf/our_turf = get_turf(src) + for (var/i in 1 to 3) + if (!length(safe_turfs)) + return + var/turf/land_turf = pick_n_take(safe_turfs) + var/obj/effect/temp_visual/hivebrood_spawn/forecast = new(land_turf) + forecast.create_from(death_spawn_type, our_turf, CALLBACK(src, PROC_REF(complete_spawn), land_turf)) + +/// Spawns a worm on the specified turf +/mob/living/basic/mining/hivelord/proc/complete_spawn(turf/spawn_turf) + var/mob/living/brood = new death_spawn_type(spawn_turf) + brood.faction = faction + brood.ai_controller?.set_blackboard_key(ai_controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET]) + brood.dir = get_dir(src, spawn_turf) + +/mob/living/basic/mining/hivelord/RangedAttack(atom/atom_target, modifiers) + spawn_brood?.Trigger(target = atom_target) + +/// Attack worms spawned by the hivelord +/mob/living/basic/hivelord_brood + name = "hivelord brood" + desc = "Short-lived attack form of the hivelord. One isn't much of a threat, but..." + icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' + icon_state = "hivelord_brood" + icon_living = "hivelord_brood" + icon_dead = "hivelord_brood" + icon_gib = "syndicate_gib" + friendly_verb_continuous = "chirrups near" + friendly_verb_simple = "chirrup near" + mob_size = MOB_SIZE_SMALL + basic_mob_flags = DEL_ON_DEATH + pass_flags = PASSTABLE | PASSMOB + mob_biotypes = MOB_ORGANIC|MOB_BEAST + faction = list(FACTION_MINING) + unsuitable_atmos_damage = 0 + minimum_survivable_temperature = 0 + maximum_survivable_temperature = INFINITY + speed = 1.5 + maxHealth = 1 + health = 1 + melee_damage_lower = 2 + melee_damage_upper = 2 + attack_verb_continuous = "bites" + attack_verb_simple = "bite" + speak_emote = list("telepathically cries") + attack_sound = 'sound/weapons/bite.ogg' + attack_vis_effect = ATTACK_EFFECT_BITE + obj_damage = 0 + density = FALSE + ai_controller = /datum/ai_controller/basic_controller/simple_hostile + +/mob/living/basic/hivelord_brood/Initialize(mapload) + . = ..() + add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE, TRAIT_PERMANENTLY_MORTAL), INNATE_TRAIT) + AddElement(/datum/element/simple_flying) + AddComponent(/datum/component/swarming) + AddComponent(/datum/component/clickbox, icon_state = "hivelord", max_scale = INFINITY) + addtimer(CALLBACK(src, PROC_REF(death)), 10 SECONDS) + +/mob/living/basic/hivelord_brood/death(gibbed) + if (!gibbed) + new /obj/effect/temp_visual/hive_spawn_wither(get_turf(src), /* copy_from = */ src) + return ..() diff --git a/code/modules/mob/living/basic/lavaland/hivelord/hivelord_ai.dm b/code/modules/mob/living/basic/lavaland/hivelord/hivelord_ai.dm new file mode 100644 index 00000000000..fd7983de397 --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/hivelord/hivelord_ai.dm @@ -0,0 +1,14 @@ +/// Basically just keep away and shit out worms +/datum/ai_controller/basic_controller/hivelord + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_AGGRO_RANGE = 5, // Only get mad at people nearby + ) + + 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/maintain_distance, + /datum/ai_planning_subtree/targeted_mob_ability, + ) diff --git a/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm b/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm new file mode 100644 index 00000000000..3fee2a003f3 --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm @@ -0,0 +1,124 @@ +/// Spawns a little worm nearby +/datum/action/cooldown/mob_cooldown/hivelord_spawn + name = "Spawn Brood" + desc = "Release an attack form to an adjacent square to attack your target or anyone nearby." + button_icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' + button_icon_state = "hivelord_brood" + background_icon_state = "bg_demon" + overlay_icon_state = "bg_demon_border" + click_to_activate = TRUE + cooldown_time = 2 SECONDS + melee_cooldown_time = 0 + check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED + shared_cooldown = NONE + /// If a mob is not clicked directly, inherit targetting data from this blackboard key and setting it upon this target key + var/ai_target_key = BB_BASIC_MOB_CURRENT_TARGET + /// What are we actually spawning? + var/spawn_type = /mob/living/basic/hivelord_brood + /// Do we automatically fire with no cooldown when damaged? + var/trigger_on_hit = TRUE + /// Minimum time between triggering on hit + var/on_hit_delay = 1 SECONDS + /// Delay between triggering on hit + COOLDOWN_DECLARE(on_hit_cooldown) + +/datum/action/cooldown/mob_cooldown/hivelord_spawn/Grant(mob/granted_to) + . = ..() + if (isnull(owner)) + return + if (trigger_on_hit) + RegisterSignal(owner, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_attacked)) + +/datum/action/cooldown/mob_cooldown/hivelord_spawn/Remove(mob/removed_from) + UnregisterSignal(removed_from, COMSIG_ATOM_WAS_ATTACKED) + return ..() + +/datum/action/cooldown/mob_cooldown/hivelord_spawn/Activate(atom/target) + . = ..() + if (!spawn_brood(target, target_turf = get_turf(target))) + StartCooldown(0.5 SECONDS) + return + StartCooldown() + +/// Called when someone whacks us +/datum/action/cooldown/mob_cooldown/hivelord_spawn/proc/on_attacked(atom/victim, atom/attacker, attack_flags) + SIGNAL_HANDLER + if (!trigger_on_hit || !(attack_flags & ATTACKER_DAMAGING_ATTACK) || !COOLDOWN_FINISHED(src, on_hit_cooldown)) + return + COOLDOWN_START(src, on_hit_cooldown, on_hit_delay) + spawn_brood(attacker, target_turf = get_step_away(owner, attacker), feedback = FALSE) + +/// Spawn a funny little worm +/datum/action/cooldown/mob_cooldown/hivelord_spawn/proc/spawn_brood(target, turf/target_turf, feedback = TRUE) + var/ai_target = isliving(target) ? target : null + if (isnull(ai_target)) + ai_target = owner.ai_controller?.blackboard[ai_target_key] + + var/dir_to_target = get_dir(owner, target_turf) + var/list/target_turfs = list() + for(var/i in -1 to 1) + var/turn_amount = rand(-1, 1) * 45 + var/test_dir = turn(dir_to_target, turn_amount) + var/turf/test_turf = get_step(owner, test_dir) + if (test_turf.is_blocked_turf(exclude_mobs = TRUE)) + continue + target_turfs += test_turf + + if (!length(target_turfs)) + if (feedback) + owner.balloon_alert(owner, "no room!") + StartCooldown(0.5 SECONDS) + return FALSE + + var/turf/land_turf = pick(target_turfs) + var/obj/effect/temp_visual/hivebrood_spawn/forecast = new(land_turf) + forecast.create_from(spawn_type, get_turf(owner), CALLBACK(src, PROC_REF(complete_spawn), land_turf, ai_target)) + StartCooldown() + + return TRUE + +/// Actually create a mob +/datum/action/cooldown/mob_cooldown/hivelord_spawn/proc/complete_spawn(turf/spawn_turf, target) + var/mob/living/brood = new spawn_type(spawn_turf) + brood.faction = owner.faction + brood.ai_controller?.set_blackboard_key(ai_target_key, target) + brood.dir = get_dir(owner, spawn_turf) + +#define BROOD_ARC_Y_OFFSET 8 +#define BROOD_ARC_ROTATION 45 + +/// Fast animation to show a worm spawning +/obj/effect/temp_visual/hivebrood_spawn + name = "brood spawn" + duration = 0.3 SECONDS + alpha = 0 + +/// Set up our visuals and start a timer for a callback +/obj/effect/temp_visual/hivebrood_spawn/proc/create_from(mob/living/spawn_type, turf/spawn_from, datum/callback/on_completed) + addtimer(on_completed, duration, TIMER_DELETE_ME) + + var/turf/my_turf = get_turf(src) + dir = get_dir(spawn_from, my_turf) + var/move_x = (my_turf.x - spawn_from.x) * world.icon_size + var/move_y = (my_turf.y - spawn_from.y) * world.icon_size + pixel_x = -move_x + pixel_y = -move_y + + icon = initial(spawn_type.icon) + icon_state = initial(spawn_type.icon_state) + + + animate(src, pixel_x = 0, time = duration) + animate(src, pixel_y = BROOD_ARC_Y_OFFSET - (move_y * 0.5), time = duration * 0.5, flags = ANIMATION_PARALLEL, easing = SINE_EASING | EASE_OUT) + animate(pixel_y = 0, time = duration * 0.5, easing = SINE_EASING | EASE_IN) + animate(src, alpha = 255, time = duration * 0.5, flags = ANIMATION_PARALLEL) + + if (dir & (NORTH | EAST)) + transform = matrix().Turn(-BROOD_ARC_ROTATION) + animate(src, transform = matrix(), time = duration, flags = ANIMATION_PARALLEL) + else + transform = matrix().Turn(BROOD_ARC_ROTATION) + animate(src, transform = matrix(), time = duration, flags = ANIMATION_PARALLEL) + +#undef BROOD_ARC_Y_OFFSET +#undef BROOD_ARC_ROTATION diff --git a/code/modules/mob/living/basic/lavaland/legion/legion.dm b/code/modules/mob/living/basic/lavaland/legion/legion.dm new file mode 100644 index 00000000000..7c6bd0fd170 --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/legion/legion.dm @@ -0,0 +1,158 @@ +/** + * Avoids players while throwing skulls at them. + * Legion skulls heal allies, bite enemies, and infest dying humans to make more legions. + */ +/mob/living/basic/mining/legion + name = "legion" + desc = "You can still see what was once a human under the shifting mass of corruption." + icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' + icon_state = "legion" + icon_living = "legion" + icon_dead = "legion" + icon_gib = "syndicate_gib" + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID + basic_mob_flags = DEL_ON_DEATH + speed = 3 + maxHealth = 75 + health = 75 + obj_damage = 60 + melee_damage_lower = 15 + melee_damage_upper = 15 + attack_verb_continuous = "lashes out at" + attack_verb_simple = "lash out at" + speak_emote = list("gurgles") + attack_sound = 'sound/weapons/pierce.ogg' + throw_blocked_message = "bounces harmlessly off of" + crusher_loot = /obj/item/crusher_trophy/legion_skull + death_message = "wails in chorus and dissolves into quivering flesh." + ai_controller = /datum/ai_controller/basic_controller/legion + /// What kind of mob do we spawn? + var/brood_type = /mob/living/basic/legion_brood + /// What kind of corpse spawner do we leave behind on death? + var/corpse_type = /obj/effect/mob_spawn/corpse/human/legioninfested + /// Who is inside of us? + var/mob/living/stored_mob + +/mob/living/basic/mining/legion/Initialize(mapload) + . = ..() + AddElement(/datum/element/death_drops, get_loot_list()) + AddElement(/datum/element/content_barfer) + + var/datum/action/cooldown/mob_cooldown/skull_launcher/skull_launcher = new(src) + skull_launcher.Grant(src) + skull_launcher.spawn_type = brood_type + ai_controller.blackboard[BB_TARGETTED_ACTION] = skull_launcher + +/// Create what we want to drop on death, in proc form so we can always return a static list +/mob/living/basic/mining/legion/proc/get_loot_list() + var/static/list/death_loot = list(/obj/item/organ/internal/monster_core/regenerative_core/legion) + return death_loot + +/mob/living/basic/mining/legion/Exited(atom/movable/gone, direction) + . = ..() + if (gone != stored_mob) + return + ai_controller.clear_blackboard_key(BB_LEGION_CORPSE) + stored_mob.remove_status_effect(/datum/status_effect/grouped/stasis, STASIS_LEGION_EATEN) + stored_mob.add_mood_event(MOOD_CATEGORY_LEGION_CORE, /datum/mood_event/healsbadman/long_term) // This will still probably mostly be gone before you are alive + stored_mob = null + +/mob/living/basic/mining/legion/death(gibbed) + if (isnull(stored_mob)) + new corpse_type(loc) + return ..() + +/// Put a corpse in this guy +/mob/living/basic/mining/legion/proc/consume(mob/living/consumed) + new /obj/effect/gibspawner/generic(consumed.loc) + gender = consumed.gender + name = consumed.real_name + consumed.investigate_log("has been killed by hivelord infestation.", INVESTIGATE_DEATHS) + consumed.death() + consumed.extinguish_mob() + consumed.fully_heal(HEAL_DAMAGE) + consumed.apply_status_effect(/datum/status_effect/grouped/stasis, STASIS_LEGION_EATEN) + consumed.forceMove(src) + ai_controller?.set_blackboard_key(BB_LEGION_CORPSE, consumed) + ai_controller?.set_blackboard_key(BB_LEGION_RECENT_LINES, consumed.copy_recent_speech(line_chance = 80)) + stored_mob = consumed + visible_message(span_warning("[src] staggers to [p_their()] feet!")) + if (prob(75)) + return + // Congratulations you have won a special prize: cancer + var/obj/item/organ/internal/legion_tumour/cancer = new() + cancer.Insert(consumed, special = TRUE, drop_if_replaced = FALSE) + +/// A Legion which only drops skeletons instead of corpses which might have fun loot, so it cannot be farmed +/mob/living/basic/mining/legion/spawner_made + corpse_type = /obj/effect/mob_spawn/corpse/human/legioninfested/skeleton/charred + + +/// Like a Legion but it's an adorable snowman +/mob/living/basic/mining/legion/snow + name = "snow legion" + desc = "You can vaguely see what was once a human under the densely packed snow. Cute, but macabre." + icon = 'icons/mob/simple/icemoon/icemoon_monsters.dmi' + icon_state = "snowlegion" + icon_living = "snowlegion" + // icon_aggro = "snowlegion_alive" + icon_dead = "snowlegion" + brood_type = /mob/living/basic/legion_brood/snow + corpse_type = /obj/effect/mob_spawn/corpse/human/legioninfested/snow + +/mob/living/basic/mining/legion/snow/Initialize(mapload) + . = ..() + AddComponent(/datum/component/appearance_on_aggro, aggro_state = "snowlegion_alive") // Surprise! I was real! + +/// As Snow Legion but spawns corpses which don't have any exciting loot +/mob/living/basic/mining/legion/snow/spawner_made + corpse_type = /obj/effect/mob_spawn/corpse/human/legioninfested/skeleton + + +/// Like a Legion but shorter and faster +/mob/living/basic/mining/legion/dwarf + name = "dwarf legion" + desc = "You can still see what was once a rather small human under the shifting mass of corruption." + icon_state = "dwarf_legion" + icon_living = "dwarf_legion" + icon_dead = "dwarf_legion" + maxHealth = 60 + health = 60 + speed = 2 + crusher_drop_chance = 20 + corpse_type = /obj/effect/mob_spawn/corpse/human/legioninfested/dwarf + + +/// Like a Legion but larger and spawns regular Legions, not currently used anywhere and very soulful +/mob/living/basic/mining/legion/large + name = "myriad" + desc = "A legion of legions, a dead end to whatever form the Necropolis was attempting to create." + icon = 'icons/mob/simple/lavaland/64x64megafauna.dmi' + icon_state = "legion" + icon_living = "legion" + icon_dead = "legion" + health_doll_icon = "legion" + speed = 5 + health = 450 + maxHealth = 450 + melee_damage_lower = 20 + melee_damage_upper = 20 + obj_damage = 30 + pixel_x = -16 + sentience_type = SENTIENCE_BOSS + +/mob/living/basic/mining/legion/large/Initialize(mapload) + . = ..() + AddComponent(\ + /datum/component/spawner,\ + spawn_types = list(/mob/living/basic/mining/legion),\ + spawn_time = 20 SECONDS,\ + max_spawned = 3,\ + spawn_text = "peels itself off from",\ + faction = faction,\ + ) + +/// Create what we want to drop on death, in proc form so we can always return a static list +/mob/living/basic/mining/legion/large/get_loot_list() + var/static/list/death_loot = list(/obj/item/organ/internal/monster_core/regenerative_core/legion = 3, /obj/effect/mob_spawn/corpse/human/legioninfested = 4) + return death_loot diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm new file mode 100644 index 00000000000..6b3525cb32a --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm @@ -0,0 +1,77 @@ +/// Keep away and launch skulls at every opportunity, prioritising injured allies +/datum/ai_controller/basic_controller/legion + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead/legion, + BB_BASIC_MOB_FLEEING = TRUE, + BB_AGGRO_RANGE = 5, // Unobservant + BB_BASIC_MOB_FLEE_DISTANCE = 6, + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + planning_subtrees = list( + /datum/ai_planning_subtree/random_speech/legion, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/targeted_mob_ability, + /datum/ai_planning_subtree/flee_target/legion, + ) + +/// Chase and attack whatever we are targetting, if it's friendly we will heal them +/datum/ai_controller/basic_controller/legion_brood + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead/legion, + ) + + 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/basic_melee_attack_subtree, + ) + +/// Target nearby friendlies if they are hurt (and are not themselves Legions) +/datum/targetting_datum/basic/attack_until_dead/legion + +/datum/targetting_datum/basic/attack_until_dead/legion/faction_check(mob/living/living_mob, mob/living/the_target) + if (!living_mob.faction_check_mob(the_target, exact_match = check_factions_exactly)) + return FALSE + if (istype(the_target, living_mob.type)) + return TRUE + var/atom/created_by = living_mob.ai_controller.blackboard[BB_LEGION_BROOD_CREATOR] + if (!QDELETED(created_by) && istype(the_target, created_by.type)) + return TRUE + return the_target.stat == DEAD || the_target.health >= the_target.maxHealth + +/// Don't run away from friendlies +/datum/ai_planning_subtree/flee_target/legion + +/datum/ai_planning_subtree/flee_target/legion/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/mob/living/target = controller.blackboard[target_key] + if (QDELETED(target) || target.faction_check_mob(controller.pawn)) + return // Only flee if we have a hostile target + return ..() + +/// Make spooky sounds, if we have a corpse inside then impersonate them +/datum/ai_planning_subtree/random_speech/legion + speech_chance = 1 + speak = list("Come...", "Legion...", "Why...?") + emote_hear = list("groans.", "wails.", "whimpers.") + emote_see = list("twitches.", "shudders.") + /// Stuff to specifically say into a radio + var/list/radio_speech = list("Come...", "Why...?") + +/datum/ai_planning_subtree/random_speech/legion/speak(datum/ai_controller/controller) + var/mob/living/carbon/human/victim = controller.blackboard[BB_LEGION_CORPSE] + if (QDELETED(victim) || prob(30)) + return ..() + + var/list/remembered_speech = controller.blackboard[BB_LEGION_RECENT_LINES] || list() + + if (length(remembered_speech) && prob(50)) // Don't spam the radio + controller.queue_behavior(/datum/ai_behavior/perform_speech, pick(remembered_speech)) + return + + var/obj/item/radio/mob_radio = locate() in victim.contents + if (QDELETED(mob_radio)) + return ..() // No radio, just talk funny + controller.queue_behavior(/datum/ai_behavior/perform_speech_radio, pick(radio_speech + remembered_speech), mob_radio, list(RADIO_CHANNEL_SUPPLY, RADIO_CHANNEL_COMMON)) diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm b/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm new file mode 100644 index 00000000000..962d232c5ef --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm @@ -0,0 +1,99 @@ +/// A spooky skull which heals lavaland mobs, attacks miners, and infests their bodies +/mob/living/basic/legion_brood + name = "legion" + desc = "One of many." + icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' + icon_state = "legion_head" + icon_living = "legion_head" + icon_dead = "legion_head" + icon_gib = "syndicate_gib" + basic_mob_flags = DEL_ON_DEATH + mob_size = MOB_SIZE_SMALL + pass_flags = PASSTABLE | PASSMOB + mob_biotypes = MOB_ORGANIC|MOB_BEAST + faction = list(FACTION_MINING) + unsuitable_atmos_damage = 0 + minimum_survivable_temperature = 0 + maximum_survivable_temperature = INFINITY + friendly_verb_continuous = "chatters near" + friendly_verb_simple = "chatter near" + maxHealth = 1 + health = 1 + melee_damage_lower = 12 + melee_damage_upper = 12 + obj_damage = 0 + attack_verb_continuous = "bites" + attack_verb_simple = "bite" + attack_vis_effect = ATTACK_EFFECT_BITE + speak_emote = list("echoes") // who the fuck speaking as this mob it dies 10 seconds after it spawns + attack_sound = 'sound/weapons/pierce.ogg' + density = FALSE + ai_controller = /datum/ai_controller/basic_controller/legion_brood + /// Reference to a guy who made us + var/mob/living/created_by + +/mob/living/basic/legion_brood/Initialize(mapload) + . = ..() + add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE, TRAIT_PERMANENTLY_MORTAL), INNATE_TRAIT) + AddElement(/datum/element/simple_flying) + AddComponent(/datum/component/swarming) + AddComponent(/datum/component/clickbox, icon_state = "sphere", max_scale = 2) + addtimer(CALLBACK(src, PROC_REF(death)), 10 SECONDS) + +/mob/living/basic/legion_brood/death(gibbed) + if (!gibbed) + new /obj/effect/temp_visual/hive_spawn_wither(get_turf(src), /* copy_from = */ src) + return ..() + +/mob/living/basic/legion_brood/melee_attack(mob/living/target, list/modifiers, ignore_cooldown) + if (ishuman(target) && target.stat > SOFT_CRIT) + infest(target) + return + if (isliving(target) && faction_check_mob(target) && !istype(target, created_by?.type)) + visible_message(span_warning("[src] melds with [target]'s flesh!")) + target.apply_status_effect(/datum/status_effect/regenerative_core) + new /obj/effect/temp_visual/heal(get_turf(target), COLOR_HEALING_CYAN) + death() + return + return ..() + +/// Turn the targetted mob into one of us +/mob/living/basic/legion_brood/proc/infest(mob/living/target) + visible_message(span_warning("[name] burrows into the flesh of [target]!")) + var/spawn_type = get_legion_type(target) + var/mob/living/basic/mining/legion/new_legion = new spawn_type(loc) + new_legion.consume(target) + new_legion.faction = faction.Copy() + qdel(src) + +/// Returns the kind of legion we make out of the target +/mob/living/basic/legion_brood/proc/get_legion_type(mob/living/target) + if (HAS_TRAIT(target, TRAIT_DWARF)) + return /mob/living/basic/mining/legion/dwarf + return /mob/living/basic/mining/legion + +/// Sets someone as our creator, mostly so you can't use skulls to heal yourself +/mob/living/basic/legion_brood/proc/assign_creator(mob/living/creator, copy_full_faction = TRUE) + if (copy_full_faction) + faction = creator.faction.Copy() + else + faction |= REF(creator) + created_by = creator + ai_controller?.set_blackboard_key(BB_LEGION_BROOD_CREATOR, creator) + RegisterSignal(creator, COMSIG_QDELETING, PROC_REF(creator_destroyed)) + +/// Reference handling +/mob/living/basic/legion_brood/proc/creator_destroyed() + SIGNAL_HANDLER + created_by = null + +/// Like the Legion's summoned skull but funnier (it's snow now) +/mob/living/basic/legion_brood/snow + name = "snow legion" + icon = 'icons/mob/simple/icemoon/icemoon_monsters.dmi' + icon_state = "snowlegion_head" + icon_living = "snowlegion_head" + icon_dead = "snowlegion_head" + +/mob/living/basic/legion_brood/snow/get_legion_type(mob/living/target) + return /mob/living/basic/mining/legion/snow diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_tumour.dm b/code/modules/mob/living/basic/lavaland/legion/legion_tumour.dm new file mode 100644 index 00000000000..078af57de2a --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/legion/legion_tumour.dm @@ -0,0 +1,159 @@ +/// Left behind when a legion infects you, for medical enrichment +/obj/item/organ/internal/legion_tumour + name = "legion tumour" + desc = "A mass of pulsing flesh and dark tendrils, containing the power to regenerate flesh at a terrible cost." + failing_desc = "pulses and writhes with horrible life, reaching towards you with its tendrils!" + icon = 'icons/obj/medical/organs/mining_organs.dmi' + icon_state = "legion_remains" + zone = BODY_ZONE_CHEST + slot = ORGAN_SLOT_PARASITE_EGG + decay_factor = STANDARD_ORGAN_DECAY * 3 // About 5 minutes outside of a host + /// What stage of growth the corruption has reached. + var/stage = 0 + /// We apply this status effect periodically or when used on someone + var/applied_status = /datum/status_effect/regenerative_core + /// How long have we been in this stage? + var/elapsed_time = 0 SECONDS + /// How long does it take to advance one stage? + var/growth_time = 80 SECONDS // Long enough that if you go back to lavaland without realising it you're not totally fucked + /// What kind of mob will we transform into? + var/spawn_type = /mob/living/basic/mining/legion + /// Spooky sounds to play as you start to turn + var/static/list/spooky_sounds = list( + 'sound/voice/lowHiss1.ogg', + 'sound/voice/lowHiss2.ogg', + 'sound/voice/lowHiss3.ogg', + 'sound/voice/lowHiss4.ogg', + ) + +/obj/item/organ/internal/legion_tumour/Initialize(mapload) + . = ..() + animate_pulse() + +/obj/item/organ/internal/legion_tumour/apply_organ_damage(damage_amount, maximum, required_organ_flag) + var/was_failing = organ_flags & ORGAN_FAILING + . = ..() + if (was_failing != (organ_flags & ORGAN_FAILING)) + animate_pulse() + +/obj/item/organ/internal/legion_tumour/set_organ_damage(damage_amount, required_organ_flag) + . = ..() + animate_pulse() + +/// Do a heartbeat animation depending on if we're failing or not +/obj/item/organ/internal/legion_tumour/proc/animate_pulse() + animate(src, transform = matrix()) // Stop any current animation + + var/speed_divider = organ_flags & ORGAN_FAILING ? 2 : 1 + + animate(src, transform = matrix().Scale(1.1), time = 0.5 SECONDS / speed_divider, easing = SINE_EASING | EASE_OUT, loop = -1, flags = ANIMATION_PARALLEL) + animate(transform = matrix(), time = 0.5 SECONDS / speed_divider, easing = SINE_EASING | EASE_IN) + animate(transform = matrix(), time = 2 SECONDS / speed_divider) + +/obj/item/organ/internal/legion_tumour/Remove(mob/living/carbon/egg_owner, special) + . = ..() + stage = 0 + elapsed_time = 0 + +/obj/item/organ/internal/legion_tumour/attack(mob/living/target, mob/living/user, params) + if (try_apply(target, user)) + qdel(src) + return + return ..() + +/// Smear it on someone like a regen core, why not. Make sure they're alive though. +/obj/item/organ/internal/legion_tumour/proc/try_apply(mob/living/target, mob/user) + if(!user.Adjacent(target) || !isliving(target)) + return FALSE + + if (target.stat <= SOFT_CRIT && !(organ_flags & ORGAN_FAILING)) + target.add_mood_event(MOOD_CATEGORY_LEGION_CORE, /datum/mood_event/healsbadman) + target.apply_status_effect(applied_status) + + if (target != user) + target.visible_message(span_notice("[user] splatters [target] with [src]... Disgusting tendrils pull [target.p_their()] wounds shut!")) + else + to_chat(user, span_notice("You smear [src] on yourself. Disgusting tendrils pull your wounds closed.")) + return TRUE + + if (!ishuman(target)) + return FALSE + + target.visible_message(span_boldwarning("[user] splatters [target] with [src]... and it springs into horrible life!")) + var/mob/living/basic/legion_brood/skull = new(target.loc) + skull.melee_attack(target) + return TRUE + +/obj/item/organ/internal/legion_tumour/on_life(seconds_per_tick, times_fired) + . = ..() + if (QDELETED(src) || QDELETED(owner)) + return + + if (stage >= 2) + if(SPT_PROB(stage / 5, seconds_per_tick)) + to_chat(owner, span_notice("You feel a bit better.")) + owner.apply_status_effect(applied_status) // It's not all bad! + if(SPT_PROB(1, seconds_per_tick)) + owner.emote("twitch") + + switch(stage) + if(2, 3) + if(SPT_PROB(1, seconds_per_tick)) + to_chat(owner, span_danger("Your chest spasms!")) + if(SPT_PROB(1, seconds_per_tick)) + to_chat(owner, span_danger("You feel weak.")) + if(SPT_PROB(1, seconds_per_tick)) + SEND_SOUND(owner, sound(pick(spooky_sounds))) + if(SPT_PROB(2, seconds_per_tick)) + owner.vomit() + if(4, 5) + if(SPT_PROB(2, seconds_per_tick)) + to_chat(owner, span_danger("Something flexes under your skin.")) + if(SPT_PROB(2, seconds_per_tick)) + if (prob(40)) + SEND_SOUND(owner, sound('sound/voice/ghost_whisper.ogg')) + else + SEND_SOUND(owner, sound(pick(spooky_sounds))) + if(SPT_PROB(3, seconds_per_tick)) + owner.vomit(vomit_type = /obj/effect/decal/cleanable/vomit/old/black_bile) + if (prob(50)) + var/turf/check_turf = get_step(owner.loc, owner.dir) + var/atom/land_turf = (check_turf.is_blocked_turf()) ? owner.loc : check_turf + var/mob/living/basic/legion_brood/child = new(land_turf) + child.assign_creator(owner, copy_full_faction = FALSE) + + if(SPT_PROB(3, seconds_per_tick)) + to_chat(owner, span_danger("Your muscles ache.")) + owner.take_bodypart_damage(3) + + if (stage == 5) + if (SPT_PROB(10, seconds_per_tick)) + infest() + return + + elapsed_time += seconds_per_tick SECONDS * ((organ_flags & ORGAN_FAILING) ? 3 : 1) // Let's call it "matured" rather than failed + if (elapsed_time < growth_time) + return + stage++ + elapsed_time = 0 + if (stage == 5) + to_chat(owner, span_bolddanger("Something is moving under your skin!")) + +/// Consume our host +/obj/item/organ/internal/legion_tumour/proc/infest() + if (QDELETED(src) || QDELETED(owner)) + return + owner.visible_message(span_boldwarning("Black tendrils burst from [owner]'s flesh, covering them in amorphous flesh!")) + var/mob/living/basic/mining/legion/new_legion = new spawn_type(owner.loc) + new_legion.consume(owner) + qdel(src) + +/obj/item/organ/internal/legion_tumour/on_find(mob/living/finder) + . = ..() + to_chat(finder, span_warning("There's an enormous tumour in [owner]'s [zone]!")) + if(stage < 4) + to_chat(finder, span_notice("Its tendrils seem to twitch towards the light.")) + return + to_chat(finder, span_notice("Its pulsing tendrils reach all throughout the body.")) + if(prob(stage * 2)) + infest() diff --git a/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm b/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm new file mode 100644 index 00000000000..1ffcafecd56 --- /dev/null +++ b/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm @@ -0,0 +1,109 @@ +/// Spawns a little worm nearby +/datum/action/cooldown/mob_cooldown/skull_launcher + name = "Launch Legion" + desc = "Propel a living piece of your body to a distant location." + button_icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' + button_icon_state = "legion_head" + background_icon_state = "bg_demon" + overlay_icon_state = "bg_demon_border" + click_to_activate = TRUE + cooldown_time = 2 SECONDS + melee_cooldown_time = 0 + check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED + shared_cooldown = NONE + /// If a mob is not clicked directly, inherit targetting data from this blackboard key and setting it upon this target key + var/ai_target_key = BB_BASIC_MOB_CURRENT_TARGET + /// What are we actually spawning? + var/spawn_type = /mob/living/basic/legion_brood + /// How far can we fire? + var/max_range = 7 + +/datum/action/cooldown/mob_cooldown/skull_launcher/Activate(atom/target) + var/turf/target_turf = get_turf(target) + + if (get_dist(owner, target_turf) > max_range) + target_turf = get_ranged_target_turf_direct(owner, target_turf, max_range) + + if (target_turf.is_blocked_turf()) + var/list/near_turfs = RANGE_TURFS(1, target_turf) - target_turf + for (var/turf/check_turf as anything in near_turfs) + if (check_turf.is_blocked_turf()) + near_turfs -= check_turf + if (length(near_turfs)) + target_turf = pick(near_turfs) + else if(target_turf.is_blocked_turf(exclude_mobs = TRUE)) + owner.balloon_alert(owner, "no room!") + StartCooldown(0.5 SECONDS) + return + + var/ai_target = isliving(target) ? target : null + if (isnull(ai_target)) + ai_target = owner.ai_controller?.blackboard[ai_target_key] + + var/target_dir = get_dir(owner, target) + + var/obj/effect/temp_visual/legion_skull_depart/launch = new(get_turf(owner)) + launch.set_appearance(spawn_type) + launch.dir = target_dir + new /obj/effect/temp_visual/legion_brood_indicator(target_turf) + var/obj/effect/temp_visual/legion_skull_land/land = new(target_turf) + land.dir = target_dir + land.set_appearance(spawn_type, CALLBACK(src, PROC_REF(spawn_skull), target_turf, ai_target)) + StartCooldown() + +/// Actually create a mob +/datum/action/cooldown/mob_cooldown/skull_launcher/proc/spawn_skull(turf/spawn_location, target) + var/mob/living/basic/legion_brood/brood = new spawn_type(spawn_location) + if (istype(brood)) + brood.assign_creator(owner) + brood.ai_controller?.set_blackboard_key(ai_target_key, target) + brood.dir = get_dir(owner, spawn_location) + if (!isnull(target)) + brood.face_atom(target) + else + brood.dir = get_dir(owner, spawn_location) + + +/// Animation for launching a skull +/obj/effect/temp_visual/legion_skull_depart + name = "legion brood launch" + icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' + icon_state = "legion_head" + duration = 0.25 SECONDS + +/// Copy appearance from the passed atom type +/obj/effect/temp_visual/legion_skull_depart/proc/set_appearance(atom/spawned_type) + icon = initial(spawned_type.icon) + icon_state = initial(spawned_type.icon_state) + animate(src, alpha = 0, pixel_y = 72, time = duration) + +/// Animation for landing a skull +/obj/effect/temp_visual/legion_skull_land + name = "legion brood land" + duration = 0.5 SECONDS + icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' + icon_state = "legion_head" + alpha = 0 + pixel_y = 72 + +/// Copy appearance from the passed atom type and store what to do on animation complete +/obj/effect/temp_visual/legion_skull_land/proc/set_appearance(atom/spawned_type, datum/callback/on_completed) + icon = initial(spawned_type.icon) + icon_state = initial(spawned_type.icon_state) + animate(src, alpha = 0, pixel_y = 72, time = duration / 2) + animate(alpha = 255, pixel_y = 0, time = duration / 2) + addtimer(on_completed, duration, TIMER_DELETE_ME) + +/// A skull is going to be here! Oh no! +/obj/effect/temp_visual/legion_brood_indicator + name = "legion brood land" + duration = 0.75 SECONDS + layer = BELOW_MOB_LAYER + plane = GAME_PLANE + icon = 'icons/mob/telegraphing/telegraph.dmi' + icon_state = "skull" + +/obj/effect/temp_visual/legion_brood_indicator/Initialize(mapload) + . = ..() + animate(src, alpha = 255, time = 0.5 SECONDS) + animate(alpha = 0, time = 0.25 SECONDS) diff --git a/code/modules/mob/living/basic/lavaland/mining.dm b/code/modules/mob/living/basic/lavaland/mining.dm index 6b1d0de5739..0b6c4f321b6 100644 --- a/code/modules/mob/living/basic/lavaland/mining.dm +++ b/code/modules/mob/living/basic/lavaland/mining.dm @@ -2,12 +2,17 @@ /mob/living/basic/mining icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' combat_mode = TRUE + status_flags = NONE //don't inherit standard basicmob flags mob_size = MOB_SIZE_LARGE mob_biotypes = MOB_ORGANIC|MOB_BEAST faction = list(FACTION_MINING) unsuitable_atmos_damage = 0 minimum_survivable_temperature = 0 maximum_survivable_temperature = INFINITY + // Pale purple, should be red enough to see stuff on lavaland + lighting_cutoff_red = 25 + lighting_cutoff_green = 15 + lighting_cutoff_blue = 35 /// Message to output if throwing damage is absorbed var/throw_blocked_message = "bounces off" /// What crusher trophy this mob drops, if any 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 1f310ac229f..a25234817f3 100644 --- a/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm +++ b/code/modules/mob/living/basic/lavaland/watcher/watcher_ai.dm @@ -9,9 +9,9 @@ planning_subtrees = list( /datum/ai_planning_subtree/target_retaliate/check_faction, /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/maintain_distance, /datum/ai_planning_subtree/use_mob_ability/gaze, /datum/ai_planning_subtree/ranged_skirmish/watcher, - /datum/ai_planning_subtree/maintain_distance, ) /datum/ai_planning_subtree/use_mob_ability/gaze diff --git a/code/modules/mob/living/basic/minebots/minebot_ai.dm b/code/modules/mob/living/basic/minebots/minebot_ai.dm index 897cddb1401..a4b082f5dd1 100644 --- a/code/modules/mob/living/basic/minebots/minebot_ai.dm +++ b/code/modules/mob/living/basic/minebots/minebot_ai.dm @@ -60,6 +60,7 @@ /datum/ai_behavior/basic_ranged_attack/minebot behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT + avoid_friendly_fire = TRUE /datum/ai_planning_subtree/basic_ranged_attack_subtree/minebot/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) var/mob/living/living_pawn = controller.pawn diff --git a/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_behavior.dm b/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_behavior.dm index 4cdaba09759..28cffa4ed8e 100644 --- a/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_behavior.dm +++ b/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_behavior.dm @@ -64,6 +64,8 @@ /datum/ai_behavior/basic_ranged_attack/hivebot action_cooldown = 3 SECONDS + avoid_friendly_fire = TRUE /datum/ai_behavior/basic_ranged_attack/hivebot_rapid action_cooldown = 1.5 SECONDS + avoid_friendly_fire = TRUE diff --git a/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_subtree.dm b/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_subtree.dm index 347219d0ef0..5bd957a7609 100644 --- a/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_subtree.dm +++ b/code/modules/mob/living/basic/space_fauna/hivebot/hivebot_subtree.dm @@ -32,7 +32,7 @@ /datum/ai_controller/basic_controller/hivebot/ranged/rapid planning_subtrees = list( /datum/ai_planning_subtree/simple_find_target, - /datum/ai_planning_subtree/basic_ranged_attack_subtree, + /datum/ai_planning_subtree/basic_ranged_attack_subtree/hivebot_rapid, /datum/ai_planning_subtree/attack_obstacle_in_path, /datum/ai_planning_subtree/hive_communicate, ) diff --git a/code/modules/mob/living/basic/space_fauna/morph.dm b/code/modules/mob/living/basic/space_fauna/morph.dm index 3f31f7f3735..32115d05602 100644 --- a/code/modules/mob/living/basic/space_fauna/morph.dm +++ b/code/modules/mob/living/basic/space_fauna/morph.dm @@ -21,6 +21,7 @@ obj_damage = 50 melee_damage_lower = 20 melee_damage_upper = 20 + melee_attack_cooldown = CLICK_CD_MELEE // Oh you KNOW it's gonna be real green lighting_cutoff_red = 10 diff --git a/code/modules/mob/living/basic/space_fauna/netherworld/blankbody.dm b/code/modules/mob/living/basic/space_fauna/netherworld/blankbody.dm index 5a7bb075f19..d49932fb704 100644 --- a/code/modules/mob/living/basic/space_fauna/netherworld/blankbody.dm +++ b/code/modules/mob/living/basic/space_fauna/netherworld/blankbody.dm @@ -26,22 +26,9 @@ lighting_cutoff_green = 15 lighting_cutoff_blue = 40 - ai_controller = /datum/ai_controller/basic_controller/blankbody + ai_controller = /datum/ai_controller/basic_controller/simple_hostile_obstacles /mob/living/basic/blankbody/Initialize(mapload) . = ..() AddElement(/datum/element/swabable, CELL_LINE_TABLE_NETHER, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 0) AddComponent(/datum/component/health_scaling_effects, min_health_attack_modifier_lower = 8, min_health_attack_modifier_upper = 14) - -/datum/ai_controller/basic_controller/blankbody - 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/attack_obstacle_in_path, - /datum/ai_planning_subtree/basic_melee_attack_subtree, - ) diff --git a/code/modules/mob/living/basic/space_fauna/netherworld/creature.dm b/code/modules/mob/living/basic/space_fauna/netherworld/creature.dm index b38ada0f6e1..cdde6ad05e4 100644 --- a/code/modules/mob/living/basic/space_fauna/netherworld/creature.dm +++ b/code/modules/mob/living/basic/space_fauna/netherworld/creature.dm @@ -27,7 +27,7 @@ lighting_cutoff_green = 25 lighting_cutoff_blue = 15 - ai_controller = /datum/ai_controller/basic_controller/creature + ai_controller = /datum/ai_controller/basic_controller/simple_hostile_obstacles /mob/living/basic/creature/Initialize(mapload) . = ..() @@ -101,16 +101,3 @@ exit_jaunt(cast_on) return enter_jaunt(cast_on) - -/datum/ai_controller/basic_controller/creature - 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/attack_obstacle_in_path, - /datum/ai_planning_subtree/basic_melee_attack_subtree, - ) diff --git a/code/modules/mob/living/basic/space_fauna/netherworld/migo.dm b/code/modules/mob/living/basic/space_fauna/netherworld/migo.dm index 18dca95013e..3f445ea1261 100644 --- a/code/modules/mob/living/basic/space_fauna/netherworld/migo.dm +++ b/code/modules/mob/living/basic/space_fauna/netherworld/migo.dm @@ -28,7 +28,7 @@ lighting_cutoff_green = 15 lighting_cutoff_blue = 50 - ai_controller = /datum/ai_controller/basic_controller/migo + ai_controller = /datum/ai_controller/basic_controller/simple_hostile_obstacles var/static/list/migo_sounds /// Odds migo will dodge var/dodge_prob = 10 @@ -71,16 +71,3 @@ . = Move(get_step(loc,pick(cdir, ccdir))) if(!.)//Can't dodge there so we just carry on . = Move(moving_to, move_direction) - -/datum/ai_controller/basic_controller/migo - 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/attack_obstacle_in_path, - /datum/ai_planning_subtree/basic_melee_attack_subtree, - ) diff --git a/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_wizard.dm b/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_wizard.dm index 3b32fbb4ce7..519e8ba1a73 100644 --- a/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_wizard.dm +++ b/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_wizard.dm @@ -110,8 +110,7 @@ faction = list(FACTION_STICKMAN) melee_damage_lower = 1 melee_damage_upper = 5 - - ai_controller = /datum/ai_controller/basic_controller/wizard_copy + ai_controller = /datum/ai_controller/basic_controller/simple_hostile /mob/living/basic/paper_wizard/copy/Initialize(mapload) . = ..() @@ -141,18 +140,6 @@ new /obj/effect/temp_visual/small_smoke/halfsecond(get_turf(src)) qdel(src) //I see through your ruse! -/datum/ai_controller/basic_controller/wizard_copy - 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/basic_melee_attack_subtree, - ) - //fancy effects /obj/effect/temp_visual/paper_scatter name = "scattering paper" diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm index 85369b72eb8..164c25fb896 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm @@ -24,6 +24,7 @@ obj_damage = 10 melee_damage_lower = 13 melee_damage_upper = 15 + melee_attack_cooldown = CLICK_CD_MELEE attack_verb_continuous = "slashes" attack_verb_simple = "slash" attack_sound = 'sound/weapons/bladeslice.ogg' diff --git a/code/modules/mob/living/simple_animal/friendly/robot_customer.dm b/code/modules/mob/living/basic/space_fauna/robot_customer.dm similarity index 63% rename from code/modules/mob/living/simple_animal/friendly/robot_customer.dm rename to code/modules/mob/living/basic/space_fauna/robot_customer.dm index 13eac2939f3..e084e11f403 100644 --- a/code/modules/mob/living/simple_animal/friendly/robot_customer.dm +++ b/code/modules/mob/living/basic/space_fauna/robot_customer.dm @@ -1,45 +1,56 @@ ///Robot customers -/mob/living/simple_animal/robot_customer - name = "space-tourist bot" +/mob/living/basic/robot_customer + name = "tourist bot" maxHealth = 150 health = 150 desc = "I wonder what they'll order..." gender = NEUTER + icon = 'icons/mob/simple/tourists.dmi' icon_state = "amerifat" icon_living = "amerifat" - ///Override so it uses datum ai - can_have_ai = FALSE - AIStatus = AI_OFF - del_on_death = TRUE + + basic_mob_flags = DEL_ON_DEATH mob_biotypes = MOB_ROBOTIC|MOB_HUMANOID sentience_type = SENTIENCE_ARTIFICIAL - ai_controller = /datum/ai_controller/robot_customer + unsuitable_atmos_damage = 0 - minbodytemp = 0 - maxbodytemp = 1000 + minimum_survivable_temperature = TCMB + maximum_survivable_temperature = T0C + 1000 + + ai_controller = /datum/ai_controller/robot_customer + + /// The clothes that we draw on this tourist. var/clothes_set = "amerifat_clothes" + /// Reference to the hud that we show when the player hovers over us. var/datum/atom_hud/hud_to_show_on_hover - -/mob/living/simple_animal/robot_customer/Initialize(mapload, datum/customer_data/customer_data = /datum/customer_data/american, datum/venue/attending_venue = SSrestaurant.all_venues[/datum/venue/restaurant]) - ADD_TRAIT(src, list(TRAIT_NOMOBSWAP, TRAIT_NO_TELEPORT, TRAIT_STRONG_GRABBER), INNATE_TRAIT) // never suffer a bitch to fuck with you - AddElement(/datum/element/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, sound_vary = TRUE) +/mob/living/basic/robot_customer/Initialize( + mapload, + datum/customer_data/customer_data = /datum/customer_data/american, + datum/venue/attending_venue = SSrestaurant.all_venues[/datum/venue/restaurant], +) var/datum/customer_data/customer_info = SSrestaurant.all_customers[customer_data] - clothes_set = pick(customer_info.clothing_sets) ai_controller = customer_info.ai_controller_used + . = ..() + + ADD_TRAIT(src, list(TRAIT_NOMOBSWAP, TRAIT_NO_TELEPORT, TRAIT_STRONG_GRABBER), INNATE_TRAIT) // never suffer a bitch to fuck with you + AddElement(/datum/element/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, sound_vary = TRUE) + ai_controller.set_blackboard_key(BB_CUSTOMER_CUSTOMERINFO, customer_info) ai_controller.set_blackboard_key(BB_CUSTOMER_ATTENDING_VENUE, attending_venue) ai_controller.set_blackboard_key(BB_CUSTOMER_PATIENCE, customer_info.total_patience) + icon = customer_info.base_icon icon_state = customer_info.base_icon_state name = "[pick(customer_info.name_prefixes)]-bot" color = rgb(rand(80,255), rand(80,255), rand(80,255)) - update_icon() + clothes_set = pick(customer_info.clothing_sets) + update_appearance(UPDATE_ICON) ///Clean up on the mobs seat etc when its deleted (Either by murder or because it left) -/mob/living/simple_animal/robot_customer/Destroy() +/mob/living/basic/robot_customer/Destroy() var/datum/venue/attending_venue = ai_controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] var/obj/structure/holosign/robot_seat/our_seat = ai_controller.blackboard[BB_CUSTOMER_MY_SEAT] attending_venue.current_visitors -= src @@ -49,18 +60,18 @@ return ..() ///Robots need robot gibs...! -/mob/living/simple_animal/robot_customer/spawn_gibs() +/mob/living/basic/robot_customer/spawn_gibs() new /obj/effect/gibspawner/robot(drop_location(), src) -/mob/living/simple_animal/robot_customer/MouseEntered(location, control, params) +/mob/living/basic/robot_customer/MouseEntered(location, control, params) . = ..() hud_to_show_on_hover?.show_to(usr) -/mob/living/simple_animal/robot_customer/MouseExited(location, control, params) +/mob/living/basic/robot_customer/MouseExited(location, control, params) . = ..() hud_to_show_on_hover?.hide_from(usr) -/mob/living/simple_animal/robot_customer/update_overlays() +/mob/living/basic/robot_customer/update_overlays() . = ..() var/datum/customer_data/customer_info = ai_controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] @@ -82,21 +93,24 @@ if(bonus_overlays) . += bonus_overlays -/mob/living/simple_animal/robot_customer/send_speech(message, message_range, obj/source, bubble_type, list/spans, datum/language/message_language, list/message_mods, forced, tts_message, list/tts_filter) +/mob/living/basic/robot_customer/send_speech(message, message_range, obj/source, bubble_type, list/spans, datum/language/message_language, list/message_mods, forced, tts_message, list/tts_filter) . = ..() var/datum/customer_data/customer_info = ai_controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] playsound(src, customer_info.speech_sound, 30, extrarange = MEDIUM_RANGE_SOUND_EXTRARANGE, falloff_distance = 5) -/mob/living/simple_animal/robot_customer/examine(mob/user) +/mob/living/basic/robot_customer/examine(mob/user) . = ..() - // this should be handled by the ai controller - if(ai_controller.blackboard[BB_CUSTOMER_CURRENT_ORDER]) - var/datum/venue/attending_venue = ai_controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] - var/wanted_item = ai_controller.blackboard[BB_CUSTOMER_CURRENT_ORDER] - var/order - if(istype(wanted_item, /datum/custom_order)) - var/datum/custom_order/custom_order = wanted_item - order = custom_order.get_order_line(attending_venue) - else - order = attending_venue.order_food_line(wanted_item) - . += span_notice("Their order was: \"[order].\"") + if(isnull(ai_controller.blackboard[BB_CUSTOMER_CURRENT_ORDER])) + return + + var/datum/venue/attending_venue = ai_controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] + var/wanted_item = ai_controller.blackboard[BB_CUSTOMER_CURRENT_ORDER] + var/order = "nothing" + + if(istype(wanted_item, /datum/custom_order)) + var/datum/custom_order/custom_order = wanted_item + order = custom_order.get_order_line(attending_venue) + else + order = attending_venue.order_food_line(wanted_item) + + . += span_notice("Their order was: \"[order].\"") diff --git a/code/modules/mob/living/basic/space_fauna/snake/snake.dm b/code/modules/mob/living/basic/space_fauna/snake/snake.dm new file mode 100644 index 00000000000..13b9a327cc5 --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/snake/snake.dm @@ -0,0 +1,86 @@ + +/mob/living/basic/snake + name = "snake" + desc = "A slithery snake. These legless reptiles are the bane of mice and adventurers alike." + icon_state = "snake" + icon_living = "snake" + icon_dead = "snake_dead" + speak_emote = list("hisses") + + health = 20 + maxHealth = 20 + melee_damage_lower = 5 + melee_damage_upper = 6 + obj_damage = 0 + environment_smash = ENVIRONMENT_SMASH_NONE + + attack_verb_continuous = "bites" + attack_verb_simple = "bite" + attack_sound = 'sound/weapons/bite.ogg' + attack_vis_effect = ATTACK_EFFECT_BITE + + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "shoos" + response_disarm_simple = "shoo" + response_harm_continuous = "steps on" + response_harm_simple = "step on" + + density = FALSE + pass_flags = PASSTABLE | PASSMOB + mob_size = MOB_SIZE_SMALL + + faction = list(FACTION_HOSTILE) + mob_biotypes = MOB_ORGANIC | MOB_BEAST | MOB_REPTILE + gold_core_spawnable = FRIENDLY_SPAWN + + ai_controller = /datum/ai_controller/basic_controller/snake + + /// List of stuff (mice) that we want to eat + var/static/list/edibles = list( + /mob/living/basic/mouse, + /obj/item/food/deadmouse, + ) + +/mob/living/basic/snake/Initialize(mapload, special_reagent) + . = ..() + ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT) + + AddElement(/datum/element/ai_retaliate) + AddElement(/datum/element/swabable, CELL_LINE_TABLE_SNAKE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) + + AddElement(/datum/element/basic_eating, 2, 0, null, edibles) + ai_controller.set_blackboard_key(BB_BASIC_FOODS, edibles) + + AddComponent(\ + /datum/component/tameable,\ + food_types = list(/obj/item/food/deadmouse),\ + tame_chance = 75,\ + bonus_tame_chance = 10,\ + ) // snakes are really fond of food, especially in the cold darkness of space :) + + if(isnull(special_reagent)) + special_reagent = /datum/reagent/toxin + + AddElement(/datum/element/venomous, special_reagent, 4) + +/mob/living/basic/snake/befriend(mob/living/new_friend) + . = ..() + visible_message("[src] hisses happily as it seems to bond with [new_friend].") + +/// Snakes are primarily concerned with getting those tasty, tasty mice, but aren't afraid to strike back at those who attack them +/datum/ai_controller/basic_controller/snake + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends/allow_items, + ) + + 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/snake, + ) diff --git a/code/modules/mob/living/basic/space_fauna/snake/snake_ai.dm b/code/modules/mob/living/basic/space_fauna/snake/snake_ai.dm new file mode 100644 index 00000000000..3eb404761c5 --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/snake/snake_ai.dm @@ -0,0 +1,6 @@ +/datum/ai_planning_subtree/random_speech/snake + speech_chance = 5 + speak = list("hsssss","sssSSsssss...","hiisssss") + sound = list('sound/creatures/snake_hissing1.ogg', 'sound/creatures/snake_hissing2.ogg') + emote_hear = list("hisses.") + emote_see = list("slithers around.", "glances.", "stares.") diff --git a/code/modules/mob/living/basic/space_fauna/spider/spider.dm b/code/modules/mob/living/basic/space_fauna/spider/spider.dm index e96482439f9..4bd773f6d0a 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/spider.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/spider.dm @@ -13,6 +13,7 @@ response_disarm_continuous = "gently pushes aside" response_disarm_simple = "gently push aside" initial_language_holder = /datum/language_holder/spider + melee_attack_cooldown = CLICK_CD_MELEE damage_coeff = list(BRUTE = 1, BURN = 1.25, TOX = 1, CLONE = 1, STAMINA = 1, OXY = 1) basic_mob_flags = FLAMMABLE_MOB status_flags = NONE diff --git a/code/modules/mob/living/basic/space_fauna/spider/young_spider/young_spider.dm b/code/modules/mob/living/basic/space_fauna/spider/young_spider/young_spider.dm index 57b9da542b7..50ec85e342c 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/young_spider/young_spider.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/young_spider/young_spider.dm @@ -30,6 +30,7 @@ /datum/ai_controller/basic_controller/young_spider blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), + BB_BASIC_MOB_FLEE_DISTANCE = 6, ) ai_traits = STOP_MOVING_WHEN_PULLED @@ -46,6 +47,3 @@ /datum/ai_planning_subtree/find_unwebbed_turf, /datum/ai_planning_subtree/spin_web, ) - -/datum/ai_behavior/run_away_from_target/young_spider - run_distance = 6 diff --git a/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm b/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm new file mode 100644 index 00000000000..2a3ba326eac --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm @@ -0,0 +1,102 @@ +/// A nasty little robotic bug that dusts people on attack. Jeepers. This should be a very, very, very rare spawn. +/mob/living/basic/supermatter_spider + name = "supermatter spider" + desc= "A sliver of supermatter placed upon a robotically enhanced pedestal." + + icon = 'icons/mob/simple/smspider.dmi' + icon_state = "smspider" + icon_living = "smspider" + icon_dead = "smspider_dead" + + gender = NEUTER + mob_biotypes = MOB_BUG|MOB_ROBOTIC + speak_emote = list("vibrates") + + + attack_verb_continuous = "slices" + attack_verb_simple = "slice" + attack_sound = 'sound/effects/supermatter.ogg' + attack_vis_effect = ATTACK_EFFECT_CLAW + + maxHealth = 10 + health = 10 + minimum_survivable_temperature = TCMB + maximum_survivable_temperature = T0C + 1250 + habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + death_message = "falls to the ground, its shard dulling to a miserable grey!" + + faction = list(FACTION_HOSTILE) + + // Gold, supermatter tinted + lighting_cutoff_red = 30 + lighting_cutoff_green = 30 + lighting_cutoff_blue = 10 + + ai_controller = /datum/ai_controller/basic_controller/supermatter_spider + + /// If we successfully dust something, should we die? + var/single_use = TRUE + +/mob/living/basic/supermatter_spider/Initialize(mapload) + . = ..() + AddComponent(/datum/component/swarming) + + AddElement(/datum/element/ai_retaliate) + AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW) + + RegisterSignal(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(on_attack)) + +/// Proc that we call on attacking something to dust 'em. +/mob/living/basic/supermatter_spider/proc/on_attack(mob/living/basic/source, atom/target) + SIGNAL_HANDLER + + if(isliving(target)) + var/mob/living/victim = target + victim.investigate_log("has been dusted by [src].", INVESTIGATE_DEATHS) + dust_feedback(target) + victim.dust() + if(single_use) + death() + return COMPONENT_HOSTILE_NO_ATTACK + + if(!isturf(target)) + dust_feedback(target) + qdel(target) + if(single_use) + death() + return COMPONENT_HOSTILE_NO_ATTACK + +/// Simple proc that plays the supermatter dusting sound and sends a visible message. +/mob/living/basic/supermatter_spider/proc/dust_feedback(atom/target) + playsound(get_turf(src), 'sound/effects/supermatter.ogg', 10, TRUE) + visible_message(span_danger("[src] knocks into [target], turning [target.p_them()] to dust in a brilliant flash of light!")) + +/mob/living/basic/supermatter_spider/overcharged + name = "overcharged supermatter spider" + desc = "A sliver of overcharged supermatter placed upon a robotically enhanced pedestal. This one seems especially dangerous." + icon_state = "smspideroc" + icon_living = "smspideroc" + maxHealth = 25 + health = 25 + single_use = FALSE + +/datum/ai_controller/basic_controller/supermatter_spider + 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/target_retaliate, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/random_speech/supermatter_spider, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) + +/datum/ai_planning_subtree/random_speech/supermatter_spider + speech_chance = 7 + emote_hear = list("clinks", "clanks") + emote_see = list("vibrates") diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index 0b3645b3e0f..46e175c5323 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -51,7 +51,7 @@ held_state = "mouse_[body_color]" // not handled by variety element AddElement(/datum/element/animal_variety, "mouse", body_color, FALSE) AddElement(/datum/element/swabable, CELL_LINE_TABLE_MOUSE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 10) - AddComponent(/datum/component/squeak, list('sound/effects/mousesqueek.ogg' = 1), 100, extrarange = SHORT_RANGE_SOUND_EXTRARANGE) //as quiet as a mouse or whatever + AddComponent(/datum/component/squeak, list('sound/creatures/mousesqueek.ogg' = 1), 100, extrarange = SHORT_RANGE_SOUND_EXTRARANGE) //as quiet as a mouse or whatever var/static/list/loc_connections = list( COMSIG_ATOM_ENTERED = PROC_REF(on_entered), ) @@ -381,6 +381,7 @@ BB_CURRENT_HUNTING_TARGET = null, // cheese BB_LOW_PRIORITY_HUNTING_TARGET = null, // cable BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), // Use this to find people to run away from + BB_BASIC_MOB_FLEE_DISTANCE = 3, ) ai_traits = STOP_MOVING_WHEN_PULLED @@ -400,9 +401,6 @@ ) /// Don't look for anything to run away from if you are distracted by being adjacent to cheese -/datum/ai_planning_subtree/flee_target/mouse - flee_behaviour = /datum/ai_behavior/run_away_from_target/mouse - /datum/ai_planning_subtree/flee_target/mouse /datum/ai_planning_subtree/flee_target/mouse/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) @@ -411,11 +409,6 @@ return // We see some cheese, which is more important than our life return ..() -/datum/ai_planning_subtree/flee_target/mouse/select - -/datum/ai_behavior/run_away_from_target/mouse - run_distance = 3 // Mostly exists in small tunnels, don't get ahead of yourself - /// AI controller for rats, slightly more complex than mice becuase they attack people /datum/ai_controller/basic_controller/mouse/rat blackboard = list( diff --git a/code/modules/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm index e182c51f54f..b63ca68d7d7 100644 --- a/code/modules/mob/living/brain/MMI.dm +++ b/code/modules/mob/living/brain/MMI.dm @@ -268,7 +268,7 @@ if(user) to_chat(user, span_warning("\The [src] indicates that there is no mind present!")) return FALSE - if(brain.decoy_override) + if(brain?.decoy_override) if(user) to_chat(user, span_warning("This [name] does not seem to fit!")) return FALSE diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 4bd275b5df1..10cff8c19ac 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -39,6 +39,21 @@ /// Maximum skillchip slots available. Do not reference this var directly and instead call get_max_skillchip_slots() var/max_skillchip_slots = 5 + /// Size modifier for the sprite + var/brain_size = 1 + +/obj/item/organ/internal/brain/Initialize(mapload) + . = ..() + // Brain size logic + transform = transform.Scale(brain_size) + +/obj/item/organ/internal/brain/examine() + . = ..() + if(brain_size < 1) + . += span_notice("It is a bit on the smaller side...") + if(brain_size > 1) + . += span_notice("It is bigger than average...") + /obj/item/organ/internal/brain/Insert(mob/living/carbon/brain_owner, special = FALSE, drop_if_replaced = TRUE, no_id_transfer = FALSE) . = ..() if(!.) @@ -406,6 +421,9 @@ . = ..() organ_owner.gain_trauma(/datum/brain_trauma/special/bluespace_prophet, TRAUMA_RESILIENCE_ABSOLUTE) +/obj/item/organ/internal/brain/felinid //A bit smaller than average + brain_size = 0.8 + ////////////////////////////////////TRAUMAS//////////////////////////////////////// /obj/item/organ/internal/brain/proc/has_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience = TRAUMA_RESILIENCE_ABSOLUTE) @@ -553,4 +571,4 @@ var/obj/item/organ/internal/brain/old_brain = new_owner.get_organ_slot(ORGAN_SLOT_BRAIN) old_brain.Remove(new_owner, special = TRUE, no_id_transfer = TRUE) qdel(old_brain) - Insert(new_owner, special = TRUE, drop_if_replaced = FALSE, no_id_transfer = TRUE) + return Insert(new_owner, special = TRUE, drop_if_replaced = FALSE, no_id_transfer = TRUE) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 8b97685d0a8..789a459b492 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -57,6 +57,13 @@ return null +/mob/living/carbon/is_ears_covered() + for(var/obj/item/worn_thing as anything in get_equipped_items()) + if(worn_thing.flags_cover & EARS_COVERED) + return worn_thing + + return null + /mob/living/carbon/check_projectile_dismemberment(obj/projectile/P, def_zone) var/obj/item/bodypart/affecting = get_bodypart(def_zone) if(affecting && !(affecting.bodypart_flags & BODYPART_UNREMOVABLE) && affecting.get_damage() >= (affecting.max_damage - P.dismemberment)) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 17718190ba5..6a8fc967cb5 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -449,6 +449,13 @@ GLOBAL_LIST_EMPTY(features_by_species) wearer.hud_used?.update_locked_slots() worn_items_fit_body_check(wearer) +/** + * Normalizes blood in a human if it is excessive. If it is above BLOOD_VOLUME_NORMAL, this will clamp it to that value. It will not give the human more blodo than they have less than this value. + */ +/datum/species/proc/normalize_blood(mob/living/carbon/human/blood_possessing_human) + var/normalized_blood_values = max(blood_possessing_human.blood_volume, 0, BLOOD_VOLUME_NORMAL) + blood_possessing_human.blood_volume = normalized_blood_values + /** * Proc called when a carbon becomes this species. * @@ -459,34 +466,37 @@ GLOBAL_LIST_EMPTY(features_by_species) * * old_species - The species that the carbon used to be before becoming this race, used for regenerating organs. * * pref_load - Preferences to be loaded from character setup, loads in preferred mutant things like bodyparts, digilegs, skin color, etc. */ -/datum/species/proc/on_species_gain(mob/living/carbon/human/C, datum/species/old_species, pref_load) +/datum/species/proc/on_species_gain(mob/living/carbon/human/human_who_gained_species, datum/species/old_species, pref_load) SHOULD_CALL_PARENT(TRUE) // Drop the items the new species can't wear - if(C.hud_used) - C.hud_used.update_locked_slots() + if(human_who_gained_species.hud_used) + human_who_gained_species.hud_used.update_locked_slots() - C.mob_biotypes = inherent_biotypes - C.mob_respiration_type = inherent_respiration_type - C.butcher_results = knife_butcher_results?.Copy() + human_who_gained_species.mob_biotypes = inherent_biotypes + human_who_gained_species.mob_respiration_type = inherent_respiration_type + human_who_gained_species.butcher_results = knife_butcher_results?.Copy() if(old_species.type != type) - replace_body(C, src) + replace_body(human_who_gained_species, src) - regenerate_organs(C, old_species, visual_only = C.visual_only_organs) + regenerate_organs(human_who_gained_species, old_species, visual_only = human_who_gained_species.visual_only_organs) // Drop the items the new species can't wear - INVOKE_ASYNC(src, PROC_REF(worn_items_fit_body_check), C, TRUE) + INVOKE_ASYNC(src, PROC_REF(worn_items_fit_body_check), human_who_gained_species, TRUE) //Assigns exotic blood type if the species has one - if(exotic_bloodtype && C.dna.blood_type != exotic_bloodtype) - C.dna.blood_type = exotic_bloodtype + if(exotic_bloodtype && human_who_gained_species.dna.blood_type != exotic_bloodtype) + human_who_gained_species.dna.blood_type = exotic_bloodtype //Otherwise, check if the previous species had an exotic bloodtype and we do not have one and assign a random blood type //(why the fuck is blood type not tied to a fucking DNA block?) else if(old_species.exotic_bloodtype && !exotic_bloodtype) - C.dna.blood_type = random_blood_type() + human_who_gained_species.dna.blood_type = random_blood_type() - if(ishuman(C)) - var/mob/living/carbon/human/human = C + //Resets blood if it is excessively high for some reason + normalize_blood(human_who_gained_species) + + if(ishuman(human_who_gained_species)) + var/mob/living/carbon/human/human = human_who_gained_species for(var/obj/item/organ/external/organ_path as anything in external_organs) if(!should_external_organ_apply_to(organ_path, human)) continue @@ -495,25 +505,27 @@ GLOBAL_LIST_EMPTY(features_by_species) var/obj/item/organ/external/new_organ = SSwardrobe.provide_type(organ_path) new_organ.Insert(human, special=TRUE, drop_if_replaced=FALSE) + + if(length(inherent_traits)) - C.add_traits(inherent_traits, SPECIES_TRAIT) + human_who_gained_species.add_traits(inherent_traits, SPECIES_TRAIT) if(inherent_factions) for(var/i in inherent_factions) - C.faction += i //Using +=/-= for this in case you also gain the faction from a different source. + human_who_gained_species.faction += i //Using +=/-= for this in case you also gain the faction from a different source. // All languages associated with this language holder are added with source [LANGUAGE_SPECIES] // rather than source [LANGUAGE_ATOM], so we can track what to remove if our species changes again var/datum/language_holder/gaining_holder = GLOB.prototype_language_holders[species_language_holder] for(var/language in gaining_holder.understood_languages) - C.grant_language(language, UNDERSTOOD_LANGUAGE, LANGUAGE_SPECIES) + human_who_gained_species.grant_language(language, UNDERSTOOD_LANGUAGE, LANGUAGE_SPECIES) for(var/language in gaining_holder.spoken_languages) - C.grant_language(language, SPOKEN_LANGUAGE, LANGUAGE_SPECIES) + human_who_gained_species.grant_language(language, SPOKEN_LANGUAGE, LANGUAGE_SPECIES) for(var/language in gaining_holder.blocked_languages) - C.add_blocked_language(language, LANGUAGE_SPECIES) - C.regenerate_icons() + human_who_gained_species.add_blocked_language(language, LANGUAGE_SPECIES) + human_who_gained_species.regenerate_icons() - SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species) + SEND_SIGNAL(human_who_gained_species, COMSIG_SPECIES_GAIN, src, old_species) properly_gained = TRUE @@ -1484,7 +1496,7 @@ GLOBAL_LIST_EMPTY(features_by_species) */ /datum/species/proc/handle_body_temperature(mob/living/carbon/human/humi, seconds_per_tick, times_fired) //when in a cryo unit we suspend all natural body regulation - if(istype(humi.loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) + if(istype(humi.loc, /obj/machinery/cryo_cell)) return //Only stabilise core temp when alive and not in statis diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 40e4bf095d5..680e5c14f7e 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -372,7 +372,7 @@ var/obj/item/bodypart/the_part = isbodypart(target_zone) ? target_zone : get_bodypart(check_zone(target_zone)) //keep these synced // Loop through the clothing covering this bodypart and see if there's any thiccmaterials if(!(injection_flags & INJECT_CHECK_PENETRATE_THICK)) - for(var/obj/item/clothing/iter_clothing in clothingonpart(the_part)) + for(var/obj/item/clothing/iter_clothing in get_clothing_on_part(the_part)) if(iter_clothing.clothing_flags & THICKMATERIAL) . = FALSE break @@ -786,6 +786,7 @@ VV_DROPDOWN_OPTION(VV_HK_MOD_QUIRKS, "Add/Remove Quirks") VV_DROPDOWN_OPTION(VV_HK_SET_SPECIES, "Set Species") VV_DROPDOWN_OPTION(VV_HK_PURRBATION, "Toggle Purrbation") + VV_DROPDOWN_OPTION(VV_HK_APPLY_DNA_INFUSION, "Apply DNA Infusion") /mob/living/carbon/human/vv_do_topic(list/href_list) . = ..() @@ -871,6 +872,19 @@ var/msg = span_notice("[key_name_admin(usr)] has removed [key_name(src)] from purrbation.") message_admins(msg) admin_ticket_log(src, msg) + if(href_list[VV_HK_APPLY_DNA_INFUSION]) + if(!check_rights(R_SPAWN)) + return + if(!ishuman(src)) + to_chat(usr, "This can only be done to human species.") + return + var/result = usr.client.grant_dna_infusion(src) + if(result) + to_chat(usr, "Successfully applied DNA Infusion [result] to [src].") + log_admin("[key_name(usr)] has applied DNA Infusion [result] to [key_name(src)].") + else + to_chat(usr, "Failed to apply DNA Infusion to [src].") + log_admin("[key_name(usr)] failed to apply a DNA Infusion to [key_name(src)].") /mob/living/carbon/human/limb_attack_self() var/obj/item/bodypart/arm = hand_bodyparts[active_hand_index] diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index bc951d49bb7..b02aaf03b17 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -6,21 +6,21 @@ if(isbodypart(def_zone)) var/obj/item/bodypart/bp = def_zone if(bp) - return checkarmor(def_zone, type) + return check_armor(def_zone, type) var/obj/item/bodypart/affecting = get_bodypart(check_zone(def_zone)) if(affecting) - return checkarmor(affecting, type) + return check_armor(affecting, type) //If a specific bodypart is targetted, check how that bodypart is protected and return the value. //If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values for(var/X in bodyparts) var/obj/item/bodypart/BP = X - armorval += checkarmor(BP, type) + armorval += check_armor(BP, type) organnum++ return (armorval/max(organnum, 1)) -/mob/living/carbon/human/proc/checkarmor(obj/item/bodypart/def_zone, damage_type) +/mob/living/carbon/human/proc/check_armor(obj/item/bodypart/def_zone, damage_type) if(!damage_type) return 0 var/protection = 100 @@ -32,7 +32,7 @@ return 100 - protection ///Get all the clothing on a specific body part -/mob/living/carbon/human/proc/clothingonpart(obj/item/bodypart/def_zone) +/mob/living/carbon/human/proc/get_clothing_on_part(obj/item/bodypart/def_zone) var/list/covering_part = list() var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id, wear_neck) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor) for(var/bp in body_parts) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index c91fc7d6638..2e061d32a6b 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -100,7 +100,7 @@ /// Environment handlers for species /mob/living/carbon/human/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) // If we are in a cryo bed do not process life functions - if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) + if(istype(loc, /obj/machinery/cryo_cell)) return dna.species.handle_environment(src, environment, seconds_per_tick, times_fired) diff --git a/code/modules/mob/living/carbon/human/species_types/abominations.dm b/code/modules/mob/living/carbon/human/species_types/abominations.dm index b7be74565ac..43ca71311c2 100644 --- a/code/modules/mob/living/carbon/human/species_types/abominations.dm +++ b/code/modules/mob/living/carbon/human/species_types/abominations.dm @@ -3,6 +3,7 @@ name = "\improper Tall Boy" id = SPECIES_TALLBOY examine_limb_id = SPECIES_HUMAN + changesource_flags = MIRROR_BADMIN | WABBAJACK bodypart_overrides = list( BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left, BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right, @@ -13,8 +14,10 @@ ) /datum/species/monkey/human_legged + name = "human-legged monkey" id = SPECIES_MONKEY_HUMAN_LEGGED examine_limb_id = SPECIES_MONKEY + changesource_flags = MIRROR_BADMIN | WABBAJACK bodypart_overrides = list( BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/monkey, BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/monkey, @@ -25,8 +28,10 @@ ) /datum/species/monkey/monkey_freak + name = "human-armed monkey" id = SPECIES_MONKEY_FREAK examine_limb_id = SPECIES_MONKEY + changesource_flags = MIRROR_BADMIN | WABBAJACK bodypart_overrides = list( BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left, BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right, diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm index 793da47c05b..c8e14a6afd1 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -4,6 +4,7 @@ id = SPECIES_FELINE examine_limb_id = SPECIES_HUMAN mutant_bodyparts = list("ears" = "Cat", "wings" = "None") + mutantbrain = /obj/item/organ/internal/brain/felinid mutanttongue = /obj/item/organ/internal/tongue/cat /* SKYRAT EDIT REMOVAL - CUSTOMIZATION mutantears = /obj/item/organ/internal/ears/cat @@ -23,8 +24,6 @@ family_heirlooms = list(/obj/item/toy/cattoy) /// When false, this is a felinid created by mass-purrbation var/original_felinid = TRUE - /// Brain size for scaling - var/brain_size = 0.8 // Prevents felinids from taking toxin damage from carpotoxin /datum/species/human/felinid/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) @@ -47,16 +46,6 @@ ears.Insert(target_human, drop_if_replaced = FALSE) else mutantears = /obj/item/organ/internal/ears - var/obj/item/organ/internal/brain/current_brain = target_human.get_organ_by_type(/obj/item/organ/internal/brain) - if(current_brain) - current_brain.transform = current_brain.transform.Scale(brain_size) //smaller brain - return ..() - -/datum/species/human/felinid/on_species_loss(mob/living/carbon/former_feline, datum/species/old_species, pref_load) - if(iscarbon(former_feline)) - var/obj/item/organ/internal/brain/current_brain = former_feline.get_organ_by_type(/obj/item/organ/internal/brain) - if(current_brain) - current_brain.transform = current_brain.transform.Scale(1 / brain_size) //bigger brain return ..() /datum/species/human/felinid/randomize_features(mob/living/carbon/human/human_mob) diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm index 2c997274ffb..9db5a3253eb 100644 --- a/code/modules/mob/living/carbon/human/species_types/humans.dm +++ b/code/modules/mob/living/carbon/human/species_types/humans.dm @@ -18,7 +18,7 @@ human_mob.skin_tone = random_skin_tone() /datum/species/human/get_scream_sound(mob/living/carbon/human/human) - if(human.gender == MALE) + if(human.physique == MALE) if(prob(1)) return 'sound/voice/human/wilhelm_scream.ogg' return pick( diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index e66d72a2c44..990f27f0707 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -579,6 +579,9 @@ if(stat != DEAD) // If you are dead your body does not stabilize naturally natural_bodytemperature_stabilization(environment, seconds_per_tick, times_fired) + else if(!on_fire && areatemp < bodytemperature) // lowers your dead body temperature to room temperature over time + adjust_bodytemperature((areatemp - bodytemperature), use_insulation=FALSE, use_steps=TRUE) + if(!on_fire || areatemp > bodytemperature) // If we are not on fire or the area is hotter adjust_bodytemperature((areatemp - bodytemperature), use_insulation=TRUE, use_steps=TRUE) diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 53a8d259393..217bc5bacba 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -58,6 +58,7 @@ dust_animation() spawn_dust(just_ash) + ghostize() QDEL_IN(src,5) // since this is sometimes called in the middle of movement, allow half a second for movement to finish, ghosting to happen and animation to play. Looks much nicer and doesn't cause multiple runtimes. /mob/living/proc/dust_animation() diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index cb4d4a8241a..532d37ed1b2 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -193,7 +193,7 @@ return var/mob/living/carbon/human/human_user = user if(human_user.dna.species.id == SPECIES_HUMAN && !HAS_MIND_TRAIT(human_user, TRAIT_MIMING)) - if(human_user.gender == FEMALE) + if(human_user.physique == FEMALE) return pick('sound/voice/human/gasp_female1.ogg', 'sound/voice/human/gasp_female2.ogg', 'sound/voice/human/gasp_female3.ogg') else return pick('sound/voice/human/gasp_male1.ogg', 'sound/voice/human/gasp_male2.ogg') diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index e4fe206cf63..fa96e7c2181 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1479,6 +1479,7 @@ var/picked_animal = pick( /mob/living/basic/bat, /mob/living/basic/bear, + /mob/living/basic/blob_minion/blobbernaut, /mob/living/basic/butterfly, /mob/living/basic/carp, /mob/living/basic/carp/magic, @@ -1504,7 +1505,6 @@ /mob/living/basic/statue, /mob/living/basic/stickman, /mob/living/basic/stickman/dog, - /mob/living/simple_animal/hostile/blob/blobbernaut/independent, /mob/living/simple_animal/hostile/gorilla, /mob/living/simple_animal/hostile/megafauna/dragon/lesser, /mob/living/simple_animal/hostile/retaliate/goat, diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 17c6d7faa9c..687359a6ff6 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -88,6 +88,11 @@ /mob/living/proc/is_pepper_proof(check_flags = ALL) return null +/// Checks if the mob's ears (BOTH EARS, BOWMANS NEED NOT APPLY) are covered by something. +/// Returns the atom covering the mob's ears, or null if their ears are uncovered. +/mob/living/proc/is_ears_covered() + return null + /mob/living/proc/on_hit(obj/projectile/P) return BULLET_ACT_HIT @@ -176,6 +181,7 @@ return ..() /mob/living/fire_act() + . = ..() adjust_fire_stacks(3) ignite_mob() diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 766a7ef89a8..e9d306875c9 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -225,3 +225,6 @@ /// What our current gravity state is. Used to avoid duplicate animates and such var/gravity_state = null + + /// Whether this mob can be mutated into a cybercop via quantum server get_valid_domain_targets(). Specifically dodges megafauna + var/can_be_cybercop = TRUE diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index b3f842e6a25..3a09256ee69 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -394,13 +394,29 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( tts_message_to_use = message_raw var/list/filter = list() + var/list/special_filter = list() + var/voice_to_use = voice + var/use_radio = FALSE if(length(voice_filter) > 0) filter += voice_filter if(length(tts_filter) > 0) filter += tts_filter.Join(",") - - INVOKE_ASYNC(SStts, TYPE_PROC_REF(/datum/controller/subsystem/tts, queue_tts_message), src, html_decode(tts_message_to_use), message_language, voice, filter.Join(","), listened, message_range = message_range, pitch = pitch, silicon = tts_silicon_voice_effect) + if(ishuman(src)) + var/mob/living/carbon/human/human_speaker = src + if(human_speaker.wear_mask) + var/obj/item/clothing/mask/worn_mask = human_speaker.wear_mask + if(worn_mask.voice_override) + voice_to_use = worn_mask.voice_override + if(worn_mask.voice_filter) + filter += worn_mask.voice_filter + use_radio = worn_mask.use_radio_beeps_tts + if(use_radio) + special_filter += TTS_FILTER_RADIO + if(issilicon(src)) + special_filter += TTS_FILTER_SILICON + + INVOKE_ASYNC(SStts, TYPE_PROC_REF(/datum/controller/subsystem/tts, queue_tts_message), src, html_decode(tts_message_to_use), message_language, voice_to_use, filter.Join(","), listened, message_range = message_range, pitch = pitch, special_filters = special_filter.Join("|")) var/image/say_popup = image('icons/mob/effects/talk.dmi', src, "[bubble_type][talk_icon_state]", FLY_LAYER) SET_PLANE_EXPLICIT(say_popup, ABOVE_GAME_PLANE, src) diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index 277b36c274b..f820d3ca1cf 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -439,11 +439,8 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real if(prob(75) && Proj.damage > 0) spark_system.start() -/mob/living/silicon/on_hit(obj/projectile/P) - if(!has_movespeed_modifier(/datum/movespeed_modifier/borg_throw)) - add_movespeed_modifier(/datum/movespeed_modifier/borg_throw) - addtimer(CALLBACK(src, TYPE_PROC_REF(/mob/living/silicon, clear_throw_slowdown)), (P.throwforce / 10) SECONDS) - return ..() - -/mob/living/silicon/proc/clear_throw_slowdown() - src.remove_movespeed_modifier(/datum/movespeed_modifier/borg_throw) +/mob/living/silicon/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) + . = ..() + if (. || AM.throwforce < CYBORG_THROW_SLOWDOWN_THRESHOLD) + return + apply_status_effect(/datum/status_effect/borg_throw_slow) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index bf785954fe7..7bd48ab62fb 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -104,8 +104,6 @@ var/reset_access_timer_id var/ignorelistcleanuptimer = 1 // This ticks up every automated action, at 300 we clean the ignore list - /// Component which allows ghosts to take over this bot - var/datum/component/ghost_direct_control/personality_download /// If true we will allow ghosts to control this mob var/can_be_possessed = FALSE /// If true we will offer this @@ -212,7 +210,6 @@ GLOB.bots_list -= src QDEL_NULL(paicard) QDEL_NULL(pa_system) - QDEL_NULL(personality_download) QDEL_NULL(internal_radio) QDEL_NULL(access_card) QDEL_NULL(path_hud) @@ -225,14 +222,14 @@ return can_be_possessed = TRUE var/can_announce = !mapload && COOLDOWN_FINISHED(src, offer_ghosts_cooldown) - personality_download = AddComponent(\ - /datum/component/ghost_direct_control,\ - ban_type = ROLE_BOT,\ - poll_candidates = can_announce,\ - poll_ignore_key = POLL_IGNORE_BOTS,\ - assumed_control_message = (bot_cover_flags & BOT_COVER_EMAGGED) ? get_emagged_message() : possessed_message,\ - extra_control_checks = CALLBACK(src, PROC_REF(check_possession)),\ - after_assumed_control = CALLBACK(src, PROC_REF(post_possession)),\ + AddComponent( + /datum/component/ghost_direct_control, \ + ban_type = ROLE_BOT, \ + poll_candidates = can_announce, \ + poll_ignore_key = POLL_IGNORE_BOTS, \ + assumed_control_message = (bot_cover_flags & BOT_COVER_EMAGGED) ? get_emagged_message() : possessed_message, \ + extra_control_checks = CALLBACK(src, PROC_REF(check_possession)), \ + after_assumed_control = CALLBACK(src, PROC_REF(post_possession)), \ ) if (can_announce) COOLDOWN_START(src, offer_ghosts_cooldown, 30 SECONDS) @@ -240,7 +237,7 @@ /// Disables this bot from being possessed by ghosts /mob/living/simple_animal/bot/proc/disable_possession(mob/user) can_be_possessed = FALSE - QDEL_NULL(personality_download) + qdel(GetComponent(/datum/component/ghost_direct_control)) if (isnull(key)) return if (user) diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index b392417aab2..2d17820af0b 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -32,7 +32,7 @@ lighting_cutoff_red = 30 lighting_cutoff_green = 15 lighting_cutoff_blue = 50 - unique_name = 1 + unique_name = TRUE gold_core_spawnable = NO_SPAWN death_sound = 'sound/voice/hiss6.ogg' death_message = "lets out a waning guttural screech, green blood bubbling from its maw..." @@ -91,7 +91,7 @@ projectiletype = /obj/projectile/neurotoxin/damaging projectilesound = 'sound/weapons/pierce.ogg' status_flags = 0 - unique_name = 0 + unique_name = FALSE var/sterile = 1 var/plants_off = 0 var/egg_cooldown = 30 diff --git a/code/modules/mob/living/simple_animal/hostile/blob.dm b/code/modules/mob/living/simple_animal/hostile/blob.dm deleted file mode 100644 index 7a40a01239c..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/blob.dm +++ /dev/null @@ -1,101 +0,0 @@ -//Do not spawn -/mob/living/simple_animal/hostile/blob - icon = 'icons/mob/nonhuman-player/blob.dmi' - pass_flags = PASSBLOB - faction = list(ROLE_BLOB) - bubble_icon = "blob" - speak_emote = null //so we use verb_yell/verb_say/etc - 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 - unique_name = 1 - combat_mode = TRUE - // ... Blob colored lighting - lighting_cutoff_red = 20 - lighting_cutoff_green = 40 - lighting_cutoff_blue = 30 - initial_language_holder = /datum/language_holder/empty - retreat_distance = null //! retreat doesn't obey pass_flags, so won't work on blob mobs. - /// Blob camera that controls the blob - var/mob/camera/blob/overmind = null - /// If this is related to anything else - var/independent = FALSE - /// The factory blob tile that generated this blob minion - var/obj/structure/blob/special/factory/factory - -/mob/living/simple_animal/hostile/blob/update_icons() - if(overmind) - add_atom_colour(overmind.blobstrain.color, FIXED_COLOUR_PRIORITY) - else - remove_atom_colour(FIXED_COLOUR_PRIORITY) - -/mob/living/simple_animal/hostile/blob/Initialize(mapload) - . = ..() - if(!independent) //no pulling people deep into the blob - remove_verb(src, /mob/living/verb/pulled) - else - pass_flags &= ~PASSBLOB - -/mob/living/simple_animal/hostile/blob/death() - factory = null - if(overmind) - overmind.blob_mobs -= src - overmind = null - return ..() - -/mob/living/simple_animal/hostile/blob/get_status_tab_items() - . = ..() - if(overmind) - . += "Blobs to Win: [overmind.blobs_legit.len]/[overmind.blobwincount]" - -/mob/living/simple_animal/hostile/blob/blob_act(obj/structure/blob/B) - if(stat != DEAD && health < maxHealth) - for(var/unused in 1 to 2) - var/obj/effect/temp_visual/heal/heal_effect = new /obj/effect/temp_visual/heal(get_turf(src)) //hello yes you are being healed - if(overmind) - heal_effect.color = overmind.blobstrain.complementary_color - else - heal_effect.color = "#000000" - adjustHealth(-maxHealth*BLOBMOB_HEALING_MULTIPLIER) - -/mob/living/simple_animal/hostile/blob/fire_act(exposed_temperature, exposed_volume) - ..() - if(exposed_temperature) - adjustFireLoss(clamp(0.01 * exposed_temperature, 1, 5)) - else - adjustFireLoss(5) - -/mob/living/simple_animal/hostile/blob/CanAllowThrough(atom/movable/mover, border_dir) - . = ..() - if(istype(mover, /obj/structure/blob)) - return TRUE - -///override to use astar/JPS instead of walk_to so we can take our blob pass_flags into account. -/mob/living/simple_animal/hostile/blob/Goto(target, delay, minimum_distance) - if(prevent_goto_movement) - return FALSE - if(target == src.target) - approaching_target = TRUE - else - approaching_target = FALSE - - SSmove_manager.jps_move(moving = src, chasing = target, delay = delay, repath_delay = 2 SECONDS, minimum_distance = minimum_distance, simulated_only = FALSE, skip_first = TRUE, timeout = 5 SECONDS, flags = MOVEMENT_LOOP_IGNORE_GLIDE) - return TRUE - -/mob/living/simple_animal/hostile/blob/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) - for(var/obj/structure/blob/blob in range(1, src)) - return 1 - return ..() - -/mob/living/simple_animal/hostile/blob/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null) - if(sanitize) - message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) - var/spanned_message = say_quote(message) - var/rendered = "\[Blob Telepathy\] [real_name] [spanned_message]" - for(var/creature in GLOB.mob_list) - if(isovermind(creature) || isblobmonster(creature)) - to_chat(creature, rendered) - if(isobserver(creature)) - var/link = FOLLOW_LINK(creature, src) - to_chat(creature, "[link] [rendered]") - diff --git a/code/modules/mob/living/simple_animal/hostile/blobbernaut.dm b/code/modules/mob/living/simple_animal/hostile/blobbernaut.dm deleted file mode 100644 index dc1d038795f..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/blobbernaut.dm +++ /dev/null @@ -1,109 +0,0 @@ -/mob/living/simple_animal/hostile/blob/blobbernaut - name = "blobbernaut" - desc = "A hulking, mobile chunk of blobmass." - icon_state = "blobbernaut" - icon_living = "blobbernaut" - icon_dead = "blobbernaut_dead" - health = BLOBMOB_BLOBBERNAUT_HEALTH - maxHealth = BLOBMOB_BLOBBERNAUT_HEALTH - damage_coeff = list(BRUTE = 0.5, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) - melee_damage_lower = BLOBMOB_BLOBBERNAUT_DMG_SOLO_LOWER - melee_damage_upper = BLOBMOB_BLOBBERNAUT_DMG_SOLO_UPPER - obj_damage = BLOBMOB_BLOBBERNAUT_DMG_OBJ - attack_verb_continuous = "slams" - attack_verb_simple = "slam" - attack_sound = 'sound/effects/blobattack.ogg' - verb_say = "gurgles" - verb_ask = "demands" - verb_exclaim = "roars" - verb_yell = "bellows" - force_threshold = 10 - pressure_resistance = 50 - mob_size = MOB_SIZE_LARGE - hud_type = /datum/hud/living/blobbernaut - -/mob/living/simple_animal/hostile/blob/blobbernaut/Initialize(mapload) - . = ..() - add_cell_sample() - -/mob/living/simple_animal/hostile/blob/blobbernaut/mind_initialize() - . = ..() - if(independent | !overmind) - return - var/datum/antagonist/blob_minion/blobbernaut/naut = new(overmind) - mind.add_antag_datum(naut) - -/mob/living/simple_animal/hostile/blob/blobbernaut/add_cell_sample() - AddElement(/datum/element/swabable, CELL_LINE_TABLE_BLOBBERNAUT, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) - -/mob/living/simple_animal/hostile/blob/blobbernaut/Life(seconds_per_tick = SSMOBS_DT, times_fired) - if(!..()) - return FALSE - var/list/blobs_in_area = range(2, src) - - if(independent) - return FALSE // strong independent blobbernaut that don't need no blob - - var/damagesources = 0 - - if(!(locate(/obj/structure/blob) in blobs_in_area)) - damagesources++ - - if(!factory) - damagesources++ - else - if(locate(/obj/structure/blob/special/core) in blobs_in_area) - adjustHealth(-maxHealth*BLOBMOB_BLOBBERNAUT_HEALING_CORE * seconds_per_tick) - var/obj/effect/temp_visual/heal/heal_effect = new /obj/effect/temp_visual/heal(get_turf(src)) //hello yes you are being healed - if(overmind) - heal_effect.color = overmind.blobstrain.complementary_color - else - heal_effect.color = "#000000" - if(locate(/obj/structure/blob/special/node) in blobs_in_area) - adjustHealth(-maxHealth*BLOBMOB_BLOBBERNAUT_HEALING_NODE * seconds_per_tick) - var/obj/effect/temp_visual/heal/heal_effect = new /obj/effect/temp_visual/heal(get_turf(src)) - if(overmind) - heal_effect.color = overmind.blobstrain.complementary_color - else - heal_effect.color = "#000000" - - if(!damagesources) - return FALSE - - adjustHealth(maxHealth * BLOBMOB_BLOBBERNAUT_HEALTH_DECAY * damagesources * seconds_per_tick) //take 2.5% of max health as damage when not near the blob or if the naut has no factory, 5% if both - var/mutable_appearance/healing = mutable_appearance('icons/mob/nonhuman-player/blob.dmi', "nautdamage", MOB_LAYER+0.01) - healing.appearance_flags = RESET_COLOR - - if(overmind) - healing.color = overmind.blobstrain.complementary_color - - flick_overlay_view(healing, 0.8 SECONDS) - -/mob/living/simple_animal/hostile/blob/blobbernaut/AttackingTarget() - . = ..() - if(. && isliving(target) && overmind) - overmind.blobstrain.blobbernaut_attack(target, src) - -/mob/living/simple_animal/hostile/blob/blobbernaut/update_icons() - ..() - if(overmind) //if we have an overmind, we're doing chemical reactions instead of pure damage - melee_damage_lower = BLOBMOB_BLOBBERNAUT_DMG_LOWER - melee_damage_upper = BLOBMOB_BLOBBERNAUT_DMG_UPPER - attack_verb_continuous = overmind.blobstrain.blobbernaut_message - else - melee_damage_lower = initial(melee_damage_lower) - melee_damage_upper = initial(melee_damage_upper) - attack_verb_continuous = initial(attack_verb_continuous) - -/mob/living/simple_animal/hostile/blob/blobbernaut/death(gibbed) - if(factory) - factory.blobbernaut = null //remove this blobbernaut from its factory - factory.max_integrity = initial(factory.max_integrity) - flick("blobbernaut_death", src) - return ..() - -/mob/living/simple_animal/hostile/blob/blobbernaut/independent - independent = TRUE - gold_core_spawnable = HOSTILE_SPAWN - - diff --git a/code/modules/mob/living/simple_animal/hostile/blobspore.dm b/code/modules/mob/living/simple_animal/hostile/blobspore.dm deleted file mode 100644 index 501afde41b0..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/blobspore.dm +++ /dev/null @@ -1,168 +0,0 @@ -/mob/living/simple_animal/hostile/blob/blobspore - name = "blob spore" - desc = "A floating, fragile spore." - icon_state = "blobpod" - icon_living = "blobpod" - health_doll_icon = "blobpod" - health = BLOBMOB_SPORE_HEALTH - maxHealth = BLOBMOB_SPORE_HEALTH - verb_say = "psychically pulses" - verb_ask = "psychically probes" - verb_exclaim = "psychically yells" - verb_yell = "psychically screams" - melee_damage_lower = BLOBMOB_SPORE_DMG_LOWER - melee_damage_upper = BLOBMOB_SPORE_DMG_UPPER - environment_smash = ENVIRONMENT_SMASH_NONE - obj_damage = 0 - attack_verb_continuous = "hits" - attack_verb_simple = "hit" - attack_sound = 'sound/weapons/genhit1.ogg' - del_on_death = TRUE - death_message = "explodes into a cloud of gas!" - gold_core_spawnable = NO_SPAWN //gold slime cores should only spawn the independent subtype - /// Size of cloud produced from a dying spore - var/death_cloud_size = 1 - /// The attached person - var/mob/living/carbon/human/corpse - /// If this is attached to a person - var/is_zombie = FALSE - /// Whether or not this is a fragile spore from Distributed Neurons - var/is_weak = FALSE - -/mob/living/simple_animal/hostile/blob/blobspore/Initialize(mapload, obj/structure/blob/special/linked_node) - . = ..() - AddElement(/datum/element/simple_flying) - - if(!istype(linked_node)) - return - - factory = linked_node - factory.spores += src - if(linked_node.overmind && istype(linked_node.overmind.blobstrain, /datum/blobstrain/reagent/distributed_neurons) && !istype(src, /mob/living/simple_animal/hostile/blob/blobspore/weak)) - notify_ghosts("A controllable spore has been created in \the [get_area(src)].", source = src, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Sentient Spore Created") - add_cell_sample() - -/mob/living/simple_animal/hostile/blob/blobspore/mind_initialize() - . = ..() - if(independent || !overmind) - return FALSE - var/datum/antagonist/blob_minion/blob_zombie/zombie = new(overmind) - mind.add_antag_datum(zombie) - -/mob/living/simple_animal/hostile/blob/blobspore/Life(seconds_per_tick = SSMOBS_DT, times_fired) - if(!is_zombie && isturf(loc)) - for(var/mob/living/carbon/human/target in view(src,1)) //Only for corpse right next to/on same tile - if(!is_weak && target.stat == DEAD) - zombify(target) - break - if(factory && !is_valid_z_level(get_turf(src), get_turf(factory))) - death() - return ..() - -/mob/living/simple_animal/hostile/blob/blobspore/attack_ghost(mob/user) - . = ..() - if(.) - return - humanize_pod(user) - -/mob/living/simple_animal/hostile/blob/blobspore/death(gibbed) - // On death, create a small smoke of harmful gas (s-Acid) - var/datum/effect_system/fluid_spread/smoke/chem/spores = new - var/turf/location = get_turf(src) - - // Create the reagents to put into the air - create_reagents(10) - - if(overmind?.blobstrain) - overmind.blobstrain.on_sporedeath(src) - else - reagents.add_reagent(/datum/reagent/toxin/spore, 10) - - // Attach the smoke spreader and setup/start it. - spores.attach(location) - spores.set_up(death_cloud_size, holder = src, location = location, carry = reagents, silent = TRUE) - spores.start() - if(factory) - factory.spore_delay = world.time + factory.spore_cooldown //put the factory on cooldown - - return ..() - -/mob/living/simple_animal/hostile/blob/blobspore/death() - if(factory) - factory.spores -= src - corpse?.forceMove(loc) - corpse = null - return ..() - -/mob/living/simple_animal/hostile/blob/blobspore/update_icons() - if(overmind) - add_atom_colour(overmind.blobstrain.complementary_color, FIXED_COLOUR_PRIORITY) - else - remove_atom_colour(FIXED_COLOUR_PRIORITY) - if(!is_zombie) - return FALSE - - copy_overlays(corpse, TRUE) - var/mutable_appearance/blob_head_overlay = mutable_appearance('icons/mob/nonhuman-player/blob.dmi', "blob_head") - if(overmind) - blob_head_overlay.color = overmind.blobstrain.complementary_color - color = initial(color) // looks better. - add_overlay(blob_head_overlay) - -/mob/living/simple_animal/hostile/blob/blobspore/add_cell_sample() - AddElement(/datum/element/swabable, CELL_LINE_TABLE_BLOBSPORE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) - -/mob/living/simple_animal/hostile/blob/blobspore/independent - gold_core_spawnable = HOSTILE_SPAWN - independent = TRUE - -/mob/living/simple_animal/hostile/blob/blobspore/weak - name = "fragile blob spore" - health = 15 - maxHealth = 15 - melee_damage_lower = 1 - melee_damage_upper = 2 - death_cloud_size = 0 - is_weak = TRUE - -/** Ghost control a blob zombie */ -/mob/living/simple_animal/hostile/blob/blobspore/proc/humanize_pod(mob/user) - if((!overmind || istype(src, /mob/living/simple_animal/hostile/blob/blobspore/weak) || !istype(overmind.blobstrain, /datum/blobstrain/reagent/distributed_neurons)) && !is_zombie) - return FALSE - if(key || stat) - return FALSE - var/pod_ask = tgui_alert(usr, "Are you bulbous enough?", "Blob Spore", list("Yes", "No")) - if(pod_ask != "Yes" || QDELETED(src)) - return FALSE - if(key) - to_chat(user, span_warning("Someone else already took this spore!")) - return FALSE - key = user.key - log_message("took control of [name].", LOG_GAME) - -/** Zombifies a dead mob, turning it into a blob zombie */ -/mob/living/simple_animal/hostile/blob/blobspore/proc/zombify(mob/living/carbon/human/target) - is_zombie = 1 - if(target.wear_suit) - maxHealth += target.get_armor_rating(MELEE) // That zombie's got armor, I want armor! - maxHealth += 40 - health = maxHealth - name = "blob zombie" - desc = "A shambling corpse animated by the blob." - mob_biotypes |= MOB_HUMANOID - melee_damage_lower += 8 - melee_damage_upper += 11 - obj_damage = 20 // now that it has a corpse to puppet, it can properly attack structures - environment_smash = ENVIRONMENT_SMASH_STRUCTURES - movement_type = GROUND - death_cloud_size = 0 - icon = target.icon - icon_state = "zombie" - target.set_facial_hairstyle("Shaved", update = FALSE) - target.set_hairstyle("Bald", update = TRUE) - target.forceMove(src) - corpse = target - update_icons() - visible_message(span_warning("The corpse of [target.name] suddenly rises!")) - if(!key) - notify_ghosts("\A [src] has been created in \the [get_area(src)].", source = src, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Blob Zombie Created") diff --git a/code/modules/mob/living/simple_animal/hostile/constructs/constructs.dm b/code/modules/mob/living/simple_animal/hostile/constructs/constructs.dm index 124b797d0da..23f7590dc8e 100644 --- a/code/modules/mob/living/simple_animal/hostile/constructs/constructs.dm +++ b/code/modules/mob/living/simple_animal/hostile/constructs/constructs.dm @@ -28,7 +28,7 @@ maxbodytemp = INFINITY faction = list(FACTION_CULT) pressure_resistance = 100 - unique_name = 1 + unique_name = TRUE AIStatus = AI_OFF //normal constructs don't have AI loot = list(/obj/item/ectoplasm) del_on_death = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/heretic_monsters.dm b/code/modules/mob/living/simple_animal/hostile/heretic_monsters.dm index 2c0b9ba983a..1b8cfe9de68 100644 --- a/code/modules/mob/living/simple_animal/hostile/heretic_monsters.dm +++ b/code/modules/mob/living/simple_animal/hostile/heretic_monsters.dm @@ -198,6 +198,7 @@ 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 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm index 3484c27375d..5bb9f314ed1 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm @@ -70,7 +70,10 @@ return ..() /mob/living/simple_animal/hostile/megafauna/death(gibbed, list/force_grant) - if(health > 0) + if(gibbed) // in case they've been force dusted + return ..() + + if(health > 0) // prevents instakills return var/datum/status_effect/crusher_damage/crusher_dmg = has_status_effect(/datum/status_effect/crusher_damage) ///Whether we killed the megafauna with primarily crusher damage or not @@ -100,8 +103,8 @@ /mob/living/simple_animal/hostile/megafauna/gib() if(health > 0) return - else - ..() + + return ..() /mob/living/simple_animal/hostile/megafauna/singularity_act() set_health(0) @@ -110,8 +113,11 @@ /mob/living/simple_animal/hostile/megafauna/dust(just_ash, drop_items, force) if(!force && health > 0) return - else - ..() + + crusher_loot.Cut() + loot.Cut() + + return ..() /mob/living/simple_animal/hostile/megafauna/AttackingTarget() if(recovery_time >= world.time) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index 66d487c8697..84e2d9c049b 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -272,7 +272,7 @@ if(!isclosedturf(T) && !islava(T)) var/lava_turf = /turf/open/lava/smooth var/reset_turf = T.type - T.ChangeTurf(lava_turf, flags = CHANGETURF_INHERIT_AIR) + T.TerraformTurf(lava_turf, flags = CHANGETURF_INHERIT_AIR) addtimer(CALLBACK(T, TYPE_PROC_REF(/turf, ChangeTurf), reset_turf, null, CHANGETURF_INHERIT_AIR), reset_time, TIMER_OVERRIDE|TIMER_UNIQUE) /obj/effect/temp_visual/drakewall diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 745a48c948c..828a78ccfb1 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -436,7 +436,7 @@ Difficulty: Hard /mob/living/simple_animal/hostile/megafauna/hierophant/CanAttack(atom/the_target) . = ..() - if(istype(the_target, /mob/living/simple_animal/hostile/asteroid/hivelordbrood)) //ignore temporary targets in favor of more permanent targets + if(istype(the_target, /mob/living/basic/legion_brood)) //ignore temporary targets in favor of more permanent targets return FALSE /mob/living/simple_animal/hostile/megafauna/hierophant/GiveTarget(new_target) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm index 05695daf59a..777cb3b878f 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -141,10 +141,9 @@ ///Attack proc. Spawns a singular legion skull. /mob/living/simple_animal/hostile/megafauna/legion/proc/create_legion_skull() - var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(loc) - A.GiveTarget(target) - A.friends = friends - A.faction = faction + var/mob/living/basic/legion_brood/minion = new(loc) + minion.assign_creator(src) + minion.ai_controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] = target //CHARGE @@ -210,7 +209,7 @@ var/mob/living/living_target = target switch(living_target.stat) if(UNCONSCIOUS, HARD_CRIT) - var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/legion = new(loc) + var/mob/living/basic/legion_brood/legion = new(loc) legion.infest(living_target) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm index e9cf04b9c21..26f3690fef1 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm @@ -267,6 +267,10 @@ Difficulty: Hard /mob/living/simple_animal/hostile/megafauna/wendigo/death(gibbed, list/force_grant) if(health > 0) return + + if(!true_spawn) + return ..() + var/obj/effect/portal/permanent/one_way/exit = new /obj/effect/portal/permanent/one_way(starting) exit.id = "wendigo arena exit" exit.add_atom_colour(COLOR_RED_LIGHT, ADMIN_COLOUR_PRIORITY) diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index 2fec84385b2..d07775b42bd 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -113,6 +113,7 @@ GLOBAL_LIST_INIT(animatable_blacklist, list(/obj/structure/table, /obj/structure /mob/living/simple_animal/hostile/mimic/copy/Initialize(mapload, obj/copy, mob/living/creator, destroy_original = 0, no_googlies = FALSE) . = ..() + ADD_TRAIT(src, TRAIT_PERMANENTLY_MORTAL, INNATE_TRAIT) // They won't remember their original contents upon ressurection and would just be floating eyes if (no_googlies) overlay_googly_eyes = FALSE CopyObject(copy, creator, destroy_original) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm index 4cb4d97f38f..bf4d33a10ed 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm @@ -249,7 +249,8 @@ /obj/projectile/herald/teleshot/on_hit(atom/target, blocked = FALSE) . = ..() - firer.forceMove(get_turf(src)) + if(!QDELETED(firer)) + firer.forceMove(get_turf(src)) //Herald's loot: Cloak of the Prophet diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm index a705e11465b..ec6c843080c 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm @@ -328,10 +328,9 @@ /obj/item/crusher_trophy/legionnaire_spine/on_mark_detonation(mob/living/target, mob/living/user) if(!prob(bonus_value) || target.stat == DEAD) return - var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(user.loc) - A.GiveTarget(target) - A.friends += user - A.faction = user.faction.Copy() + var/mob/living/basic/legion_brood/minion = new (user.loc) + minion.assign_creator(user) + minion.ai_controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] = target /obj/item/crusher_trophy/legionnaire_spine/attack_self(mob/user) if(!isliving(user)) @@ -342,9 +341,9 @@ to_chat(LivingUser, "You need to wait longer to use this again.") return LivingUser.visible_message(span_boldwarning("[LivingUser] shakes the [src] and summons a legion skull!")) - var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/LegionSkull = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(LivingUser.loc) - LegionSkull.friends += LivingUser - LegionSkull.faction = LivingUser.faction.Copy() + + var/mob/living/basic/legion_brood/minion = new (LivingUser.loc) + minion.assign_creator(LivingUser) next_use_time = world.time + 4 SECONDS #undef LEGIONNAIRE_CHARGE diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm deleted file mode 100644 index 2d92ef88a65..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm +++ /dev/null @@ -1,333 +0,0 @@ -/mob/living/simple_animal/hostile/asteroid/hivelord - name = "hivelord" - desc = "A levitating swarm of tiny creatures which act as a single individual. When threatened or hunting they rapidly replicate additional short-lived bodies." - icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' - icon_state = "hivelord" - icon_living = "hivelord" - icon_aggro = "hivelord_alert" - icon_dead = "hivelord_dead" - icon_gib = "syndicate_gib" - mob_biotypes = MOB_ORGANIC - move_to_delay = 14 - ranged = 1 - vision_range = 5 - aggro_vision_range = 9 - speed = 3 - maxHealth = 75 - health = 75 - harm_intent_damage = 5 - melee_damage_lower = 0 - melee_damage_upper = 0 - attack_verb_continuous = "weakly tackles" - attack_verb_simple = "weakly tackles" - speak_emote = list("telepathically cries") - attack_sound = 'sound/weapons/pierce.ogg' - throw_message = "passes between the bodies of the" - ranged_cooldown = 0 - ranged_cooldown_time = 20 - obj_damage = 0 - environment_smash = ENVIRONMENT_SMASH_NONE - retreat_distance = 3 - minimum_distance = 3 - pass_flags = PASSTABLE - loot = list(/obj/item/organ/internal/monster_core/regenerative_core) - var/brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood - var/has_clickbox = TRUE - -/mob/living/simple_animal/hostile/asteroid/hivelord/Initialize(mapload) - . = ..() - if(has_clickbox) - AddComponent(/datum/component/clickbox, icon_state = "hivelord", max_scale = INFINITY, dead_state = "hivelord_dead") //they writhe so much. - -/mob/living/simple_animal/hostile/asteroid/hivelord/OpenFire(the_target) - if(world.time < ranged_cooldown) - return - var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/brood = new brood_type(src.loc) - brood.flags_1 |= (flags_1 & ADMIN_SPAWNED_1) - brood.GiveTarget(target) - brood.friends = friends - brood.faction = faction.Copy() - ranged_cooldown = world.time + ranged_cooldown_time - -/mob/living/simple_animal/hostile/asteroid/hivelord/AttackingTarget() - OpenFire() - return TRUE - -/mob/living/simple_animal/hostile/asteroid/hivelord/death(gibbed) - mouse_opacity = MOUSE_OPACITY_ICON - return ..() - -//A fragile but rapidly produced creature -/mob/living/simple_animal/hostile/asteroid/hivelordbrood - name = "hivelord brood" - desc = "Short-lived attack form of the hivelord. One isn't much of a threat, but..." - icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' - icon_state = "hivelord_brood" - icon_living = "hivelord_brood" - icon_aggro = "hivelord_brood" - icon_dead = "hivelord_brood" - icon_gib = "syndicate_gib" - move_to_delay = 1 - friendly_verb_continuous = "buzzes near" - friendly_verb_simple = "buzz near" - vision_range = 10 - speed = 3 - maxHealth = 1 - health = 1 - harm_intent_damage = 5 - melee_damage_lower = 2 - melee_damage_upper = 2 - attack_verb_continuous = "slashes" - attack_verb_simple = "slash" - speak_emote = list("telepathically cries") - attack_sound = 'sound/weapons/pierce.ogg' - attack_vis_effect = ATTACK_EFFECT_SLASH - throw_message = "falls right through the strange body of the" - obj_damage = 0 - environment_smash = ENVIRONMENT_SMASH_NONE - pass_flags = PASSTABLE | PASSMOB - density = FALSE - del_on_death = 1 - var/clickbox_state = "hivelord" - var/clickbox_max_scale = INFINITY - -/mob/living/simple_animal/hostile/asteroid/hivelordbrood/Initialize(mapload) - . = ..() - addtimer(CALLBACK(src, PROC_REF(death)), 10 SECONDS) - AddElement(/datum/element/simple_flying) - AddComponent(/datum/component/swarming) - AddComponent(/datum/component/clickbox, icon_state = clickbox_state, max_scale = clickbox_max_scale) - -/mob/living/simple_animal/hostile/asteroid/hivelordbrood/death(gibbed) - if (!gibbed) - new /obj/effect/temp_visual/hive_spawn_wither(get_turf(src), /* copy_from = */ src) - return ..() - -//Legion -/mob/living/simple_animal/hostile/asteroid/hivelord/legion - name = "legion" - desc = "You can still see what was once a human under the shifting mass of corruption." - icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' - icon_state = "legion" - icon_living = "legion" - icon_aggro = "legion" - icon_dead = "legion" - icon_gib = "syndicate_gib" - mob_biotypes = MOB_ORGANIC|MOB_HUMANOID - mouse_opacity = MOUSE_OPACITY_ICON - obj_damage = 60 - melee_damage_lower = 15 - melee_damage_upper = 15 - attack_verb_continuous = "lashes out at" - attack_verb_simple = "lash out at" - speak_emote = list("echoes") - attack_sound = 'sound/weapons/pierce.ogg' - throw_message = "bounces harmlessly off of" - crusher_loot = /obj/item/crusher_trophy/legion_skull - loot = list(/obj/item/organ/internal/monster_core/regenerative_core/legion) - brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion - del_on_death = 1 - stat_attack = HARD_CRIT - robust_searching = 1 - has_clickbox = FALSE - var/dwarf_mob = FALSE - var/snow_legion = FALSE - var/mob/living/carbon/human/stored_mob - -/mob/living/simple_animal/hostile/asteroid/hivelord/legion/Initialize(mapload) - . = ..() - AddElement(/datum/element/content_barfer) - -/mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf - name = "dwarf legion" - desc = "You can still see what was once a rather small human under the shifting mass of corruption." - icon_state = "dwarf_legion" - icon_living = "dwarf_legion" - icon_aggro = "dwarf_legion" - icon_dead = "dwarf_legion" - maxHealth = 60 - health = 60 - speed = 2 //faster! - crusher_drop_mod = 20 - dwarf_mob = TRUE - -/mob/living/simple_animal/hostile/asteroid/hivelord/legion/death(gibbed) - visible_message(span_warning("The skulls on [src] wail in anger as they flee from their dying host!")) - if (!isnull(stored_mob)) - stored_mob = null - return ..() - - // We didn't contain a real body so spawn a random one - var/turf/our_turf = get_turf(src) - if(our_turf) - if(from_spawner) - new /obj/effect/mob_spawn/corpse/human/charredskeleton(our_turf) - else if(dwarf_mob) - new /obj/effect/mob_spawn/corpse/human/legioninfested/dwarf(our_turf) - else if(snow_legion) - new /obj/effect/mob_spawn/corpse/human/snowlegioninfested(our_turf) - else - new /obj/effect/mob_spawn/corpse/human/legioninfested(our_turf) - return ..() - -/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril - from_spawner = TRUE - -//Legion skull -/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion - name = "legion" - desc = "One of many." - icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' - icon_state = "legion_head" - icon_living = "legion_head" - icon_aggro = "legion_head" - icon_dead = "legion_head" - icon_gib = "syndicate_gib" - friendly_verb_continuous = "buzzes near" - friendly_verb_simple = "buzz near" - vision_range = 10 - maxHealth = 1 - health = 5 - harm_intent_damage = 5 - melee_damage_lower = 12 - melee_damage_upper = 12 - attack_verb_continuous = "bites" - attack_verb_simple = "bite" - attack_vis_effect = ATTACK_EFFECT_BITE - speak_emote = list("echoes") - attack_sound = 'sound/weapons/pierce.ogg' - throw_message = "is shrugged off by" - del_on_death = TRUE - stat_attack = HARD_CRIT - robust_searching = 1 - clickbox_state = "sphere" - clickbox_max_scale = 2 - var/can_infest_dead = FALSE - -/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/Life(seconds_per_tick = SSMOBS_DT, times_fired) - . = ..() - if(stat == DEAD || !isturf(loc)) - return - for(var/mob/living/carbon/human/victim in range(src, 1)) //Only for corpse right next to/on same tile - switch(victim.stat) - if(UNCONSCIOUS, HARD_CRIT) - infest(victim) - return //This will qdelete the legion. - if(DEAD) - if(can_infest_dead) - infest(victim) - return //This will qdelete the legion. - -///Create a legion at the location of a corpse. Exists so that legion subtypes can override it with their own type of legion. -/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/proc/make_legion(mob/living/carbon/human/H) - if(HAS_TRAIT(H, TRAIT_DWARF)) //dwarf legions aren't just fluff! - return new /mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf(H.loc) - else - return new /mob/living/simple_animal/hostile/asteroid/hivelord/legion(H.loc) - -///Create a new legion using the supplied human H -/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/proc/infest(mob/living/carbon/human/H) - visible_message(span_warning("[name] burrows into the flesh of [H]!")) - var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/L = make_legion(H) - visible_message(span_warning("[L] staggers to [L.p_their()] feet!")) - H.investigate_log("has been killed by hivelord infestation.", INVESTIGATE_DEATHS) - H.death() - H.adjustBruteLoss(1000) - L.stored_mob = H - H.forceMove(L) - qdel(src) - -//Advanced Legion is slightly tougher to kill and can raise corpses (revive other legions) -/mob/living/simple_animal/hostile/asteroid/hivelord/legion/advanced - stat_attack = DEAD - maxHealth = 120 - health = 120 - brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/advanced - icon_state = "dwarf_legion" - icon_living = "dwarf_legion" - icon_aggro = "dwarf_legion" - icon_dead = "dwarf_legion" - -/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/advanced - stat_attack = DEAD - can_infest_dead = TRUE - -//Legion that spawns Legions -/mob/living/simple_animal/hostile/big_legion - name = "legion" - desc = "One of many." - icon = 'icons/mob/simple/lavaland/64x64megafauna.dmi' - icon_state = "legion" - icon_living = "legion" - icon_dead = "legion" - health_doll_icon = "legion" - health = 450 - maxHealth = 450 - melee_damage_lower = 20 - melee_damage_upper = 20 - anchored = FALSE - AIStatus = AI_ON - stop_automated_movement = FALSE - wander = TRUE - maxbodytemp = INFINITY - layer = MOB_LAYER - del_on_death = TRUE - sentience_type = SENTIENCE_BOSS - loot = list(/obj/item/organ/internal/monster_core/regenerative_core/legion = 3, /obj/effect/mob_spawn/corpse/human/legioninfested = 5) - move_to_delay = 14 - vision_range = 5 - aggro_vision_range = 9 - speed = 3 - faction = list(FACTION_MINING) - weather_immunities = list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE) - obj_damage = 30 - environment_smash = ENVIRONMENT_SMASH_STRUCTURES - // Purple, but bright cause we're gonna need to spot mobs on lavaland - lighting_cutoff_red = 35 - lighting_cutoff_green = 20 - lighting_cutoff_blue = 45 - - -/mob/living/simple_animal/hostile/big_legion/Initialize(mapload) - .=..() - AddComponent(\ - /datum/component/spawner,\ - spawn_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion),\ - spawn_time = 20 SECONDS,\ - max_spawned = 3,\ - spawn_text = "peels itself off from",\ - faction = faction,\ - ) - - -// Snow Legion -/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow - name = "snow legion" - desc = "You can still see what was once a human under the shifting snowy mass, clearly decorated by a clown." - icon = 'icons/mob/simple/icemoon/icemoon_monsters.dmi' - icon_state = "snowlegion" - icon_living = "snowlegion" - icon_aggro = "snowlegion_alive" - icon_dead = "snowlegion" - crusher_loot = /obj/item/crusher_trophy/legion_skull - loot = list(/obj/item/organ/internal/monster_core/regenerative_core/legion) - brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/snow - weather_immunities = list(TRAIT_SNOWSTORM_IMMUNE) - snow_legion = TRUE - -/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/snow/make_legion(mob/living/carbon/human/H) - return new /mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow(H.loc) - -/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow/portal - from_spawner = TRUE - -// Snow Legion skull -/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/snow - name = "snow legion" - desc = "One of many." - icon = 'icons/mob/simple/icemoon/icemoon_monsters.dmi' - icon_state = "snowlegion_head" - icon_living = "snowlegion_head" - icon_aggro = "snowlegion_head" - icon_dead = "snowlegion_head" - weather_immunities = list(TRAIT_SNOWSTORM_IMMUNE) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/snake.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/snake.dm deleted file mode 100644 index e128349bc2e..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/snake.dm +++ /dev/null @@ -1,76 +0,0 @@ - -/mob/living/simple_animal/hostile/retaliate/snake - name = "snake" - desc = "A slithery snake. These legless reptiles are the bane of mice and adventurers alike." - icon_state = "snake" - icon_living = "snake" - icon_dead = "snake_dead" - speak_emote = list("hisses") - health = 20 - maxHealth = 20 - attack_verb_continuous = "bites" - attack_verb_simple = "bite" - attack_sound = 'sound/weapons/bite.ogg' - attack_vis_effect = ATTACK_EFFECT_BITE - melee_damage_lower = 5 - melee_damage_upper = 6 - response_help_continuous = "pets" - response_help_simple = "pet" - response_disarm_continuous = "shoos" - response_disarm_simple = "shoo" - response_harm_continuous = "steps on" - response_harm_simple = "step on" - faction = list(FACTION_HOSTILE) - density = FALSE - pass_flags = PASSTABLE | PASSMOB - mob_size = MOB_SIZE_SMALL - mob_biotypes = MOB_ORGANIC|MOB_BEAST|MOB_REPTILE - gold_core_spawnable = FRIENDLY_SPAWN - obj_damage = 0 - environment_smash = ENVIRONMENT_SMASH_NONE - -/mob/living/simple_animal/hostile/retaliate/snake/Initialize(mapload, special_reagent) - . = ..() - add_cell_sample() - ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT) - if(!special_reagent) - special_reagent = /datum/reagent/toxin - AddElement(/datum/element/venomous, special_reagent, 4) - -/mob/living/simple_animal/hostile/retaliate/snake/add_cell_sample() - AddElement(/datum/element/swabable, CELL_LINE_TABLE_SNAKE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) - -/mob/living/simple_animal/hostile/retaliate/snake/ListTargets(atom/the_target) - var/atom/target_from = GET_TARGETS_FROM(src) - . = oview(vision_range, target_from) //get list of things in vision range - var/list/living_mobs = list() - var/list/mice = list() - for (var/HM in .) - //Yum a tasty mouse - if(ismouse(HM)) - mice += HM - if(isliving(HM)) - living_mobs += HM - - // if no tasty mice to chase, lets chase any living mob enemies in our vision range - if(length(mice)) - return mice - - var/list/actual_enemies = list() - for(var/datum/weakref/enemy as anything in enemies) - var/mob/flesh_and_blood = enemy.resolve() - if(!flesh_and_blood) - enemies -= enemy - continue - actual_enemies += flesh_and_blood - - //Filter living mobs (in range mobs) by those we consider enemies (retaliate behaviour) - return living_mobs & actual_enemies - -/mob/living/simple_animal/hostile/retaliate/snake/AttackingTarget() - if(ismouse(target)) - visible_message(span_notice("[name] consumes [target] in a single gulp!"), span_notice("You consume [target] in a single gulp!")) - QDEL_NULL(target) - adjustBruteLoss(-2) - else - return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/smspider.dm b/code/modules/mob/living/simple_animal/hostile/smspider.dm deleted file mode 100644 index 150180a11cf..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/smspider.dm +++ /dev/null @@ -1,64 +0,0 @@ -/mob/living/simple_animal/hostile/smspider - name = "supermatter spider" - desc= "A sliver of supermatter placed upon a robotically enhanced pedestal." - icon = 'icons/mob/simple/smspider.dmi' - icon_state = "smspider" - icon_living = "smspider" - icon_dead = "smspider_dead" - gender = NEUTER - mob_biotypes = MOB_BUG|MOB_ROBOTIC - turns_per_move = 2 - speak_emote = list("vibrates") - emote_see = list("vibrates") - emote_taunt = list("vibrates") - taunt_chance = 40 - combat_mode = TRUE - maxHealth = 10 - health = 10 - minbodytemp = 0 - maxbodytemp = 1500 - attack_verb_continuous = "slices" - attack_verb_simple = "slice" - attack_sound = 'sound/effects/supermatter.ogg' - attack_vis_effect = ATTACK_EFFECT_CLAW - 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) - robust_searching = 1 - faction = list(FACTION_HOSTILE) - // Gold, supermatter tinted - lighting_cutoff_red = 30 - lighting_cutoff_green = 30 - lighting_cutoff_blue = 10 - death_message = "falls to the ground, its shard dulling to a miserable grey!" - footstep_type = FOOTSTEP_MOB_CLAW - var/overcharged = FALSE // if true, spider will not die if it dusts a limb - -/mob/living/simple_animal/hostile/smspider/AttackingTarget() - . = ..() - if(isliving(target)) - playsound(get_turf(src), 'sound/effects/supermatter.ogg', 10, TRUE) - visible_message(span_danger("[src] knocks into [target], turning them to dust in a brilliant flash of light!")) - var/mob/living/victim = target - victim.investigate_log("has been dusted by [src].", INVESTIGATE_DEATHS) - victim.dust() - if(!overcharged) - death() - else if(!isturf(target)) - playsound(get_turf(src), 'sound/effects/supermatter.ogg', 10, TRUE) - visible_message(span_danger("[src] knocks into [target], turning it to dust in a brilliant flash of light!")) - qdel(target) - if(!overcharged) - death() - return FALSE - -/mob/living/simple_animal/hostile/smspider/Initialize(mapload) - . = ..() - AddComponent(/datum/component/swarming) - -/mob/living/simple_animal/hostile/smspider/overcharged - name = "overcharged supermatter spider" - desc = "A sliver of overcharged supermatter placed upon a robotically enhanced pedestal. This one seems especially dangerous." - icon_state = "smspideroc" - icon_living = "smspideroc" - maxHealth = 25 - health = 25 - overcharged = TRUE diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 74a27e2a014..4966ac76a8e 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -315,7 +315,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( if(parrot_state == PARROT_PERCH) parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched - parrot_interest = user + set_parrot_interest(user) parrot_state = PARROT_SWOOP //The parrot just got hit, it WILL move, now to pick a direction.. if(health > 30) //Let's get in there and squawk it up! @@ -344,7 +344,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched if(user.melee_damage_upper > 0 && !stat) - parrot_interest = user + set_parrot_interest(user) parrot_state = PARROT_SWOOP | PARROT_ATTACK //Attack other animals regardless icon_state = icon_living @@ -355,7 +355,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( if(parrot_state == PARROT_PERCH) parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched - parrot_interest = user + set_parrot_interest(user) parrot_state = PARROT_SWOOP if(health > 30) //Let's get in there and squawk it up! parrot_state |= PARROT_ATTACK @@ -380,7 +380,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( if(parrot_state == PARROT_PERCH) parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched - parrot_interest = null + set_parrot_interest(null) parrot_state = PARROT_WANDER | PARROT_FLEE //Been shot and survived! RUN LIKE HELL! //parrot_been_shot += 5 icon_state = icon_living @@ -475,7 +475,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( speak = newspeak //Search for item to steal - parrot_interest = search_for_item() + set_parrot_interest(search_for_item()) if(parrot_interest) manual_emote("looks in [parrot_interest]'s direction and takes flight.") parrot_state = PARROT_SWOOP | PARROT_STEAL @@ -486,7 +486,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( else if(parrot_state == PARROT_WANDER) //Stop movement, we'll set it later SSmove_manager.stop_looping(src) - parrot_interest = null + set_parrot_interest(null) //Wander around aimlessly. This will help keep the loops from searches down //and possibly move the mob into a new are in view of something they can use @@ -498,7 +498,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( var/atom/movable/AM = search_for_perch_and_item() //This handles checking through lists so we know it's either a perch or stealable item if(AM) if(isitem(AM) || isliving(AM)) //If stealable item - parrot_interest = AM + set_parrot_interest(AM) manual_emote("turns and flies towards [parrot_interest].") parrot_state = PARROT_SWOOP | PARROT_STEAL return @@ -543,7 +543,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( parrot_interest.forceMove(src) visible_message(span_notice("[src] grabs [held_item]!"), span_notice("You grab [held_item]!"), span_hear("You hear the sounds of wings flapping furiously.")) - parrot_interest = null + set_parrot_interest(null) parrot_state = PARROT_SWOOP | PARROT_RETURN return @@ -591,7 +591,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( //If we're attacking a nothing, an object, a turf or a ghost for some stupid reason, switch to wander if(!parrot_interest || !isliving(parrot_interest)) - parrot_interest = null + set_parrot_interest(null) parrot_state = PARROT_WANDER return @@ -605,7 +605,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( //If the mob we've been chasing/attacking dies or falls into crit, check for loot! if(L.stat) - parrot_interest = null + set_parrot_interest(null) if(!held_item) held_item = steal_from_ground() if(!held_item) @@ -629,7 +629,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( //-----STATE MISHAP else //This should not happen. If it does lets reset everything and try again SSmove_manager.stop_looping(src) - parrot_interest = null + set_parrot_interest(null) parrot_perch = null drop_held_item() parrot_state = PARROT_WANDER @@ -639,6 +639,17 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( * Procs */ +/mob/living/simple_animal/parrot/proc/set_parrot_interest(atom/movable/shiny) + if(parrot_interest) + UnregisterSignal(parrot_interest, COMSIG_QDELETING) + parrot_interest = shiny + if(parrot_interest) + RegisterSignal(parrot_interest, COMSIG_QDELETING, PROC_REF(shiny_deleted)) + +/mob/living/simple_animal/parrot/proc/shiny_deleted(datum/source) + SIGNAL_HANDLER + set_parrot_interest(null) + /mob/living/simple_animal/parrot/proc/isStuck() //Check to see if the parrot is stuck due to things like windows or doors or windowdoors if(parrot_lastmove) @@ -1038,7 +1049,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( /mob/living/simple_animal/parrot/poly/ghost/handle_automated_movement() if(isliving(parrot_interest)) if(!ishuman(parrot_interest)) - parrot_interest = null + set_parrot_interest(null) else if(parrot_state == (PARROT_SWOOP | PARROT_ATTACK) && Adjacent(parrot_interest)) SSmove_manager.move_to(src, parrot_interest, 0, parrot_speed) Possess(parrot_interest) @@ -1051,7 +1062,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( P.parrot = src forceMove(H) H.ForceContractDisease(P, FALSE) - parrot_interest = null + set_parrot_interest(null) H.visible_message(span_danger("[src] dive bombs into [H]'s chest and vanishes!"), span_userdanger("[src] dive bombs into your chest, vanishing! This can't be good!")) #undef PARROT_PERCH diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 041c76fac42..3b16ab685eb 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -449,19 +449,21 @@ drop_loot() if(dextrous) drop_all_held_items() + if(del_on_death) ..() //Prevent infinite loops if the mob Destroy() is overridden in such //a manner as to cause a call to death() again //Pain del_on_death = FALSE qdel(src) - else - health = 0 - icon_state = icon_dead - if(flip_on_death) - transform = transform.Turn(180) - ADD_TRAIT(src, TRAIT_UNDENSE, BASIC_MOB_DEATH_TRAIT) - ..() + return + + health = 0 + icon_state = icon_dead + if(flip_on_death) + transform = transform.Turn(180) + ADD_TRAIT(src, TRAIT_UNDENSE, BASIC_MOB_DEATH_TRAIT) + return ..() /mob/living/simple_animal/proc/CanAttack(atom/the_target) if(!isatom(the_target)) // no diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 2fdec746899..cebb747f6ba 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1405,8 +1405,11 @@ . = ..() VV_DROPDOWN_OPTION("", "---------") VV_DROPDOWN_OPTION(VV_HK_GIB, "Gib") + VV_DROPDOWN_OPTION(VV_HK_REMOVE_SPELL, "Remove Spell") VV_DROPDOWN_OPTION(VV_HK_GIVE_SPELL, "Give Spell") VV_DROPDOWN_OPTION(VV_HK_REMOVE_SPELL, "Remove Spell") + VV_DROPDOWN_OPTION(VV_HK_GIVE_MOB_ACTION, "Give Mob Ability") + VV_DROPDOWN_OPTION(VV_HK_REMOVE_MOB_ACTION, "Remove Mob Ability") VV_DROPDOWN_OPTION(VV_HK_GIVE_DISEASE, "Give Disease") VV_DROPDOWN_OPTION(VV_HK_GODMODE, "Toggle Godmode") VV_DROPDOWN_OPTION(VV_HK_DROP_ALL, "Drop Everything") @@ -1433,6 +1436,14 @@ if(!check_rights(R_ADMIN)) return usr.client.cmd_admin_godmode(src) + if(href_list[VV_HK_GIVE_MOB_ACTION]) + if(!check_rights(NONE)) + return + usr.client.give_mob_action(src) + if(href_list[VV_HK_REMOVE_MOB_ACTION]) + if(!check_rights(NONE)) + return + usr.client.remove_mob_action(src) if(href_list[VV_HK_GIVE_SPELL]) if(!check_rights(NONE)) return diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 3e561c75341..7df256d1873 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -207,20 +207,38 @@ return "" // moved out of admins.dm because things other than admin procs were calling this. -/// Returns TRUE if the game has started and we're either an AI with a 0th law, or we're someone with a special role/antag datum -/proc/is_special_character(mob/M) +/** + * Returns TRUE if the game has started and we're either an AI with a 0th law, or we're someone with a special role/antag datum + * If allow_fake_antags is set to FALSE, Valentines, ERTs, and any such roles with FLAG_FAKE_ANTAG won't pass. +*/ +/proc/is_special_character(mob/M, allow_fake_antags = FALSE) if(!SSticker.HasRoundStarted()) return FALSE if(!istype(M)) return FALSE if(iscyborg(M)) //as a borg you're now beholden to your laws rather than greentext return FALSE + + + // Returns TRUE if AI has a zeroth law *and* either has a special role *or* an antag datum. if(isAI(M)) var/mob/living/silicon/ai/A = M return (A.laws?.zeroth && (A.mind?.special_role || !isnull(M.mind?.antag_datums))) - if(M.mind?.special_role || !isnull(M.mind?.antag_datums)) //they have an antag datum! + + if(M.mind?.special_role) return TRUE - return FALSE + + // Turns 'faker' to TRUE if the antag datum is fake. If it's not fake, returns TRUE directly. + var/faker = FALSE + for(var/datum/antagonist/antag_datum as anything in M.mind?.antag_datums) + if((antag_datum.antag_flags & FLAG_FAKE_ANTAG)) + faker = TRUE + else + return TRUE + + // If 'faker' was assigned TRUE in the above loop and the argument 'allow_fake_antags' is set to TRUE, this passes. + // Else, return FALSE. + return (faker && allow_fake_antags) /** * Fancy notifications for ghosts @@ -521,3 +539,33 @@ "[key_name(src)] manually changed selected zone", data, ) + +/** + * Returns an associative list of the logs of a certain amount of lines spoken recently by this mob + * copy_amount - number of lines to return + * line_chance - chance to return a line, if you don't want just the most recent x lines + */ +/mob/proc/copy_recent_speech(copy_amount = LING_ABSORB_RECENT_SPEECH, line_chance = 100) + var/list/recent_speech = list() + var/list/say_log = list() + var/log_source = logging + for(var/log_type in log_source) + var/nlog_type = text2num(log_type) + if(nlog_type & LOG_SAY) + var/list/reversed = log_source[log_type] + if(islist(reversed)) + say_log = reverse_range(reversed.Copy()) + break + + for(var/spoken_memory in say_log) + if(recent_speech.len >= copy_amount) + break + if(!prob(line_chance)) + continue + recent_speech[spoken_memory] = splittext(say_log[spoken_memory], "\"", 1, 0, TRUE)[3] + + var/list/raw_lines = list() + for (var/key as anything in recent_speech) + raw_lines += recent_speech[key] + + return raw_lines diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index e9b0f532da5..03712663249 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -132,7 +132,7 @@ //Basically an optional override for our glide size //Sometimes you want to look like you're moving with a delay you don't actually have yet visual_delay = 0 - var/old_dir = dir + var/old_dir = mob.dir . = ..() diff --git a/code/modules/mob/mob_transformation_simple.dm b/code/modules/mob/mob_transformation_simple.dm index 9bc6a5b22db..fe901b3ad9e 100644 --- a/code/modules/mob/mob_transformation_simple.dm +++ b/code/modules/mob/mob_transformation_simple.dm @@ -66,7 +66,7 @@ else desired_mob.key = key - SEND_SIGNAL(src, COMSIG_MOB_CHANGED_TYPE) + SEND_SIGNAL(src, COMSIG_MOB_CHANGED_TYPE, desired_mob) if(delete_old_mob) QDEL_IN(src, 1) return desired_mob diff --git a/code/modules/mob_spawn/corpses/job_corpses.dm b/code/modules/mob_spawn/corpses/job_corpses.dm index c8dd458f42d..3893f3e1ba6 100644 --- a/code/modules/mob_spawn/corpses/job_corpses.dm +++ b/code/modules/mob_spawn/corpses/job_corpses.dm @@ -83,4 +83,4 @@ name = JOB_ROBOTICIST outfit = /datum/outfit/job/roboticist icon_state = "corpseroboticist" - + diff --git a/code/modules/mob_spawn/corpses/mining_corpses.dm b/code/modules/mob_spawn/corpses/mining_corpses.dm index c0ea4b6af42..8b7ad474b16 100644 --- a/code/modules/mob_spawn/corpses/mining_corpses.dm +++ b/code/modules/mob_spawn/corpses/mining_corpses.dm @@ -16,18 +16,21 @@ //Legion infested mobs -//dwarf type which spawns dwarfy versions -/obj/effect/mob_spawn/corpse/human/legioninfested/dwarf - -/obj/effect/mob_spawn/corpse/human/legioninfested/dwarf/special(mob/living/carbon/human/spawned_human) - . = ..() - spawned_human.dna.add_mutation(/datum/mutation/human/dwarfism) - -//main type, rolls a pool of legion victims +/// Mob spawner used by Legion to spawn costumed bodies /obj/effect/mob_spawn/corpse/human/legioninfested brute_damage = 1000 /obj/effect/mob_spawn/corpse/human/legioninfested/Initialize(mapload) + outfit = select_outfit() + return ..() + +/obj/effect/mob_spawn/corpse/human/legioninfested/special(mob/living/carbon/human/spawned_human) + . = ..() + var/obj/item/organ/internal/legion_tumour/cancer = new() + cancer.Insert(spawned_human, special = TRUE, drop_if_replaced = FALSE) + +/// Returns the outfit worn by our corpse +/obj/effect/mob_spawn/corpse/human/legioninfested/proc/select_outfit() var/corpse_theme = pick_weight(list( "Miner" = 64, "Clown" = 5, @@ -40,26 +43,36 @@ "Shadow", )) = 4, )) + switch(corpse_theme) if("Miner") - outfit = /datum/outfit/consumed_miner + return /datum/outfit/consumed_miner if("Ashwalker") - outfit = /datum/outfit/consumed_ashwalker + return /datum/outfit/consumed_ashwalker if("Golem") - outfit = /datum/outfit/consumed_golem + return /datum/outfit/consumed_golem if("Clown") - outfit = /datum/outfit/consumed_clown + return /datum/outfit/consumed_clown if("Cultist") - outfit = /datum/outfit/consumed_cultist + return /datum/outfit/consumed_cultist if("Dame") - outfit = /datum/outfit/consumed_dame + return /datum/outfit/consumed_dame if("Operative") - outfit = /datum/outfit/syndicatecommandocorpse/lessenedgear + return /datum/outfit/syndicatecommandocorpse/lessenedgear if("Shadow") - outfit = /datum/outfit/consumed_shadowperson + return /datum/outfit/consumed_shadowperson + +/// Corpse spawner used by dwarf legions to make small corpses +/obj/effect/mob_spawn/corpse/human/legioninfested/dwarf + +/obj/effect/mob_spawn/corpse/human/legioninfested/dwarf/special(mob/living/carbon/human/spawned_human) . = ..() + spawned_human.dna.add_mutation(/datum/mutation/human/dwarfism) + +/// Corpse spawner used by snow legions with alternate costumes +/obj/effect/mob_spawn/corpse/human/legioninfested/snow -/obj/effect/mob_spawn/corpse/human/snowlegioninfested/Initialize(mapload) +/obj/effect/mob_spawn/corpse/human/legioninfested/snow/select_outfit() var/corpse_theme = pick_weight(list( "Miner" = 64, "Clown" = 5, @@ -72,24 +85,49 @@ "Shadow", )) = 4, )) + switch(corpse_theme) if("Miner") - outfit = /datum/outfit/consumed_miner + return /datum/outfit/consumed_miner if("Settler") - outfit = /datum/outfit/consumed_ice_settler + return /datum/outfit/consumed_ice_settler if("Heremoth") - outfit = /datum/outfit/consumed_heremoth + return /datum/outfit/consumed_heremoth if("Clown") - outfit = /datum/outfit/consumed_clown + return /datum/outfit/consumed_clown if("Cultist") - outfit = /datum/outfit/consumed_cultist + return /datum/outfit/consumed_cultist if("Golem") - outfit = /datum/outfit/consumed_golem + return /datum/outfit/consumed_golem if("Operative") - outfit = /datum/outfit/syndicatecommandocorpse/lessenedgear + return /datum/outfit/syndicatecommandocorpse/lessenedgear if("Shadow") - outfit = /datum/outfit/consumed_shadowperson + return /datum/outfit/consumed_shadowperson + +/// Creates a dead legion-infested skeleton +/obj/effect/mob_spawn/corpse/human/legioninfested/skeleton + name = "legion-infested skeleton" + mob_name = "skeleton" + mob_species = /datum/species/skeleton + +/obj/effect/mob_spawn/corpse/human/legioninfested/skeleton/select_outfit() + return null + +/obj/effect/mob_spawn/corpse/human/legioninfested/skeleton/special(mob/living/carbon/human/spawned_human) . = ..() + spawned_human.gender = NEUTER + +/// Creates a dead and burned legion-infested skeleton +/obj/effect/mob_spawn/corpse/human/legioninfested/skeleton/charred + name = "charred legion-infested skeleton" + mob_name = "charred skeleton" + brute_damage = 0 + burn_damage = 1000 + +/obj/effect/mob_spawn/corpse/human/legioninfested/skeleton/charred/special(mob/living/carbon/human/spawned_human) + . = ..() + spawned_human.color = "#454545" + /datum/outfit/consumed_miner name = "Legion-Consumed Miner" diff --git a/code/modules/mob_spawn/ghost_roles/drone_roles.dm b/code/modules/mob_spawn/ghost_roles/drone_roles.dm new file mode 100644 index 00000000000..b8a31a16b13 --- /dev/null +++ b/code/modules/mob_spawn/ghost_roles/drone_roles.dm @@ -0,0 +1,6 @@ +/obj/effect/mob_spawn/ghost_role/drone/name_mob(mob/living/spawned_mob, forced_name) + if(!forced_name) + var/designation = pick(GLOB.posibrain_names) + forced_name = "Drone ([designation]-[rand(100, 999)])" + + return ..() diff --git a/code/modules/mob_spawn/ghost_roles/mining_roles.dm b/code/modules/mob_spawn/ghost_roles/mining_roles.dm index de461380b54..62861c6f303 100644 --- a/code/modules/mob_spawn/ghost_roles/mining_roles.dm +++ b/code/modules/mob_spawn/ghost_roles/mining_roles.dm @@ -236,7 +236,7 @@ return ..() /obj/effect/mob_spawn/ghost_role/human/ash_walker/allow_spawn(mob/user, silent = FALSE) - if(!(user.key in team.players_spawned))//one per person unless you get a bonus spawn + if(!(user.ckey in team.players_spawned))//one per person unless you get a bonus spawn SKYRAT EDIT: Original: if(!(user.key in team.players_spawned)) return TRUE if(!silent) to_chat(user, span_warning("You have exhausted your usefulness to the Necropolis.")) @@ -254,7 +254,7 @@ spawned_human.mind.add_antag_datum(/datum/antagonist/ashwalker, team) spawned_human.remove_language(/datum/language/common) - team.players_spawned += (spawned_human.key) + team.players_spawned += (spawned_human.ckey) //SKYRAT EDIT: Original: team.players_spawned += (spawned_human.key) eggshell.egg = null QDEL_NULL(eggshell) diff --git a/code/modules/mob_spawn/mob_spawn.dm b/code/modules/mob_spawn/mob_spawn.dm index a853d48c0ec..d24850b8732 100644 --- a/code/modules/mob_spawn/mob_spawn.dm +++ b/code/modules/mob_spawn/mob_spawn.dm @@ -32,6 +32,8 @@ var/facial_haircolor ///sets a human's skin tone var/skin_tone + /// Weakref to the mob this spawner created - just if you needed to do something with it. + var/datum/weakref/spawned_mob_ref /obj/effect/mob_spawn/Initialize(mapload) . = ..() @@ -44,6 +46,7 @@ name_mob(spawned_mob, newname) special(spawned_mob, mob_possessor) equip(spawned_mob) + spawned_mob_ref = WEAKREF(spawned_mob) return spawned_mob /obj/effect/mob_spawn/proc/special(mob/living/spawned_mob) @@ -250,6 +253,7 @@ if(isnull(created)) // If we explicitly return FALSE instead of just not returning a mob, we don't want to spam the admins CRASH("An instance of [type] didn't return anything when creating a mob, this might be broken!") + SEND_SIGNAL(src, COMSIG_GHOSTROLE_SPAWNED, created) check_uses() // Now we check if the spawner should delete itself or not return created diff --git a/code/modules/mod/mod_link.dm b/code/modules/mod/mod_link.dm index 8a3340fad3e..12ce7fa4827 100644 --- a/code/modules/mod/mod_link.dm +++ b/code/modules/mod/mod_link.dm @@ -173,6 +173,10 @@ /obj/item/clothing/neck/link_scryer/examine(mob/user) . = ..() + // SKYRAT EDIT NIFSOFT SCRYERS - START + if(custom_examine_controls) + return + // SKYRAT EDIT NIFSOFT SCRYERS - END if(cell) . += span_notice("The battery charge reads [cell.percent()]%. Right-click with an empty hand to remove it.") else diff --git a/code/modules/mod/mod_types.dm b/code/modules/mod/mod_types.dm index f11c6b9b4b9..f8daa9bab54 100644 --- a/code/modules/mod/mod_types.dm +++ b/code/modules/mod/mod_types.dm @@ -260,6 +260,12 @@ /obj/item/mod/module/jump_jet, ) +/obj/item/mod/control/pre_equipped/nuclear/no_jetpack + +/obj/item/mod/control/pre_equipped/nuclear/no_jetpack/Initialize(mapload, new_theme, new_skin, new_core) + applied_modules -= list(/obj/item/mod/module/jetpack/advanced, /obj/item/mod/module/jump_jet) + return ..() + /obj/item/mod/control/pre_equipped/nuclear/plasmaman /obj/item/mod/control/pre_equipped/nuclear/plasmaman/Initialize(mapload, new_theme, new_skin, new_core) diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index 21d2b8352fb..6fe91c9575b 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -150,6 +150,7 @@ close_all_programs() //Some components will actually try and interact with this, so let's do it later QDEL_NULL(soundloop) + looping_sound = FALSE // Necessary to stop a possible runtime trying to call soundloop.stop() when soundloop has been qdel'd QDEL_LIST(stored_files) if(istype(inserted_disk)) @@ -802,14 +803,8 @@ /obj/item/modular_computer/wrench_act_secondary(mob/living/user, obj/item/tool) . = ..() tool.play_tool_sound(src, user, 20, volume=20) - internal_cell?.forceMove(drop_location()) - computer_id_slot?.forceMove(drop_location()) - inserted_disk?.forceMove(drop_location()) - remove_pai() - new /obj/item/stack/sheet/iron(get_turf(loc), steel_sheet_cost) + deconstruct(TRUE) user.balloon_alert(user, "disassembled") - relay_qdel() - qdel(src) return TOOL_ACT_TOOLTYPE_SUCCESS /obj/item/modular_computer/welder_act(mob/living/user, obj/item/tool) @@ -830,15 +825,26 @@ return TOOL_ACT_TOOLTYPE_SUCCESS /obj/item/modular_computer/deconstruct(disassembled = TRUE) - break_apart() - return ..() - -/obj/item/modular_computer/proc/break_apart() + remove_pai() + eject_aicard() if(!(flags_1 & NODECONSTRUCT_1)) - physical.visible_message(span_notice("\The [src] breaks apart!")) - var/turf/newloc = get_turf(src) - new /obj/item/stack/sheet/iron(newloc, round(steel_sheet_cost / 2)) + if (disassembled) + internal_cell?.forceMove(drop_location()) + computer_id_slot?.forceMove(drop_location()) + inserted_disk?.forceMove(drop_location()) + new /obj/item/stack/sheet/iron(drop_location(), steel_sheet_cost) + else + physical.visible_message(span_notice("\The [src] breaks apart!")) + new /obj/item/stack/sheet/iron(drop_location(), round(steel_sheet_cost * 0.5)) relay_qdel() + return ..() + +// Ejects the inserted intellicard, if one exists. Used when the computer is deconstructed. +/obj/item/modular_computer/proc/eject_aicard() + var/datum/computer_file/program/ai_restorer/program = locate() in stored_files + if (program) + return program.try_eject(forced = TRUE) + return FALSE // Used by processor to relay qdel() to machinery type. /obj/item/modular_computer/proc/relay_qdel() diff --git a/code/modules/modular_computers/computers/item/role_tablet_presets.dm b/code/modules/modular_computers/computers/item/role_tablet_presets.dm index b96f61d44b4..e2f1b354eda 100644 --- a/code/modules/modular_computers/computers/item/role_tablet_presets.dm +++ b/code/modules/modular_computers/computers/item/role_tablet_presets.dm @@ -270,6 +270,14 @@ /datum/computer_file/program/skill_tracker, ) +/obj/item/modular_computer/pda/bitrunner + name = "bit runner PDA" + greyscale_colors = "#D6B328#6BC906" + starting_programs = list( + /datum/computer_file/program/arcade, + /datum/computer_file/program/skill_tracker, + ) + /** * Service */ diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm index 33f4bc29a16..293cdd9c5f7 100644 --- a/code/modules/modular_computers/computers/machinery/modular_computer.dm +++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm @@ -125,9 +125,9 @@ return cpu.screwdriver_act(user, tool) return ..() -/obj/machinery/modular_computer/wrench_act(mob/user, obj/item/tool) +/obj/machinery/modular_computer/wrench_act_secondary(mob/user, obj/item/tool) if(cpu) - return cpu.wrench_act(user, tool) + return cpu.wrench_act_secondary(user, tool) return ..() /obj/machinery/modular_computer/welder_act(mob/user, obj/item/tool) diff --git a/code/modules/modular_computers/file_system/programs/budgetordering.dm b/code/modules/modular_computers/file_system/programs/budgetordering.dm index c261f3a3d43..d2133697194 100644 --- a/code/modules/modular_computers/file_system/programs/budgetordering.dm +++ b/code/modules/modular_computers/file_system/programs/budgetordering.dm @@ -118,9 +118,11 @@ if(SSshuttle.supply_blocked) message = blockade_warning data["message"] = message + var/list/amount_by_name = list() var/cart_list = list() for(var/datum/supply_order/order in SSshuttle.shopping_list) if(cart_list[order.pack.name]) + amount_by_name[order.pack.name] += 1 cart_list[order.pack.name][1]["amount"]++ cart_list[order.pack.name][1]["cost"] += order.get_final_cost() if(order.department_destination) @@ -145,15 +147,23 @@ data["cart"] += cart_list[item_id] data["requests"] = list() - for(var/datum/supply_order/SO in SSshuttle.request_list) + for(var/datum/supply_order/order in SSshuttle.request_list) + var/datum/supply_pack/pack = order.pack + amount_by_name[pack.name] += 1 data["requests"] += list(list( - "object" = SO.pack.name, - "cost" = SO.pack.get_cost(), - "orderer" = SO.orderer, - "reason" = SO.reason, - "id" = SO.id + "object" = pack.name, + "cost" = pack.get_cost(), + "orderer" = order.orderer, + "reason" = order.reason, + "id" = order.id )) + data["amount_by_name"] = amount_by_name + + return data +/datum/computer_file/program/budgetorders/ui_static_data(mob/user) + var/list/data = list() + data["max_order"] = CARGO_MAX_ORDER return data /datum/computer_file/program/budgetorders/ui_act(action, params, datum/tgui/ui) @@ -233,15 +243,20 @@ return if(pack.goody && !self_paid) - playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE) + playsound(computer, 'sound/machines/buzz-sigh.ogg', 50, FALSE) computer.say("ERROR: Small crates may only be purchased by private accounts.") return + if(SSshuttle.supply.get_order_count(pack) == OVER_ORDER_LIMIT) + playsound(computer, 'sound/machines/buzz-sigh.ogg', 50, FALSE) + computer.say("ERROR: No more then [CARGO_MAX_ORDER] of any pack may be ordered at once") + return + if(!requestonly && !self_paid && ishuman(usr) && !account) var/obj/item/card/id/id_card = computer.computer_id_slot?.GetID() account = SSeconomy.get_dep_account(id_card?.registered_account?.account_job.paycheck_department) - var/turf/T = get_turf(src) + var/turf/T = get_turf(computer) var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account) SO.generateRequisition(T) if((requestonly && !self_paid) || !(computer.computer_id_slot?.GetID())) diff --git a/code/modules/modular_computers/file_system/programs/crewmanifest.dm b/code/modules/modular_computers/file_system/programs/crewmanifest.dm index 3215f62eef8..cdd05d6b4c6 100644 --- a/code/modules/modular_computers/file_system/programs/crewmanifest.dm +++ b/code/modules/modular_computers/file_system/programs/crewmanifest.dm @@ -4,7 +4,7 @@ category = PROGRAM_CATEGORY_CREW program_icon_state = "id" extended_desc = "Program for viewing and printing the current crew manifest" - transfer_access = list(ACCESS_COMMAND) + transfer_access = list(ACCESS_SECURITY, ACCESS_COMMAND) requires_ntnet = TRUE size = 4 tgui_id = "NtosCrewManifest" diff --git a/code/modules/modular_computers/file_system/programs/records.dm b/code/modules/modular_computers/file_system/programs/records.dm index 960702d608c..9b5617364c0 100644 --- a/code/modules/modular_computers/file_system/programs/records.dm +++ b/code/modules/modular_computers/file_system/programs/records.dm @@ -45,6 +45,7 @@ current_record["rank"] = person.rank current_record["species"] = person.species current_record["wanted"] = person.wanted_status + current_record["voice"] = person.voice all_records += list(current_record) if("medical") diff --git a/code/modules/movespeed/modifiers/mobs.dm b/code/modules/movespeed/modifiers/mobs.dm index 59b514a3d57..e5f29323223 100644 --- a/code/modules/movespeed/modifiers/mobs.dm +++ b/code/modules/movespeed/modifiers/mobs.dm @@ -84,9 +84,6 @@ /datum/movespeed_modifier/shove multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH -/datum/movespeed_modifier/borg_throw - multiplicative_slowdown = 0.9 - /datum/movespeed_modifier/human_carry multiplicative_slowdown = HUMAN_CARRY_SLOWDOWN blacklisted_movetypes = FLOATING diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm index 8c3039d8c62..e1a4dfb0ae0 100644 --- a/code/modules/pai/pai.dm +++ b/code/modules/pai/pai.dm @@ -111,6 +111,7 @@ "crow" = TRUE, "duffel" = TRUE, "fox" = FALSE, + "frog" = TRUE, "hawk" = FALSE, "lizard" = FALSE, "monkey" = TRUE, diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm index cb6aae768fa..ed99e7ea179 100644 --- a/code/modules/paperwork/filingcabinet.dm +++ b/code/modules/paperwork/filingcabinet.dm @@ -193,9 +193,9 @@ GLOBAL_LIST_EMPTY(employmentCabinets) /obj/structure/filingcabinet/employment/proc/fillCurrent() //This proc fills the cabinet with the current crew. for(var/datum/record/locked/target in GLOB.manifest.locked) - var/datum/mind/mind_ref = target.mind_ref - if(mind_ref && ishuman(mind_ref.current)) - addFile(mind_ref.current) + var/datum/mind/filed_mind = target.mind_ref.resolve() + if(filed_mind && ishuman(filed_mind.current)) + addFile(filed_mind.current) /obj/structure/filingcabinet/employment/proc/addFile(mob/living/carbon/human/employee) new /obj/item/paper/employment_contract(src, employee.mind.name) diff --git a/code/modules/photography/_pictures.dm b/code/modules/photography/_pictures.dm index 8c949892dbf..45fa5654ad9 100644 --- a/code/modules/photography/_pictures.dm +++ b/code/modules/photography/_pictures.dm @@ -5,6 +5,8 @@ var/list/mobs_seen = list() /// List of weakrefs pointing at dead mobs that appear in this photo var/list/dead_seen = list() + /// List of strings of face-visible humans in this photo + var/list/names_seen = list() var/caption var/icon/picture_image var/icon/picture_icon @@ -16,7 +18,7 @@ ///Was this image capable of seeing ghosts? var/see_ghosts = CAMERA_NO_GHOSTS -/datum/picture/New(name, desc, mobs_spotted, dead_spotted, image, icon, size_x, size_y, bp, caption_, autogenerate_icon, can_see_ghosts) +/datum/picture/New(name, desc, mobs_spotted, dead_spotted, names, image, icon, size_x, size_y, bp, caption_, autogenerate_icon, can_see_ghosts) if(!isnull(name)) picture_name = name if(!isnull(desc)) @@ -27,6 +29,9 @@ if(!isnull(dead_spotted)) for(var/mob/seen as anything in dead_spotted) dead_seen += WEAKREF(seen) + if(!isnull(names)) + for(var/seen in names) + names_seen += seen if(!isnull(image)) picture_image = image if(!isnull(icon)) diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm index 1c0e360ed75..b168aaf54da 100644 --- a/code/modules/photography/camera/camera.dm +++ b/code/modules/photography/camera/camera.dm @@ -188,6 +188,8 @@ var/list/mobs = list() var/blueprints = FALSE var/clone_area = SSmapping.request_turf_block_reservation(size_x * 2 + 1, size_y * 2 + 1, 1) + ///list of human names taken on picture + var/list/names = list() var/width = size_x * 2 + 1 var/height = size_y * 2 + 1 @@ -218,8 +220,11 @@ var/icon/get_icon = camera_get_icon(turfs, target_turf, psize_x, psize_y, clone_area, size_x, size_y, (size_x * 2 + 1), (size_y * 2 + 1)) qdel(clone_area) get_icon.Blend("#000", ICON_UNDERLAY) + for(var/mob/living/carbon/human/person in mobs) + if(person.is_face_visible()) + names += "[person.name]" - var/datum/picture/picture = new("picture", desc.Join(" "), mobs_spotted, dead_spotted, get_icon, null, psize_x, psize_y, blueprints, can_see_ghosts = see_ghosts) + var/datum/picture/picture = new("picture", desc.Join(" "), mobs_spotted, dead_spotted, names, get_icon, null, psize_x, psize_y, blueprints, can_see_ghosts = see_ghosts) after_picture(user, picture) SEND_SIGNAL(src, COMSIG_CAMERA_IMAGE_CAPTURED, target, user) blending = FALSE diff --git a/code/modules/photography/photos/photo.dm b/code/modules/photography/photos/photo.dm index 9be79a58266..b34ff459c00 100644 --- a/code/modules/photography/photos/photo.dm +++ b/code/modules/photography/photos/photo.dm @@ -54,11 +54,11 @@ icon = I return ..() -/obj/item/photo/suicide_act(mob/living/carbon/user) +/obj/item/photo/suicide_act(mob/living/carbon/human/user) user.visible_message(span_suicide("[user] is taking one last look at \the [src]! It looks like [user.p_theyre()] giving in to death!"))//when you wanna look at photo of waifu one last time before you die... - if (user.gender == MALE) + if (!ishuman(user) || user.physique == MALE) playsound(user, 'sound/voice/human/manlaugh1.ogg', 50, TRUE)//EVERY TIME I DO IT MAKES ME LAUGH - else if (user.gender == FEMALE) + else playsound(user, 'sound/voice/human/womanlaugh.ogg', 50, TRUE) return OXYLOSS diff --git a/code/modules/power/rtg.dm b/code/modules/power/rtg.dm index c49bc455165..974c2e66737 100644 --- a/code/modules/power/rtg.dm +++ b/code/modules/power/rtg.dm @@ -71,7 +71,7 @@ visible_message(span_danger("\The [src] lets out a shower of sparks as it starts to lose stability!"),\ span_hear("You hear a loud electrical crack!")) playsound(src.loc, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) - tesla_zap(src, 5, power_gen * 0.05) + tesla_zap(src, 5, power_gen * 20) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(explosion), src, 2, 3, 4, null, 8), 10 SECONDS) // Not a normal explosion. /obj/machinery/power/rtg/abductor/bullet_act(obj/projectile/Proj) diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 654ea805440..8598b3cccf2 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -53,8 +53,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) var/damage_archived = 0 var/list/damage_factors - /// How much extra power does the main zap generate. - var/zap_multiplier = 1 + /// The zap power transmission over internal energy. W/MeV. + var/zap_transmission_rate = BASE_POWER_TRANSMISSION_RATE var/list/zap_factors /// The temperature at which we start taking damage @@ -95,7 +95,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) /// How much power decay is negated. Complete power decay negation at 1. var/gas_powerloss_inhibition = 0 /// Affects the amount of power the main SM zap makes. - var/gas_power_transmission = 0 + var/gas_power_transmission_rate = 0 /// Affects the power gain the SM experiances from heat. var/gas_heat_power_generation = 0 @@ -109,7 +109,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) var/external_damage_immediate = 0 ///The cutoff for a bolt jumping, grows with heat, lowers with higher mol count, - var/zap_cutoff = 1500 + var/zap_cutoff = 1.2e6 ///How much the bullets damage should be multiplied by when it is added to the internal variables var/bullet_energy = SUPERMATTER_DEFAULT_BULLET_ENERGY ///How much hallucination should we produce per unit of power? @@ -153,6 +153,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) ///Stores the time of when the last zap occurred var/last_power_zap = 0 + var/last_high_energy_zap = 0 ///Do we show this crystal in the CIMS modular program var/include_in_cims = TRUE @@ -275,7 +276,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) // PART 3: POWER PROCESSING internal_energy_factors = calculate_internal_energy() - zap_factors = calculate_zap_multiplier() + zap_factors = calculate_zap_transmission_rate() if(internal_energy && (last_power_zap + (4 - internal_energy * 0.001) SECONDS) < world.time) playsound(src, 'sound/weapons/emitter2.ogg', 70, TRUE) hue_angle_shift = clamp(903 * log(10, (internal_energy + 8000)) - 3590, -50, 240) @@ -286,9 +287,9 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) supermatter_zap( zapstart = src, range = 3, - zap_str = 1.25 * internal_energy * zap_multiplier * delta_time, + zap_str = internal_energy * zap_transmission_rate * delta_time, zap_flags = ZAP_SUPERMATTER_FLAGS, - zap_cutoff = 300 * delta_time, + zap_cutoff = 2.4e5 * delta_time, power_level = internal_energy, color = zap_color, ) @@ -374,15 +375,20 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) "name" = factor, "amount" = amount * -1 )) + var/list/internal_energy_si_derived_data = siunit_isolated(internal_energy * 1e6, "eV", 3) data["internal_energy"] = internal_energy + data["internal_energy_coefficient"] = internal_energy_si_derived_data[SI_COEFFICIENT] + data["internal_energy_unit"] = internal_energy_si_derived_data[SI_UNIT] data["internal_energy_factors"] = list() for (var/factor in internal_energy_factors) + var/list/internal_energy_factor_si_derived_data = siunit_isolated(internal_energy_factors[factor] * 1e6, "eV", 3) var/amount = round(internal_energy_factors[factor], 0.01) if(!amount) continue data["internal_energy_factors"] += list(list( "name" = factor, - "amount" = amount + "amount" = internal_energy_factor_si_derived_data[SI_COEFFICIENT], + "unit" = internal_energy_factor_si_derived_data[SI_UNIT], )) data["temp_limit"] = temp_limit data["temp_limit_factors"] = list() @@ -392,7 +398,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) continue data["temp_limit_factors"] += list(list( "name" = factor, - "amount" = amount + "amount" = amount, )) data["waste_multiplier"] = waste_multiplier data["waste_multiplier_factors"] = list() @@ -402,18 +408,42 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) continue data["waste_multiplier_factors"] += list(list( "name" = factor, - "amount" = amount + "amount" = amount, )) - data["zap_multiplier"] = zap_multiplier - data["zap_multiplier_factors"] = list() + + data["zap_transmission_factors"] = list() for (var/factor in zap_factors) - var/amount = round(zap_factors[factor], 0.01) - if(!amount) + var/list/zap_factor_si_derived_data = siunit_isolated(zap_factors[factor] * internal_energy, "W", 2) + if(!zap_factor_si_derived_data[SI_COEFFICIENT]) continue - data["zap_multiplier_factors"] += list(list( + data["zap_transmission_factors"] += list(list( "name" = factor, - "amount" = amount + "amount" = zap_factor_si_derived_data[SI_COEFFICIENT], + "unit" = zap_factor_si_derived_data[SI_UNIT], )) + + ///Add high energy bonus to the zap transmission data so we can accurately measure our power generation from zaps. + var/high_energy_bonus = 0 + var/zap_transmission = zap_transmission_rate * internal_energy + var/zap_power_multiplier = 1 + if(internal_energy > POWER_PENALTY_THRESHOLD) //Supermatter zaps multiply power internally under some conditions for some reason, so we'll snowflake this for now. + ///Power multiplier bonus applied to all zaps. Zap power generation doubles when it reaches 7GeV and 9GeV. + zap_power_multiplier *= 2 ** clamp(round((internal_energy - POWER_PENALTY_THRESHOLD) / 2000), 0, 2) + ///The supermatter releases additional zaps after 5GeV, with more at 7GeV and 9GeV. + var/additional_zap_bonus = clamp(internal_energy * 3200, 6.4e6, 3.2e7) * clamp(round(INVERSE_LERP(1000, 3000, internal_energy)), 1, 4) + high_energy_bonus = (zap_transmission + additional_zap_bonus) * zap_power_multiplier - zap_transmission + var/list/zap_factor_si_derived_data = siunit_isolated(high_energy_bonus, "W", 2) + data["zap_transmission_factors"] += list(list( + "name" = "High Energy Bonus", + "amount" = zap_factor_si_derived_data[SI_COEFFICIENT], + "unit" = zap_factor_si_derived_data[SI_UNIT], + )) + + var/list/zap_transmission_si_derived_data = siunit_isolated(zap_transmission + high_energy_bonus, "W", 2) + data["zap_transmission"] = zap_transmission + high_energy_bonus + data["zap_transmission_coefficient"] = zap_transmission_si_derived_data[SI_COEFFICIENT] + data["zap_transmission_unit"] = zap_transmission_si_derived_data[SI_UNIT] + data["absorbed_ratio"] = absorption_ratio var/list/formatted_gas_percentage = list() for (var/datum/gas/gas_path as anything in subtypesof(/datum/gas)) @@ -577,7 +607,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) * * Updates: * [/obj/machinery/power/supermatter_crystal/var/list/gas_percentage] - * [/obj/machinery/power/supermatter_crystal/var/gas_power_transmission] + * [/obj/machinery/power/supermatter_crystal/var/gas_power_transmission_rate] * [/obj/machinery/power/supermatter_crystal/var/gas_heat_modifier] * [/obj/machinery/power/supermatter_crystal/var/gas_heat_resistance] * [/obj/machinery/power/supermatter_crystal/var/gas_heat_power_generation] @@ -590,7 +620,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) return gas_percentage = list() - gas_power_transmission = 0 + gas_power_transmission_rate = 0 gas_heat_modifier = 0 gas_heat_resistance = 0 gas_heat_power_generation = 0 @@ -607,7 +637,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) var/datum/sm_gas/sm_gas = current_gas_behavior[gas_path] if(!sm_gas) continue - gas_power_transmission += sm_gas.power_transmission * gas_percentage[gas_path] + gas_power_transmission_rate += sm_gas.power_transmission * gas_percentage[gas_path] gas_heat_modifier += sm_gas.heat_modifier * gas_percentage[gas_path] gas_heat_resistance += sm_gas.heat_resistance * gas_percentage[gas_path] gas_heat_power_generation += sm_gas.heat_power_generation * gas_percentage[gas_path] @@ -637,7 +667,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) external_power_trickle -= min(additive_power[SM_POWER_EXTERNAL_TRICKLE], external_power_trickle) additive_power[SM_POWER_EXTERNAL_IMMEDIATE] = external_power_immediate external_power_immediate = 0 - additive_power[SM_POWER_HEAT] = gas_heat_power_generation * absorbed_gasmix.temperature / 6 + additive_power[SM_POWER_HEAT] = gas_heat_power_generation * absorbed_gasmix.temperature * GAS_HEAT_POWER_SCALING_COEFFICIENT additive_power[SM_POWER_HEAT] && log_activation(who = "environmental factors") // I'm sorry for this, but we need to calculate power lost immediately after power gain. @@ -660,6 +690,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) if(internal_energy && !activation_logged) stack_trace("Supermatter powered for the first time without being logged. Internal energy factors: [json_encode(internal_energy_factors)]") activation_logged = TRUE // so we dont spam the log. + else if(!internal_energy) + last_power_zap = world.time return additive_power /** Log when the supermatter is activated for the first time. @@ -685,24 +717,24 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) activation_logged = TRUE /** - * Perform calculation for the main zap power multiplier. + * Perform calculation for the main zap power transmission rate in W/MeV. * Description of each factors can be found in the defines. * * Updates: - * [/obj/machinery/power/supermatter_crystal/var/zap_multiplier] + * [/obj/machinery/power/supermatter_crystal/var/zap_transmission_rate] * * Returns: The factors that have influenced the calculation. list[FACTOR_DEFINE] = number */ -/obj/machinery/power/supermatter_crystal/proc/calculate_zap_multiplier() - var/list/additive_transmission = list() - additive_transmission[SM_ZAP_BASE] = 1 - additive_transmission[SM_ZAP_GAS] = gas_power_transmission +/obj/machinery/power/supermatter_crystal/proc/calculate_zap_transmission_rate() + var/list/additive_transmission_rate = list() + additive_transmission_rate[SM_ZAP_BASE] = BASE_POWER_TRANSMISSION_RATE + additive_transmission_rate[SM_ZAP_GAS] = BASE_POWER_TRANSMISSION_RATE * gas_power_transmission_rate - zap_multiplier = 0 - for (var/transmission_types in additive_transmission) - zap_multiplier += additive_transmission[transmission_types] - zap_multiplier = max(zap_multiplier, 0) - return additive_transmission + zap_transmission_rate = 0 + for (var/transmission_types in additive_transmission_rate) + zap_transmission_rate += additive_transmission_rate[transmission_types] + zap_transmission_rate = max(zap_transmission_rate, 0) + return additive_transmission_rate /** * Perform calculation for the waste multiplier. @@ -836,7 +868,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) delamination_strategy.on_select(src) return TRUE -/obj/machinery/proc/supermatter_zap(atom/zapstart = src, range = 5, zap_str = 4000, zap_flags = ZAP_SUPERMATTER_FLAGS, list/targets_hit = list(), zap_cutoff = 1500, power_level = 0, zap_icon = DEFAULT_ZAP_ICON_STATE, color = null) +/obj/machinery/proc/supermatter_zap(atom/zapstart = src, range = 5, zap_str = 3.2e6, zap_flags = ZAP_SUPERMATTER_FLAGS, list/targets_hit = list(), zap_cutoff = 1.2e6, power_level = 0, zap_icon = DEFAULT_ZAP_ICON_STATE, color = null) if(QDELETED(zapstart)) return . = zapstart.dir @@ -931,13 +963,13 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) //Going boom should be rareish if(prob(80)) zap_flags &= ~ZAP_MACHINE_EXPLOSIVE - if(target_type == COIL) - var/multi = 2 - switch(power_level)//Between 7k and 9k it's 4, above that it's 8 + if(target_type == COIL || target_type == ROD) + var/multi = 1 + switch(power_level)//Between 7k and 9k it's 2, above that it's 4 if(SEVERE_POWER_PENALTY_THRESHOLD to CRITICAL_POWER_PENALTY_THRESHOLD) - multi = 4 + multi = 2 if(CRITICAL_POWER_PENALTY_THRESHOLD to INFINITY) - multi = 8 + multi = 4 if(zap_flags & ZAP_SUPERMATTER_FLAGS) var/remaining_power = target.zap_act(zap_str * multi, zap_flags) zap_str = remaining_power / multi //Coils should take a lot out of the power of the zap diff --git a/code/modules/power/supermatter/supermatter_extra_effects.dm b/code/modules/power/supermatter/supermatter_extra_effects.dm index 7fe56d9c2d4..efd84c677fa 100644 --- a/code/modules/power/supermatter/supermatter_extra_effects.dm +++ b/code/modules/power/supermatter/supermatter_extra_effects.dm @@ -91,6 +91,7 @@ /obj/machinery/power/supermatter_crystal/proc/handle_high_power() if(internal_energy <= POWER_PENALTY_THRESHOLD && damage <= danger_point) //If the power is above 5000 or if the damage is above 550 + last_high_energy_zap = world.time //Prevent oddly high initial zap due to high energy zaps not getting triggered via too low energy. return var/range = 4 zap_cutoff = 1500 @@ -99,7 +100,7 @@ var/temp = absorbed_gasmix.temperature if(pressure > 0 && temp > 0) //You may be able to freeze the zapstate of the engine with good planning, we'll see - zap_cutoff = clamp(3000 - (internal_energy * total_moles / 10) / temp, 350, 3000)//If the core is cold, it's easier to jump, ditto if there are a lot of mols + zap_cutoff = clamp(1.2e6 - (internal_energy * total_moles * 40) / temp, 1.4e5, 1.2e6)//If the core is cold, it's easier to jump, ditto if there are a lot of mols //We should always be able to zap our way out of the default enclosure //See supermatter_zap() for more details range = clamp(internal_energy / pressure * 10, 2, 7) @@ -128,9 +129,10 @@ if(zap_count >= 1) playsound(loc, 'sound/weapons/emitter2.ogg', 100, TRUE, extrarange = 10) + var/delta_time = min((world.time - last_high_energy_zap) * 0.1, 16) for(var/i in 1 to zap_count) - supermatter_zap(src, range, clamp(internal_energy*2, 4000, 20000), flags, zap_cutoff = src.zap_cutoff, power_level = internal_energy, zap_icon = src.zap_icon) - + supermatter_zap(src, range, clamp(internal_energy * 3200, 6.4e6, 3.2e7) * delta_time, flags, zap_cutoff = src.zap_cutoff * delta_time, power_level = internal_energy, zap_icon = src.zap_icon) + last_high_energy_zap = world.time if(prob(5)) supermatter_anomaly_gen(src, FLUX_ANOMALY, rand(5, 10)) if(prob(5)) diff --git a/code/modules/power/supermatter/supermatter_gas.dm b/code/modules/power/supermatter/supermatter_gas.dm index 141f78a38b8..df8ef8e5b4f 100644 --- a/code/modules/power/supermatter/supermatter_gas.dm +++ b/code/modules/power/supermatter/supermatter_gas.dm @@ -17,33 +17,40 @@ // Positive is true if more of the amount is a good thing. var/list/numeric_data = list() if(sm_gas.power_transmission) + var/list/si_derived_data = siunit_isolated(sm_gas.power_transmission * BASE_POWER_TRANSMISSION_RATE, "W/MeV", 2) numeric_data += list(list( - "name" = "Power Transmission", - "amount" = sm_gas.power_transmission, + "name" = "Power Transmission Bonus", + "amount" = si_derived_data["coefficient"], + "unit" = si_derived_data["unit"], "positive" = TRUE, )) if(sm_gas.heat_modifier) numeric_data += list(list( "name" = "Waste Multiplier", - "amount" = sm_gas.heat_modifier, + "amount" = 100 * sm_gas.heat_modifier, + "unit" = "%", "positive" = FALSE, )) if(sm_gas.heat_resistance) numeric_data += list(list( "name" = "Heat Resistance", - "amount" = sm_gas.heat_resistance, + "amount" = 100 * sm_gas.heat_resistance, + "unit" = "%", "positive" = TRUE, )) if(sm_gas.heat_power_generation) + var/list/si_derived_data = siunit_isolated(sm_gas.heat_power_generation * GAS_HEAT_POWER_SCALING_COEFFICIENT * 1e7 / SSair.wait, "eV/K/s", 2) numeric_data += list(list( "name" = "Heat Power Gain", - "amount" = sm_gas.heat_power_generation, + "amount" = si_derived_data["coefficient"], + "unit" = si_derived_data["unit"], "positive" = TRUE, )) if(sm_gas.powerloss_inhibition) numeric_data += list(list( "name" = "Power Decay Negation", - "amount" = sm_gas.powerloss_inhibition, + "amount" = 100 * sm_gas.powerloss_inhibition, + "unit" = "%", "positive" = TRUE, )) singular_gas_data["numeric_data"] = numeric_data @@ -59,8 +66,7 @@ GLOBAL_LIST_INIT(sm_gas_behavior, init_sm_gas()) /datum/sm_gas /// Path of the [/datum/gas] involved with this interaction. var/gas_path - - /// Influences zap power without interfering with the crystal's own energy. + /// Influences zap power without interfering with the crystal's own energy. Gets scaled by [BASE_POWER_TRANSMISSION_RATE]. var/power_transmission = 0 /// How much more waste heat and gas the SM generates. var/heat_modifier = 0 @@ -216,7 +222,7 @@ GLOBAL_LIST_INIT(sm_gas_behavior, init_sm_gas()) sm.supermatter_zap( sm, range = 6, - zap_str = clamp(sm.internal_energy * 2, 4000, 20000), + zap_str = clamp(sm.internal_energy * 1600, 3.2e6, 1.6e7), zap_flags = ZAP_MOB_STUN, zap_cutoff = sm.zap_cutoff, power_level = sm.internal_energy, diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm index 098ff7ceaee..3cf040b76ef 100644 --- a/code/modules/power/tesla/coil.dm +++ b/code/modules/power/tesla/coil.dm @@ -1,7 +1,5 @@ // zap needs to be over this amount to get power -#define TESLA_COIL_THRESHOLD 80 -// each zap power unit produces 400 joules -#define ZAP_TO_ENERGY(p) (joules_to_energy((p) * 400)) +#define TESLA_COIL_THRESHOLD 32000 /obj/machinery/power/energy_accumulator/tesla_coil name = "tesla coil" @@ -107,7 +105,7 @@ power /= 10 zap_buckle_check(power) var/power_removed = powernet ? power * input_power_multiplier : power - stored_energy += max(ZAP_TO_ENERGY(power_removed - TESLA_COIL_THRESHOLD), 0) + stored_energy += max(joules_to_energy(power_removed - TESLA_COIL_THRESHOLD), 0) return max(power - power_removed, 0) //You get back the amount we didn't use /obj/machinery/power/energy_accumulator/tesla_coil/proc/zap() @@ -170,10 +168,9 @@ if(anchored && !panel_open) flick("grounding_rodhit", src) zap_buckle_check(power) - stored_energy += ZAP_TO_ENERGY(power) + stored_energy += joules_to_energy(power) return 0 else . = ..() #undef TESLA_COIL_THRESHOLD -#undef ZAP_TO_ENERGY diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index b21938e2608..7ee8c0085c9 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -1,5 +1,5 @@ -#define TESLA_DEFAULT_POWER 1738260 -#define TESLA_MINI_POWER 869130 +#define TESLA_DEFAULT_POWER 6.95304e8 +#define TESLA_MINI_POWER 3.47652e8 //Zap constants, speeds up targeting #define BIKE (COIL + 1) #define COIL (ROD + 1) @@ -205,7 +205,7 @@ if(!(zap_flags & ZAP_ALLOW_DUPLICATES)) LAZYSET(shocked_targets, source, TRUE) //I don't want no null refs in my list yeah? . = source.dir - if(power < 1000) + if(power < 4e5) return /* @@ -334,7 +334,7 @@ var/mob/living/closest_mob = closest_atom ADD_TRAIT(closest_mob, TRAIT_BEING_SHOCKED, WAS_SHOCKED) addtimer(TRAIT_CALLBACK_REMOVE(closest_mob, TRAIT_BEING_SHOCKED, WAS_SHOCKED), 1 SECONDS) - var/shock_damage = (zap_flags & ZAP_MOB_DAMAGE) ? (min(round(power/600), 90) + rand(-5, 5)) : 0 + var/shock_damage = (zap_flags & ZAP_MOB_DAMAGE) ? (min(round(power/2.4e5), 90) + rand(-5, 5)) : 0 closest_mob.electrocute_act(shock_damage, source, 1, SHOCK_TESLA | ((zap_flags & ZAP_MOB_STUN) ? NONE : SHOCK_NOSTUN)) if(issilicon(closest_mob)) var/mob/living/silicon/S = closest_mob diff --git a/code/modules/procedural_mapping/mapGenerators/asteroid.dm b/code/modules/procedural_mapping/mapGenerators/asteroid.dm index ab2bc6f2ca4..bf6c84ebf88 100644 --- a/code/modules/procedural_mapping/mapGenerators/asteroid.dm +++ b/code/modules/procedural_mapping/mapGenerators/asteroid.dm @@ -22,7 +22,7 @@ spawnableAtoms = list( /mob/living/basic/mining/basilisk = 10, /mob/living/basic/mining/goliath/ancient = 10, - /mob/living/simple_animal/hostile/asteroid/hivelord = 10, + /mob/living/basic/mining/hivelord = 10, ) diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index 6439b78a9bd..2b62416fe7f 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -275,10 +275,15 @@ user.visible_message(span_danger("[user.name]'s soul is captured by \the [src]!"), span_userdanger("You've lost the gamble! Your soul is forfeit!")) /obj/item/gun/ballistic/revolver/reverse //Fires directly at its user... unless the user is a clown, of course. - name = "\improper Syndicate Revolver" clumsy_check = FALSE icon_state = "revolversyndie" +/obj/item/gun/ballistic/revolver/reverse/Initialize(mapload) + . = ..() + var/obj/item/gun/ballistic/revolver/syndicate/syndie_revolver = /obj/item/gun/ballistic/revolver/syndicate + name = initial(syndie_revolver.name) + desc = initial(syndie_revolver.desc) + /obj/item/gun/ballistic/revolver/reverse/can_trigger_gun(mob/living/user, akimbo_usage) if(akimbo_usage) return FALSE diff --git a/code/modules/projectiles/guns/energy/energy_gun.dm b/code/modules/projectiles/guns/energy/energy_gun.dm index 3fd1e7c1949..69acb79ac2a 100644 --- a/code/modules/projectiles/guns/energy/energy_gun.dm +++ b/code/modules/projectiles/guns/energy/energy_gun.dm @@ -9,6 +9,18 @@ ammo_x_offset = 3 dual_wield_spread = 60 +/obj/item/gun/energy/e_gun/Initialize(mapload) + . = ..() + // Only actual eguns can be converted + if(type != /obj/item/gun/energy/e_gun) + return + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/advancedegun, /datum/crafting_recipe/tempgun, /datum/crafting_recipe/beam_rifle) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/gun/energy/e_gun/add_seclight_point() AddComponent(/datum/component/seclite_attachable, \ light_overlay_icon = 'icons/obj/weapons/guns/flashlights.dmi', \ @@ -65,7 +77,7 @@ name = "\improper X-01 MultiPhase Energy Gun" desc = "This is an expensive, modern recreation of an antique laser gun. This gun has several unique firemodes, but lacks the ability to recharge over time." icon_state = "hoslaser" - cell_type = /obj/item/stock_parts/cell //SKYRAT EDIT ADDITION - GUNSGALORE + cell_type = /obj/item/stock_parts/cell/hos_gun w_class = WEIGHT_CLASS_NORMAL force = 10 ammo_type = list(/obj/item/ammo_casing/energy/disabler/hos, /obj/item/ammo_casing/energy/laser/hos, /obj/item/ammo_casing/energy/ion/hos) diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index 8d9a29d3b80..06e82a37aae 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -16,6 +16,19 @@ var/list/modkits = list() gun_flags = NOT_A_REAL_GUN + +/obj/item/gun/energy/recharge/kinetic_accelerator/Initialize(mapload) + . = ..() + // Only actual KAs can be converted + if(type != /obj/item/gun/energy/recharge/kinetic_accelerator) + return + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/ebow) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/gun/energy/recharge/kinetic_accelerator/apply_fantasy_bonuses(bonus) . = ..() max_mod_capacity = modify_fantasy_variable("max_mod_capacity", max_mod_capacity, bonus * 10) diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index dafaaa6a7de..0409f2fe037 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -9,6 +9,18 @@ ammo_x_offset = 1 shaded_charge = 1 +/obj/item/gun/energy/laser/Initialize(mapload) + . = ..() + // Only actual lasguns can be converted + if(type != /obj/item/gun/energy/laser) + return + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/xraylaser, /datum/crafting_recipe/hellgun, /datum/crafting_recipe/ioncarbine, /datum/crafting_recipe/decloner) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) + /obj/item/gun/energy/laser/practice name = "practice laser gun" desc = "A modified version of the basic laser gun, this one fires less concentrated energy bolts designed for target practice." diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 90a3d723bf5..5e938c49953 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -12,7 +12,6 @@ wound_bonus = 0 wound_falloff_tile = -5 embed_falloff_tile = -3 - wound_bonus = 20 //SKYRAT EDIT ADDITION /obj/projectile/bullet/smite name = "divine retribution" diff --git a/code/modules/projectiles/projectile/energy/tesla.dm b/code/modules/projectiles/projectile/energy/tesla.dm index 9afb816088f..687bd1b8e73 100644 --- a/code/modules/projectiles/projectile/energy/tesla.dm +++ b/code/modules/projectiles/projectile/energy/tesla.dm @@ -5,7 +5,7 @@ damage = 10 //A worse lasergun var/zap_flags = ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_LOW_POWER_GEN var/zap_range = 3 - var/power = 10000 + var/power = 4e6 /obj/projectile/energy/tesla/on_hit(atom/target) . = ..() @@ -22,7 +22,7 @@ /obj/projectile/energy/tesla/cannon name = "tesla orb" - power = 20000 + power = 8e6 damage = 15 //Mech man big /obj/projectile/energy/tesla_cannon diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index afe59235478..c8da91b9dde 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -481,7 +481,7 @@ speed = 0.3 /// The power of the zap itself when it electrocutes someone - var/zap_power = 20000 + var/zap_power = 8e6 /// The range of the zap itself when it electrocutes someone var/zap_range = 15 /// The flags of the zap itself when it electrocutes someone @@ -503,7 +503,7 @@ return ..() /obj/projectile/magic/aoe/lightning/no_zap - zap_power = 10000 + zap_power = 4e6 zap_range = 4 zap_flags = ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_LOW_POWER_GEN diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 902ccf35e6a..503560aa224 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -1136,7 +1136,8 @@ //If the reaction pollutes, pollute it here if we have an atom if(equilibrium.reaction.pollutant_type && my_atom) var/turf/my_turf = get_turf(my_atom) - my_turf.pollute_turf(equilibrium.reaction.pollutant_type, equilibrium.reaction.pollutant_amount * equilibrium.reacted_vol) + if(my_turf) // reactions can happen in nullspace (like inside of a mob's stomach for instance). + my_turf.pollute_turf(equilibrium.reaction.pollutant_type, equilibrium.reaction.pollutant_amount * equilibrium.reacted_vol) //SKYRAT EDIT END qdel(equilibrium) update_total() @@ -1293,7 +1294,8 @@ //If the reaction pollutes, pollute it here if we have an atom if(selected_reaction.pollutant_type && my_atom) var/turf/my_turf = get_turf(my_atom) - my_turf.pollute_turf(selected_reaction.pollutant_type, selected_reaction.pollutant_amount * multiplier) + if(my_turf) // just to be safe here + my_turf.pollute_turf(selected_reaction.pollutant_type, selected_reaction.pollutant_amount * multiplier) //SKYRAT EDIT END selected_reaction.on_reaction(src, null, multiplier) diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 8de1d98cc2e..110107d103f 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -7,6 +7,10 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) 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 diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm index f67b813be0c..b81e1600bbf 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm @@ -57,6 +57,20 @@ booze_power *= 0.7 if(HAS_TRAIT(drinker, TRAIT_LIGHT_DRINKER)) booze_power *= 2 + + // water will dilute alcohol effects + var/total_water_volume = 0 + var/total_alcohol_volume = 0 + for(var/datum/reagent/water/sobriety in drinker.reagents.reagent_list) + total_water_volume += sobriety.volume + + for(var/datum/reagent/consumable/ethanol/alcohol in drinker.reagents.reagent_list) + total_alcohol_volume += alcohol.volume + + var/combined_dilute_volume = total_alcohol_volume + total_water_volume + if(combined_dilute_volume) // safety check to prevent division by zero + booze_power *= (total_alcohol_volume / combined_dilute_volume) + // Volume, power, and server alcohol rate effect how quickly one gets drunk drinker.adjust_drunk_effect(sqrt(volume) * booze_power * ALCOHOL_RATE * REM * seconds_per_tick * 0.25) // SKYRAT EDIT CHANGE - Alcohol Tolerance - Original: (sqrt(volume) * booze_power * ALCOHOL_RATE * REM * seconds_per_tick) if(boozepwr > 0) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 1e0559d6034..17867389c3d 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -272,9 +272,9 @@ color = "#FFFFFF" // rgb: 255, 255, 255 taste_mult = 1.5 // stop sugar drowning out other flavours nutriment_factor = 2 - metabolization_rate = 2 * REAGENTS_METABOLISM + metabolization_rate = 5 * REAGENTS_METABOLISM creation_purity = 1 // impure base reagents are a big no-no - overdose_threshold = 100 // Hyperglycaemic shock + overdose_threshold = 120 // Hyperglycaemic shock taste_description = "sweetness" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED default_container = /obj/item/reagent_containers/condiment/sugar @@ -286,11 +286,11 @@ /datum/reagent/consumable/sugar/overdose_start(mob/living/M) to_chat(M, span_userdanger("You go into hyperglycaemic shock! Lay off the twinkies!")) - M.AdjustSleeping(600) + M.AdjustSleeping(20 SECONDS) . = TRUE /datum/reagent/consumable/sugar/overdose_process(mob/living/M, seconds_per_tick, times_fired) - M.AdjustSleeping(40 * REM * seconds_per_tick) + M.adjust_drowsiness_up_to((5 SECONDS * REM * seconds_per_tick), 60 SECONDS) ..() . = TRUE diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 2a46d537233..dddf966be72 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -292,6 +292,7 @@ . = ..() if(affected_mob.blood_volume) affected_mob.blood_volume += 0.1 * REM * seconds_per_tick // water is good for you! + affected_mob.adjust_drunk_effect(-0.25 * REM * seconds_per_tick) // and even sobers you up slowly!! // For weird backwards situations where water manages to get added to trays nutrients, as opposed to being snowflaked away like usual. /datum/reagent/water/on_hydroponics_apply(obj/machinery/hydroponics/mytray, mob/user) @@ -2686,13 +2687,16 @@ metal_morph(exposed_turf) ///turn an object into a special material -/datum/reagent/metalgen/proc/metal_morph(atom/A) +/datum/reagent/metalgen/proc/metal_morph(atom/target) var/metal_ref = data["material"] if(!metal_ref) return + if(is_type_in_typecache(target, GLOB.blacklisted_metalgen_types)) //some stuff can lead to exploits if transmuted + return + var/metal_amount = 0 - var/list/materials_to_transmute = A.get_material_composition(BREAKDOWN_INCLUDE_ALCHEMY) + var/list/materials_to_transmute = target.get_material_composition(BREAKDOWN_INCLUDE_ALCHEMY) for(var/metal_key in materials_to_transmute) //list with what they're made of metal_amount += materials_to_transmute[metal_key] @@ -2700,9 +2704,9 @@ metal_amount = default_material_amount //some stuff doesn't have materials at all. To still give them properties, we give them a material. Basically doesn't exist var/list/metal_dat = list((metal_ref) = metal_amount) - A.material_flags = applied_material_flags - A.set_custom_materials(metal_dat) - ADD_TRAIT(A, TRAIT_MAT_TRANSMUTED, type) + target.material_flags = applied_material_flags + target.set_custom_materials(metal_dat) + ADD_TRAIT(target, TRAIT_MAT_TRANSMUTED, type) /datum/reagent/gravitum name = "Gravitum" diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index 707a1dca350..9083de70902 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -542,9 +542,9 @@ reaction_tags = REACTION_TAG_EASY | REACTION_TAG_EXPLOSIVE | REACTION_TAG_DANGEROUS /datum/chemical_reaction/reagent_explosion/teslium_lightning/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) - var/T1 = created_volume * 20 //100 units : Zap 3 times, with powers 2000/5000/12000. Tesla revolvers have a power of 10000 for comparison. - var/T2 = created_volume * 50 - var/T3 = created_volume * 120 + var/T1 = created_volume * 8e3 //100 units : Zap 3 times, with powers 8e5/2e6/4.8e6. Tesla revolvers have a power of 10000 for comparison. + var/T2 = created_volume * 2e4 + var/T3 = created_volume * 4.8e4 var/added_delay = 0.5 SECONDS if(created_volume >= 75) addtimer(CALLBACK(src, PROC_REF(zappy_zappy), holder, T1), added_delay) diff --git a/code/modules/reagents/reagent_containers/cups/glassbottle.dm b/code/modules/reagents/reagent_containers/cups/glassbottle.dm index e2f445c6a1a..e204c6803fb 100644 --- a/code/modules/reagents/reagent_containers/cups/glassbottle.dm +++ b/code/modules/reagents/reagent_containers/cups/glassbottle.dm @@ -40,6 +40,12 @@ tool_behaviour = TOOL_ROLLINGPIN // Used to knock out the Chef. toolspeed = 1.3 //it's a little awkward to use, but it's a cylinder alright. +/obj/item/reagent_containers/cup/glass/bottle/Initialize(mapload, vol) + . = ..() + AddComponent(/datum/component/slapcrafting,\ + slapcraft_recipes = list(/datum/crafting_recipe/molotov)\ + ) + /obj/item/reagent_containers/cup/glass/bottle/small name = "small glass bottle" desc = "This blank bottle is unyieldingly anonymous, offering no clues to its contents." diff --git a/code/modules/reagents/reagent_containers/cups/soda.dm b/code/modules/reagents/reagent_containers/cups/soda.dm index 4908942b2c0..5bf0eb782c5 100644 --- a/code/modules/reagents/reagent_containers/cups/soda.dm +++ b/code/modules/reagents/reagent_containers/cups/soda.dm @@ -21,6 +21,12 @@ /// If the can hasn't been opened yet, this is the measure of how fizzed up it is from being shaken or thrown around. When opened, this is rolled as a percentage chance to burst var/fizziness = 0 +/obj/item/reagent_containers/cup/soda_cans/Initialize(mapload, vol) + . = ..() + AddComponent(/datum/component/slapcrafting,\ + slapcraft_recipes = list(/datum/crafting_recipe/improv_explosive)\ + ) + /obj/item/reagent_containers/cup/soda_cans/random/Initialize(mapload) ..() var/T = pick(subtypesof(/obj/item/reagent_containers/cup/soda_cans) - /obj/item/reagent_containers/cup/soda_cans/random) diff --git a/code/modules/religion/religion_sects.dm b/code/modules/religion/religion_sects.dm index a322303b00d..9075a656ae9 100644 --- a/code/modules/religion/religion_sects.dm +++ b/code/modules/religion/religion_sects.dm @@ -55,8 +55,8 @@ /// Activates once selected and on newjoins, oriented around people who become holy. /datum/religion_sect/proc/on_conversion(mob/living/chap) SHOULD_CALL_PARENT(TRUE) - to_chat(chap, "\"[quote]\"") - to_chat(chap, "[desc]") + to_chat(chap, span_boldnotice("\"[quote]\"")) + to_chat(chap, span_notice("[desc]")) /// Activates if religious sect is reset by admins, should clean up anything you added on conversion. /datum/religion_sect/proc/on_deconversion(mob/living/chap) @@ -66,17 +66,17 @@ to_chat(chap, span_notice("Return to an altar to reform your sect.")) /// Returns TRUE if the item can be sacrificed. Can be modified to fit item being tested as well as person offering. Returning TRUE will stop the attackby sequence and proceed to on_sacrifice. -/datum/religion_sect/proc/can_sacrifice(obj/item/I, mob/living/chap) +/datum/religion_sect/proc/can_sacrifice(obj/item/sacrifice, mob/living/chap) . = TRUE if(chap.mind.holy_role == HOLY_ROLE_DEACON) to_chat(chap, "You are merely a deacon of [GLOB.deity], and therefore cannot perform rites.") return - if(!is_type_in_typecache(I,desired_items_typecache)) + if(!is_type_in_typecache(sacrifice, desired_items_typecache)) return FALSE /// Activates when the sect sacrifices an item. This proc has NO bearing on the attackby sequence of other objects when used in conjunction with the religious_tool component. -/datum/religion_sect/proc/on_sacrifice(obj/item/I, mob/living/chap) - return adjust_favor(default_item_favor,chap) +/datum/religion_sect/proc/on_sacrifice(obj/item/sacrifice, mob/living/chap) + return adjust_favor(default_item_favor, chap) /// Returns a description for religious tools /datum/religion_sect/proc/tool_examine(mob/living/holy_creature) @@ -89,7 +89,7 @@ . = favor //if favor = 5 and we want to subtract 10, we'll only be able to subtract 5 if((favor + amount > max_favor)) . = (max_favor-favor) //if favor = 5 and we want to add 10 with a max of 10, we'll only be able to add 5 - favor = clamp(0,max_favor, favor+amount) + favor = clamp(0, max_favor, favor+amount) /// Sets favor to a specific amount. Can provide optional features based on a user. /datum/religion_sect/proc/set_favor(amount = 0, mob/living/chap) @@ -190,16 +190,17 @@ blessed.add_mood_event("blessing", /datum/mood_event/blessing) return TRUE -/datum/religion_sect/mechanical/on_sacrifice(obj/item/I, mob/living/chap) - var/obj/item/stock_parts/cell/the_cell = I - if(!istype(the_cell)) //how... +/datum/religion_sect/mechanical/on_sacrifice(obj/item/stock_parts/cell/power_cell, mob/living/chap) + if(!istype(power_cell)) return - if(the_cell.charge < 300) - to_chat(chap,span_notice("[GLOB.deity] does not accept pity amounts of power.")) + + if(power_cell.charge < 300) + to_chat(chap, span_notice("[GLOB.deity] does not accept pity amounts of power.")) return - adjust_favor(round(the_cell.charge/300), chap) - to_chat(chap, span_notice("You offer [the_cell]'s power to [GLOB.deity], pleasing them.")) - qdel(I) + + adjust_favor(round(power_cell.charge/300), chap) + to_chat(chap, span_notice("You offer [power_cell]'s power to [GLOB.deity], pleasing them.")) + qdel(power_cell) return TRUE /**** Pyre God ****/ diff --git a/code/modules/research/bepis.dm b/code/modules/research/bepis.dm deleted file mode 100644 index d0640ed5d1c..00000000000 --- a/code/modules/research/bepis.dm +++ /dev/null @@ -1,296 +0,0 @@ -//This system is designed to act as an in-between for cargo and science, and the first major money sink in the game outside of just buying things from cargo (As of 10/9/19, anyway). - -//economics defined values, subject to change should anything be too high or low in practice. - -#define MACHINE_OPERATION 100000 -#define MACHINE_OVERLOAD 500000 -#define MAJOR_THRESHOLD (6*CARGO_CRATE_VALUE) -#define MINOR_THRESHOLD (4*CARGO_CRATE_VALUE) -#define STANDARD_DEVIATION (2*CARGO_CRATE_VALUE) -#define PART_CASH_OFFSET_AMOUNT (0.5*CARGO_CRATE_VALUE) - -/obj/machinery/rnd/bepis - name = "\improper B.E.P.I.S. Chamber" - desc = "A high fidelity testing device which unlocks the secrets of the known universe using the two most powerful substances available to man: excessive amounts of electricity and capital." - icon = 'icons/obj/machines/bepis.dmi' - icon_state = "chamber" - base_icon_state = "chamber" - density = TRUE - layer = ABOVE_MOB_LAYER - plane = GAME_PLANE_UPPER - circuit = /obj/item/circuitboard/machine/bepis - - ///How much cash the UI and machine are depositing at a time. - var/banking_amount = 100 - ///How much stored player cash exists within the machine. - var/banked_cash = 0 - ///Payer's bank account. - var/datum/bank_account/account - ///Name on the payer's bank account. - var/account_name - ///When the BEPIS fails to hand out any reward, the ERROR cause will be a randomly picked string displayed on the UI. - var/error_cause = null - - //Vars related to probability and chance of success for testing, using gaussian normal distribution. - ///How much cash you will need to obtain a Major Tech Disk reward. - var/major_threshold = MAJOR_THRESHOLD - ///How much cash you will need to obtain a minor invention reward. - var/minor_threshold = MINOR_THRESHOLD - ///The standard deviation of the BEPIS's gaussian normal distribution. - var/std = STANDARD_DEVIATION - - //Stock part variables - ///Multiplier that lowers how much the BEPIS' power costs are. Maximum of 1, upgraded to a minimum of 0.7. See RefreshParts. - var/power_saver = 1 - ///Variability on the money you actively spend on the BEPIS, with higher inaccuracy making the most change, good and bad to spent cash. - var/inaccuracy_percentage = 1.5 - ///How much "cash" is added to your inserted cash efforts for free. Based on manipulator stock part level. - var/positive_cash_offset = 0 - ///How much "cost" is removed from both the minor and major threshold costs. Based on laser stock part level. - var/negative_cash_offset = 0 - ///List of objects that constitute your minor rewards. All rewards are unique or rare outside of the BEPIS. - var/minor_rewards = list( - //To add a new minor reward, add it here. - /obj/item/stack/circuit_stack/full, - /obj/item/pen/survival, - /obj/item/flashlight/flashdark,//SKYRAT EDIT - /obj/item/circuitboard/machine/sleeper/party, - /obj/item/toy/sprayoncan, - ) - -/obj/machinery/rnd/bepis/attackby(obj/item/O, mob/user, params) - if(!is_operational) - to_chat(user, span_notice("[src] can't accept money when it's not functioning.")) - return - if(istype(O, /obj/item/holochip) || istype(O, /obj/item/stack/spacecash)) - var/deposit_value = O.get_item_credit_value() - banked_cash += deposit_value - qdel(O) - say("Deposited [deposit_value] credits into storage.") - update_appearance() - return - if(isidcard(O)) - var/obj/item/card/id/Card = O - if(Card.registered_account) - account = Card.registered_account - account_name = Card.registered_name - say("New account detected. Console Updated.") - else - say("No account detected on card. Aborting.") - return - return ..() - -/obj/machinery/rnd/bepis/screwdriver_act(mob/living/user, obj/item/tool) - return default_deconstruction_screwdriver(user, "chamber_open", "chamber", tool) - -/obj/machinery/rnd/bepis/screwdriver_act_secondary(mob/living/user, obj/item/tool) - return default_deconstruction_screwdriver(user, "chamber_open", "chamber", tool) - -/obj/machinery/rnd/bepis/RefreshParts() - . = ..() - var/C = 0 - var/M = 0 - var/L = 0 - var/S = 0 - for(var/datum/stock_part/capacitor/capacitor in component_parts) - C += ((capacitor.tier - 1) * 0.1) - power_saver = 1 - C - for(var/datum/stock_part/servo/servo in component_parts) - M += ((servo.tier - 1) * PART_CASH_OFFSET_AMOUNT) - positive_cash_offset = M - for(var/datum/stock_part/micro_laser/Laser in component_parts) - L += ((Laser.tier - 1) * PART_CASH_OFFSET_AMOUNT) - negative_cash_offset = L - for(var/datum/stock_part/scanning_module/scanning_module in component_parts) - S += ((scanning_module.tier - 1) * 0.25) - inaccuracy_percentage = (1.5 - S) - -/obj/machinery/rnd/bepis/update_icon_state() - if(panel_open == TRUE) - icon_state = "[base_icon_state]_open" - return ..() - if((use_power == ACTIVE_POWER_USE) && (banked_cash > 0) && (is_operational)) - icon_state = "[base_icon_state]_active_loaded" - return ..() - if (((use_power == IDLE_POWER_USE) && (banked_cash > 0)) || (banked_cash > 0) && (!is_operational)) - icon_state = "[base_icon_state]_loaded" - return ..() - if(use_power == ACTIVE_POWER_USE && is_operational) - icon_state = "[base_icon_state]_active" - return ..() - if(((use_power == IDLE_POWER_USE) && (banked_cash == 0)) || (!is_operational)) - icon_state = base_icon_state - return ..() - return ..() - -/obj/machinery/rnd/bepis/ui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "Bepis", name) - ui.open() - RefreshParts() - if(isliving(user)) - var/mob/living/customer = user - account = customer.get_bank_account() - -/obj/machinery/rnd/bepis/ui_data(mob/user) - var/list/data = list() - var/powered = FALSE - var/zvalue = ((banking_amount + banked_cash) - (major_threshold - positive_cash_offset - negative_cash_offset))/(std) - var/std_success = 0 - var/prob_success = 0 - //Admittedly this is messy, but not nearly as messy as the alternative, which is jury-rigging an entire Z-table into the code, or making an adaptive z-table. - var/z = abs(zvalue) - if(z > 0 && z <= 0.5) - std_success = 19.1 - else if(z > 0.5 && z <= 1.0) - std_success = 34.1 - else if(z > 1.0 && z <= 1.5) - std_success = 43.3 - else if(z > 1.5 && z <= 2.0) - std_success = 47.7 - else if(z > 2.0 && z <= 2.5) - std_success = 49.4 - else - std_success = 50 - if(zvalue > 0) - prob_success = 50 + std_success - else if(zvalue == 0) - prob_success = 50 - else - prob_success = 50 - std_success - - if(use_power == ACTIVE_POWER_USE) - powered = TRUE - data["account_owner"] = account_name - data["amount"] = banking_amount - data["stored_cash"] = account?.account_balance - data["mean_value"] = (major_threshold - positive_cash_offset - negative_cash_offset) - data["error_name"] = error_cause - data["power_saver"] = power_saver - data["accuracy_percentage"] = inaccuracy_percentage * 100 - data["positive_cash_offset"] = positive_cash_offset - data["negative_cash_offset"] = negative_cash_offset - data["manual_power"] = powered ? FALSE : TRUE - data["silicon_check"] = issilicon(user) - data["success_estimate"] = prob_success - return data - -/obj/machinery/rnd/bepis/ui_act(action,params) - . = ..() - if(.) - return - switch(action) - if("begin_experiment") - if(use_power == IDLE_POWER_USE) - return - depositcash() - if(banked_cash == 0) - say("Please select funds to deposit to begin testing.") - return - calcsuccess() - use_power(MACHINE_OPERATION * power_saver) //This thing should eat your APC battery if you're not careful. - update_use_power(IDLE_POWER_USE) //Machine shuts off after use to prevent spam and look better visually. - update_appearance() - if("amount") - var/input = text2num(params["amount"]) - if(input) - banking_amount = input - if("toggle_power") - if(use_power == ACTIVE_POWER_USE) - update_use_power(IDLE_POWER_USE) - else - update_use_power(ACTIVE_POWER_USE) - update_appearance() - if("account_reset") - if(use_power == IDLE_POWER_USE) - return - account_name = "" - account = null - say("Account settings reset.") - . = TRUE - -/** - * Proc that handles the user's account to deposit credits for the BEPIS. - * Handles success and fail cases for transferring credits, then logs the transaction and uses small amounts of power. - **/ -/obj/machinery/rnd/bepis/proc/depositcash() - var/deposit_value = 0 - deposit_value = banking_amount - if(deposit_value == 0) - update_appearance() - say("Attempting to deposit 0 credits. Aborting.") - return - deposit_value = clamp(round(deposit_value, 1), 1, 10000) - if(!account) - say("Cannot find user account. Please swipe a valid ID.") - return - if(!account.has_money(deposit_value)) - say("You do not possess enough credits.") - return - account.adjust_money(-deposit_value, "Vending: B.E.P.I.S. Chamber") //The money vanishes, not paid to any accounts. - SSblackbox.record_feedback("amount", "BEPIS_credits_spent", deposit_value) - log_econ("[deposit_value] credits were inserted into [src] by [account.account_holder]") - banked_cash += deposit_value - use_power(1000 * power_saver) - return - -/** - * Proc used to determine the experiment math and results all in one. - * Uses banked_cash and stock part levels to determine minor, major, and real gauss values for the BEPIS to hold. - * If by the end real is larger than major, You get a tech disk. If all the disks are earned or you at least beat minor, you get a minor reward. - **/ - -/obj/machinery/rnd/bepis/proc/calcsuccess() - var/turf/dropturf = null - var/gauss_major = 0 - var/gauss_minor = 0 - var/gauss_real = 0 - - var/turf/my_turf = get_turf(src) - var/list/turfs = TURF_NEIGHBORS(my_turf) //NO MORE DISCS IN WINDOWS - while(length(turfs)) - var/turf/T = pick_n_take(turfs) - if(T.is_blocked_turf(TRUE)) - continue - else - dropturf = T - break - - if (!dropturf) - dropturf = drop_location() - gauss_major = (gaussian(major_threshold, std) - negative_cash_offset) //This is the randomized profit value that this experiment has to surpass to unlock a tech. - gauss_minor = (gaussian(minor_threshold, std) - negative_cash_offset) //And this is the threshold to instead get a minor prize. - gauss_real = (gaussian(banked_cash, std*inaccuracy_percentage) + positive_cash_offset) //this is the randomized profit value that your experiment expects to give. - say("Real: [gauss_real]. Minor: [gauss_minor]. Major: [gauss_major].") - flick("chamber_flash",src) - update_appearance() - banked_cash = 0 - if((gauss_real >= gauss_major)) //Major Success. - if(SSresearch.techweb_nodes_experimental.len > 0) - say("Experiment concluded with major success. New technology node discovered on technology disc.") - new /obj/item/disk/design_disk/bepis/remove_tech(dropturf,1) - return - say("Expended all available experimental technology nodes. Resorting to minor rewards.") - if(gauss_real >= gauss_minor) //Minor Success. - var/reward = pick(minor_rewards) - new reward(dropturf) - say("Experiment concluded with partial success. Dispensing compiled research efforts.") - return - if(gauss_real <= -1) //Critical Failure - say("ERROR: CRITICAL MACHIME MALFUNCTI- ON. CURRENCY IS NOT CRASH. CANNOT COMPUTE COMMAND: 'make bucks'") //not a typo, for once. - new /mob/living/basic/deer(dropturf, 1) - use_power(MACHINE_OVERLOAD * power_saver) //To prevent gambling at low cost and also prevent spamming for infinite deer. - return - //Minor Failure - error_cause = pick("attempted to sell grey products to American dominated market.","attempted to sell gray products to British dominated market.","placed wild assumption that PDAs would go out of style.","simulated product #76 damaged brand reputation mortally.","simulated business model resembled 'pyramid scheme' by 98.7%.","product accidently granted override access to all station doors.") - say("Experiment concluded with zero product viability. Cause of error: [error_cause]") - return - - -#undef MACHINE_OPERATION -#undef MACHINE_OVERLOAD -#undef MAJOR_THRESHOLD -#undef MINOR_THRESHOLD -#undef STANDARD_DEVIATION -#undef PART_CASH_OFFSET_AMOUNT diff --git a/code/modules/research/designs/biogenerator_designs.dm b/code/modules/research/designs/biogenerator_designs.dm index f07ef21a8e7..14d5c12eb43 100644 --- a/code/modules/research/designs/biogenerator_designs.dm +++ b/code/modules/research/designs/biogenerator_designs.dm @@ -185,3 +185,11 @@ materials = list(/datum/material/biomass = 1) build_path = /obj/item/rollingpaper category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_MATERIALS) + +/datum/design/candle + name = "Candle" + id = "candle" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 3) + build_path = /obj/item/flashlight/flare/candle + category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_MATERIALS) diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm index 1c44e8bc4fb..0a2c96dddd5 100644 --- a/code/modules/research/designs/machine_designs.dm +++ b/code/modules/research/designs/machine_designs.dm @@ -358,16 +358,6 @@ ) departmental_flags = DEPARTMENT_BITFLAG_SCIENCE -/datum/design/board/bepis - name = "B.E.P.I.S. Board" - desc = "The circuit board for a B.E.P.I.S." - id = "bepis" - build_path = /obj/item/circuitboard/machine/bepis - category = list( - RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_RESEARCH - ) - departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_CARGO - /datum/design/board/protolathe name = "Protolathe Board" desc = "The circuit board for a protolathe." @@ -1106,3 +1096,13 @@ RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ROBOTICS ) departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/board/fishing_portal_generator + name = "Fishing Portal Generator Board" + desc = "The circuit board for the fishing portal generator" + id = "fishing_portal_generator" + build_path = /obj/item/circuitboard/machine/fishing_portal_generator + category = list( + RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_SERVICE + ) + departmental_flags = DEPARTMENT_BITFLAG_SERVICE | DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SCIENCE diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 2bb779e318b..285878e7f26 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -1114,6 +1114,13 @@ surgery = /datum/surgery/advanced/wing_reconstruction research_icon_state = "surgery_chest" +/datum/design/surgery/advanced_plastic_surgery + name = "Advanced Plastic Surgery" + desc = "An advanced form of the plastic surgery, allowing oneself to remodel someone's face and voice based off a picture of someones face" + surgery = /datum/surgery/plastic_surgery/advanced + id = "surgery_advanced_plastic_surgery" + research_icon_state = "surgery_head" + /datum/design/surgery/experimental_dissection name = "Experimental Dissection" desc = "An experimental surgical procedure that dissects bodies in exchange for research points at ancient R&D consoles." diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm index 521504da351..8a06607ec59 100644 --- a/code/modules/research/techweb/_techweb.dm +++ b/code/modules/research/techweb/_techweb.dm @@ -283,7 +283,7 @@ var/datum/experiment/experiment = completed_experiment if (experiment == experiment_type) return FALSE - available_experiments += new experiment_type() + available_experiments += new experiment_type(src) /** * Adds a list of experiments to this techweb by their types, ensures that no duplicates are added. @@ -310,13 +310,21 @@ var/refund = skipped_experiment_types[completed_experiment.type] || 0 if(refund > 0) add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = refund)) - result_text += ", refunding [refund] points." + result_text += ", refunding [refund] points" // Nothing more to gain here, but we keep it in the list to prevent double dipping skipped_experiment_types[completed_experiment.type] = -1 - else - result_text += "!" - - log_research("[completed_experiment.name] ([completed_experiment.type]) has been completed on techweb [id]/[organization][refund ? ", refunding [refund] points" : ""].") + var/points_rewarded + if(completed_experiment.points_reward) + add_point_list(completed_experiment.points_reward) + points_rewarded = ",[refund > 0 ? " and" : ""] rewarding " + var/list/english_list_keys = list() + for(var/points_type in completed_experiment.points_reward) + english_list_keys += "[completed_experiment.points_reward[points_type]] [points_type]" + points_rewarded += "[english_list(english_list_keys)] points" + result_text += points_rewarded + result_text += "!" + + log_research("[completed_experiment.name] ([completed_experiment.type]) has been completed on techweb [id]/[organization][refund ? ", refunding [refund] points" : ""][points_rewarded].") return result_text /datum/techweb/proc/printout_points() diff --git a/code/modules/research/techweb/_techweb_node.dm b/code/modules/research/techweb/_techweb_node.dm index 2f01252548a..ae50ea7f65f 100644 --- a/code/modules/research/techweb/_techweb_node.dm +++ b/code/modules/research/techweb/_techweb_node.dm @@ -16,7 +16,7 @@ var/description = "Why are you seeing this?" /// Whether it starts off hidden var/hidden = FALSE - /// If the tech can be randomly generated by the BEPIS as a reward. MEant to be fully given in tech disks, not researched + /// If the tech can be randomly generated by BEPIS tech as a reward. Meant to be fully given in tech disks, not researched var/experimental = FALSE /// Whether it's available without any research var/starting_node = FALSE diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 2ec692f0575..507199164b8 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -14,7 +14,6 @@ "basic_matter_bin", "basic_micro_laser", "basic_scanning", - "bepis", "blast", "bounced_radio", "bowl", @@ -50,6 +49,7 @@ "extinguisher", "fax", "fishing_rod", + "fishing_portal_generator", "flashlight", "fluid_ducts", "foam_dart", @@ -1491,6 +1491,19 @@ required_experiments = list(/datum/experiment/scanning/random/plants/wild) discount_experiments = list(/datum/experiment/scanning/random/plants/traits = 3000) +/datum/techweb_node/fishing + id = "fishing" + display_name = "Fishing Technology" + description = "Cutting edge fishing advancements." + prereq_ids = list("base") + design_ids = list( + "fishing_rod_tech", + "stabilized_hook", + "fish_analyzer", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + required_experiments = list(/datum/experiment/scanning/fish) + /datum/techweb_node/exp_tools id = "exp_tools" display_name = "Experimental Tools" @@ -2355,15 +2368,13 @@ hidden = TRUE experimental = TRUE -/datum/techweb_node/fishing - id = "fishing" - display_name = "Fishing Technology" - description = "Cutting edge fishing advancements." +/datum/techweb_node/advanced_plastic_surgery + id = "plastic_surgery" + display_name = "Advanced Plastic Surgery" + description = "A Procedure long lost due to licensing problems now once again available." prereq_ids = list("base") design_ids = list( - "fishing_rod_tech", - "stabilized_hook", - "fish_analyzer", + "surgery_advanced_plastic_surgery" ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) hidden = TRUE diff --git a/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm b/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm index abb764d0689..0152b343c45 100644 --- a/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm +++ b/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm @@ -223,7 +223,7 @@ /datum/reagent/consumable/corn_syrup = -6, /datum/reagent/sulfur = -3) //sulfur repels snakes according to professor google. - resulting_atoms = list(/mob/living/simple_animal/hostile/retaliate/snake = 1) + resulting_atoms = list(/mob/living/basic/snake = 1) /////////////////////////////////////////// @@ -263,7 +263,7 @@ /datum/reagent/medicine/psicodine = -2) //Blob zombies likely wouldn't appreciate psicodine so why this is here virus_suspectibility = 0 - resulting_atoms = list(/mob/living/simple_animal/hostile/blob/blobspore/independent = 2) //These are useless so we might as well spawn 2. + resulting_atoms = list(/mob/living/basic/blob_minion/spore = 2) //These are useless so we might as well spawn 2. /datum/micro_organism/cell_line/blobbernaut desc = "Blobular myocytes" @@ -282,7 +282,7 @@ suppressive_reagents = list(/datum/reagent/consumable/tinlux = -6) virus_suspectibility = 0 - resulting_atoms = list(/mob/living/simple_animal/hostile/blob/blobbernaut/independent = 1) + resulting_atoms = list(/mob/living/basic/blob_minion/blobbernaut = 1) /datum/micro_organism/cell_line/gelatinous_cube desc = "Cubic ooze particles" diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index aba37b37a55..cdabfdc4926 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -61,17 +61,61 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( /obj/docking_port/mobile/supply/proc/check_blacklist(areaInstances) for(var/place in areaInstances) var/area/shuttle/shuttle_area = place - for(var/turf/shuttle_turf in shuttle_area) + for(var/turf/shuttle_turf in shuttle_area.get_contained_turfs()) for(var/atom/passenger in shuttle_turf.get_all_contents()) if((is_type_in_typecache(passenger, GLOB.blacklisted_cargo_types) || HAS_TRAIT(passenger, TRAIT_BANNED_FROM_CARGO_SHUTTLE)) && !istype(passenger, /obj/docking_port)) return FALSE return TRUE +/// Returns anything on the cargo blacklist found within areas_to_check back to the turf of the home docking port via Centcom branded supply pod. +/obj/docking_port/mobile/supply/proc/return_blacklisted_things_home(list/area/areas_to_check, obj/docking_port/stationary/home) + var/list/stuff_to_send_home = list() + for(var/area/shuttle_area as anything in areas_to_check) + for(var/turf/shuttle_turf in shuttle_area.get_contained_turfs()) + for(var/atom/passenger in shuttle_turf.get_all_contents()) + if((is_type_in_typecache(passenger, GLOB.blacklisted_cargo_types) || HAS_TRAIT(passenger, TRAIT_BANNED_FROM_CARGO_SHUTTLE)) && !istype(passenger, /obj/docking_port)) + stuff_to_send_home += passenger + + if(!length(stuff_to_send_home)) + return FALSE + + var/obj/structure/closet/supplypod/centcompod/et_go_home = new() + + for(var/atom/movable/et as anything in stuff_to_send_home) + et.forceMove(et_go_home) + + new /obj/effect/pod_landingzone(get_turf(home), et_go_home) + + return stuff_to_send_home + /obj/docking_port/mobile/supply/request(obj/docking_port/stationary/S) if(mode != SHUTTLE_IDLE) return 2 return ..() +/obj/docking_port/mobile/supply/check_dock(obj/docking_port/stationary/S, silent) + . = ..() + + if(!.) + return + + // If we're not trying to dock at Centcom, we don't care. + if(S.shuttle_id != "cargo_away") + return + + // Else we are docking at Centcom, check the blacklist to make sure no contraband was put onto the shuttle mid-transit. + // If there's anything contrabandy, send these items back to the origin docking port. + // This is a sort of catch-all Centcom exploit check. + var/list/stuff_sent_home = return_blacklisted_things_home(shuttle_areas, previous) + if(!length(stuff_sent_home)) + return + + for(var/atom/thing_sent_home as anything in stuff_sent_home) + investigate_log("Blacklisted item found on in-transit Cargo Shuttle: [thing_sent_home] ([thing_sent_home.type])", INVESTIGATE_CARGO) + + message_admins("Blacklisted item found on in-transit Cargo Shuttle. See cargo logs for more details.") + SSshuttle.centcom_message = "Contraband found on Cargo Shuttle. This has been returned via drop pod." + /obj/docking_port/mobile/supply/initiate_docking() if(getDockedId() == "cargo_away") // Buy when we leave home. buy() @@ -278,5 +322,17 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( new /obj/structure/closet/crate/mail/economy(pick(empty_turfs)) +/// Takes a supply pack, returns the amount we currently have on order (or OVER_ORDER_LIMIT if we are over the hardcap on orders of this type) +/obj/docking_port/mobile/supply/proc/get_order_count(datum/supply_pack/ordering) + var/similar_count = 0 + for(var/datum/supply_order/order as anything in (SSshuttle.shopping_list | SSshuttle.request_list)) + if(order.pack == ordering) + similar_count += 1 + + if(similar_count >= CARGO_MAX_ORDER) + return OVER_ORDER_LIMIT + + return similar_count + #undef GOODY_FREE_SHIPPING_MAX #undef CRATE_TAX diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index 966f618376d..f03cd4927f8 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -180,11 +180,6 @@ to_chat(owner, span_warning("Some form of antimagic is preventing you from casting [src]!")) return FALSE - if(!(spell_requirements & SPELL_CASTABLE_WHILE_PHASED) && HAS_TRAIT(owner, TRAIT_MAGICALLY_PHASED)) - if(feedback) - to_chat(owner, span_warning("[src] cannot be cast unless you are completely manifested in the material plane!")) - return FALSE - if(!try_invoke(owner, feedback = feedback)) return FALSE diff --git a/code/modules/spells/spell_types/jaunt/_jaunt.dm b/code/modules/spells/spell_types/jaunt/_jaunt.dm index 4a94f03c041..207a7ed8b5b 100644 --- a/code/modules/spells/spell_types/jaunt/_jaunt.dm +++ b/code/modules/spells/spell_types/jaunt/_jaunt.dm @@ -62,7 +62,7 @@ var/obj/effect/dummy/phased_mob/jaunt = new jaunt_type(loc_override || get_turf(jaunter), jaunter) RegisterSignal(jaunt, COMSIG_MOB_EJECTED_FROM_JAUNT, PROC_REF(on_jaunt_exited)) - spell_requirements |= SPELL_CASTABLE_WHILE_PHASED + check_flags &= ~AB_CHECK_PHASED jaunter.add_traits(list(TRAIT_MAGICALLY_PHASED, TRAIT_RUNECHAT_HIDDEN, TRAIT_WEATHER_IMMUNE), REF(src)) // Don't do the feedback until we have runechat hidden. // Otherwise the text will follow the jaunt holder, which reveals where our caster is travelling. @@ -106,7 +106,7 @@ */ /datum/action/cooldown/spell/jaunt/proc/on_jaunt_exited(obj/effect/dummy/phased_mob/jaunt, mob/living/unjaunter) SHOULD_CALL_PARENT(TRUE) - spell_requirements &= ~SPELL_CASTABLE_WHILE_PHASED + check_flags |= AB_CHECK_PHASED unjaunter.remove_traits(list(TRAIT_MAGICALLY_PHASED, TRAIT_RUNECHAT_HIDDEN, TRAIT_WEATHER_IMMUNE), REF(src)) // This needs to happen at the end, after all the traits and stuff is handled SEND_SIGNAL(unjaunter, COMSIG_MOB_AFTER_EXIT_JAUNT, src) diff --git a/code/modules/spells/spell_types/self/splattercasting_spell.dm b/code/modules/spells/spell_types/self/splattercasting_spell.dm index 1af0cacd2aa..184a2afab7c 100644 --- a/code/modules/spells/spell_types/self/splattercasting_spell.dm +++ b/code/modules/spells/spell_types/self/splattercasting_spell.dm @@ -29,6 +29,7 @@ merely a vessel for the arcane flow. Soon, all that is left is not pain, but hunger.")) cast_on.set_species(/datum/species/vampire) + cast_on.blood_volume = BLOOD_VOLUME_NORMAL ///for predictable blood total amounts when the spell is first cast. cast_on.AddComponent(/datum/component/splattercasting) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 4b9c0114024..c6d0f25cb4c 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -152,7 +152,7 @@ /// How much generic bleedstacks we have on this bodypart var/generic_bleedstacks /// If we have a gauze wrapping currently applied (not including splints) - var/obj/item/stack/current_gauze + var/obj/item/stack/medical/gauze/current_gauze /// If something is currently grasping this bodypart and trying to staunch bleeding (see [/obj/item/hand_item/self_grasp]) var/obj/item/hand_item/self_grasp/grasped_by @@ -408,10 +408,10 @@ var/atom/drop_loc = drop_location() if(IS_ORGANIC_LIMB(src)) playsound(drop_loc, 'sound/misc/splort.ogg', 50, TRUE, -1) - seep_gauze(9999) // destroy any existing gauze if any exists - for(var/obj/item/organ/bodypart_organ in get_organs()) + QDEL_NULL(current_gauze) + for(var/obj/item/organ/bodypart_organ as anything in get_organs()) bodypart_organ.transfer_to_limb(src, owner) - for(var/obj/item/organ/external/external in external_organs) + for(var/obj/item/organ/external/external as anything in external_organs) external.remove_from_limb() external.forceMove(drop_loc) for(var/obj/item/item_in_bodypart in src) @@ -1308,17 +1308,18 @@ * Arguments: * * gauze- Just the gauze stack we're taking a sheet from to apply here */ -/obj/item/bodypart/proc/apply_gauze(obj/item/stack/gauze) - if(!istype(gauze) || !gauze.absorption_capacity) +/obj/item/bodypart/proc/apply_gauze(obj/item/stack/medical/gauze/new_gauze) + if(!istype(new_gauze) || !new_gauze.absorption_capacity) return var/newly_gauzed = FALSE if(!current_gauze) newly_gauzed = TRUE QDEL_NULL(current_gauze) - current_gauze = new gauze.type(src, 1) - gauze.use(1) + current_gauze = new new_gauze.type(src, 1) + new_gauze.use(1) + current_gauze.gauzed_bodypart = src if(newly_gauzed) - SEND_SIGNAL(src, COMSIG_BODYPART_GAUZED, gauze) + SEND_SIGNAL(src, COMSIG_BODYPART_GAUZED, current_gauze, new_gauze) /** * seep_gauze() is for when a gauze wrapping absorbs blood or pus from wounds, lowering its absorption capacity. @@ -1335,7 +1336,6 @@ if(current_gauze.absorption_capacity <= 0) owner.visible_message(span_danger("\The [current_gauze.name] on [owner]'s [name] falls away in rags."), span_warning("\The [current_gauze.name] on your [name] falls away in rags."), vision_distance=COMBAT_MESSAGE_RANGE) QDEL_NULL(current_gauze) - SEND_SIGNAL(src, COMSIG_BODYPART_GAUZE_DESTROYED) ///Loops through all of the bodypart's external organs and update's their color. /obj/item/bodypart/proc/recolor_external_organs() diff --git a/code/modules/surgery/bodyparts/wounds.dm b/code/modules/surgery/bodyparts/wounds.dm index 1b50dbc8fd1..94c503614a2 100644 --- a/code/modules/surgery/bodyparts/wounds.dm +++ b/code/modules/surgery/bodyparts/wounds.dm @@ -85,7 +85,7 @@ // quick re-check to see if bare_wound_bonus applies, for the benefit of log_wound(), see about getting the check from check_woundings_mods() somehow if(ishuman(owner)) var/mob/living/carbon/human/human_wearer = owner - var/list/clothing = human_wearer.clothingonpart(src) + var/list/clothing = human_wearer.get_clothing_on_part(src) for(var/obj/item/clothing/clothes_check as anything in clothing) // unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary if(clothes_check.get_armor_rating(WOUND)) @@ -242,7 +242,7 @@ if(owner && ishuman(owner)) var/mob/living/carbon/human/human_owner = owner - var/list/clothing = human_owner.clothingonpart(src) + var/list/clothing = human_owner.get_clothing_on_part(src) for(var/obj/item/clothing/clothes as anything in clothing) // unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary armor_ablation += clothes.get_armor_rating(WOUND) diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm index 04103648fda..632e4c8b511 100644 --- a/code/modules/surgery/organs/_organ.dm +++ b/code/modules/surgery/organs/_organ.dm @@ -57,6 +57,8 @@ var/list/organ_traits /// Status Effects that are given to the holder of the organ. var/list/organ_effects + /// String displayed when the organ has decayed. + var/failing_desc = "has decayed for too long, and has turned a sickly color. It probably won't work without repairs." // Players can look at prefs before atoms SS init, and without this // they would not be able to see external organs, such as moth wings. @@ -242,10 +244,7 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) . += span_notice("It should be inserted in the [parse_zone(zone)].") if(organ_flags & ORGAN_FAILING) - if(IS_ROBOTIC_ORGAN(src)) - . += span_warning("[src] seems to be broken.") - return - . += span_warning("[src] has decayed for too long, and has turned a sickly color. It probably won't work without repairs.") + . += span_warning("[src] [failing_desc]") return if(damage > high_threshold) @@ -424,4 +423,4 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) /// Tries to replace the existing organ on the passed mob with this one, with special handling for replacing a brain without ghosting target /obj/item/organ/proc/replace_into(mob/living/carbon/new_owner) - Insert(new_owner, special = TRUE, drop_if_replaced = FALSE) + return Insert(new_owner, special = TRUE, drop_if_replaced = FALSE) diff --git a/code/modules/surgery/organs/external/_external_organ.dm b/code/modules/surgery/organs/external/_external_organ.dm index 54eb937e0ae..fd1af3d5f93 100644 --- a/code/modules/surgery/organs/external/_external_organ.dm +++ b/code/modules/surgery/organs/external/_external_organ.dm @@ -82,14 +82,13 @@ return if(bodypart_overlay.imprint_on_next_insertion) //We only want this set *once* - - // SKYRAT EDIT - Customization - ORIGINAL: bodypart_overlay.set_appearance_from_name(receiver.dna.features[bodypart_overlay.feature_key]) - if(receiver.dna.features[bodypart_overlay.feature_key]) - bodypart_overlay.set_appearance_from_name(receiver.dna.features[bodypart_overlay.feature_key]) - + var/feature_name = receiver.dna.features[bodypart_overlay.feature_key] + if (isnull(feature_name)) + bodypart_overlay.set_appearance_from_dna(receiver.dna) // SKYRAT EDIT CHANGE - ORIGINAL: feature_name = receiver.dna.species.external_organs[type] + // SKYRAT EDIT CHANGE START - Puts the following line in an else block else - bodypart_overlay.set_appearance_from_dna(receiver.dna) - // SKYRAT EDIT END + bodypart_overlay.set_appearance_from_name(feature_name) + // SKYRAT EDIT CHANGE END bodypart_overlay.imprint_on_next_insertion = FALSE ownerlimb = limb diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm index 0a7332c0dd8..f0578832969 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm @@ -4,6 +4,7 @@ desc = "A state-of-the-art implant that improves a baseline's functionality." visual = FALSE organ_flags = ORGAN_ROBOTIC + failing_desc = "seems to be broken." var/implant_color = "#FFFFFF" var/implant_overlay diff --git a/code/modules/surgery/organs/internal/ears/_ears.dm b/code/modules/surgery/organs/internal/ears/_ears.dm index 52f5d740520..b77efe90c2e 100644 --- a/code/modules/surgery/organs/internal/ears/_ears.dm +++ b/code/modules/surgery/organs/internal/ears/_ears.dm @@ -109,6 +109,7 @@ desc = "A basic cybernetic organ designed to mimic the operation of ears." damage_multiplier = 0.9 organ_flags = ORGAN_ROBOTIC + failing_desc = "seems to be broken." /obj/item/organ/internal/ears/cybernetic/upgraded name = "cybernetic ears" diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm index f2365c3988e..aca812a6186 100644 --- a/code/modules/surgery/organs/internal/eyes/_eyes.dm +++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm @@ -318,6 +318,7 @@ icon_state = "cybernetic_eyeballs" desc = "Your vision is augmented." organ_flags = ORGAN_ROBOTIC + failing_desc = "seems to be broken." /obj/item/organ/internal/eyes/robotic/emp_act(severity) . = ..() @@ -656,7 +657,7 @@ if(QDELETED(eye_owner) || !ishuman(eye_owner)) //Other carbon mobs don't have eye color. return - + if(!eye.on) eye_icon_state = initial(eye_icon_state) overlay_ignore_lighting = FALSE diff --git a/code/modules/surgery/organs/internal/heart/_heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm index ce4b948c653..e553f8f1307 100644 --- a/code/modules/surgery/organs/internal/heart/_heart.dm +++ b/code/modules/surgery/organs/internal/heart/_heart.dm @@ -203,6 +203,7 @@ base_icon_state = "heart-c" organ_flags = ORGAN_ROBOTIC maxHealth = STANDARD_ORGAN_THRESHOLD*0.75 //This also hits defib timer, so a bit higher than its less important counterparts + failing_desc = "seems to be broken." var/dose_available = FALSE var/rid = /datum/reagent/medicine/epinephrine diff --git a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm index f29ee2e731d..bb0b30ddd62 100644 --- a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm +++ b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm @@ -108,7 +108,7 @@ if(!COOLDOWN_FINISHED(src, crystalize_cooldown) || ethereal.stat != DEAD) return //Should probably not happen, but lets be safe. - if(ismob(location) || isitem(location) || HAS_TRAIT_FROM(src, TRAIT_HUSK, CHANGELING_DRAIN)) //Stops crystallization if they are eaten by a dragon, turned into a legion, consumed by his grace, etc. + if(ismob(location) || isitem(location) || iseffect(location) || HAS_TRAIT_FROM(src, TRAIT_HUSK, CHANGELING_DRAIN)) //Stops crystallization if they are eaten by a dragon, turned into a legion, consumed by his grace, etc. to_chat(ethereal, span_warning("You were unable to finish your crystallization, for obvious reasons.")) stop_crystalization_process(ethereal, FALSE) return diff --git a/code/modules/surgery/organs/internal/liver/_liver.dm b/code/modules/surgery/organs/internal/liver/_liver.dm index fe5ca01df4f..7baeb04b8b6 100644 --- a/code/modules/surgery/organs/internal/liver/_liver.dm +++ b/code/modules/surgery/organs/internal/liver/_liver.dm @@ -245,6 +245,7 @@ /obj/item/organ/internal/liver/cybernetic name = "basic cybernetic liver" desc = "A very basic device designed to mimic the functions of a human liver. Handles toxins slightly worse than an organic liver." + failing_desc = "seems to be broken." icon_state = "liver-c" organ_flags = ORGAN_ROBOTIC maxHealth = STANDARD_ORGAN_THRESHOLD*0.5 diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index 5e4e0648067..71dc305ac5f 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -837,6 +837,7 @@ /obj/item/organ/internal/lungs/cybernetic name = "basic cybernetic lungs" desc = "A basic cybernetic version of the lungs found in traditional humanoid entities." + failing_desc = "seems to be broken." icon_state = "lungs-c" organ_flags = ORGAN_ROBOTIC maxHealth = STANDARD_ORGAN_THRESHOLD * 0.5 diff --git a/code/modules/surgery/organs/internal/stomach/_stomach.dm b/code/modules/surgery/organs/internal/stomach/_stomach.dm index bebeaacf110..e7d22a3ece6 100644 --- a/code/modules/surgery/organs/internal/stomach/_stomach.dm +++ b/code/modules/surgery/organs/internal/stomach/_stomach.dm @@ -289,6 +289,7 @@ /obj/item/organ/internal/stomach/cybernetic name = "basic cybernetic stomach" desc = "A basic device designed to mimic the functions of a human stomach" + failing_desc = "seems to be broken." icon_state = "stomach-c" organ_flags = ORGAN_ROBOTIC maxHealth = STANDARD_ORGAN_THRESHOLD * 0.5 diff --git a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm index 4d43b6a3a0a..4cc8ee404c1 100644 --- a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm @@ -92,7 +92,7 @@ playsound(carbon, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) carbon.cut_overlay(overcharge) - tesla_zap(carbon, 2, crystal_charge*2.5, ZAP_OBJ_DAMAGE | ZAP_LOW_POWER_GEN | ZAP_ALLOW_DUPLICATES) + tesla_zap(carbon, 2, crystal_charge * 1e3, ZAP_OBJ_DAMAGE | ZAP_LOW_POWER_GEN | ZAP_ALLOW_DUPLICATES) adjust_charge(ETHEREAL_CHARGE_FULL - crystal_charge) carbon.visible_message(span_danger("[carbon] violently discharges energy!"), span_warning("You violently discharge energy!")) diff --git a/code/modules/surgery/organs/internal/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm index e9c47a0f237..08ee3d20faf 100644 --- a/code/modules/surgery/organs/internal/tongue/_tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -190,7 +190,7 @@ languages_native = list(/datum/language/draconic, /datum/language/ashtongue) //SKYRAT EDIT: Ashtongue for Ashwalkers liked_foodtypes = GORE | MEAT | SEAFOOD | NUTS | BUGS disliked_foodtypes = GRAIN | DAIRY | CLOTH | GROSS - + voice_filter = @{"[0:a] asplit [out0][out2]; [out0] asetrate=%SAMPLE_RATE%*0.9,aresample=%SAMPLE_RATE%,atempo=1/0.9,aformat=channel_layouts=mono,volume=0.2 [p0]; [out2] asetrate=%SAMPLE_RATE%*1.1,aresample=%SAMPLE_RATE%,atempo=1/1.1,aformat=channel_layouts=mono,volume=0.2[p2]; [p0][0][p2] amix=inputs=3"} /obj/item/organ/internal/tongue/lizard/modify_speech(datum/source, list/speech_args) var/static/regex/lizard_hiss = new("s+", "g") var/static/regex/lizard_hiSS = new("S+", "g") @@ -499,7 +499,7 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) say_mod = "hisses" taste_sensitivity = 10 // LIZARDS ARE ALIENS CONFIRMED modifies_speech = TRUE // not really, they just hiss - + voice_filter = @{"[0:a] asplit [out0][out2]; [out0] asetrate=%SAMPLE_RATE%*0.8,aresample=%SAMPLE_RATE%,atempo=1/0.8,aformat=channel_layouts=mono [p0]; [out2] asetrate=%SAMPLE_RATE%*1.2,aresample=%SAMPLE_RATE%,atempo=1/1.2,aformat=channel_layouts=mono[p2]; [p0][0][p2] amix=inputs=3"} // Aliens can only speak alien and a few other languages. /obj/item/organ/internal/tongue/alien/get_possible_languages() return list( @@ -560,6 +560,7 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) /obj/item/organ/internal/tongue/robot name = "robotic voicebox" desc = "A voice synthesizer that can interface with organic lifeforms." + failing_desc = "seems to be broken." organ_flags = ORGAN_ROBOTIC icon_state = "tonguerobot" say_mod = "states" @@ -607,6 +608,7 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) toxic_foodtypes = NONE //no food is particularly toxic to ethereals attack_verb_continuous = list("shocks", "jolts", "zaps") attack_verb_simple = list("shock", "jolt", "zap") + voice_filter = @{"[0:a] asplit [out0][out2]; [out0] asetrate=%SAMPLE_RATE%*0.99,aresample=%SAMPLE_RATE%,volume=0.3 [p0]; [p0][out2] amix=inputs=2"} // Ethereal tongues can speak all default + voltaic /obj/item/organ/internal/tongue/ethereal/get_possible_languages() diff --git a/code/modules/surgery/plastic_surgery.dm b/code/modules/surgery/plastic_surgery.dm index 440d48d1c5e..424251143c3 100644 --- a/code/modules/surgery/plastic_surgery.dm +++ b/code/modules/surgery/plastic_surgery.dm @@ -1,3 +1,9 @@ +/// Disk containing info for doing advanced plastic surgery. Spawns in maint and available as a role-restricted item in traitor uplinks. +/obj/item/disk/surgery/advanced_plastic_surgery + name = "Advanced Plastic Surgery Disk" + desc = "The disk provides instructions on how to do an Advanced Plastic Surgery, this surgery allows one-self to completely remake someone's face with that of another. Provided they have a picture of them in their offhand when reshaping the face. With the surgery long becoming obsolete with the rise of genetics technology. This item became an antique to many collectors, With only the cheaper and easier basic form of plastic surgery remaining in use in most places." + surgeries = list(/datum/surgery/plastic_surgery/advanced) + /datum/surgery/plastic_surgery name = "Plastic surgery" surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB | SURGERY_MORBID_CURIOSITY @@ -9,6 +15,41 @@ /datum/surgery_step/close, ) +/datum/surgery/plastic_surgery/advanced + name = "advanced plastic surgery" + steps = list( + /datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/insert_plastic, + /datum/surgery_step/reshape_face, + /datum/surgery_step/close, + ) + +//Insert plastic step, It ain't called plastic surgery for nothing! :) +/datum/surgery_step/insert_plastic + name = "insert plastic (plastic)" + implements = list( + /obj/item/stack/sheet/plastic = 100, + /obj/item/stack/sheet/meat = 100) + time = 3.2 SECONDS + preop_sound = 'sound/effects/blobattack.ogg' + success_sound = 'sound/effects/attackblob.ogg' + failure_sound = 'sound/effects/blobattack.ogg' + +/datum/surgery_step/insert_plastic/preop(mob/user, mob/living/target, target_zone, obj/item/stack/tool, datum/surgery/surgery) + display_results( + user, + target, + span_notice("You begin to insert [tool] into the incision in [target]'s [parse_zone(target_zone)]..."), + span_notice("[user] begins to insert [tool] into the incision in [target]'s [parse_zone(target_zone)]."), + span_notice("[user] begins to insert [tool] into the incision in [target]'s [parse_zone(target_zone)]."), + ) + display_pain(target, "You feel something inserting just below the skin in your [parse_zone(target_zone)].") + +/datum/surgery_step/insert_plastic/success(mob/user, mob/living/target, target_zone, obj/item/stack/tool, datum/surgery/surgery, default_display_results) + . = ..() + tool.use(1) + //reshape_face /datum/surgery_step/reshape_face name = "reshape face (scalpel)" @@ -43,8 +84,15 @@ else var/list/names = list() if(!isabductor(user)) - for(var/i in 1 to 10) - names += target.dna.species.random_name(target.gender, TRUE) + var/obj/item/offhand = user.get_inactive_held_item() + if(istype(offhand, /obj/item/photo) && istype(surgery, /datum/surgery/plastic_surgery/advanced)) + var/obj/item/photo/disguises = offhand + for(var/namelist as anything in disguises.picture?.names_seen) + names += namelist + else + user.visible_message(span_warning("You have no picture to base the appearance on, reverting to random appearances.")) + for(var/i in 1 to 10) + names += target.dna.species.random_name(target.gender, TRUE) else for(var/_i in 1 to 9) names += "Subject [target.gender == MALE ? "i" : "o"]-[pick("a", "b", "c", "d", "e")]-[rand(10000, 99999)]" diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index 49fbecc2271..c5f62883b5f 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -259,6 +259,12 @@ butcher_sound = 'sound/weapons/circsawhit.ogg', \ ) //saws are very accurate and fast at butchering + var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/chainsaw) + + AddComponent( + /datum/component/slapcrafting,\ + slapcraft_recipes = slapcraft_recipe_list,\ + ) /obj/item/circular_saw/get_surgery_tool_overlay(tray_extended) return surgical_tray_overlay diff --git a/code/modules/unit_tests/fish_unit_tests.dm b/code/modules/unit_tests/fish_unit_tests.dm index 1ef15f8d0f5..d0d39227f43 100644 --- a/code/modules/unit_tests/fish_unit_tests.dm +++ b/code/modules/unit_tests/fish_unit_tests.dm @@ -28,10 +28,10 @@ var/obj/structure/aquarium/traits/aquarium = allocate(/obj/structure/aquarium/traits) TEST_ASSERT(!aquarium.sterile.try_to_reproduce(), "The test aquarium's sterile fish managed to reproduce when it shouldn't have") var/obj/item/fish/crossbreeder_jr = aquarium.crossbreeder.try_to_reproduce() - TEST_ASSERT(crossbreeder_jr, "The test aquarium's crossbreeder fish didn't manage to reproduce when it should have.") + TEST_ASSERT(crossbreeder_jr, "The test aquarium's crossbreeder fish didn't manage to reproduce when it should have") TEST_ASSERT_EQUAL(crossbreeder_jr.type, aquarium.cloner.type, "The test aquarium's crossbreeder fish mated with the wrong type of fish") var/obj/item/fish/cloner_jr = aquarium.cloner.try_to_reproduce() - TEST_ASSERT(cloner_jr, "The test aquarium's cloner fish didn't manage to reproduce when it should have.") + TEST_ASSERT(cloner_jr, "The test aquarium's cloner fish didn't manage to reproduce when it should have") TEST_ASSERT_NOTEQUAL(cloner_jr.type, aquarium.sterile.type, "The test aquarium's cloner fish mated with the sterile fish") ///Checks that fish evolutions work correctly. @@ -41,11 +41,24 @@ var/obj/structure/aquarium/evolution/aquarium = allocate(/obj/structure/aquarium/evolution) var/obj/item/fish/evolve_jr = aquarium.evolve.try_to_reproduce() TEST_ASSERT(evolve_jr, "The test aquarium's evolution fish didn't manage to reproduce when it should have") - TEST_ASSERT_NOTEQUAL(evolve_jr.type, /obj/item/fish/goldfish, "The test aquarium's evolution fish managed to pass the conditions of an impossible evolution.") + TEST_ASSERT_NOTEQUAL(evolve_jr.type, /obj/item/fish/goldfish, "The test aquarium's evolution fish managed to pass the conditions of an impossible evolution") TEST_ASSERT_EQUAL(evolve_jr.type, /obj/item/fish/clownfish, "The test aquarium's evolution fish's offspring isn't of the expected type") TEST_ASSERT(!(/datum/fish_trait/dummy in evolve_jr.fish_traits), "The test aquarium's evolution fish's offspring still has the old trait that ought to be removed by the evolution datum") TEST_ASSERT(/datum/fish_trait/dummy/two in evolve_jr.fish_traits, "The test aquarium's evolution fish's offspring doesn't have the evolution trait") +/datum/unit_test/fish_scanning + +/datum/unit_test/fish_scanning/Run() + var/scannable_fishes = 0 + for(var/obj/item/fish/fish_prototype as anything in subtypesof(/obj/item/fish)) + if(initial(fish_prototype.experisci_scannable)) + scannable_fishes++ + for(var/datum/experiment/scanning/fish/fish_scan as anything in typesof(/datum/experiment/scanning/fish)) + fish_scan = new fish_scan + var/scan_key = fish_scan.required_atoms[1] + if(fish_scan.required_atoms[scan_key] > scannable_fishes) + TEST_FAIL("[fish_scan.type] has requirements higher than the number of scannable fish types in the game: [scannable_fishes]") + ///dummy fish item used for the tests, as well with related subtypes and datums. /obj/item/fish/testdummy grind_results = list() diff --git a/code/modules/unit_tests/greyscale_config.dm b/code/modules/unit_tests/greyscale_config.dm index 9c5106be5b0..d3d9ce9d4fd 100644 --- a/code/modules/unit_tests/greyscale_config.dm +++ b/code/modules/unit_tests/greyscale_config.dm @@ -38,4 +38,4 @@ continue var/number_of_colors = length(colors) - 1 if(config.expected_colors != number_of_colors) - TEST_FAIL("[thing] has the wrong amount of colors configured for [config.DebugName()]. Expected [config.expected_colors] but only found [number_of_colors].") + TEST_FAIL("[thing] has the wrong amount of colors configured for [config.DebugName()]. Expected [config.expected_colors] colors but found [number_of_colors].") diff --git a/code/modules/unit_tests/heretic_rituals.dm b/code/modules/unit_tests/heretic_rituals.dm index 7298a163274..4ac5bce8d3d 100644 --- a/code/modules/unit_tests/heretic_rituals.dm +++ b/code/modules/unit_tests/heretic_rituals.dm @@ -63,6 +63,8 @@ var/list/created_atoms = list() for(var/ritual_item_path in knowledge.required_atoms) var/amount_to_create = knowledge.required_atoms[ritual_item_path] + if(islist(ritual_item_path)) + ritual_item_path = pick(ritual_item_path) for(var/i in 1 to amount_to_create) created_atoms += new ritual_item_path(get_turf(our_heretic)) diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_cyberpolice.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_cyberpolice.png new file mode 100644 index 00000000000..180be6064f8 Binary files /dev/null and b/code/modules/unit_tests/screenshots/screenshot_antag_icons_cyberpolice.png differ diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm index 8de11513eaa..181eeee72dc 100644 --- a/code/modules/unit_tests/simple_animal_freeze.dm +++ b/code/modules/unit_tests/simple_animal_freeze.dm @@ -64,28 +64,10 @@ /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/hivelord, - /mob/living/simple_animal/hostile/asteroid/hivelord/legion, - /mob/living/simple_animal/hostile/asteroid/hivelord/legion/advanced, - /mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf, - /mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow, - /mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow/portal, - /mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril, - /mob/living/simple_animal/hostile/asteroid/hivelordbrood, - /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion, - /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/advanced, - /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/snow, /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, - /mob/living/simple_animal/hostile/big_legion, - /mob/living/simple_animal/hostile/blob, - /mob/living/simple_animal/hostile/blob/blobbernaut, - /mob/living/simple_animal/hostile/blob/blobbernaut/independent, - /mob/living/simple_animal/hostile/blob/blobspore, - /mob/living/simple_animal/hostile/blob/blobspore/independent, - /mob/living/simple_animal/hostile/blob/blobspore/weak, /mob/living/simple_animal/hostile/construct, /mob/living/simple_animal/hostile/construct/artificer, /mob/living/simple_animal/hostile/construct/artificer/angelic, @@ -140,21 +122,28 @@ /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/doom, /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/guidance, /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/hunter, + /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/virtual_domain, /mob/living/simple_animal/hostile/megafauna/bubblegum, /mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination, + /mob/living/simple_animal/hostile/megafauna/bubblegum/virtual_domain, /mob/living/simple_animal/hostile/megafauna/clockwork_defender, /mob/living/simple_animal/hostile/megafauna/colossus, + /mob/living/simple_animal/hostile/megafauna/colossus/virtual_domain, /mob/living/simple_animal/hostile/megafauna/demonic_frost_miner, /mob/living/simple_animal/hostile/megafauna/dragon, /mob/living/simple_animal/hostile/megafauna/dragon/lesser, + /mob/living/simple_animal/hostile/megafauna/dragon/virtual_domain, /mob/living/simple_animal/hostile/megafauna/hierophant, + /mob/living/simple_animal/hostile/megafauna/hierophant/virtual_domain, /mob/living/simple_animal/hostile/megafauna/legion, + /mob/living/simple_animal/hostile/megafauna/legion/virtual_domain, /mob/living/simple_animal/hostile/megafauna/legion/medium, /mob/living/simple_animal/hostile/megafauna/legion/medium/eye, /mob/living/simple_animal/hostile/megafauna/legion/medium/left, /mob/living/simple_animal/hostile/megafauna/legion/medium/right, /mob/living/simple_animal/hostile/megafauna/legion/small, /mob/living/simple_animal/hostile/megafauna/wendigo, + /mob/living/simple_animal/hostile/megafauna/wendigo/virtual_domain, /mob/living/simple_animal/hostile/mimic, /mob/living/simple_animal/hostile/mimic/copy, /mob/living/simple_animal/hostile/mimic/copy/machine, @@ -181,7 +170,6 @@ /mob/living/simple_animal/hostile/retaliate/goose/vomit, /mob/living/simple_animal/hostile/retaliate/nanotrasenpeace, /mob/living/simple_animal/hostile/retaliate/nanotrasenpeace/ranged, - /mob/living/simple_animal/hostile/retaliate/snake, /mob/living/simple_animal/hostile/retaliate/trader, /mob/living/simple_animal/hostile/retaliate/trader/mrbones, /mob/living/simple_animal/hostile/skeleton, @@ -190,8 +178,6 @@ /mob/living/simple_animal/hostile/skeleton/plasmaminer, /mob/living/simple_animal/hostile/skeleton/plasmaminer/jackhammer, /mob/living/simple_animal/hostile/skeleton/templar, - /mob/living/simple_animal/hostile/smspider, - /mob/living/simple_animal/hostile/smspider/overcharged, /mob/living/simple_animal/hostile/space_dragon, /mob/living/simple_animal/hostile/space_dragon/spawn_with_antag, /mob/living/simple_animal/hostile/vatbeast, @@ -214,8 +200,8 @@ /mob/living/simple_animal/pet/cat/space, /mob/living/simple_animal/pet/gondola, /mob/living/simple_animal/pet/gondola/gondolapod, + /mob/living/simple_animal/pet/gondola/virtual_domain, /mob/living/simple_animal/revenant, - /mob/living/simple_animal/robot_customer, /mob/living/simple_animal/shade, /mob/living/simple_animal/slime, /mob/living/simple_animal/slime/pet, diff --git a/code/modules/uplink/uplink_items/implant.dm b/code/modules/uplink/uplink_items/implant.dm index 34fc9eedb0f..87c9fd6c96c 100644 --- a/code/modules/uplink/uplink_items/implant.dm +++ b/code/modules/uplink/uplink_items/implant.dm @@ -9,11 +9,14 @@ /datum/uplink_item/implants/freedom name = "Freedom Implant" - desc = "An implant injected into the body and later activated at the user's will. It will attempt to free the \ - user from common restraints such as handcuffs." + desc = "Can be activated to release common restraints such as handcuffs, legcuffs, and even bolas tethered around the legs." item = /obj/item/storage/box/syndie_kit/imp_freedom cost = 5 +/datum/uplink_item/implants/freedom/New() + . = ..() + desc += " Implant has enough energy for [FREEDOM_IMPLANT_CHARGES] uses before it becomes inert and harmlessly self-destructs." + /datum/uplink_item/implants/radio name = "Internal Syndicate Radio Implant" desc = "An implant injected into the body, allowing the use of an internal Syndicate radio. \ diff --git a/code/modules/uplink/uplink_items/job.dm b/code/modules/uplink/uplink_items/job.dm index b971e07619c..e585b07bb5f 100644 --- a/code/modules/uplink/uplink_items/job.dm +++ b/code/modules/uplink/uplink_items/job.dm @@ -173,6 +173,16 @@ cost = 5 surplus = 50 +/datum/uplink_item/role_restricted/advanced_plastic_surgery + name = "Advanced Plastic Surgery Program" + desc = "A bootleg copy of an collector item, this disk contains the procedure to perform advanced plastic surgery, allowing you to model someone's face and voice based on a picture taken by a camera on your offhand. \ + All changes are superficial and does not change ones genetic makeup. \ + Insert into an Operating Console to enable the procedure." + item = /obj/item/disk/surgery/brainwashing + restricted_roles = list(JOB_MEDICAL_DOCTOR, JOB_CHIEF_MEDICAL_OFFICER, JOB_ROBOTICIST) + cost = 1 + surplus = 50 + /datum/uplink_item/role_restricted/springlock_module name = "Heavily Modified Springlock MODsuit Module" desc = "A module that spans the entire size of the MOD unit, sitting under the outer shell. \ diff --git a/code/modules/uplink/uplink_items/stealthy.dm b/code/modules/uplink/uplink_items/stealthy.dm index 54c9bbe9adc..491f8e8e99d 100644 --- a/code/modules/uplink/uplink_items/stealthy.dm +++ b/code/modules/uplink/uplink_items/stealthy.dm @@ -90,7 +90,16 @@ slur as if inebriated. It can produce an infinite number \ of bolts, but takes time to automatically recharge after each shot." item = /obj/item/gun/energy/recharge/ebow - progression_minimum = 30 MINUTES cost = 10 surplus = 50 purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) + +/datum/uplink_item/stealthy_weapons/contrabaton + name = "Contractor Baton" + desc = "A compact, specialised baton assigned to Syndicate contractors. Applies light electrical shocks to targets. \ + These shocks are capable of affecting the inner circuitry of most robots as well, applying a short stun. \ + Has the added benefit of affecting the vocal cords of your victim, causing them to slur as if inebriated." + item = /obj/item/melee/baton/telescopic/contractor_baton + cost = 12 + surplus = 50 + purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) diff --git a/code/modules/vending/autodrobe.dm b/code/modules/vending/autodrobe.dm index 55e19152528..02daa0ce7e7 100644 --- a/code/modules/vending/autodrobe.dm +++ b/code/modules/vending/autodrobe.dm @@ -66,6 +66,8 @@ "products" = list( /obj/item/clothing/suit/costume/imperium_monk = 1, /obj/item/clothing/suit/chaplainsuit/holidaypriest = 1, + /obj/item/clothing/suit/chaplainsuit/habit = 1, + /obj/item/clothing/head/chaplain/habit_veil = 1, /obj/item/clothing/suit/chaplainsuit/whiterobe = 1, /obj/item/clothing/head/wizard/marisa/fake = 1, /obj/item/clothing/suit/wizrobe/marisa/fake = 1, diff --git a/code/modules/vending/games.dm b/code/modules/vending/games.dm index 80fb1350841..e51205c00e4 100644 --- a/code/modules/vending/games.dm +++ b/code/modules/vending/games.dm @@ -56,6 +56,7 @@ /obj/item/skillchip/sabrage = 2, /obj/item/skillchip/useless_adapter = 5, /obj/item/skillchip/wine_taster = 2, + /obj/item/skillchip/master_angler = 2, ), ), list( diff --git a/code/modules/vending/medical.dm b/code/modules/vending/medical.dm index 576cbb0b8b2..ad1c63e7e79 100644 --- a/code/modules/vending/medical.dm +++ b/code/modules/vending/medical.dm @@ -19,6 +19,7 @@ /obj/item/stack/medical/bone_gel = 4, /obj/item/cane/white = 2, /obj/item/clothing/glasses/eyepatch/medical = 2, + /obj/item/storage/box/bandages = 2, ) contraband = list( /obj/item/storage/box/gum/happiness = 3, diff --git a/code/modules/vending/medical_wall.dm b/code/modules/vending/medical_wall.dm index 4fd120bdc48..66badd4adf2 100644 --- a/code/modules/vending/medical_wall.dm +++ b/code/modules/vending/medical_wall.dm @@ -15,6 +15,7 @@ /obj/item/reagent_containers/medigel/sterilizine = 1, /obj/item/healthanalyzer/simple = 2, /obj/item/stack/medical/bone_gel = 2, + /obj/item/storage/box/bandages = 1, ) contraband = list( /obj/item/reagent_containers/pill/tox = 2, diff --git a/code/modules/vending/security.dm b/code/modules/vending/security.dm index 6a7edd8e854..9b5af87ab44 100644 --- a/code/modules/vending/security.dm +++ b/code/modules/vending/security.dm @@ -29,6 +29,7 @@ /obj/item/clothing/gloves/tackler = 5, /obj/item/grenade/stingbang = 1, /obj/item/watertank/pepperspray = 2, + /obj/item/storage/belt/holster/energy = 4, ) refill_canister = /obj/item/vending_refill/security default_price = PAYCHECK_CREW diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm index da2c08e04c9..e43314aa307 100644 --- a/code/modules/vending/wardrobes.dm +++ b/code/modules/vending/wardrobes.dm @@ -61,6 +61,7 @@ /obj/item/clothing/head/utility/surgerycap/green = 4, /obj/item/clothing/head/beret/medical/paramedic = 4, /obj/item/clothing/head/soft/paramedic = 4, + /obj/item/clothing/head/utility/head_mirror = 4, /obj/item/clothing/mask/bandana/striped/medical = 4, /obj/item/clothing/mask/surgical = 4, /obj/item/clothing/under/rank/medical/doctor = 4, @@ -523,6 +524,8 @@ /obj/item/storage/backpack/cultpack = 1, /obj/item/storage/fancy/candle_box = 2, /obj/item/radio/headset/headset_srv = 2, + /obj/item/clothing/suit/chaplainsuit/habit = 1, + /obj/item/clothing/head/chaplain/habit_veil = 1, ) contraband = list( /obj/item/toy/plush/ratplush = 1, diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm index 9d3a298812e..4258dc5a304 100644 --- a/code/modules/zombie/items.dm +++ b/code/modules/zombie/items.dm @@ -11,20 +11,24 @@ bare_wound_bonus = 15 sharpness = SHARP_EDGED -/obj/item/mutant_hand/zombie/afterattack(atom/target, mob/user, proximity_flag) +/obj/item/mutant_hand/zombie/afterattack(atom/target, mob/living/user, proximity_flag) . = ..() if(!proximity_flag) return else if(isliving(target)) if(ishuman(target)) - try_to_zombie_infect(target) + try_to_zombie_infect(target, user, user.zone_selected) else . |= AFTERATTACK_PROCESSED_ITEM check_feast(target, user) -/proc/try_to_zombie_infect(mob/living/carbon/human/target) +/proc/try_to_zombie_infect(mob/living/carbon/human/target, mob/living/user, def_zone = BODY_ZONE_CHEST) CHECK_DNA_AND_SPECIES(target) + // Can't zombify with no head + if(!target.get_bodypart(BODY_ZONE_HEAD)) + return + if(HAS_TRAIT(target, TRAIT_NO_ZOMBIFY)) // cannot infect any TRAIT_NO_ZOMBIFY human return @@ -33,11 +37,31 @@ if(HAS_TRAIT(target, TRAIT_VIRUS_RESISTANCE) && prob(75)) return + var/obj/item/bodypart/actual_limb = target.get_bodypart(def_zone) + + // What you hitting bro? + if(!actual_limb) + return + + var/limb_damage = actual_limb.get_damage() + var/limb_armor = max(0, target.getarmor(actual_limb, BIO) - 25) + + // This is a pretty jank way to do this, but in short: + // if they have thick material on that bodypart it will always need at least 25 previous limb damage to trigger an infection. + // and if their bio armor isn't thick it's a bit weaker. + for(var/obj/item/clothing/iter_clothing in target.get_clothing_on_part(actual_limb)) + if(iter_clothing.clothing_flags & THICKMATERIAL) + limb_armor += 25 + + if(limb_armor > limb_damage) + return + var/obj/item/organ/internal/zombie_infection/infection infection = target.get_organ_slot(ORGAN_SLOT_ZOMBIE) if(!infection) infection = new() infection.Insert(target) + to_chat(user, span_alien("You see [target] twitch for a moment as [target.p_their()] head is covered in \a [infection] - [target.p_Theyve()] been infected.")) /obj/item/mutant_hand/zombie/suicide_act(mob/living/user) user.visible_message(span_suicide("[user] is ripping [user.p_their()] brains out! It looks like [user.p_theyre()] trying to commit suicide!")) diff --git a/html/changelogs/archive/2023-09.yml b/html/changelogs/archive/2023-09.yml index aa41425b439..a45513671ce 100644 --- a/html/changelogs/archive/2023-09.yml +++ b/html/changelogs/archive/2023-09.yml @@ -972,3 +972,291 @@ lukevale: - rscadd: Adds bras as a selectable preference in the same vein as underwear. Separates all tops from undershirts. +2023-09-25: + Iamgoofball: + - bugfix: Fixes a bug with the steampunk goggles that deletes items that aren't + welding goggles when hit by it. + Melbert: + - rscadd: Changelings can now speak through their decoy brain if it is placed in + an MMI, to maintain the illusion they are actually dead and have been debrained. + SkyratBot: + - bugfix: Fix secret documents steal objective failing while inside folder. + - rscadd: Added the Hippocrates bust to medbay heirlooms. Paramedics don't get one. + - rscadd: You can now swear the Hippocratic oath with these busts! It'll give you + pacifism but nothing else. The process is reversible. + - rscadd: There's a very small chance that the Hippocrates bust was once wielded + by a certain German doctor. This chance is increased for coroner heirlooms. + - bugfix: Fixed players being able to roll antagonist without ever being eligible + to play any role. Players who have their preferences set up so that they're + likely to return to lobby when the round starts have a lowered chance of becoming + antagonist. + - bugfix: Fixed beams rendering below mobs by default. + - bugfix: The fishing line beam is no longer emissive (it doesn't glow in the dark). + - bugfix: Fixed the overflow role having less slots than it actually should. + - code_imp: New flags/args to electrocute_act() + - balance: Makes it so Ephedrine spasms have a 10 * (1.5 - purity)% chance per second + to happen, Adding a downside to pure Ephedrine + - bugfix: Syndicate Modsuit AI's now downloads the current codespeak book upon being + downloaded. + Vekter: + - bugfix: Fixes Birdshot's recycler being turned the wrong direction. + distributivgesetz: + - bugfix: Clamping/closing a wound should now heal the bodypart that was damaged + instead of a random one. + honkpocket: + - rscdel: Removed wall-mushroom outbreak event +2023-09-26: + LT3: + - spellcheck: Improved wording in greyscale JSON error message + - admin: Successful restart votes will now restart on the current map + - code_imp: End round and persistence data will be saved before executing successful + restart vote + Rhials: + - bugfix: '"Spooky" meteors will now properly spawn during halloween.' + SkyratBot: + - image: the security records suspected status is now teal instead of orange + - bugfix: Intellicards in computers are no longer deleted when the computer is destroyed. + - bugfix: Modular consoles can now be deconstructed by right clicking with a wrench. + - bugfix: cigarettes no longer smoke themselves from inside your pockets or on your + hands. + - admin: First time user connections are now logged + - qol: NT CIMs shows how much power the supermatter is releasing. + - qol: NT CIMs internal energy will adjust its prefix. + - qol: Energy displays (such as multitooling grid) will use the full range of SI + prefixes available, up to the peta prefix if you somehow managed to reach that. + - rscdel: Removes the per cubic centimeter part of internal energy. + - bugfix: Fix unnecessary delta time scaling on inactive supermatters. + - bugfix: Fix high energy zaps not scaling with delta time. + - bugfix: Fixes grounding rods lying about potential power you can generate. + - code_imp: Convert supermatter_zap() and tesla_zap() zap_str argument unit to be + in joules, and scales everything that uses that argument. + - rscadd: Adds an advanced plastic surgery procedure, allowing you to imitate people + in pictures. Simply hold a picture in your offhand of the person you wish to + imitate as while conducting the surgery! Remember, it's not foolproof, it only + changes your name and voice! + - rscadd: You can obtain the disk containing the afromentioned surgery. as a role-restricted + item to doctors and roboticists for 1TC, as a rare maint loot and BEPIS technode + reward + - bugfix: Centcom now rejects contraband that somehow makes it way onto the cargo + shuttle mid-transit and returns it. + - bugfix: you can no longer push watchers (and any other lavaland basic mob) around + by running into them + - bugfix: posibrains can be inserted again + - bugfix: Metalgen can no longer be used to transmute indestructible turfs. + - image: adds a frog holoform for pAIs + - bugfix: The custom error message for when there is only one map to vote for should + pop up in all cases rather than just a select few. + - bugfix: Stun immune people should no longer have issues with gripper gloves and + other tackle gloves. + sqnztb: + - rscadd: New medicine to clear up scars, made from synthflesh, ethanol, and miner's + salve. Be sure to apply it via patches! +2023-09-27: + SkyratBot: + - rscadd: added ranged attack friendly fire checks for basic mobs. minebots and + hivebots will now try to avoid shooting their friends + - bugfix: fixed Strong Stone ruin generation + - rscadd: Added a candle box crate for all your candle needs! + - bugfix: '[Tramstation] Mass Driver in chapel now has tiny fan so you don''t space + yourself.' + jjpark-kb: + - bugfix: actually fixed the ash revival ritual for basic mobs + - bugfix: basic animals now will have their health affected positively and negatively + by medicine and toxins respectively. +2023-09-28: + Melbert: + - rscadd: Doctors can now get head mirrors from their clothes vendor, to complete + the doctor outfit + SkyratBot: + - bugfix: Fixed job configs not being loaded properly. + - bugfix: You can no longer break the game by AI rolling in a card or APC + - qol: AI Roll now doesnt require you to click the exact turf to move you + - qol: AI roll cooldown and roll time is now a variable, making it possible for + AIs to become terrifying catamari damacy balls + - bugfix: Fixes full advanced surgery trays spawning with 'nothing' + - spellcheck: Tweaks the message that players get when not being able to qualify + for roundstart antag to be more accurate as to what's happening. + - qol: you can undeploy fulton beacons by clicking them with an empty hand + - qol: you can rename fulton beacons with a pen + - bugfix: Fix altars not allowing items to be sacrificed + - bugfix: Seeds will no longer be removed from existence after receiving the "You + can't seem to add [seed type] to the seed extractor" message + - bugfix: Some seeds that were previously not able to be added to the seed extractor + may now be added (starthistle for example) + - bugfix: fixes replica pod seeds spawning humans in nullspace + - qol: right clicking the seed extractor with a plant/food stores the extracted + seeds in the machine. + - bugfix: Valentines and ERTs will no longer get mood boosts from traitor moodener + items + - bugfix: Fixed zombies being able to infect headless corpses (Including former + zombies) + - bugfix: 'Fixed bio armor being totally useless against zombies. Now it checks + how hurt your limb is: If it''s more than the bio armor value, you get infected. + THICKMATERIAL clothing guarantees at least 25 damage required to infect you, + non-thick clothing reduces effective defence by 25. In practice this means people + with MODsuits, biosuits will resist infection unless they''re pummeled into + crit, and wearing a firesuit will save you from the first few slashes.' + - bugfix: Fixed the bomb hood armor not having the same bio armor value as bomb + armor. + - qol: Added a message to the zed when they succesfully infect someone. + - code_imp: Turned some proc names into snake_case rather than, uh, nospacecase. + - rscdel: removes surgical duffelbags + - bugfix: the surgery supply order now comes with a surgery tray + - bugfix: (skyrat) Hospital gowns will now spawn in surgery trays like they used + to in the surgery duffelbags + - bugfix: Left-clicking an empty surgery tray will now tell you exactly why it does + nothing. + - refactor: Turned slapcrafting into a component! You can examine compatible items + to see what recipes they can be used in, and what the ingredients for them are. + For example, spears and the head-on-spear crafting recipe. + - bugfix: The flight potion wings will no longer fail to work on lavaland/icemoon + on rare occasions. + - bugfix: Throwing things at cyborgs will now slow them down, as intended + - balance: Adjusted the calculation of throwforce -> slowdown for cyborgs such that + it is simply a flat duration for anything above a certain damage threshold (the + value of throwing iron rods) + - bugfix: Selecting "Monkey" on a magic mirror will now once again turn you into + a Monkey rather than a disgusting freak of nature. + - bugfix: Tall Boys have once again been barred from joining the Wizard Federation. + - rscadd: Contractor baton in traitor uplink for 12 TC + - balance: Ebow no longer has a reputation requirement. + - bugfix: Added complexity factors to foods that were missing them. + - balance: Gave the bluespace geode pirates 4 more teleporter bolt turrets. + - bugfix: The bluespace geode pirates no longer have a bluespace portal to the bottomless + pit dimension. + - rscadd: Station-safe dirt tiles for all your mapping needs, but surely no station + maps use the chasm baseturf ones, right? Right? + - bugfix: you can now deconstruct exodrone scanner arrays + - bugfix: the tree in space exodrone adventure no longer softlocks you + - qol: the exodrone launchers now tell you on examine how to remove their fuel canister + if you somehow needed to do that + - balance: exodrone wide scans are now capped at 10 minutes + - balance: exodrone travel times are 18% faster + - balance: you can now upgrade scanner arrays for faster wide scan + - balance: exodrone point scan and deep scan are faster + - spellcheck: fixes several typos related to exodrones and gives scanner control + console a description + - qol: Gas masks now muffle your voice with TTS. + - qol: Security Hailer masks now disguise your voice to protect your right to brutalize + greytiders. + - qol: Lizards, Ethereals, and Xenomorphs now have a vocal effect. + - qol: Security Records now show someone's voice name. + - bugfix: fixed geysers spawning on turfs with plants + Tattle: + - qol: drones now have individual names, instead of just "drone" + Vekter: + - rscadd: Added a holodeck to Birdshot Station. It can be reached via the Crew Facilities + hallway. + softcerv: + - rscadd: Adds in a wiki-book NIFSoft, allowing the user to access various wiki + books. + - qol: the speech impairment on the adult gas mask can now be toggled + tattle: + - qol: Basic animals now make sounds for audible emotes + - sound: Added new sound effects for chicks, chickens, crabs, and insects +2023-09-29: + A.C.M.O.: + - bugfix: Fixes the death sandwich, making it safe to examine. + BurgerBB: + - bugfix: Scrubbers and Vents will no longer reset their settings on map load. + GoldenAlpharex: + - server: Added a way for calls to be made to interfere with player ranks on live + servers (updating the players if they're connected) from outside of the game. + Rhials: + - qol: The freedom implant has received minor feedback and other minor usage improvements. + - bugfix: The Polymorph Belt should now update its sprite when active. + SkyratBot: + - qol: allowed names to start with a number if AI/Borg + - rscadd: Add drinking water causes drunk mobs to become sober + - balance: Diabetics rejoice! Nerfed sugar OD/hyperglycaemic shock to be an immediate + KO followed by drowsiness afterwards until the OD is gone. + - code_imp: Robot Customers have recently been touched codewise, please report any + bugs or unexpected behavior as there really should not be any. + - admin: There is now a tool to apply a DNA Infuser entry to any human. + - bugfix: The Nuke Op MODsuit AI downloader only works once per purchase, as intended. + - code_imp: adds a gas connector component that allows connection to the atmos piping + system without the need of repathing + - refactor: changes the cryo machine to use this new system + - refactor: Hivelords and Legions now use the basic mob framework. Please report + any unusual behaviour. + - rscadd: Hivelords shed more spawn when they are attacked. + - rscadd: Legions have learned how to fling their skulls across long distances. + - rscadd: Legions can heal other lavaland mobs with their skulls. + - rscadd: Legions are better at preserving corpses they consume, and sometimes make + use of their radios. + - rscadd: Legions may leave behind an unpleasant surprise after you are rescued + from them. + - balance: The crew monitoring console will now display you as dead if you are dead, + an critically injured if in crit, rather than setting those icons purely based + on your current health. + - qol: You won't continue burning to a husk if consumed by a snow legion after being + set on fire by an ice drake. + - bugfix: removes incorrect stack traces when using some admin secrets + - balance: Head revolutionaries and heads of staff are no longer immediately considered + disqualified when going AFK or disconnecting and are given a 2 minute grace + period. + - admin: Admins now get a log when a head revolutionary or head of staff disconnects + or goes AFK during a revolution. They also get the same log 1 minute after to + give them a chance to act on the information. + - refactor: Snakes have been refactored into basic mobs. This means that they are + a bit more intelligent than previous snakes, making them more docile and averse + to harming people (unless otherwise provoked). They do chomp all sorts of mice + though. You can feed them a dead mouse to make them your friend if you'd want + that. + - sound: If you listen closely to snakes, you might be able to hear a small hissing + sound... + - bugfix: fixed lobstrosities becoming unmovable when killed during their charge + windup + - bugfix: Splattercasting resets your blood to normal values when you transsform + into a vampire. + - bugfix: Gaining a new species will set your blood volume down to the normal volume + levels if higher than normal. + - bugfix: Fix water puddle runtime when washing items + - bugfix: the parole status and discharged status are now green and blue respectively + in the security record interface + - bugfix: Dimensional Anomalies no longer destroy wall-mounted equipment. + - code_imp: Your bodytype now decides what gendered sounds you make. + - bugfix: Fixed crabs not correctly (kinda) walking sideway. + - bugfix: dead bodies now cool down to room temperature over time + - rscadd: Add candle design to biogenerator + sergeirocks100: + - bugfix: Undershirts will now look as they should if you have a body type that + differs from the gender default. + softcerv: + - rscadd: Adds in the ability for certain NIFSofts to be kept between rounds. +2023-09-30: + DrDiasyl aka DrTuxedo: + - balance: Holsters can now be clipped to any suit, and house Captain antique gun + and HoS gun. You now can buy holsters from the SecTech premium section. + Paxilmaniac: + - qol: The half mask respirator can have its TTS voice muffling properties toggled + with control click + - qol: Icecats are now listed in the round end report, so you can see who was up + icing they cat + - bugfix: Icecats should hopefully spawn with their special language correctly now + SkyratBot: + - code_imp: removed some redundant code for airlocks + - admin: Mob abilities can be granted to arbitrary mobs via the VV menu in a similar + way to spells. + - bugfix: Lavaland syndicate operatives can no longer trivially use the jetpack + on their modsuit to fly over the lava. + - bugfix: If two cosmic heretics ascend in the same round, their star gazer survival + will be linked to each individual heretic and not shared by just one of them. + - bugfix: You can't click the Knock heretic portal to join as a mob while already + signed up to become a mob. + - balance: Cosmic heretics can't order the Star Gazer around while jaunting. + - balance: The Knock Heretic portal cannot summon Flesh Worms, but can summon Fire + Sharks. + - balance: The Knock Heretic portal will disperse if its creator is killed. + - rscadd: SM crystal can now dust someone or something if it falls on it. + - bugfix: The reverse revolver now looks like a normal Syndicate revolver on inspection. + - bugfix: fixed the stamp in the metastation CMO office always spawning on the floor + - bugfix: You can now spray paint the SM without getting dusted + Smol42: + - rscadd: Added some new hairstyles + Zergspower: + - bugfix: Crew Monitor works again properly + nikothedude: + - rscadd: A waterbreathing quirk + - qol: Waterbreathing is now documented on species pages of the species that have + it diff --git a/html/changelogs/archive/2023-10.yml b/html/changelogs/archive/2023-10.yml new file mode 100644 index 00000000000..ccff91affb0 --- /dev/null +++ b/html/changelogs/archive/2023-10.yml @@ -0,0 +1,122 @@ +2023-10-01: + Hatterhat: + - balance: Bullets have had their base type's wound bonus reduced back to 0, down + from 20, because wounds are actually quite punishing. Funnily enough, most bullets + already have modified wound bonuses - except c9mm, c10mm, and most incendiaries, + so this probably doesn't change much. + - balance: .50 (used in the snipers and renamed to .416 or whatever) is now back + to TG balance standards. Knockdown on hit, 60 instead of 110 damage, etc. etc. + - bugfix: .50 Soporific was removed because disruptor ammo was right there and nobody + realized it existed. + - bugfix: After review of a missing equipment complaint, Nanotrasen remembered to + pay Lopland's quartermasters to put the customary flashbang and teargas grenade + boxes into the Void Raptor's armory. + Melbert: + - qol: Examine blocked out roundstart / latejoin job information. + - qol: Captain gets a little bit more information about how their radio works roundstart. + - bugfix: Fixed roundstart players not getting radio information. + Paxilmaniac: + - image: The buttondown shirts (underwear) have been updated with a better look + and more contrasted palette + SkyratBot: + - rscadd: A new export has arrived in the imports section, the Galactic Materials + Market! You can use this to buy and sell minerals for profit or cost, as well + as stock your station when you don't have any miners. + - rscadd: Insert sheets of minerals into the Galactic Materials Market to convert + them into a stock block, allowing you to lock in your price for 5 minutes. Wait + too long and it'll be subject to market value again! + - rscadd: Minerals can be bought on the market either using the station's cargo + budget by cargo crew, or privately by everyone else. + - rscdel: Any material stacks that can be bought and sold on the market before have + been removed from the cargo catalog. + - rscadd: Adds Bitrunning to supply department- a semi-offstation role that rewards + teamwork. + - rscadd: Adds new machines to complement the job- net pod, quantum server, quantum + consoles, and the nexacache vendor. + - rscadd: Adds several new maps which can be loaded and unloaded at will. + - rscadd: Some flair for the new bitrunning vendor. + - rscadd: Adds a new antagonist for the virtual domain only. Short lived ghost role + that fights bitrunners. + - rscdel: Removes the BEPIS machine, moves its tech into the Bitrunning vendor. + - bugfix: Fixes missing baseturfs and clowns in mining planet VDOM.. + - qol: Font settings in the chat panel applies to all text now. + - image: new chaplain outfit + - bugfix: Blob spores will respond to rallies more reliably (it won't runtime every + time they try and pathfind). + - bugfix: Blobbernaut pain animation overlays should align with the direction the + mob is facing instead of always facing South + - refactor: Blob spores, zombies, and blobbernauts now all use the basic mob framework. + They should work the same, but please report any issues. + - bugfix: Added warden to list of default required enemies for rulesets. + - bugfix: Blob Zombies and Blobbernauts have had their attack speed restored to + its original value + - refactor: Supermatter Spiders have been refactored into basic mobs, on the extremely + off chance you spot one and also notice any weird bugs regarding it, please + report it. + - balance: There are now 3 roundstart cyborg job slots open by default. + - rscadd: Quantum servers now talk over supply channel when they're done cooling + off. Go outside! + - bugfix: You can no longer use dragon swoop to bypass cordons. + - bugfix: Netpod brain damage is now properly reduced upon server upgrades. + - bugfix: Fixed an bug where swapping bodies in vdom prevented you from disconnecting. + - bugfix: Fixed a bug where a quantum server could get locked out of loading new + domains. + - bugfix: Changed quantum console UI to display "no bandwidth" rather than "none" + - bugfix: Actually fixed the hooked item exploit. + - rscadd: Heretic Rebalance + - balance: Researching the Main Knowledge paths that unlock Side Paths will grant + one Side Point that can be used only on those side paths. You can still spend + normal knowledge points on them if you wish. + - balance: Rune drawing time has been reduced from 30->20 seconds. Codex drawing + time has been reduced from 15->8. + - balance: 'Codex Cicatrix is now a roundstart knowledge, works as an amber focus + when held in-hand and opened, and has had its recipe changed to: 1 of any non-standard + pen (literally anything that isn''t the base pen), any book, and either animal + hide OR a corpse, any kind.' + - code_imp: Added support for using a list inside ritual requirements and a special + 'snowflake check' rituals can utilize. + - balance: The first non-path knowledge, the Mansus Hand Mark, has had its cost + reduced from 2->1 points. + - bugfix: Aloe and other baked foods that don't have reagents can be baked again + without turning to ash + Vekter: + - bugfix: Fixes the missing grinder in Birdshot's Virology department + jjpark-kb: + - bugfix: the ashwalker tendril will allow you to respawn again (the tendril blessing) + - bugfix: the round end report will accurately report ashwalker sacrifices + nikothedude: + - code_imp: Gauze removal is now handled by the gauze's destroy instead of seep_gauze + ninjanomnom: + - rscdel: An easter egg plushie that was spawning where it shouldn't has been brought + back home. + - rscadd: The secure closet can now spawn live gibtonite, enjoy your free bomb. +2023-10-02: + SkyratBot: + - balance: Sci now has access to the materials & canisters section in their departmental + order console + - rscadd: Expanded the fishing portal generator. It now comes with several portal + options that can be unlocked by performing fish scanning experiments, which + also award a modest amount of techweb points. + - balance: The fishing portal generator is now buildable and no longer orderable. + The board can be printed from cargo, service and science lathes. + - balance: Advanced fishing tech is no longer a BEPIS design. It now requires the + base fish scanning experiment and 2000 points to be unlocked. + - rscadd: The advanced fishing rod now comes with an incorporated experiscanner + specific for fish scanning. + - rscadd: Added a new skillchip that may change the icon of the "fish" shown in + the minigame UI to less generic ones. Reaching master level in fishing also + does that. + - qol: The experiment handler UI no longer shows unselectable experiments. + - bugfix: Security officers can now download the crew manifest PDA app that they + start with. + - rscadd: Wizards who complete the grand ritual can now gift everyone with eternal + life + distributivgesetz: + - bugfix: Font scaling in TGUI chat has been reverted to its original implementation. + softcerv: + - rscadd: Adds the mini-soulcatcher, a more lightweight soulcatcher that can be + attached to objects + - rscadd: Adds in the RSD brain interface, an item that allows for soulcatcher souls, + that died within a round and were scanned, to be transferred to a new brain. + - rscadd: Adds in the NIFSoft Scryer, a NIFSoft that gives the user a Scryer they + can use to communicate with other Scryer users. diff --git a/icons/area/areas_station.dmi b/icons/area/areas_station.dmi index b07ea38a159..cbfe463efa5 100644 Binary files a/icons/area/areas_station.dmi and b/icons/area/areas_station.dmi differ diff --git a/icons/effects/96x96.dmi b/icons/effects/96x96.dmi index 38d1d44a000..31f26c3e6e1 100644 Binary files a/icons/effects/96x96.dmi and b/icons/effects/96x96.dmi differ diff --git a/icons/effects/bitrunning.dmi b/icons/effects/bitrunning.dmi new file mode 100644 index 00000000000..bfdc7c63436 Binary files /dev/null and b/icons/effects/bitrunning.dmi differ diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 29e59dc6c71..d59f065da28 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/hud/fishing_hud.dmi b/icons/hud/fishing_hud.dmi index b68acee09b7..58c478d0710 100644 Binary files a/icons/hud/fishing_hud.dmi and b/icons/hud/fishing_hud.dmi differ diff --git a/icons/hud/radial_fishing.dmi b/icons/hud/radial_fishing.dmi new file mode 100644 index 00000000000..65fd55176b7 Binary files /dev/null and b/icons/hud/radial_fishing.dmi differ diff --git a/icons/hud/screen_alert.dmi b/icons/hud/screen_alert.dmi index a1fc01434e4..1edd4d29cb5 100755 Binary files a/icons/hud/screen_alert.dmi and b/icons/hud/screen_alert.dmi differ diff --git a/icons/mob/clothing/belt.dmi b/icons/mob/clothing/belt.dmi index 546e3da0f86..d1a1777e4e4 100644 Binary files a/icons/mob/clothing/belt.dmi and b/icons/mob/clothing/belt.dmi differ diff --git a/icons/mob/clothing/head/chaplain.dmi b/icons/mob/clothing/head/chaplain.dmi index efb6ec3c9e9..100b7ee922f 100644 Binary files a/icons/mob/clothing/head/chaplain.dmi and b/icons/mob/clothing/head/chaplain.dmi differ diff --git a/icons/mob/clothing/head/pai_head.dmi b/icons/mob/clothing/head/pai_head.dmi index 0a04e7e8ab2..e5dd4965d8b 100644 Binary files a/icons/mob/clothing/head/pai_head.dmi and b/icons/mob/clothing/head/pai_head.dmi differ diff --git a/icons/mob/clothing/head/plasmaman_head.dmi b/icons/mob/clothing/head/plasmaman_head.dmi index 9846cf02200..1917ae7bcf5 100644 Binary files a/icons/mob/clothing/head/plasmaman_head.dmi and b/icons/mob/clothing/head/plasmaman_head.dmi differ diff --git a/icons/mob/clothing/head/utility.dmi b/icons/mob/clothing/head/utility.dmi index 3f3a668181c..ada1b90c4b0 100644 Binary files a/icons/mob/clothing/head/utility.dmi and b/icons/mob/clothing/head/utility.dmi differ diff --git a/icons/mob/clothing/suits/chaplain.dmi b/icons/mob/clothing/suits/chaplain.dmi index 4b6368fb291..8806bf5f679 100644 Binary files a/icons/mob/clothing/suits/chaplain.dmi and b/icons/mob/clothing/suits/chaplain.dmi differ diff --git a/icons/mob/clothing/suits/jacket.dmi b/icons/mob/clothing/suits/jacket.dmi index cd924e847eb..a6f25d91c59 100644 Binary files a/icons/mob/clothing/suits/jacket.dmi and b/icons/mob/clothing/suits/jacket.dmi differ diff --git a/icons/mob/clothing/under/cargo.dmi b/icons/mob/clothing/under/cargo.dmi index 4bf30a67a2d..180f0e4ec87 100644 Binary files a/icons/mob/clothing/under/cargo.dmi and b/icons/mob/clothing/under/cargo.dmi differ diff --git a/icons/mob/clothing/under/plasmaman.dmi b/icons/mob/clothing/under/plasmaman.dmi index 41cbfb4482b..fcc8f008cd7 100644 Binary files a/icons/mob/clothing/under/plasmaman.dmi and b/icons/mob/clothing/under/plasmaman.dmi differ diff --git a/icons/mob/huds/hud.dmi b/icons/mob/huds/hud.dmi index ec9be118f57..d71ba4b0940 100644 Binary files a/icons/mob/huds/hud.dmi and b/icons/mob/huds/hud.dmi differ diff --git a/icons/mob/inhands/clothing/hats_lefthand.dmi b/icons/mob/inhands/clothing/hats_lefthand.dmi index 7111ee4d748..191c85cf482 100644 Binary files a/icons/mob/inhands/clothing/hats_lefthand.dmi and b/icons/mob/inhands/clothing/hats_lefthand.dmi differ diff --git a/icons/mob/inhands/clothing/hats_righthand.dmi b/icons/mob/inhands/clothing/hats_righthand.dmi index 96756fc44db..8038e7474ee 100644 Binary files a/icons/mob/inhands/clothing/hats_righthand.dmi and b/icons/mob/inhands/clothing/hats_righthand.dmi differ diff --git a/icons/mob/inhands/clothing/suits_lefthand.dmi b/icons/mob/inhands/clothing/suits_lefthand.dmi index 757fb8b8593..8b9fa5256a9 100644 Binary files a/icons/mob/inhands/clothing/suits_lefthand.dmi and b/icons/mob/inhands/clothing/suits_lefthand.dmi differ diff --git a/icons/mob/inhands/clothing/suits_righthand.dmi b/icons/mob/inhands/clothing/suits_righthand.dmi index c749a2ed98a..c88f4d22444 100644 Binary files a/icons/mob/inhands/clothing/suits_righthand.dmi and b/icons/mob/inhands/clothing/suits_righthand.dmi differ diff --git a/icons/mob/inhands/equipment/medical_lefthand.dmi b/icons/mob/inhands/equipment/medical_lefthand.dmi index 7ce3674c86a..feaed169078 100644 Binary files a/icons/mob/inhands/equipment/medical_lefthand.dmi and b/icons/mob/inhands/equipment/medical_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/medical_righthand.dmi b/icons/mob/inhands/equipment/medical_righthand.dmi index 6ceb5efe4d8..15ccf5c090e 100644 Binary files a/icons/mob/inhands/equipment/medical_righthand.dmi and b/icons/mob/inhands/equipment/medical_righthand.dmi differ diff --git a/icons/mob/silicon/pai.dmi b/icons/mob/silicon/pai.dmi index 624ed669519..2be986d411d 100644 Binary files a/icons/mob/silicon/pai.dmi and b/icons/mob/silicon/pai.dmi differ diff --git a/icons/mob/simple/lavaland/lavaland_monsters.dmi b/icons/mob/simple/lavaland/lavaland_monsters.dmi index 13c37dca594..38b78cf468f 100644 Binary files a/icons/mob/simple/lavaland/lavaland_monsters.dmi and b/icons/mob/simple/lavaland/lavaland_monsters.dmi differ diff --git a/icons/mob/telegraphing/telegraph.dmi b/icons/mob/telegraphing/telegraph.dmi index d5e03419cd8..de525ead4ee 100644 Binary files a/icons/mob/telegraphing/telegraph.dmi and b/icons/mob/telegraphing/telegraph.dmi differ diff --git a/icons/obj/aquarium.dmi b/icons/obj/aquarium.dmi index 3a27c83c906..19e2e68c4f8 100644 Binary files a/icons/obj/aquarium.dmi and b/icons/obj/aquarium.dmi differ diff --git a/icons/obj/card.dmi b/icons/obj/card.dmi index a5c4e828301..2bbec93eed2 100644 Binary files a/icons/obj/card.dmi and b/icons/obj/card.dmi differ diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi index 20f24dd2240..fd898d3105f 100644 Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ diff --git a/icons/obj/clothing/head/chaplain.dmi b/icons/obj/clothing/head/chaplain.dmi index d95436fdd2d..ed6f6248b31 100644 Binary files a/icons/obj/clothing/head/chaplain.dmi and b/icons/obj/clothing/head/chaplain.dmi differ diff --git a/icons/obj/clothing/head/plasmaman_hats.dmi b/icons/obj/clothing/head/plasmaman_hats.dmi index adcf9129c45..f593a08b88c 100644 Binary files a/icons/obj/clothing/head/plasmaman_hats.dmi and b/icons/obj/clothing/head/plasmaman_hats.dmi differ diff --git a/icons/obj/clothing/head/utility.dmi b/icons/obj/clothing/head/utility.dmi index 9571b2add78..17040f5bb8b 100644 Binary files a/icons/obj/clothing/head/utility.dmi and b/icons/obj/clothing/head/utility.dmi differ diff --git a/icons/obj/clothing/suits/chaplain.dmi b/icons/obj/clothing/suits/chaplain.dmi index 64474a04d31..730e47cd6fa 100644 Binary files a/icons/obj/clothing/suits/chaplain.dmi and b/icons/obj/clothing/suits/chaplain.dmi differ diff --git a/icons/obj/clothing/suits/jacket.dmi b/icons/obj/clothing/suits/jacket.dmi index c63f262f104..dc507017cd2 100644 Binary files a/icons/obj/clothing/suits/jacket.dmi and b/icons/obj/clothing/suits/jacket.dmi differ diff --git a/icons/obj/clothing/under/cargo.dmi b/icons/obj/clothing/under/cargo.dmi index fc04a897d5e..63e40538899 100644 Binary files a/icons/obj/clothing/under/cargo.dmi and b/icons/obj/clothing/under/cargo.dmi differ diff --git a/icons/obj/clothing/under/plasmaman.dmi b/icons/obj/clothing/under/plasmaman.dmi index 4277c43d54b..4d416d5b05f 100644 Binary files a/icons/obj/clothing/under/plasmaman.dmi and b/icons/obj/clothing/under/plasmaman.dmi differ diff --git a/icons/obj/economy.dmi b/icons/obj/economy.dmi index dc90265b6e9..04abc41cae1 100644 Binary files a/icons/obj/economy.dmi and b/icons/obj/economy.dmi differ diff --git a/icons/obj/exploration.dmi b/icons/obj/exploration.dmi index 2f9d004bee2..b7224d2df84 100644 Binary files a/icons/obj/exploration.dmi and b/icons/obj/exploration.dmi differ diff --git a/icons/obj/fishing.dmi b/icons/obj/fishing.dmi index 39bcc853442..f7ab9fc1ad9 100644 Binary files a/icons/obj/fishing.dmi and b/icons/obj/fishing.dmi differ diff --git a/icons/obj/machines/bepis.dmi b/icons/obj/machines/bepis.dmi deleted file mode 100644 index f348c2e1b05..00000000000 Binary files a/icons/obj/machines/bepis.dmi and /dev/null differ diff --git a/icons/obj/machines/bitrunning.dmi b/icons/obj/machines/bitrunning.dmi new file mode 100644 index 00000000000..a910a16b35c Binary files /dev/null and b/icons/obj/machines/bitrunning.dmi differ diff --git a/icons/obj/machines/computer.dmi b/icons/obj/machines/computer.dmi index 10974f97bac..5ffa3445db6 100644 Binary files a/icons/obj/machines/computer.dmi and b/icons/obj/machines/computer.dmi differ diff --git a/icons/obj/medical/organs/mining_organs.dmi b/icons/obj/medical/organs/mining_organs.dmi index f3fc298284b..172f94001ff 100644 Binary files a/icons/obj/medical/organs/mining_organs.dmi and b/icons/obj/medical/organs/mining_organs.dmi differ diff --git a/icons/obj/medical/stack_medical.dmi b/icons/obj/medical/stack_medical.dmi index d12949da595..c4ec905786c 100644 Binary files a/icons/obj/medical/stack_medical.dmi and b/icons/obj/medical/stack_medical.dmi differ diff --git a/icons/obj/railings.dmi b/icons/obj/railings.dmi index 28332e21324..3dbbd7c8318 100644 Binary files a/icons/obj/railings.dmi and b/icons/obj/railings.dmi differ diff --git a/icons/obj/storage/box.dmi b/icons/obj/storage/box.dmi index 7ff4067c288..d660e1b7bfe 100644 Binary files a/icons/obj/storage/box.dmi and b/icons/obj/storage/box.dmi differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index 8a1575fcec6..6ddc178b98c 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/modular_skyrat/master_files/code/datums/traits/good.dm b/modular_skyrat/master_files/code/datums/traits/good.dm index 22987f7705d..08f265145a9 100644 --- a/modular_skyrat/master_files/code/datums/traits/good.dm +++ b/modular_skyrat/master_files/code/datums/traits/good.dm @@ -68,6 +68,16 @@ right_arm.unarmed_miss_sound = initial(right_arm.unarmed_miss_sound) right_arm.unarmed_sharpness = initial(right_arm.unarmed_sharpness) +/datum/quirk/water_breathing + name = "Water breathing" + desc = "You are able to breathe underwater!" + value = 2 + mob_trait = TRAIT_WATER_BREATHING + gain_text = span_notice("You become acutely aware of the moisture in your lungs and in the air. It feels nice.") + lose_text = span_danger("You suddenly realize the moisture in your lungs feels really weird, and you almost choke on it!") + medical_record_text = "Patient possesses biology compatible with aquatic respiration." + icon = FA_ICON_FISH + // AdditionalEmotes *turf quirks /datum/quirk/water_aspect name = "Water aspect (Emotes)" diff --git a/modular_skyrat/master_files/code/modules/bitrunning/orders/tech.dm b/modular_skyrat/master_files/code/modules/bitrunning/orders/tech.dm new file mode 100644 index 00000000000..6c9a0626517 --- /dev/null +++ b/modular_skyrat/master_files/code/modules/bitrunning/orders/tech.dm @@ -0,0 +1,3 @@ +/datum/orderable_item/bepis/flashdark + item_path = /obj/item/flashlight/flashdark + cost_per_order = 750 diff --git a/modular_skyrat/master_files/code/modules/mob/living/human/species.dm b/modular_skyrat/master_files/code/modules/mob/living/human/species.dm index b2b9eaeecba..30df82a7f11 100644 --- a/modular_skyrat/master_files/code/modules/mob/living/human/species.dm +++ b/modular_skyrat/master_files/code/modules/mob/living/human/species.dm @@ -32,3 +32,14 @@ /datum/species/proc/apply_supplementary_body_changes(mob/living/carbon/human/target, datum/preferences/preferences, visuals_only = FALSE) return + +/datum/species/create_pref_traits_perks() + . = ..() + + if (TRAIT_WATER_BREATHING in inherent_traits) + . += list(list( + SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, + SPECIES_PERK_ICON = FA_ICON_FISH, + SPECIES_PERK_NAME = "Waterbreathing", + SPECIES_PERK_DESC = "[plural_form] can breathe in water, making pools a lot safer to be in!", + )) diff --git a/modular_skyrat/master_files/code/modules/research/techweb/all_nodes.dm b/modular_skyrat/master_files/code/modules/research/techweb/all_nodes.dm index e263c4062c7..b09de049865 100644 --- a/modular_skyrat/master_files/code/modules/research/techweb/all_nodes.dm +++ b/modular_skyrat/master_files/code/modules/research/techweb/all_nodes.dm @@ -206,12 +206,14 @@ . = ..() design_ids += list( "borg_upgrade_snacks", + "mini_soulcatcher", ) /datum/techweb_node/neural_programming/New() . = ..() design_ids += list( "soulcatcher_device", + "rsd_interface", ) /datum/techweb_node/cyborg_upg_util/New() diff --git a/modular_skyrat/master_files/icons/mob/actions/actions_nif.dmi b/modular_skyrat/master_files/icons/mob/actions/actions_nif.dmi index 0e3d125038e..eac81c9cca9 100644 Binary files a/modular_skyrat/master_files/icons/mob/actions/actions_nif.dmi and b/modular_skyrat/master_files/icons/mob/actions/actions_nif.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/under/cargo.dmi b/modular_skyrat/master_files/icons/mob/clothing/under/cargo.dmi index 9a8042cf0a0..8d18e50d623 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/under/cargo.dmi and b/modular_skyrat/master_files/icons/mob/clothing/under/cargo.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/under/cargo_digi.dmi b/modular_skyrat/master_files/icons/mob/clothing/under/cargo_digi.dmi index c4ecb9e4f81..faceea6def3 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/under/cargo_digi.dmi and b/modular_skyrat/master_files/icons/mob/clothing/under/cargo_digi.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/underwear.dmi b/modular_skyrat/master_files/icons/mob/clothing/underwear.dmi index 3d9209905cb..ff6f4218c27 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/underwear.dmi and b/modular_skyrat/master_files/icons/mob/clothing/underwear.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/sprite_accessory/hair.dmi b/modular_skyrat/master_files/icons/mob/sprite_accessory/hair.dmi index fdfc3fee1c8..681457fe596 100644 Binary files a/modular_skyrat/master_files/icons/mob/sprite_accessory/hair.dmi and b/modular_skyrat/master_files/icons/mob/sprite_accessory/hair.dmi differ diff --git a/modular_skyrat/modules/aesthetics/guns/code/guns.dm b/modular_skyrat/modules/aesthetics/guns/code/guns.dm index ccc43793c33..767ca1608c1 100644 --- a/modular_skyrat/modules/aesthetics/guns/code/guns.dm +++ b/modular_skyrat/modules/aesthetics/guns/code/guns.dm @@ -383,12 +383,11 @@ advanced_print_req = TRUE // you are NOT printing more ammo for this without effort. // then again the offstations with ammo printers and sniper rifles come with an ammo disk anyway, so -/obj/item/ammo_casing/p50/soporific - name = ".416 Stabilis tranquilizer casing" +/obj/item/ammo_casing/p50/disruptor + name = ".416 Stabilis disruptor casing" desc = "A .416 bullet casing that specialises in sending the target to sleep rather than hell.\

\ - SOPORIFIC: Forces targets to sleep, deals no damage." - projectile_type = /obj/projectile/bullet/p50/soporific + DISRUPTOR: Forces humanoid targets to sleep, does heavy damage against cyborgs, EMPs struck targets." /obj/item/ammo_casing/p50/penetrator name = ".416 Stabilis APFSDS ++P bullet casing" @@ -528,8 +527,11 @@ /obj/projectile/bullet/incendiary/c46x30mm name = "8mm incendiary bullet" -/obj/projectile/bullet/p50/soporific // COMMON BULLET IS ALREADY OVERRIDEN IN MODULAR > BULLETREBALANCE > CODE > sniper.dm - name = ".416 tranquilizer" +/obj/projectile/bullet/p50 + name = ".416 Stabilis bullet" + +/obj/projectile/bullet/p50/disruptor + name = ".416 disruptor bullet" /obj/projectile/bullet/p50/penetrator name = ".416 penetrator bullet" diff --git a/modular_skyrat/modules/alerts/code/default_announcer.dm b/modular_skyrat/modules/alerts/code/default_announcer.dm index 7ae320f01f8..86add70db58 100644 --- a/modular_skyrat/modules/alerts/code/default_announcer.dm +++ b/modular_skyrat/modules/alerts/code/default_announcer.dm @@ -43,7 +43,6 @@ ANNOUNCER_KLAXON = 'modular_skyrat/modules/black_mesa/sound/siren1_long.ogg', ANNOUNCER_ICARUS = 'modular_skyrat/modules/assault_operatives/sound/icarus_alarm.ogg', ANNOUNCER_NRI_RAIDERS = 'modular_skyrat/modules/encounters/sounds/morse.ogg', - ANNOUNCER_FUNGI = 'modular_skyrat/modules/alerts/sound/alerts/fungi.ogg', ANNOUNCER_DEPARTMENTAL = 'modular_skyrat/modules/alerts/sound/alerts/alert3.ogg', ANNOUNCER_SHUTTLE = 'modular_skyrat/modules/alerts/sound/alerts/alert3.ogg', ) diff --git a/modular_skyrat/modules/alerts/sound/alerts/fungi.ogg b/modular_skyrat/modules/alerts/sound/alerts/fungi.ogg deleted file mode 100644 index 7eb45de94a2..00000000000 Binary files a/modular_skyrat/modules/alerts/sound/alerts/fungi.ogg and /dev/null differ diff --git a/modular_skyrat/modules/alternative_job_titles/code/job.dm b/modular_skyrat/modules/alternative_job_titles/code/job.dm index 2f47a4c1f05..13edfe45aa4 100644 --- a/modular_skyrat/modules/alternative_job_titles/code/job.dm +++ b/modular_skyrat/modules/alternative_job_titles/code/job.dm @@ -11,6 +11,9 @@ if(!player_client) return + if(!ishuman(equipping)) + return + var/chosen_title = player_client.prefs.alt_job_titles[job.title] || job.title var/obj/item/card/id/card = equipping.wear_id diff --git a/modular_skyrat/modules/ashwalkers/code/buildings/ash_tendril.dm b/modular_skyrat/modules/ashwalkers/code/buildings/ash_tendril.dm index eaa80cc5941..18d3baa3b51 100644 --- a/modular_skyrat/modules/ashwalkers/code/buildings/ash_tendril.dm +++ b/modular_skyrat/modules/ashwalkers/code/buildings/ash_tendril.dm @@ -99,7 +99,7 @@ viewable_living.gib() continue - if(viewable_living.mind?.has_antag_datum(/datum/antagonist/ashwalker) && (viewable_living.key || viewable_living.get_ghost(FALSE, TRUE))) //special interactions for dead lava lizards with ghosts attached + if(viewable_living.mind?.has_antag_datum(/datum/antagonist/ashwalker) && (viewable_living.ckey || viewable_living.get_ghost(FALSE, TRUE))) //special interactions for dead lava lizards with ghosts attached revive_ashwalker(viewable_living) continue @@ -129,6 +129,8 @@ else living_observers.add_mood_event("oogabooga", /datum/mood_event/sacrifice_bad) + ashies.sacrifices_made++ + /** * Proc that will spawn the egg that will revive the ashwalker * This is also the Skyrat replacement for /proc/remake_walker diff --git a/modular_skyrat/modules/ashwalkers/code/effects/ash_rituals.dm b/modular_skyrat/modules/ashwalkers/code/effects/ash_rituals.dm index e34a414cf8e..ba1dd931c3a 100644 --- a/modular_skyrat/modules/ashwalkers/code/effects/ash_rituals.dm +++ b/modular_skyrat/modules/ashwalkers/code/effects/ash_rituals.dm @@ -173,7 +173,7 @@ . = ..() var/mob_type = pick( /mob/living/basic/mining/goliath, - /mob/living/simple_animal/hostile/asteroid/hivelord/legion, + /mob/living/basic/mining/legion, /mob/living/basic/mining/brimdemon, /mob/living/basic/mining/watcher, /mob/living/basic/mining/lobstrosity/lava, @@ -373,5 +373,5 @@ find_animal.faction = list(FACTION_ASHWALKER) - find_animal.revive() + find_animal.revive(HEAL_ALL) return TRUE diff --git a/modular_skyrat/modules/assault_operatives/code/equipment_items/guns.dm b/modular_skyrat/modules/assault_operatives/code/equipment_items/guns.dm index 357c25e02f9..430d627d526 100644 --- a/modular_skyrat/modules/assault_operatives/code/equipment_items/guns.dm +++ b/modular_skyrat/modules/assault_operatives/code/equipment_items/guns.dm @@ -238,7 +238,7 @@ possible_types = list(AMMO_TYPE_LETHAL, AMMO_TYPE_RUBBER, AMMO_TYPE_AP) /obj/item/ammo_box/magazine/multi_sprite/assault_ops_sniper/sleepytime - ammo_type = /obj/item/ammo_casing/p50/soporific + ammo_type = /obj/item/ammo_casing/p50/disruptor round_type = AMMO_TYPE_RUBBER /obj/item/ammo_box/magazine/multi_sprite/assault_ops_sniper/penetrator diff --git a/modular_skyrat/modules/bulletrebalance/code/sniper.dm b/modular_skyrat/modules/bulletrebalance/code/sniper.dm deleted file mode 100644 index 632f80251fd..00000000000 --- a/modular_skyrat/modules/bulletrebalance/code/sniper.dm +++ /dev/null @@ -1,22 +0,0 @@ -/obj/projectile/bullet/p50 - name =".416 Stabilis bullet" - speed = 0.2 //This means it's insanely fast, not insanely slow - damage = 110 //You have 135 health, which does not make this an instant crit - paralyze = 0 //Knocks you on your ass hard enough as-is, we won't need the paralyze stat - dismemberment = 30 - armour_penetration = 61 //Bulletproof armor alone will not stop this - wound_bonus = 90 //Theoretically guaranteed wound - -/obj/projectile/bullet/p50/soporific - name = ".416 Stabilis tranquilizer casing" - damage_type = STAMINA - dismemberment = 0 - catastropic_dismemberment = FALSE - object_damage = 0 - -/obj/projectile/bullet/p50/soporific/on_hit(atom/target, blocked = FALSE) - . = ..() - if((blocked != 100) && isliving(target)) - var/mob/living/living_guy = target - living_guy.Sleeping(40 SECONDS) //Yes, its really 40 seconds of sleep, I hope you had your morning coffee. - diff --git a/modular_skyrat/modules/company_imports/code/armament_datums/deforest_medical.dm b/modular_skyrat/modules/company_imports/code/armament_datums/deforest_medical.dm index 3f9b9b73b28..40f8ef775f7 100644 --- a/modular_skyrat/modules/company_imports/code/armament_datums/deforest_medical.dm +++ b/modular_skyrat/modules/company_imports/code/armament_datums/deforest_medical.dm @@ -121,7 +121,7 @@ cost = PAYCHECK_COMMAND /datum/armament_entry/company_import/deforest/equipment/surgical_tools - item_type = /obj/item/storage/backpack/duffelbag/med/surgery + item_type = /obj/item/surgery_tray/full cost = PAYCHECK_COMMAND /datum/armament_entry/company_import/deforest/equipment/advanced_health_analyer diff --git a/modular_skyrat/modules/customization/game/objects/items/plushes.dm b/modular_skyrat/modules/customization/game/objects/items/plushes.dm index d718d409b49..1d2992cf8ef 100644 --- a/modular_skyrat/modules/customization/game/objects/items/plushes.dm +++ b/modular_skyrat/modules/customization/game/objects/items/plushes.dm @@ -467,7 +467,7 @@ gender = FEMALE attack_verb_continuous = list("pats", "hugs", "scolds", "pets") attack_verb_simple = list("pat", "hug", "scold", "pet") - squeak_override = list('sound/effects/mousesqueek.ogg' = 1, 'modular_skyrat/modules/emotes/sound/voice/mothsqueak.ogg' = 1,) + squeak_override = list('sound/creatures/mousesqueek.ogg' = 1, 'modular_skyrat/modules/emotes/sound/voice/mothsqueak.ogg' = 1,) responses = list("Rabbits are prey animals and are therefore constantly aware of their surroundings.", "Things to jump up on (they like to be in high places)", "become a rabbit today!", "Be cunning and full of tricks...", "Subscription confirmed! Thank you for choosing RABBITFACTS +TM+!", "Holland Lops are a breed of rabbit originating in the Netherlands.", "Rabbits may need medication to keep themselves healthy, and that's ok! Make sure to take yours too!", "rabbits really liked this product", "A healthy rabbit diet includes fresh vegetables.", "Rabbits do not hibernate. Their schedules are much too busy.", "the rate of bunnies is measured by RPB (rabbits per bunny)", ) /obj/item/toy/plush/skyrat/chunko/andrew @@ -477,7 +477,7 @@ gender = MALE attack_verb_continuous = list("pats", "hugs", "scolds", "pets") attack_verb_simple = list("pat", "hug", "scold", "pet") - squeak_override = list('sound/effects/mousesqueek.ogg' = 1, 'modular_skyrat/modules/emotes/sound/voice/mothsqueak.ogg' = 1,) + squeak_override = list('sound/creatures/mousesqueek.ogg' = 1, 'modular_skyrat/modules/emotes/sound/voice/mothsqueak.ogg' = 1,) // All lowercase messages are intentional responses = list("bunny who you best pray you never encounter, lest you suffer a fate worse than death.", "this is a bunny!", "I wonder what would happen if you took bunnies, and combined them with rabbits, and merged their properties and characteristics. It's something to think about.", "If you're cold, they're cold. Give them the deed to your house.", "bunny that goes yeah! woo! yeah! woo! yeah! woo! yeah! woo! yeah! woo! yeah!", "the bunnies are beyond my comprehension", "it's a bunny thing, you wouldn't get it", "this bunny has an unfathomable power level", "%pull the string and I'll bink at you...I'm your bunny.", "Bunny (1954)", "the bunny that pulls the strings....", ) diff --git a/modular_skyrat/modules/customization/modules/clothing/masks/gasmask.dm b/modular_skyrat/modules/customization/modules/clothing/masks/gasmask.dm index 9174700e738..47ae6a48e89 100644 --- a/modular_skyrat/modules/customization/modules/clothing/masks/gasmask.dm +++ b/modular_skyrat/modules/customization/modules/clothing/masks/gasmask.dm @@ -94,6 +94,19 @@ greyscale_config_worn_vox = /datum/greyscale_config/respirator/worn/vox greyscale_config_worn_teshari = /datum/greyscale_config/respirator/worn/teshari +/obj/item/clothing/mask/gas/respirator/examine(mob/user) + . = ..() + . += span_notice("You can toggle its ability to muffle your TTS voice with control click.") + +/obj/item/clothing/mask/gas/respirator/CtrlClick(mob/living/user) + if(!isliving(user)) + return + if(user.get_active_held_item() != src) + to_chat(user, span_warning("You must hold the [src] in your hand to do this!")) + return + voice_filter = voice_filter ? null : initial(voice_filter) + to_chat(user, span_notice("Mask voice muffling [voice_filter ? "enabled" : "disabled"].")) + /obj/item/clothing/mask/gas/clown_hat/vox desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask. This one's got an easily accessible feeding port to be more suitable for the Vox crewmembers." icon = 'modular_skyrat/master_files/icons/mob/clothing/species/vox/mask.dmi' diff --git a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm index 64a6c5c1339..746380b59cb 100644 --- a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm +++ b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm @@ -936,7 +936,8 @@ /obj/item/clothing/glasses/welding/steampunk_goggles/attackby(obj/item/attacking_item, mob/living/user, params) if(!istype(attacking_item, /obj/item/clothing/glasses/welding)) - ..() + return ..() + if(welding_upgraded) to_chat(user, span_warning("\The [src] was already upgraded to have welding protection!")) return diff --git a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/hair.dm b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/hair.dm index 172ea352ac2..cbb1565392f 100644 --- a/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/hair.dm +++ b/modular_skyrat/modules/customization/modules/mob/dead/new_player/sprite_accessories/hair.dm @@ -479,6 +479,146 @@ name = "Hairfre" icon_state = "hair_hairfre" +/datum/sprite_accessory/hair/skyrat/bobcut_over_eye_1 + name = "Bobcut over eye 1" + icon_state = "hair_bobcut_over_eye_1" + +/datum/sprite_accessory/hair/skyrat/bobcut_over_eye_2 + name = "Bobcut over eye 2" + icon_state = "hair_bobcut_over_eye_2" + +/datum/sprite_accessory/hair/skyrat/bobcut_over_eye_3 + name = "Bobcut over eye 3" + icon_state = "hair_bobcut_over_eye_3" + +/datum/sprite_accessory/hair/skyrat/bonnie + name = "Bonnie" + icon_state = "hair_bonnie" + +/datum/sprite_accessory/hair/skyrat/bonnie_short + name = "Bonnie short" + icon_state = "hair_bonnie_short" + +/datum/sprite_accessory/hair/skyrat/bonnie_long + name = "Bonnie long" + icon_state = "hair_bonnie_long" + +/datum/sprite_accessory/hair/skyrat/bonnie_2 + name = "Bonnie 2" + icon_state = "hair_bonnie_2" + +/datum/sprite_accessory/hair/skyrat/bonnie_2_long + name = "Bonnie long 2" + icon_state = "hair_bonnie_2_long" + +/datum/sprite_accessory/hair/skyrat/bonie_2_short + name = "Bonnie short 2" + icon_state = "hair_bonnie_2_short" + +/datum/sprite_accessory/hair/skyrat/dawn + name = "Dawn" + icon_state = "hair_dawn" + +/datum/sprite_accessory/hair/skyrat/fluffy + name = "Fluffy" + icon_state = "hair_fluffy" + +/datum/sprite_accessory/hair/skyrat/fluffy_long + name = "Fluffy long" + icon_state = "hair_fluffy_long" + +/datum/sprite_accessory/hair/skyrat/khmuro + name = "Khmuro" + icon_state = "hair_khmuro" + +/datum/sprite_accessory/hair/skyrat/kobeni_1 + name = "Kobeni 1" + icon_state = "hair_kobeni_1" + +/datum/sprite_accessory/hair/skyrat/kobeni_2 + name = "Kobeni 2" + icon_state = "hair_kobeni_2" + +/datum/sprite_accessory/hair/skyrat/low_bun + name = "Low bun" + icon_state = "hair_low_bun" + +/datum/sprite_accessory/hair/skyrat/low_ponytail + name = "Low ponytail" + icon_state = "hair_low_ponytail" + +/datum/sprite_accessory/hair/skyrat/morning + name = "Morning" + icon_state = "hair_morning" + +/datum/sprite_accessory/hair/skyrat/over_ear_1 + name = "Over ear 1" + icon_state = "hair_over_ear_1" + +/datum/sprite_accessory/hair/skyrat/over_ear_2 + name = "Over ear 2" + icon_state = "hair_over_ear_2" + +/datum/sprite_accessory/hair/skyrat/over_eye + name = "Over eye" + icon_state = "hair_over_eye" + +/datum/sprite_accessory/hair/skyrat/ponytail + name = "Fluffy ponytail" + icon_state = "hair_ponytail" + +/datum/sprite_accessory/hair/skyrat/ponytail_short + name = "Short fluffy ponytail" + icon_state = "hair_ponytail_short" + +/datum/sprite_accessory/hair/skyrat/simple + name = "Simple" + icon_state = "hair_simple" + +/datum/sprite_accessory/hair/skyrat/simple_long + name = "Simple long" + icon_state = "hair_simple_long" + +/datum/sprite_accessory/hair/skyrat/simple_short + name = "Simple short" + icon_state = "hair_simple_short" + +/datum/sprite_accessory/hair/skyrat/strict + name = "Strict" + icon_state = "hair_strict" + +/datum/sprite_accessory/hair/skyrat/strict_long + name = "Strict long" + icon_state = "hair_strict_long" + +/datum/sprite_accessory/hair/skyrat/strict_short + name = "Strict short" + icon_state = "hair_strict_short" + +/datum/sprite_accessory/hair/skyrat/thin_ponytail + name = "Thin ponytail" + icon_state = "hair_thin_ponytail" + +/datum/sprite_accessory/hair/skyrat/thin_ponytail_long + name = "Long thin ponytail" + icon_state = "hair_thin_ponytail_long" + +/datum/sprite_accessory/hair/skyrat/twintails_2 + name = "Twintails 2" + icon_state = "hair_twintails_2" + +/datum/sprite_accessory/hair/skyrat/twintails_2_long + name = "Long twintails" + icon_state = "hair_twintails_2_long" + +/datum/sprite_accessory/hair/skyrat/twintails_2_short + name = "Short twintails" + icon_state = "hair_twintails_2_short" + +/datum/sprite_accessory/hair/skyrat/upwards + name = "Upwards" + icon_state = "hair_upwards" + // Facial hair /datum/sprite_accessory/facial_hair/skyrat diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm index 3d0aaf94db5..76ebf34b682 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm @@ -149,7 +149,7 @@ GLOBAL_LIST_EMPTY(customizable_races) var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[species_human.undershirt] if(undershirt) var/mutable_appearance/undershirt_overlay - if(species_human.dna.species.sexes && species_human.gender == FEMALE) + if(species_human.dna.species.sexes && species_human.physique == FEMALE) undershirt_overlay = wear_female_version(undershirt.icon_state, undershirt.icon, BODY_LAYER) else undershirt_overlay = mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER) diff --git a/modular_skyrat/modules/customization/modules/reagents/chemistry/reagents/other_reagents.dm b/modular_skyrat/modules/customization/modules/reagents/chemistry/reagents/other_reagents.dm index fabba52db0f..1c03bbf2ca3 100644 --- a/modular_skyrat/modules/customization/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/modular_skyrat/modules/customization/modules/reagents/chemistry/reagents/other_reagents.dm @@ -70,3 +70,30 @@ else to_chat(M, span_notice("[pick("I feel oddly calm.", "I feel relaxed.", "Mew?")]")) ..() + +#define DERMAGEN_SCAR_FIX_AMOUNT 10 + +/datum/reagent/medicine/dermagen + name = "Dermagen" + description = "Heals scars formed by past physical trauma when applied. Minimum 10u needed, only works when applied topically." + reagent_state = LIQUID + color = "#FFEBEB" + ph = 6 + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + +/datum/reagent/medicine/dermagen/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE) + . = ..() + if(!iscarbon(exposed_mob)) + return + if(!(methods & (PATCH|TOUCH|VAPOR))) + return + var/mob/living/carbon/scarred = exposed_mob + if(scarred.stat == DEAD) + show_message = FALSE + if(show_message) + to_chat(scarred, span_danger("The scars on your body start to fade and disappear.")) + if(reac_volume >= DERMAGEN_SCAR_FIX_AMOUNT) + for(var/i in scarred.all_scars) + qdel(i) + +#undef DERMAGEN_SCAR_FIX_AMOUNT diff --git a/modular_skyrat/modules/customization/modules/reagents/chemistry/recipes/medicine.dm b/modular_skyrat/modules/customization/modules/reagents/chemistry/recipes/medicine.dm index afcfa2da8cd..34b97214bb8 100644 --- a/modular_skyrat/modules/customization/modules/reagents/chemistry/recipes/medicine.dm +++ b/modular_skyrat/modules/customization/modules/reagents/chemistry/recipes/medicine.dm @@ -24,3 +24,8 @@ results = list(/datum/reagent/medicine/taste_suppressor = 3, /datum/reagent/chlorine = 1) // The chlorine dissociated from the sodium to allow for the synthesis of the taste suppressor required_reagents = list(/datum/reagent/consumable/salt = 2, /datum/reagent/sulfur = 1, /datum/reagent/water = 1) required_temp = 300 + +/datum/chemical_reaction/medicine/dermagen + results = list(/datum/reagent/medicine/dermagen = 5) + required_reagents = list(/datum/reagent/consumable/ethanol = 4, /datum/reagent/medicine/c2/synthflesh = 3, /datum/reagent/medicine/mine_salve = 3) + mix_message = "The slurry congeals into a thick cream." diff --git a/modular_skyrat/modules/decay_subsystem/code/nests.dm b/modular_skyrat/modules/decay_subsystem/code/nests.dm index 3a8dad43888..74424371e87 100644 --- a/modular_skyrat/modules/decay_subsystem/code/nests.dm +++ b/modular_skyrat/modules/decay_subsystem/code/nests.dm @@ -200,7 +200,7 @@ desc = "These pulsating eggs are oozing out a puss like substance..." icon_state = "nest_eggs" light_color = LIGHT_COLOR_BRIGHT_YELLOW - monster_types = list(/mob/living/simple_animal/hostile/retaliate/snake) + monster_types = list(/mob/living/basic/snake) max_mobs = 8 spawn_cooldown = 5 SECONDS diff --git a/modular_skyrat/modules/emotes/code/emotes.dm b/modular_skyrat/modules/emotes/code/emotes.dm index 5f41b22751b..16c8ecbcef6 100644 --- a/modular_skyrat/modules/emotes/code/emotes.dm +++ b/modular_skyrat/modules/emotes/code/emotes.dm @@ -143,7 +143,7 @@ message = "squeaks!" emote_type = EMOTE_AUDIBLE vary = TRUE - sound = 'sound/effects/mousesqueek.ogg' + sound = 'sound/creatures/mousesqueek.ogg' /datum/emote/living/merp key = "merp" diff --git a/modular_skyrat/modules/faction/code/outfit.dm b/modular_skyrat/modules/faction/code/outfit.dm index 4728353e4ec..a808f58c05f 100644 --- a/modular_skyrat/modules/faction/code/outfit.dm +++ b/modular_skyrat/modules/faction/code/outfit.dm @@ -43,7 +43,7 @@ back = /obj/item/storage/backpack id = /obj/item/card/id/faction_crew l_pocket = /obj/item/melee/energy/sword - l_hand = /obj/item/storage/backpack/duffelbag/med/surgery + l_hand = /obj/item/surgery_tray/full backpack_contents = list(/obj/item/storage/box/survival/engineer=1, /obj/item/storage/medkit/tactical=1,/obj/item/storage/medkit/regular=1,/obj/item/storage/medkit/toxin=1, /obj/item/ammo_box/magazine/m45=2, /obj/item/gun/ballistic/automatic/pistol/m1911=1,/obj/item/healthanalyzer=1,/obj/item/stack/spacecash/c1000=1) /datum/outfit/faction_tech diff --git a/modular_skyrat/modules/fauna_reagent/fauna_reagent.dm b/modular_skyrat/modules/fauna_reagent/fauna_reagent.dm index cee0e7efab5..796dbef0daf 100644 --- a/modular_skyrat/modules/fauna_reagent/fauna_reagent.dm +++ b/modular_skyrat/modules/fauna_reagent/fauna_reagent.dm @@ -15,14 +15,57 @@ /mob/living/simple_animal/Life(seconds_per_tick, times_fired) . = ..() - if(reagent_health && reagents) - for(var/datum/reagent/reagents_within as anything in reagents.reagent_list) - if(istype(reagents_within, /datum/reagent/toxin)) - var/datum/reagent/toxin/toxin_reagent = reagents_within - var/toxin_damage = round(toxin_reagent.toxpwr) - adjustHealth(toxin_damage + 1) - reagents.remove_reagent(toxin_reagent.type, 0.5) - continue - if(istype(reagents_within, /datum/reagent/medicine)) - adjustHealth(-1) - reagents.remove_reagent(reagents_within.type, 0.5) + + if(!reagent_health) + return + + if(!reagents) + return + + if(stat == DEAD) + return + + for(var/datum/reagent/reagents_within as anything in reagents.reagent_list) + if(istype(reagents_within, /datum/reagent/toxin)) + var/datum/reagent/toxin/toxin_reagent = reagents_within + var/toxin_damage = round(toxin_reagent.toxpwr) + adjustHealth(toxin_damage + 1) + reagents.remove_reagent(toxin_reagent.type, 0.5) + continue + + if(istype(reagents_within, /datum/reagent/medicine)) + adjustHealth(-1) + reagents.remove_reagent(reagents_within.type, 0.5) + +/mob/living/basic + /// whether the simple animal can be healed/damaged through reagents + var/reagent_health = TRUE + +/mob/living/basic/Initialize(mapload) + . = ..() + if(reagent_health) + create_reagents(1000, REAGENT_HOLDER_ALIVE) + +/mob/living/basic/Life(seconds_per_tick, times_fired) + . = ..() + + if(!reagent_health) + return + + if(!reagents) + return + + if(stat == DEAD) + return + + for(var/datum/reagent/reagents_within as anything in reagents.reagent_list) + if(istype(reagents_within, /datum/reagent/toxin)) + var/datum/reagent/toxin/toxin_reagent = reagents_within + var/toxin_damage = round(toxin_reagent.toxpwr) + adjust_health(toxin_damage + 1) + reagents.remove_reagent(toxin_reagent.type, 0.5) + continue + + if(istype(reagents_within, /datum/reagent/medicine)) + adjust_health(-1) + reagents.remove_reagent(reagents_within.type, 0.5) diff --git a/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm b/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm index ea06dc1163c..f1bece74ab4 100644 --- a/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm +++ b/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm @@ -762,6 +762,8 @@ /obj/item/gun/energy/dueling, /obj/item/gun/energy/laser/thermal, /obj/item/gun/ballistic/rifle/boltaction, //fits if you make it an obrez + /obj/item/gun/energy/laser/captain, + /obj/item/gun/energy/e_gun/hos, )) /obj/item/storage/belt/holster/detective @@ -785,6 +787,8 @@ /obj/item/gun/energy/dueling, /obj/item/gun/energy/laser/thermal, /obj/item/gun/ballistic/rifle/boltaction, //fits if you make it an obrez + /obj/item/gun/energy/laser/captain, + /obj/item/gun/energy/e_gun/hos, )) /* diff --git a/modular_skyrat/modules/ices_events/code/ICES_event_config.dm b/modular_skyrat/modules/ices_events/code/ICES_event_config.dm index bd49fc1de17..c65aafe5da5 100644 --- a/modular_skyrat/modules/ices_events/code/ICES_event_config.dm +++ b/modular_skyrat/modules/ices_events/code/ICES_event_config.dm @@ -588,12 +588,6 @@ max_occurrences = 2 weight = VERY_HIGH_EVENT_FREQ -/** - * Wall Fungus - */ -/datum/round_event_control/wall_fungus - weight = MED_EVENT_FREQ - /** * Wisdom Cow * diff --git a/modular_skyrat/modules/mapping/code/lavaland_ruin_code.dm b/modular_skyrat/modules/mapping/code/lavaland_ruin_code.dm index c66faed0810..c2e667004c2 100644 --- a/modular_skyrat/modules/mapping/code/lavaland_ruin_code.dm +++ b/modular_skyrat/modules/mapping/code/lavaland_ruin_code.dm @@ -108,3 +108,15 @@ /obj/item/radio/headset/interdyne/comms keyslot = new /obj/item/encryptionkey/headset_syndicate/interdyne keyslot2 = new /obj/item/encryptionkey/syndicate + +//MOBS + +// hivelords that stand guard where they spawn +/mob/living/basic/mining/hivelord/no_wander + ai_controller = /datum/ai_controller/basic_controller/hivelord/no_wander + +//MOB AI + +// same as a regular hivelord minus the idle walking +/datum/ai_controller/basic_controller/hivelord/no_wander + idle_behavior = null diff --git a/modular_skyrat/modules/medical/code/wounds/medical.dm b/modular_skyrat/modules/medical/code/wounds/medical.dm index 80662956e5f..5a3723fff4b 100644 --- a/modular_skyrat/modules/medical/code/wounds/medical.dm +++ b/modular_skyrat/modules/medical/code/wounds/medical.dm @@ -4,8 +4,6 @@ /obj/item/stack/medical/gauze /// The amount of direct hits our limb can take before we fall off. var/integrity = 2 - /// The bodypart we are attached to. Nullable if we aren't applied to anything. - var/obj/item/bodypart/bodypart /// If we are splinting a limb, this is the overlay prefix we will use. var/splint_prefix = "splint" /// If we are bandaging a limb, this is the overlay prefix we will use. @@ -14,25 +12,16 @@ var/can_splint = TRUE /obj/item/bodypart/apply_gauze(obj/item/stack/gauze) - RegisterSignal(src, COMSIG_BODYPART_GAUZED, PROC_REF(got_gauzed)) - . = ..() - UnregisterSignal(src, COMSIG_BODYPART_GAUZED) + owner?.update_bandage_overlays() -/// Signal handler that allows us to modularly detect if we were applied to a limb or not. -/obj/item/bodypart/proc/got_gauzed(datum/signal_source, obj/item/stack/medical/gauze/new_gauze) - SIGNAL_HANDLER +/obj/item/stack/medical/gauze/Destroy() + var/mob/living/carbon/previously_gauzed = gauzed_bodypart?.owner - if (istype(current_gauze, /obj/item/stack/medical/gauze)) - var/obj/item/stack/medical/gauze/applied_gauze = current_gauze - applied_gauze.set_limb(src) // new_gauze isnt actually the gauze that was applied weirdly + . = ..() -/obj/item/stack/medical/gauze/Destroy() - bodypart?.current_gauze = null - bodypart?.owner?.update_bandage_overlays() - set_limb(null) - return ..() + previously_gauzed?.update_bandage_overlays() /** * rip_off() called when someone rips it off @@ -43,7 +32,7 @@ /obj/item/stack/medical/gauze/proc/rip_off() if (is_pristine()) . = new src.type(null, 1) - bodypart?.owner?.update_bandage_overlays() + qdel(src) /// Returns either [splint_prefix] or [gauze_prefix] depending on if we are splinting or not. Suffixes it with a digitigrade flag if applicable for the limb. @@ -56,8 +45,8 @@ else prefix = gauze_prefix - var/suffix = bodypart.body_zone - if(bodypart.bodytype & BODYTYPE_DIGITIGRADE) + var/suffix = gauzed_bodypart.body_zone + if(gauzed_bodypart.bodytype & BODYTYPE_DIGITIGRADE) suffix += "_digitigrade" return "[prefix]_[suffix]" @@ -69,7 +58,7 @@ if (!can_splint) return FALSE - for (var/datum/wound/iterated_wound as anything in bodypart.wounds) + for (var/datum/wound/iterated_wound as anything in gauzed_bodypart.wounds) if (iterated_wound.wound_flags & SPLINT_OVERLAY) return TRUE @@ -95,35 +84,30 @@ /obj/item/stack/medical/gauze/proc/get_hit() integrity-- if(integrity <= 0) - if(bodypart.owner) - to_chat(bodypart.owner, span_warning("The [name] on your [bodypart.name] tears and falls off!")) + if(gauzed_bodypart.owner) + to_chat(gauzed_bodypart.owner, span_warning("The [name] on your [gauzed_bodypart.name] tears and falls off!")) qdel(src) /obj/item/stack/medical/gauze/Topic(href, href_list) . = ..() if(href_list["remove"]) - if(!bodypart.owner) + if(!gauzed_bodypart.owner) return if(!iscarbon(usr)) return - if(!in_range(usr, bodypart.owner)) + if(!in_range(usr, gauzed_bodypart.owner)) return - var/mob/living/carbon/C = usr - var/self = (C == bodypart.owner) - C.visible_message(span_notice("[C] begins removing [name] from [self ? "[bodypart.owner.p_Their()]" : "[bodypart.owner]'s" ] [bodypart.name]..."), span_notice("You begin to remove [name] from [self ? "your" : "[bodypart.owner]'s"] [bodypart.name]...")) - if(!do_after(C, (self ? SELF_AID_REMOVE_DELAY : OTHER_AID_REMOVE_DELAY), target=bodypart.owner)) + var/mob/living/carbon/carbon_user = usr + var/self = (carbon_user == gauzed_bodypart.owner) + carbon_user.visible_message(span_notice("[carbon_user] begins removing [name] from [self ? "[gauzed_bodypart.owner.p_Their()]" : "[gauzed_bodypart.owner]'s" ] [gauzed_bodypart.name]..."), span_notice("You begin to remove [name] from [self ? "your" : "[gauzed_bodypart.owner]'s"] [gauzed_bodypart.name]...")) + if(!do_after(carbon_user, (self ? SELF_AID_REMOVE_DELAY : OTHER_AID_REMOVE_DELAY), target = gauzed_bodypart.owner)) return if(QDELETED(src)) return - C.visible_message(span_notice("[C] removes [name] from [self ? "[bodypart.owner.p_Their()]" : "[bodypart.owner]'s" ] [bodypart.name]."), span_notice("You remove [name] from [self ? "your" : "[bodypart.owner]'s" ] [bodypart.name].")) + carbon_user.visible_message(span_notice("[carbon_user] removes [name] from [self ? "[gauzed_bodypart.owner.p_Their()]" : "[gauzed_bodypart.owner]'s" ] [gauzed_bodypart.name]."), span_notice("You remove [name] from [self ? "your" : "[gauzed_bodypart.owner]'s" ] [gauzed_bodypart.name].")) var/obj/item/gotten = rip_off() - if(gotten && !C.put_in_hands(gotten)) - gotten.forceMove(get_turf(C)) - -/// Sets bodypart to limb, and then updates owner's bandage overlays. Limb is nullable. -/obj/item/stack/medical/gauze/proc/set_limb(limb) - bodypart = limb - bodypart?.owner?.update_bandage_overlays() + if(gotten && !carbon_user.put_in_hands(gotten)) + gotten.forceMove(get_turf(carbon_user)) /// Returns the name of ourself when used in a "owner is [usage_prefix] by [name]" examine_more situation/ /obj/item/stack/proc/get_gauze_description() diff --git a/modular_skyrat/modules/modular_implants/code/nif_persistence.dm b/modular_skyrat/modules/modular_implants/code/nif_persistence.dm index 1dc272c434e..fd24fd3b579 100644 --- a/modular_skyrat/modules/modular_implants/code/nif_persistence.dm +++ b/modular_skyrat/modules/modular_implants/code/nif_persistence.dm @@ -15,6 +15,8 @@ var/nif_is_calibrated /// How many rewards points does the NIF have stored on it? var/stored_rewards_points + /// A string containing programs that are transfered from one round to the next. + var/persistent_nifsofts /// Saves the NIF data for a individual user. /mob/living/carbon/human/proc/save_nif_data(datum/modular_persistence/persistence, remove_nif = FALSE) @@ -51,14 +53,19 @@ persistence.stored_rewards_points = installed_nif.rewards_points var/datum/component/nif_examine/examine_component = GetComponent(/datum/component/nif_examine) - persistence.nif_examine_text = examine_component?.nif_examine_text + + var/persistent_nifsoft_paths = "" // We need to convert all of the paths in the list into a single string for(var/datum/nifsoft/nifsoft as anything in installed_nif.loaded_nifsofts) - if(!nifsoft.persistence) + if(nifsoft.persistence) + nifsoft.save_persistence_data(persistence) + + if(!nifsoft.able_to_keep || !nifsoft.keep_installed) continue - nifsoft.save_persistence_data(persistence) + persistent_nifsoft_paths += "&[(nifsoft.type)]" + persistence.persistent_nifsofts = persistent_nifsoft_paths /// Loads the NIF data for an individual user. /mob/living/carbon/human/proc/load_nif_data(datum/modular_persistence/persistence) @@ -74,6 +81,16 @@ new_nif.current_theme = persistence.nif_theme new_nif.is_calibrated = persistence.nif_is_calibrated new_nif.rewards_points = persistence.stored_rewards_points + + var/list/persistent_nifsoft_paths = list() + for(var/text as anything in splittext(persistence.persistent_nifsofts, "&")) + var/datum/nifsoft/nifsoft_to_add = text2path(text) + if(!ispath(nifsoft_to_add, /datum/nifsoft) || !initial(nifsoft_to_add.able_to_keep)) + continue + + persistent_nifsoft_paths.Add(nifsoft_to_add) + + new_nif.persistent_nifsofts = persistent_nifsoft_paths.Copy() new_nif.Insert(src) var/datum/component/nif_examine/examine_component = GetComponent(/datum/component/nif_examine) diff --git a/modular_skyrat/modules/modular_implants/code/nif_research.dm b/modular_skyrat/modules/modular_implants/code/nif_research.dm index 7e8e1ca94f8..4e88040cddf 100644 --- a/modular_skyrat/modules/modular_implants/code/nif_research.dm +++ b/modular_skyrat/modules/modular_implants/code/nif_research.dm @@ -28,6 +28,16 @@ category = list(RND_CATEGORY_TOOLS + RND_SUBCATEGORY_EQUIPMENT_MEDICAL) // look, the anesthetic machine's there too departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE +/datum/design/mini_soulcatcher + name = "Poltergeist-Type RSD" + desc = "A miniature version of a Soulcatcher that can be attached to various objects." + id = "mini_soulcatcher" + build_type = PROTOLATHE | AWAY_LATHE + build_path = /obj/item/attachable_soulcatcher + materials = list(/datum/material/glass = SMALL_MATERIAL_AMOUNT * 5, /datum/material/iron = SMALL_MATERIAL_AMOUNT * 5) + category = list(RND_CATEGORY_AI + RND_SUBCATEGORY_AI_MISC) // look, the anesthetic machine's there too + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_SERVICE | DEPARTMENT_BITFLAG_MEDICAL + /datum/design/nifsoft_hud build_type = PROTOLATHE | AWAY_LATHE materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT, /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT, /datum/material/plastic = SHEET_MATERIAL_AMOUNT) diff --git a/modular_skyrat/modules/modular_implants/code/nifs.dm b/modular_skyrat/modules/modular_implants/code/nifs.dm index 69c0a581c35..9dd1af28751 100644 --- a/modular_skyrat/modules/modular_implants/code/nifs.dm +++ b/modular_skyrat/modules/modular_implants/code/nifs.dm @@ -92,6 +92,8 @@ var/list/loaded_nifsofts = list() ///What programs come already installed on the NIF? var/list/preinstalled_nifsofts = list(/datum/nifsoft/soul_poem) + ///What programs do we want to carry between rounds? + var/list/persistent_nifsofts = list() ///This shows up in the NIF settings screen as a way to ICly display lore. var/manufacturer_notes = "There is no data currently avalible for this product." @@ -147,8 +149,8 @@ linked_mob.AddComponent(/datum/component/nif_examine) RegisterSignal(linked_mob, COMSIG_LIVING_DEATH, PROC_REF(damage_on_death)) - if(preinstalled_nifsofts) - send_message("Loading preinstalled NIFSofts, please wait...") + if(preinstalled_nifsofts || persistent_nifsofts) + send_message("Loading preinstalled and stored NIFSofts, please wait...") addtimer(CALLBACK(src, PROC_REF(install_preinstalled_nifsofts)), 3 SECONDS) /obj/item/organ/internal/cyberimp/brain/nif/Remove(mob/living/carbon/organ_owner, special = FALSE) @@ -174,6 +176,10 @@ for(var/datum/nifsoft/preinstalled_nifsoft as anything in preinstalled_nifsofts) new preinstalled_nifsoft(src) + for(var/stored_nifsoft in persistent_nifsofts) + var/datum/nifsoft/new_stored_nifsoft = new stored_nifsoft(src) + new_stored_nifsoft.keep_installed = TRUE + return TRUE /obj/item/organ/internal/cyberimp/brain/nif/process(seconds_per_tick) diff --git a/modular_skyrat/modules/modular_implants/code/nifs_tgui.dm b/modular_skyrat/modules/modular_implants/code/nifs_tgui.dm index 0423e28c830..6da74c6b89f 100644 --- a/modular_skyrat/modules/modular_implants/code/nifs_tgui.dm +++ b/modular_skyrat/modules/modular_implants/code/nifs_tgui.dm @@ -45,6 +45,8 @@ "active_cost" = nifsoft.active_cost, "reference" = REF(nifsoft), "ui_icon" = nifsoft.ui_icon, + "able_to_keep" = nifsoft.able_to_keep, + "keep_installed" = nifsoft.keep_installed, ) data["loaded_nifsofts"] += list(nifsoft_data) @@ -126,3 +128,11 @@ return FALSE activated_nifsoft.activate() + + if("toggle_keeping_nifsoft") + var/datum/nifsoft/nifsoft_to_keep = locate(params["nifsoft_to_keep"]) in loaded_nifsofts + if(!nifsoft_to_keep || !nifsoft_to_keep.able_to_keep) + return FALSE + + nifsoft_to_keep.keep_installed = !nifsoft_to_keep.keep_installed + update_static_data_for_all_viewers() diff --git a/modular_skyrat/modules/modular_implants/code/nifsoft_catalog.dm b/modular_skyrat/modules/modular_implants/code/nifsoft_catalog.dm index aac352bab4c..4cd6beea379 100644 --- a/modular_skyrat/modules/modular_implants/code/nifsoft_catalog.dm +++ b/modular_skyrat/modules/modular_implants/code/nifsoft_catalog.dm @@ -1,10 +1,13 @@ GLOBAL_LIST_INIT(purchasable_nifsofts, list( /datum/nifsoft/hivemind, /datum/nifsoft/summoner, - /datum/nifsoft/shapeshifter, + /datum/nifsoft/action_granter/shapeshifter, /datum/nifsoft/summoner/dorms, /datum/nifsoft/soul_poem, /datum/nifsoft/soulcatcher, + /datum/nifsoft/scryer, + /datum/nifsoft/summoner/book, + /datum/nifsoft/action_granter/hypnosis, )) /datum/computer_file/program/nifsoft_downloader @@ -79,6 +82,7 @@ GLOBAL_LIST_INIT(purchasable_nifsofts, list( "category" = initial(buyable_nifsoft.buying_category), "ui_icon" = initial(buyable_nifsoft.ui_icon), "reference" = buyable_nifsoft, + "keepable" = initial(buyable_nifsoft.able_to_keep), ) var/category = nifsoft_details["category"] if(!(category in product_list)) diff --git a/modular_skyrat/modules/modular_implants/code/nifsofts.dm b/modular_skyrat/modules/modular_implants/code/nifsofts.dm index d7c382cfddb..1bf551866f5 100644 --- a/modular_skyrat/modules/modular_implants/code/nifsofts.dm +++ b/modular_skyrat/modules/modular_implants/code/nifsofts.dm @@ -47,6 +47,10 @@ var/rewards_points_eligible = TRUE ///Does the NIFSoft have anything that is saved cross-round? var/persistence = FALSE + /// Is the NIFSoft something that we want to allow the user to keep? + var/able_to_keep = FALSE + /// Are we keeping the NIFSoft installed between rounds? This is decided by the user + var/keep_installed = FALSE ///Is it a lewd item? var/lewd_nifsoft = FALSE diff --git a/modular_skyrat/modules/modular_implants/code/nifsofts/base_types/action_granter.dm b/modular_skyrat/modules/modular_implants/code/nifsofts/base_types/action_granter.dm new file mode 100644 index 00000000000..05d1012d629 --- /dev/null +++ b/modular_skyrat/modules/modular_implants/code/nifsofts/base_types/action_granter.dm @@ -0,0 +1,26 @@ +/// This type of NIFSoft grans the user an action when active. +/datum/nifsoft/action_granter + active_mode = TRUE + activation_cost = 10 + active_cost = 1 + /// What is the path of the action that we want to grant? + var/action_to_grant = /datum/action/innate + /// What action are we giving the user of the NIFSoft? + var/datum/action/innate/granted_action + +/datum/nifsoft/action_granter/activate() + . = ..() + if(active) + granted_action = new action_to_grant + granted_action.Grant(linked_mob) + return + + if(granted_action) + granted_action.Remove(linked_mob) + +/datum/nifsoft/action_granter/Destroy() + if(granted_action) + QDEL_NULL(granted_action) + return ..() + + diff --git a/modular_skyrat/modules/modular_implants/code/nifsofts/book_summoner.dm b/modular_skyrat/modules/modular_implants/code/nifsofts/book_summoner.dm new file mode 100644 index 00000000000..954a56e9ff9 --- /dev/null +++ b/modular_skyrat/modules/modular_implants/code/nifsofts/book_summoner.dm @@ -0,0 +1,36 @@ +/obj/item/disk/nifsoft_uploader/summoner/book + name = "Grimoire Akasha" + loaded_nifsoft = /datum/nifsoft/summoner/book + +/datum/nifsoft/summoner/book + name = "Grimoire Akasha" + program_desc = "Grimoire Akasha is a fork of the Grimoire Caeruleam NIFSoft that is designed around giving the user access to various educational hardlight books. \ + Due to its educational nature and miniscule size, Grimoire Akasha is typically provided for free at most NIFSoft marketplaces." + summonable_items = list() + purchase_price = 0 // This is a tool intended to help out newer players. + max_summoned_items = 2 + buying_category = NIFSOFT_CATEGORY_INFORMATION + ui_icon = "book" + +/datum/nifsoft/summoner/book/New() + . = ..() + summonable_items += subtypesof(/obj/item/book/manual/wiki) //That's right! all of the manual books! + +/datum/nifsoft/summoner/book/apply_custom_properties(obj/item/book/generated_book) + if(!istype(generated_book)) + return FALSE + + generated_book.cannot_carve = TRUE + return TRUE + +// Need this code here so that we don't have people carving out the summoned books +/obj/item/book + /// Is the parent book unable to be carved? TRUE prevents carving. By default this is unset + var/cannot_carve + +/obj/item/book/try_carve(obj/item/carving_item, mob/living/user, params) + if(cannot_carve) + balloon_alert(user, "unable to be carved!") + return FALSE + + return ..() diff --git a/modular_skyrat/modules/modular_implants/code/nifsofts/hypnosis.dm b/modular_skyrat/modules/modular_implants/code/nifsofts/hypnosis.dm new file mode 100644 index 00000000000..b4f59561872 --- /dev/null +++ b/modular_skyrat/modules/modular_implants/code/nifsofts/hypnosis.dm @@ -0,0 +1,62 @@ +/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.))" + buying_category = NIFSOFT_CATEGORY_FUN + lewd_nifsoft = TRUE + purchase_price = 150 + able_to_keep = TRUE + active_cost = 0.1 + ui_icon = "eye" + action_to_grant = /datum/action/innate/nif_hypnotize + +/datum/action/innate/nif_hypnotize + name = "Hypnotize" + background_icon = 'modular_skyrat/master_files/icons/mob/actions/action_backgrounds.dmi' + background_icon_state = "android" + button_icon = 'modular_skyrat/master_files/icons/mob/actions/actions_nif.dmi' + button_icon_state = "hypnotize" + +/datum/action/innate/nif_hypnotize/Activate() + var/mob/living/carbon/human/user = owner + if(!istype(user)) + return FALSE + + var/mob/living/carbon/human/target_human = user.pulling + if(!istype(target_human) || user.grab_state < GRAB_AGGRESSIVE) + to_chat(user, span_warning("You need to aggressively grab someone to hypnotize them.")) + return FALSE + + if(!target_human.client?.prefs?.read_preference(/datum/preference/toggle/erp/sex_toy)) + to_chat(user, span_warning("[target_human] doesn't want to be hypnotized.")) + return FALSE + + to_chat(user, span_notice("You begin to place [target_human] into a hypnotic trance.")) + + if(!do_after(user, 12 SECONDS, target_human)) + return FALSE + + var/choice = tgui_alert(target_human, "Do you believe in hypnosis? (This will allow [user] to issue hypnotic suggestions.)", "Hypnosis", list("Yes", "No")) + if(choice != "Yes") + to_chat(user, span_warning("[target_human]'s attention breaks despite your efforts. They clearly don't seem interested!")) + to_chat(target_human, span_warning("Your attention breaks as you realize that you don't want to listen to [user]'s suggestions.")) + return FALSE + + user.visible_message(span_purple("[target_human] falls into a deep, hypnotic slumber right at the snap of your fingers."), span_purple("You suddenly fall limp at the snap of [user]'s fingers.")) + user.emote("snap") + target_human.SetSleeping(60 SECONDS) + target_human.log_message("[target_human] was placed into a hypnotic sleep by [user].", LOG_GAME) + + var/secondary_choice = tgui_alert(user, "Would you like to give [target_human] a hypnotic suggestion or release them?", "Hypnosis", list("Suggestion", "Release")) + while(secondary_choice == "Suggestion" && target_human.IsSleeping()) + if(!in_range(user, target_human)) + to_chat(user, span_warning("You must be in whisper range to [target_human] in order to give hypnotic suggestions.")) + target_human.SetSleeping(0) + return FALSE + + var/input_text = tgui_input_text(user, "What would you like to suggest?", "Hypnotic Suggestion") + to_chat(user, span_purple("You whisper into [target_human]'s ears in a soothing voice.")) + to_chat(target_human, span_hypnophrase("[input_text]")) + secondary_choice = tgui_alert(user, "Would you like to give [target_human] an additional hypnotic suggestion or release them?", "Hypnosis", list("Suggestion", "Release")) + + user.visible_message(span_purple("You wake up from your deep, hypnotic slumber. The suggestions from [user] now settled into your mind."), span_purple("[target_human] wakes up from their slumber.")) + target_human.SetSleeping(0) diff --git a/modular_skyrat/modules/modular_implants/code/nifsofts/prop_summoner.dm b/modular_skyrat/modules/modular_implants/code/nifsofts/prop_summoner.dm index 5cd8a0443cb..aab1cc52b7a 100644 --- a/modular_skyrat/modules/modular_implants/code/nifsofts/prop_summoner.dm +++ b/modular_skyrat/modules/modular_implants/code/nifsofts/prop_summoner.dm @@ -16,6 +16,7 @@ activation_cost = 100 // Around 1/10th the energy of a standard NIF buying_category = NIFSOFT_CATEGORY_FUN ui_icon = "book-open" + able_to_keep = TRUE // These NIFSofts are mostly for comsetic/fun reasons anyways. /// Does the resulting object have a holographic like filter appiled to it? var/holographic_filter = TRUE @@ -88,9 +89,17 @@ refund_activation_cost() return FALSE + apply_custom_properties(new_item) summoned_items += new_item new_item.AddComponent(/datum/component/summoned_item, holographic_filter) +/// This proc is called while an item is being summoned, use this to modifiy aspects of the item that aren't modified by the component. +/datum/nifsoft/summoner/proc/apply_custom_properties(obj/item/target_item) + if(!target_item) + return FALSE + + return TRUE + /datum/nifsoft/summoner/Destroy() QDEL_LIST(summoned_items) return ..() diff --git a/modular_skyrat/modules/modular_implants/code/nifsofts/scryer.dm b/modular_skyrat/modules/modular_implants/code/nifsofts/scryer.dm new file mode 100644 index 00000000000..3cf689624e0 --- /dev/null +++ b/modular_skyrat/modules/modular_implants/code/nifsofts/scryer.dm @@ -0,0 +1,117 @@ +/obj/item/disk/nifsoft_uploader/scryer + name = "NIFSoft Scryer Uploader Disk" + loaded_nifsoft = /datum/nifsoft/scryer + +/datum/nifsoft/scryer + name = "NIFLink Holocaller" + program_desc = "This ubiquitous NIFSoft adds Scryer functionality similar to MODSuits to the user's NIF; allowing for real-time communication through AR hologlass screens from a hardlight projector sat around the wearer's neck" + active_mode = TRUE + active_cost = 1 + activation_cost = 20 + purchase_price = 200 + buying_category = NIFSOFT_CATEGORY_UTILITY + ui_icon = "video" + /// What is the scryer currently associated with the NIFSoft? + var/obj/item/clothing/neck/link_scryer/loaded/nifsoft/linked_scryer + +/datum/nifsoft/scryer/New() + . = ..() + var/obj/item/organ/internal/cyberimp/brain/nif/parent_resolved = parent_nif.resolve() + if(!istype(parent_resolved)) + stack_trace("[src] ([REF(src)]) tried to create a linked scryer but it had no parent_nif!") + if(!linked_scryer) + stack_trace("[src] ([REF(src)]) created with no linked scryer!") + linked_scryer = new (parent_resolved) + linked_scryer.parent_nifsoft = WEAKREF(src) + +/datum/nifsoft/scryer/Destroy() + if(!QDELETED(linked_scryer)) + QDEL_NULL(linked_scryer) + + return ..() + +/datum/nifsoft/scryer/activate() + . = ..() + if(. == FALSE) + return FALSE + + if(!active) + if(linked_scryer) + var/parent_resolved = parent_nif.resolve() + if(parent_resolved) + return linked_mob.transferItemToLoc(linked_scryer, parent_resolved, TRUE) + return FALSE + + if(linked_mob.handcuffed) + linked_mob.balloon_alert(linked_mob, "handcuffed") + activate() + return FALSE + + if(!linked_mob.equip_to_slot_if_possible(linked_scryer, ITEM_SLOT_NECK)) //This sends out a message to the mob if it can't be put on. + activate() + return FALSE + + return TRUE + +/obj/item/clothing/neck/link_scryer + /// Do we have custom controls? This is only affects the text shown when examining + var/custom_examine_controls = FALSE + +/obj/item/clothing/neck/link_scryer/loaded/nifsoft + name = "\improper NIFLink Holocaller" + desc = "A nanomachine construct working as a modified version of the MODlink scryer, conjured using a NIF; functionally the same, but able to carry out holocalls in a more portable format." + custom_examine_controls = TRUE + /// A weakref of the parent NIFSoft that the scryer belongs to. + var/datum/weakref/parent_nifsoft + +/obj/item/clothing/neck/link_scryer/loaded/nifsoft/Initialize(mapload) + . = ..() + if(cell) + QDEL_NULL(cell) + + cell = new /obj/item/stock_parts/cell/infinite/nif_cell(src) + +/obj/item/clothing/neck/link_scryer/loaded/nifsoft/Destroy() + if(parent_nifsoft) + var/datum/nifsoft/scryer/resolved_nifsoft = parent_nifsoft.resolve() + if(!QDELETED(resolved_nifsoft)) + resolved_nifsoft.linked_scryer = null + + return ..() + +/obj/item/clothing/neck/link_scryer/loaded/nifsoft/examine(mob/user) + . = ..() + . += span_notice("The MODlink ID is [mod_link.id], frequency is [mod_link.frequency || "unset"]. Right-click with a multitool to copy/imprint the frequency.") + . += span_notice("Right-click with an empty hand to change the name.") + +/obj/item/clothing/neck/link_scryer/loaded/nifsoft/equipped(mob/living/user, slot) + . = ..() + if(slot & ITEM_SLOT_NECK) + return TRUE + + var/datum/nifsoft/scryer/scryer_nifsoft = parent_nifsoft.resolve() + if(!istype(scryer_nifsoft)) + return FALSE + + scryer_nifsoft.activate() //If it's not on the neck, it shouldn't be active. + return TRUE + +/obj/item/clothing/neck/link_scryer/loaded/nifsoft/screwdriver_act(mob/living/user, obj/item/tool) + balloon_alert(user, "cell non-removable!") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/item/clothing/neck/link_scryer/loaded/nifsoft/attack_hand_secondary(mob/user, list/modifiers) + var/new_label = reject_bad_text(tgui_input_text(user, "Change the visible name", "Set Name", label, MAX_NAME_LEN)) + if(!new_label) + balloon_alert(user, "invalid name!") + return + label = new_label + balloon_alert(user, "name set!") + update_name() + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/// This cell is only meant for use in items temporarily created by a NIF. Do not let players extract this from devices. +/obj/item/stock_parts/cell/infinite/nif_cell + name = "Nanite Cell" + desc = "If you see this, please make an issue on GitHub." + diff --git a/modular_skyrat/modules/modular_implants/code/nifsofts/shapeshifter.dm b/modular_skyrat/modules/modular_implants/code/nifsofts/shapeshifter.dm index bbbf7dc2c07..dfa70dc78eb 100644 --- a/modular_skyrat/modules/modular_implants/code/nifsofts/shapeshifter.dm +++ b/modular_skyrat/modules/modular_implants/code/nifsofts/shapeshifter.dm @@ -1,35 +1,15 @@ /obj/item/disk/nifsoft_uploader/shapeshifter name = "Polymorph" - loaded_nifsoft = /datum/nifsoft/shapeshifter + loaded_nifsoft = /datum/nifsoft/action_granter -/datum/nifsoft/shapeshifter +/datum/nifsoft/action_granter/shapeshifter name = "Polymorph" program_desc = "This program is a large-scale refitting of the nanomachine channels running over the skin of a NIF user. This allows the nanites to reach under the skin and even into the very bone structure of the host; including incorporation of mimetic materials and femto-level manipulation devices all for the purpose of allowing the user to, essentially, shapeshift on a low level. However, despite the incredible complexity behind these processes, there are still limits on the range of 'forms' a user can take. Mass can neither be created nor destroyed, after all, and you can only distribute and rearrange it in so many ways across a functioning humanoid body; meaning, the user cannot adopt forms too far out of their 'true' one." - activation_cost = 10 - active_mode = TRUE - active_cost = 1 compatible_nifs = list(/obj/item/organ/internal/cyberimp/brain/nif/standard) purchase_price = 350 buying_category = NIFSOFT_CATEGORY_COSMETIC ui_icon = "paintbrush" - - ///The NIF version of the Shapeshifter Ability - var/datum/action/innate/alter_form/nif/shapeshifter - -/datum/nifsoft/shapeshifter/activate() - . = ..() - if(active) - shapeshifter = new - shapeshifter.Grant(linked_mob) - return - - if(shapeshifter) - shapeshifter.Remove(linked_mob) - -/datum/nifsoft/shapeshifter/Destroy() - . = ..() - if(shapeshifter) - QDEL_NULL(shapeshifter) + action_to_grant = /datum/action/innate/alter_form/nif /// The NIF version of alter form. This lacks the ability to change body color. diff --git a/modular_skyrat/modules/modular_implants/code/nifsofts/soulcatcher.dm b/modular_skyrat/modules/modular_implants/code/nifsofts/soulcatcher.dm index 9236a49f963..019ff546edc 100644 --- a/modular_skyrat/modules/modular_implants/code/nifsofts/soulcatcher.dm +++ b/modular_skyrat/modules/modular_implants/code/nifsofts/soulcatcher.dm @@ -7,6 +7,7 @@ program_desc = "The 'Soulcatcher' coreware is a near-complete upgrade of the nanomachine systems in a NIF, meant for one purpose; supposedly, channeling the dead. This upgrade, in truth, functions as a Resonance Simulation Device; an RSD for short, an instrument capable of hosting someone's consciousness, context or otherwise. 'Resonance', a term for the specific pattern of neural activity that gives way to someone's consciousness, was discovered in the early 2500s by researchers Yun-Seo Jin and Kamakshi Padmanabhan, coining what is now called 'Jin-Padmanabhan Resonance,' or 'JP/Soul Resonance.' This 'Resonance' gives off a sophont's consciousness, their sense of continuation, and their 'I am me.' This Resonance can vary in structure and 'strength' from person to person, and even change over someone's life. When the brain of a sophont undergoes death and stops neural activity, then Resonance dissipates entirely and lingering consciousness becomes essentially an echo, rapidly fading over time.\n\nThe earliest RSDs were massive machines, drawing incredible power and utilizing bleeding-edge, clunky software to 'play' someone's Resonance at 1:1 accuracy with their original brain. However, complications arose that are still being studied. Resonance is replicable and can be re-created artificially; however, like trying to duplicate genetic code, the capture needs to be extremely accurate, and rapidly put into place. Instruments such as RSDs are capable of picking up on lingering consciousness after the end of Resonance, and resuming it through artificial neural activity can give it strength to continue once more. RSDs such as Soulcatchers can only work at such a distance, otherwise running the risk of the Resonance essentially corrupting due to poor signal.\n\nIt is currently impossible to run Resonance in two places at once, because the same Resonance over two places experiences interference; like noise canceling headphones. Slimes and other gestalt consciousnesses can modulate their harmonics to a degree, bearing a partial disconnect and bringing themselves into constructive interference with similar harmonic signatures. A deepscan of the person's brain is necessary to give their consciousness 'context;' running their Resonance and capturing their consciousness alone results in a person with their same original intelligence, but zero memories or identity. These scans rapidly become outdated due to the growth of the brain, and it is prohibitively complex to store them in their entirety.\n\nThe first portable RSD, or Soulcatcher, was developed by the Spider Clan. These were initially designed for the captive interrogation of a person's consciousness without having to worry about the struggling of their body, and for dead or aging members of the mysterious group of orbital shinobi to be able to guide field operatives. These Soulcatchers are the main instrument to play Resonance, but recent advances in medical science have been leading to more. Occasionally, it is known for unusual sources of 'wild' Resonance, called Phantoms, to end up inside of the nearest Soulcatcher, a key finding its own lock; with a wide array of theories as to how these come into existence. Much as how some people intentionally become stable Engrams to achieve digital immortality, such as the witches of the Altspace Coven, it is possible for others to forcibly enter a Soulcatcher and act as a sort of Phantom by hacking their way in." purchase_price = 150 //RP tool persistence = TRUE + able_to_keep = TRUE ui_icon = "ghost" /// What is the linked soulcatcher datum used by this NIFSoft? diff --git a/modular_skyrat/modules/modular_implants/code/soulcatcher/attachable_soulcatcher.dm b/modular_skyrat/modules/modular_implants/code/soulcatcher/attachable_soulcatcher.dm new file mode 100644 index 00000000000..cd84179e083 --- /dev/null +++ b/modular_skyrat/modules/modular_implants/code/soulcatcher/attachable_soulcatcher.dm @@ -0,0 +1,111 @@ +/datum/component/soulcatcher/small_device + max_souls = 1 + +/datum/component/soulcatcher/attachable_soulcatcher + max_souls = 1 + communicate_as_parent = TRUE + removable = TRUE + +/datum/component/soulcatcher/attachable_soulcatcher/New() + . = ..() + var/obj/item/parent_item = parent + if(!istype(parent_item)) + return COMPONENT_INCOMPATIBLE + + name = parent_item.name + var/datum/soulcatcher_room/first_room = soulcatcher_rooms[1] + first_room.name = parent_item.name + first_room.room_description = parent_item.desc + + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + RegisterSignal(parent, COMSIG_CLICK_CTRL_SHIFT, PROC_REF(bring_up_ui)) + RegisterSignal(parent, COMSIG_PREQDELETED, PROC_REF(remove_self)) + +/// Adds text to the examine text of the parent item, explaining that the item can be used to enable the use of NIFSoft HUDs +/datum/component/soulcatcher/attachable_soulcatcher/proc/on_examine(datum/source, mob/user, list/examine_text) + SIGNAL_HANDLER + examine_text += span_cyan("[source] has a soulcatcher attached to it, Ctrl+Shift+Click to use it.") + +/datum/component/soulcatcher/attachable_soulcatcher/proc/bring_up_ui(datum/source, mob/user) + SIGNAL_HANDLER + INVOKE_ASYNC(src, PROC_REF(ui_interact), user) + +/datum/component/soulcatcher/attachable_soulcatcher/Destroy(force) + UnregisterSignal(parent, COMSIG_ATOM_EXAMINE) + UnregisterSignal(parent, COMSIG_CLICK_CTRL_SHIFT) + UnregisterSignal(parent, COMSIG_PREQDELETED) + return ..() + +/datum/component/soulcatcher/attachable_soulcatcher/remove_self() + var/obj/item/parent_item = parent + var/turf/drop_turf = get_turf(parent_item) + var/obj/item/attachable_soulcatcher/dropped_item = new (drop_turf) + + var/datum/component/soulcatcher/dropped_soulcatcher = dropped_item.GetComponent(/datum/component/soulcatcher) + var/datum/soulcatcher_room/target_room = dropped_soulcatcher.soulcatcher_rooms[1] + var/list/current_souls = get_current_souls() + + if(current_souls) // If we have souls inside of here, they should be transferred to the new object + for(var/mob/living/soulcatcher_soul/soul as anything in current_souls) + var/datum/soulcatcher_room/current_room = soul.current_room.resolve() + if(istype(current_room)) + current_room.transfer_soul(soul, target_room) + + return ..() + +/obj/item/attachable_soulcatcher + name = "Poltergeist-Type RSD" + desc = "This device, a polymorphic nanomachine net, wraps around objects of most sizes and allows them to function as a container for Resonance. The soul in question within the vessel is imbued much like it would be in a body or a normal Soulcatcher, perceiving the world and even speaking out of their new form. The nanomachine net of the device allows for the consciousness to somewhat manipulate their container, but any large-scale movement is out of the question." + icon = 'modular_skyrat/modules/modular_implants/icons/obj/devices.dmi' + icon_state = "attachable-soulcatcher" + w_class = WEIGHT_CLASS_SMALL + /// Do we want to destory the item once it is attached to an item? + var/destroy_on_use = TRUE + /// What items do we want to prevent the viewer from attaching this to? + var/list/blacklisted_items = list( + /obj/item/organ, + /obj/item/mmi, + /obj/item/pai_card, + /obj/item/aicard, + /obj/item/card, + /obj/item/radio, + /obj/item/disk/nuclear, // Woah there + ) + /// What soulcathcer component is currnetly linked to this object? + var/datum/component/soulcatcher/small_device/linked_soulcatcher + +/obj/item/attachable_soulcatcher/Initialize(mapload) + . = ..() + linked_soulcatcher = AddComponent(/datum/component/soulcatcher/small_device) + linked_soulcatcher.name = name + +/obj/item/attachable_soulcatcher/attack_self(mob/user, modifiers) + linked_soulcatcher.ui_interact(user) + +/obj/item/attachable_soulcatcher/afterattack(obj/item/target_item, mob/user, proximity_flag, click_parameters) + . = ..() + if(!proximity_flag || !istype(target_item)) + return FALSE + + if(target_item.GetComponent(/datum/component/soulcatcher)) + balloon_alert(user, "already attached!") + return FALSE + + if(is_type_in_list(target_item, blacklisted_items)) + balloon_alert(user, "incompatible!") + return FALSE + + var/datum/component/soulcatcher/new_soulcatcher = target_item.AddComponent(/datum/component/soulcatcher/attachable_soulcatcher) + playsound(target_item.loc, 'sound/weapons/circsawhit.ogg', 50, vary = TRUE) + + var/datum/soulcatcher_room/target_room = new_soulcatcher.soulcatcher_rooms[1] + var/list/current_souls = linked_soulcatcher.get_current_souls() + if(current_souls) + for(var/mob/living/soulcatcher_soul/soul as anything in current_souls) + var/datum/soulcatcher_room/current_room = soul.current_room.resolve() + if(istype(current_room)) + current_room.transfer_soul(soul, target_room) + current_room.transfer_soul(soul, target_room) + + if(destroy_on_use) + qdel(src) diff --git a/modular_skyrat/modules/modular_implants/code/soulcatcher/handheld_soulcatcher.dm b/modular_skyrat/modules/modular_implants/code/soulcatcher/handheld_soulcatcher.dm index 842aee82d59..767f396057e 100644 --- a/modular_skyrat/modules/modular_implants/code/soulcatcher/handheld_soulcatcher.dm +++ b/modular_skyrat/modules/modular_implants/code/soulcatcher/handheld_soulcatcher.dm @@ -111,4 +111,52 @@ return TRUE +/obj/item/handheld_soulcatcher/attack_secondary(mob/living/carbon/human/target_mob, mob/living/user, params) + if(!istype(target_mob)) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + var/obj/item/organ/internal/brain/target_brain = target_mob.get_organ_slot(ORGAN_SLOT_BRAIN) + if(!istype(target_brain)) + to_chat(user, span_warning("[target_mob] lacks a brain!")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if(!HAS_TRAIT(target_brain, TRAIT_RSD_COMPATIBLE)) + to_chat(user, span_warning("[target_mob]'s brain isn't compatible.")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if(target_mob.mind || target_mob.ckey || GetComponent(/datum/component/previous_body)) + to_chat(user, span_warning("[target_mob] is not able to receive a soul")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + var/list/soul_list = list() + for(var/datum/soulcatcher_room/room as anything in linked_soulcatcher.soulcatcher_rooms) + for(var/mob/living/soulcatcher_soul/soul as anything in room.current_souls) + if(!soul.round_participant || soul.body_scan_needed) + continue + + soul_list += soul + + if(!length(soul_list)) + to_chat(user, span_warning("There are no souls that can be transferred to [target_mob].")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + var/mob/living/soulcatcher_soul/chosen_soul = tgui_input_list(user, "Choose a soul to transfer into the body", name, soul_list) + if(!chosen_soul) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if(chosen_soul.previous_body) + var/mob/living/old_body = chosen_soul.previous_body.resolve() + if(!old_body) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + SEND_SIGNAL(old_body, COMSIG_SOULCATCHER_CHECK_SOUL, FALSE) + + chosen_soul.mind.transfer_to(target_mob, TRUE) + playsound(src, 'modular_skyrat/modules/modular_implants/sounds/default_good.ogg', 50, FALSE, ignore_walls = FALSE) + visible_message(span_notice("[src] beeps: Body transfer complete.")) + log_admin("[src] was used by [user] to transfer [chosen_soul]'s soulcatcher soul to [target_mob].") + + qdel(chosen_soul) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + #undef RSD_ATTEMPT_COOLDOWN diff --git a/modular_skyrat/modules/modular_implants/code/soulcatcher/soulcatcher_component.dm b/modular_skyrat/modules/modular_implants/code/soulcatcher/soulcatcher_component.dm index 97158ba5d91..03512b2c205 100644 --- a/modular_skyrat/modules/modular_implants/code/soulcatcher/soulcatcher_component.dm +++ b/modular_skyrat/modules/modular_implants/code/soulcatcher/soulcatcher_component.dm @@ -23,6 +23,12 @@ GLOBAL_LIST_EMPTY(soulcatchers) var/ghost_joinable = TRUE /// Do we want to ask the user permission before the ghost joins? var/require_approval = TRUE + /// What is the max number of people we can keep in this soulcatcher? If this is set to `FALSE` we don't have a limit + var/max_souls = FALSE + /// Are are the souls inside able to emote/speak as the parent? + var/communicate_as_parent = FALSE + /// Is the soulcatcher removable from the parent object? + var/removable = FALSE /datum/component/soulcatcher/New() . = ..() @@ -136,6 +142,32 @@ GLOBAL_LIST_EMPTY(soulcatchers) return TRUE +/// Returns a list containing all of the souls currently present within a soulcatcher. +/datum/component/soulcatcher/proc/get_current_souls() + var/list/current_souls = list() + for(var/datum/soulcatcher_room/room as anything in soulcatcher_rooms) + for(var/mob/living/soulcatcher_soul as anything in room.current_souls) + current_souls += soulcatcher_soul + + return current_souls + +/// Checks the total number of souls present and compares it with `max_souls` returns `TRUE` if there is room (or no limit), otherwise returns `FALSE` +/datum/component/soulcatcher/proc/check_for_vacancy() + if(!max_souls) + return TRUE + + if(length(get_current_souls()) >= max_souls) + return FALSE + + return TRUE + +/// Attempts to remove the soulcatcher from the attached object +/datum/component/soulcatcher/proc/remove_self() + if(!removable) + return FALSE + + qdel(src) + /** * Soulcatcher Room * @@ -266,10 +298,6 @@ GLOBAL_LIST_EMPTY(soulcatchers) if(!message_to_send) //Why say nothing? return FALSE - var/sender_name = "" - if(message_sender) - sender_name = "[message_sender] " - var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/chat) var/tag = sheet.icon_tag("nif-soulcatcher") var/soulcatcher_icon = "" @@ -277,6 +305,33 @@ GLOBAL_LIST_EMPTY(soulcatchers) if(tag) soulcatcher_icon = tag + var/mob/living/soulcatcher_soul/soul_sender = message_sender + if(istype(soul_sender) && soul_sender.communicating_externally) + var/master_resolved = master_soulcatcher.resolve() + if(!master_resolved) + return FALSE + var/datum/component/soulcatcher/parent_soulcatcher = master_resolved + var/obj/item/parent_object = parent_soulcatcher.parent + if(!istype(parent_object)) + return FALSE + + var/temp_name = parent_object.name + parent_object.name = "[parent_object.name] [soulcatcher_icon]" + + if(emote) + parent_object.manual_emote(html_decode(message_to_send)) + log_emote("[soul_sender] in [name] soulcatcher room emoted: [message_to_send], as an external object") + else + parent_object.say(html_decode(message_to_send)) + log_say("[soul_sender] in [name] soulcatcher room said: [message_to_send], as an external object") + + parent_object.name = temp_name + return TRUE + + var/sender_name = "" + if(message_sender) + sender_name = "[message_sender] " + var/first_room_name_word = splittext(name, " ") var/message = "" var/owner_message = "" @@ -334,7 +389,7 @@ GLOBAL_LIST_EMPTY(soulcatchers) var/list/joinable_soulcatchers = list() for(var/datum/component/soulcatcher/soulcatcher in GLOB.soulcatchers) - if(!soulcatcher.ghost_joinable || !isobj(soulcatcher.parent)) + if(!soulcatcher.ghost_joinable || !isobj(soulcatcher.parent) || !soulcatcher.check_for_vacancy()) continue var/obj/item/soulcatcher_parent = soulcatcher.parent @@ -360,6 +415,7 @@ GLOBAL_LIST_EMPTY(soulcatchers) var/datum/soulcatcher_room/room_to_join if(length(rooms_to_join) < 1) + to_chat(src, span_warning("There no rooms that you can join.")) return FALSE if(length(rooms_to_join) == 1) diff --git a/modular_skyrat/modules/modular_implants/code/soulcatcher/soulcatcher_mob.dm b/modular_skyrat/modules/modular_implants/code/soulcatcher/soulcatcher_mob.dm index fefaf69c25e..8ae004b9667 100644 --- a/modular_skyrat/modules/modular_implants/code/soulcatcher/soulcatcher_mob.dm +++ b/modular_skyrat/modules/modular_implants/code/soulcatcher/soulcatcher_mob.dm @@ -23,6 +23,12 @@ var/able_to_speak = TRUE /// Is the soul able to change their own name? var/able_to_rename = TRUE + /// Is the soul able to speak as the object it is inside? + var/able_to_speak_as_container = TRUE + /// Is the soul able to emote as the object it is inside? + var/able_to_emote_as_container = TRUE + /// Are emote's and Say's done through the container the mob is in? + var/communicating_externally = FALSE /// Is the soul able to leave the soulcatcher? var/able_to_leave = TRUE @@ -110,7 +116,7 @@ if(!message || message == "") return - if(!able_to_speak) + if((!able_to_speak && !communicating_externally) || (!able_to_speak_as_container && communicating_externally)) to_chat(src, span_warning("You are unable to speak!")) return FALSE @@ -126,7 +132,7 @@ if(!message) return FALSE - if(!able_to_emote) + if((!able_to_emote && !communicating_externally) || (!able_to_emote_as_container && communicating_externally)) to_chat(src, span_warning("You are unable to emote!")) return FALSE diff --git a/modular_skyrat/modules/modular_implants/code/soulcatcher/soulcatcher_tgui.dm b/modular_skyrat/modules/modular_implants/code/soulcatcher/soulcatcher_tgui.dm index b59cee1f7ad..0c1d11c272e 100644 --- a/modular_skyrat/modules/modular_implants/code/soulcatcher/soulcatcher_tgui.dm +++ b/modular_skyrat/modules/modular_implants/code/soulcatcher/soulcatcher_tgui.dm @@ -13,6 +13,10 @@ data["ghost_joinable"] = ghost_joinable data["require_approval"] = require_approval + data["communicate_as_parent"] = communicate_as_parent + data["current_soul_count"] = length(get_current_souls()) + data["max_souls"] = max_souls + data["removable"] = removable data["current_rooms"] = list() for(var/datum/soulcatcher_room/room in soulcatcher_rooms) @@ -41,6 +45,8 @@ "able_to_rename" = soul.able_to_rename, "ooc_notes" = soul.ooc_notes, "scan_needed" = soul.body_scan_needed, + "able_to_speak_as_container" = soul.able_to_speak_as_container, + "able_to_emote_as_container" = soul.able_to_emote_as_container, ) room_data["souls"] += list(soul_list) @@ -147,7 +153,7 @@ continue var/datum/component/soulcatcher/soulcatcher_component = held_item.GetComponent(/datum/component/soulcatcher) - if(!soulcatcher_component) + if(!soulcatcher_component || !soulcatcher_component.check_for_vacancy()) continue for(var/datum/soulcatcher_room/room in soulcatcher_component.soulcatcher_rooms) @@ -191,6 +197,14 @@ return TRUE + if("toggle_soul_external_communication") + if(params["communication_type"] == "emote") + target_soul.able_to_emote_as_container = !target_soul.able_to_emote_as_container + else + target_soul.able_to_speak_as_container = !target_soul.able_to_speak_as_container + + return TRUE + if("toggle_soul_renaming") target_soul.able_to_rename = !target_soul.able_to_rename return TRUE @@ -224,6 +238,13 @@ target_room.send_message(message_to_send, message_sender, emote) return TRUE + if("delete_self") + if(tgui_alert(usr, "Are you sure you want to detach the soulcatcher?", parent, list("Yes", "No")) != "Yes") + return FALSE + + remove_self() + return TRUE + /datum/component/soulcatcher_user/New() . = ..() var/mob/living/soulcatcher_soul/parent_soul = parent @@ -259,6 +280,9 @@ "able_to_emote" = user_soul.able_to_emote, "able_to_speak" = user_soul.able_to_speak, "able_to_rename" = user_soul.able_to_rename, + "able_to_speak_as_container" = user_soul.able_to_speak_as_container, + "able_to_emote_as_container" = user_soul.able_to_emote_as_container, + "communicating_externally" = user_soul.communicating_externally, "ooc_notes" = user_soul.ooc_notes, "scan_needed" = user_soul.body_scan_needed, ) @@ -272,6 +296,9 @@ "owner" = current_room.outside_voice, ) + var/datum/component/soulcatcher/master_soulcatcher = current_room.master_soulcatcher.resolve() + data["communicate_as_parent"] = master_soulcatcher.communicate_as_parent + for(var/mob/living/soulcatcher_soul/soul in current_room.current_souls) if(soul == user_soul) continue @@ -310,3 +337,6 @@ user_soul.reset_name() + if("toggle_external_communication") + user_soul.communicating_externally = !user_soul.communicating_externally + return TRUE diff --git a/modular_skyrat/modules/modular_implants/icons/obj/devices.dmi b/modular_skyrat/modules/modular_implants/icons/obj/devices.dmi index d0a3f736fa6..401441f95de 100644 Binary files a/modular_skyrat/modules/modular_implants/icons/obj/devices.dmi and b/modular_skyrat/modules/modular_implants/icons/obj/devices.dmi differ diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm index 81cd35398b0..6a8f8a37c58 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm @@ -27,11 +27,14 @@ actions_types = list( /datum/action/item_action/toggle_breathcontrol, /datum/action/item_action/mask_inhale, + /datum/action/item_action/toggle_gag, ) var/list/moans = list("Mmmph...", "Hmmphh", "Mmmfhg", "Gmmmh...") // Phrases to be said when the player attempts to talk when speech modification / voicebox is enabled. var/list/moans_alt = list("Mhgm...", "Hmmmp!...", "Gmmmhp!") // Power probability phrases to be said when talking. var/moans_alt_probability = 5 // Probability for alternative sounds to play. var/temp_check = TRUE //Used to check if user unconsious to prevent choking him until he wakes up + /// Does the gasmask impede the user's ability to talk? + var/speech_disabled w_class = WEIGHT_CLASS_SMALL modifies_speech = TRUE flags_cover = MASKCOVERSMOUTH @@ -53,6 +56,9 @@ update_icon() /obj/item/clothing/mask/gas/bdsm_mask/handle_speech(datum/source, list/speech_args) + if(speech_disabled) + return + speech_args[SPEECH_MESSAGE] = pick((prob(moans_alt_probability) && LAZYLEN(moans_alt)) ? moans_alt : moans) play_lewd_sound(loc, pick('modular_skyrat/modules/modular_items/lewd_items/sounds/under_moan_f1.ogg', 'modular_skyrat/modules/modular_items/lewd_items/sounds/under_moan_f2.ogg', @@ -164,6 +170,15 @@ if(istype(mask)) mask.check() +/datum/action/item_action/toggle_gag + name = "Toggle gag" + desc = "Toggles whether or not the wearer is able to speak." + +/datum/action/item_action/toggle_gag/Trigger(trigger_flags) + var/obj/item/clothing/mask/gas/bdsm_mask/mask = target + if(istype(mask)) + mask.check_gag() + /datum/action/item_action/mask_inhale name = "Inhale oxygen" desc = "You must inhale oxygen!" @@ -236,6 +251,19 @@ else STOP_PROCESSING(SSobj, src) +/obj/item/clothing/mask/gas/bdsm_mask/proc/check_gag(user) + var/mob/living/carbon/affected_carbon = user + if(src == affected_carbon.wear_mask) + to_chat(user, span_notice("You can't reach the gag switch!")) + else + toggle_gag(affected_carbon) + +/obj/item/clothing/mask/gas/bdsm_mask/proc/toggle_gag(user) + speech_disabled = !speech_disabled + to_chat(user, span_notice("You [speech_disabled ? "disable" : "enable"] the gag on the mask.")) + update_mob_action_buttonss() + update_icon() + // Mask choke processor /obj/item/clothing/mask/gas/bdsm_mask/process(seconds_per_tick) var/mob/living/affected_mob = loc diff --git a/modular_skyrat/modules/modular_vending/code/games.dm b/modular_skyrat/modules/modular_vending/code/games.dm index cbc169a99ff..99edcdb796c 100644 --- a/modular_skyrat/modules/modular_vending/code/games.dm +++ b/modular_skyrat/modules/modular_vending/code/games.dm @@ -13,6 +13,7 @@ "products" = list( /obj/item/hairbrush = 3, /obj/item/clothing/mask/holocigarette = 5, + /obj/item/attachable_soulcatcher = 5, ), ) ) diff --git a/modular_skyrat/modules/novaya_ert/code/surplus_weapons.dm b/modular_skyrat/modules/novaya_ert/code/surplus_weapons.dm index 5e40743aa8e..bcc8b49c26d 100644 --- a/modular_skyrat/modules/novaya_ert/code/surplus_weapons.dm +++ b/modular_skyrat/modules/novaya_ert/code/surplus_weapons.dm @@ -59,7 +59,7 @@ weak_against_armour = TRUE /obj/projectile/beam/laser/plasma_glob/on_hit(atom/target, blocked) - if(istype(target, /obj/structure/blob) || istype(target, /mob/living/simple_animal/hostile/blob)) + if(istype(target, /obj/structure/blob) || HAS_TRAIT(target, TRAIT_BLOB_ALLY)) damage = damage * 0.75 return ..() diff --git a/modular_skyrat/modules/player_ranks/code/subsystem/player_ranks.dm b/modular_skyrat/modules/player_ranks/code/subsystem/player_ranks.dm index 264d9f8bedc..6e724e44dbc 100644 --- a/modular_skyrat/modules/player_ranks/code/subsystem/player_ranks.dm +++ b/modular_skyrat/modules/player_ranks/code/subsystem/player_ranks.dm @@ -254,21 +254,37 @@ SUBSYSTEM_DEF(player_ranks) * or in the legacy system. * * Arguments: - * * admin - The admin making the rank change. + * * admin - The admin making the rank change. Can be a /client or a /datum/admins. * * ckey - The ckey of the player you want to now possess that player rank. * * rank_title - The title of the group you want to add the ckey to. */ -/datum/controller/subsystem/player_ranks/proc/add_player_to_group(client/admin, ckey, rank_title) +/datum/controller/subsystem/player_ranks/proc/add_player_to_group(admin, ckey, rank_title) if(IsAdminAdvancedProcCall()) return FALSE if(!ckey || !admin || !rank_title) + stack_trace("Missing either ckey ([ckey || "*NULL*"]), admin ([admin || "*NULL*"]) or rank_title ([rank_title || "*NULL*"]) in add_player_to_group()! Fix this ASAP!") return FALSE - if(!check_rights_for(admin, R_PERMISSIONS)) - to_chat(admin, span_warning("You do not possess the permissions to do this.")) + var/is_admin_client = istype(admin, /client) + var/client/admin_client = is_admin_client ? admin : null + // If it's not a client, then it should be an admins datum. + var/datum/admins/admin_holder = null + if(is_admin_client) + admin_holder = admin_client?.holder + else if(istype(admin, /datum/admins)) + admin_holder = admin + + if(!admin_holder) + return FALSE + + if(!admin_holder.check_for_rights(R_PERMISSIONS)) + if(is_admin_client) + to_chat(admin, span_warning("You do not possess the permissions to do this.")) + return FALSE + rank_title = lowertext(rank_title) var/datum/player_rank_controller/controller = get_controller_for_group(rank_title) @@ -282,14 +298,16 @@ SUBSYSTEM_DEF(player_ranks) var/already_in_config = controller.get_ckeys_for_legacy_save() if(already_in_config[ckey]) - to_chat(admin, span_warning("\"[ckey]\" is already a [rank_title]!")) + if(is_admin_client) + to_chat(admin, span_warning("\"[ckey]\" is already a [rank_title]!")) + return FALSE if(controller.should_use_legacy_system()) controller.add_player_legacy(ckey) return TRUE - return add_player_rank_sql(controller, ckey, admin.ckey) + return add_player_rank_sql(controller, ckey, admin_holder.target) /** @@ -325,19 +343,34 @@ SUBSYSTEM_DEF(player_ranks) * or in the legacy system. * * Arguments: - * * admin - The admin making the rank change. + * * admin - The admin making the rank change. Can be a /client or a /datum/admins. * * ckey - The ckey of the player you want to no longer possess that player rank. * * rank_title - The title of the group you want to remove the ckey from. */ -/datum/controller/subsystem/player_ranks/proc/remove_player_from_group(client/admin, ckey, rank_title) +/datum/controller/subsystem/player_ranks/proc/remove_player_from_group(admin, ckey, rank_title) if(IsAdminAdvancedProcCall()) return FALSE if(!ckey || !admin || !rank_title) + stack_trace("Missing either ckey ([ckey || "*NULL*"]), admin ([admin || "*NULL*"]) or rank_title ([rank_title || "*NULL*"]) in remove_player_from_group()! Fix this ASAP!") return FALSE - if(!check_rights_for(admin, R_PERMISSIONS)) - to_chat(admin, span_warning("You do not possess the permissions to do this.")) + var/is_admin_client = istype(admin, /client) + var/client/admin_client = is_admin_client ? admin : null + // If it's not a client, then it should be an admins datum. + var/datum/admins/admin_holder = null + if(is_admin_client) + admin_holder = admin_client?.holder + else if(istype(admin, /datum/admins)) + admin_holder = admin + + if(!admin_holder) + return FALSE + + if(!admin_holder.check_for_rights(R_PERMISSIONS)) + if(is_admin_client) + to_chat(admin, span_warning("You do not possess the permissions to do this.")) + return FALSE rank_title = lowertext(rank_title) @@ -345,22 +378,16 @@ SUBSYSTEM_DEF(player_ranks) var/datum/player_rank_controller/controller = get_controller_for_group(rank_title) if(!controller) - stack_trace("Invalid player rank \"[rank_title]\" supplied in add_player_to_group()!") + stack_trace("Invalid player rank \"[rank_title]\" supplied in remove_player_from_group()!") return FALSE ckey = ckey(ckey) - var/already_in_config = controller.get_ckeys_for_legacy_save() - - if(!already_in_config[ckey]) - to_chat(admin, span_warning("\"[ckey]\" is already not a [rank_title]!")) - return FALSE - if(controller.should_use_legacy_system()) controller.remove_player_legacy(ckey) return TRUE - return remove_player_rank_sql(controller, ckey, admin.ckey) + return remove_player_rank_sql(controller, ckey, admin_holder.target) /** diff --git a/modular_skyrat/modules/player_ranks/code/world_topic.dm b/modular_skyrat/modules/player_ranks/code/world_topic.dm new file mode 100644 index 00000000000..086373fd33f --- /dev/null +++ b/modular_skyrat/modules/player_ranks/code/world_topic.dm @@ -0,0 +1,67 @@ + +/datum/world_topic/set_player_rank + keyword = "set_player_rank" + require_comms_key = TRUE + +/datum/world_topic/set_player_rank/Run(list/input) + . = list() + + var/sender_discord_id = input["sender_discord_id"] + + if(!sender_discord_id) + .["success"] = FALSE + .["message"] = "Invalid sender Discord ID, this should not be happening! Report this immediately!" + return + + var/target_ckey = ckey(input["target_ckey"]) + + if(!target_ckey) + .["success"] = FALSE + .["message"] = "Invalid target ckey provided." + return + + var/sender_ckey = ckey(SSdiscord.lookup_ckey(sender_discord_id)) + + if(!sender_ckey) + .["success"] = FALSE + .["message"] = "No ckey was found to be attached to the provided Discord account ID, **[sender_discord_id]**. Please verify your Discord account following the instructions of the in-game verb before trying this command again." + return + + var/datum/admins/linked_admin_holder = GLOB.admin_datums[sender_ckey] || GLOB.deadmins[sender_ckey] + + if(!linked_admin_holder) + .["success"] = FALSE + .["message"] = "No valid admin datum was found associated with the ckey associated to your Discord account." + return + + if(!linked_admin_holder.check_for_rights(R_PERMISSIONS)) + .["success"] = FALSE + .["message"] = "You do not possess the permissions to execute this command." + return + + var/target_rank = input["target_rank"] + + if(!target_rank) + .["success"] = FALSE + .["message"] = "Invalid target rank provided." + return + + target_rank = capitalize(target_rank) + + var/desired_rank_status = !!text2num(input["desired_rank_status"]) + + if(desired_rank_status) + var/result = SSplayer_ranks.add_player_to_group(linked_admin_holder, target_ckey, target_rank) + + .["success"] = !!result + .["message"] = result ? "**[linked_admin_holder.target]** successfully added **[target_rank]** status to **[target_ckey]**." : "**[linked_admin_holder.target]** was unable to add **[target_rank]** status to **[target_ckey]**. Please verify that you entered their ckey correctly and that they did not already possess that status before trying again. Use the in-game verb to get more information if you keep on receiving this error." + message_admins(replacetext(.["message"], "*", "")) + return + + else + var/result = SSplayer_ranks.remove_player_from_group(linked_admin_holder, target_ckey, target_rank) + + .["success"] = !!result + .["message"] = result ? "**[linked_admin_holder.target]** successfully removed **[target_rank]** status from **[target_ckey]**." : "**[linked_admin_holder.target]** was unable to remove **[target_rank]** status from **[target_ckey]**. Please verify that you entered their ckey correctly and that they did possess that status before trying again. Use the in-game verb to get more information if you keep on receiving this error." + message_admins(replacetext(.["message"], "*", "")) + return diff --git a/modular_skyrat/modules/primitive_catgirls/code/spawner.dm b/modular_skyrat/modules/primitive_catgirls/code/spawner.dm index 8cb3f3234fe..5cbe1d682c0 100644 --- a/modular_skyrat/modules/primitive_catgirls/code/spawner.dm +++ b/modular_skyrat/modules/primitive_catgirls/code/spawner.dm @@ -66,8 +66,23 @@ /datum/team/primitive_catgirls name = "Icewalkers" + member_name = "Icewalker" show_roundend_report = FALSE +/datum/team/primitive_catgirls/roundend_report() + var/list/report = list() + + report += span_header("An Ice Walker Tribe inhabited the wastes...

") + if(length(members)) + report += "The [member_name]s were:" + report += printplayerlist(members) + else + report += "But none of its members woke up!" + + return "
[report.Join("
")]
" + +// Antagonist datum + /datum/antagonist/primitive_catgirl name = "\improper Icewalker" job_rank = ROLE_LAVALAND // If you're ashwalker banned you should also not be playing this, other way around as well diff --git a/modular_skyrat/modules/primitive_catgirls/code/species.dm b/modular_skyrat/modules/primitive_catgirls/code/species.dm index 7bcaec865dd..586c7b22900 100644 --- a/modular_skyrat/modules/primitive_catgirls/code/species.dm +++ b/modular_skyrat/modules/primitive_catgirls/code/species.dm @@ -21,6 +21,7 @@ mutanttongue = /obj/item/organ/internal/tongue/cat/primitive species_language_holder = /datum/language_holder/primitive_felinid + language_prefs_whitelist = list(/datum/language/primitive_catgirl) bodytemp_normal = 270 // If a normal human gets hugged by one its gonna feel cold bodytemp_heat_damage_limit = 283 // To them normal station atmos would be sweltering diff --git a/modular_skyrat/modules/resleeving/code/research/resleeving_research.dm b/modular_skyrat/modules/resleeving/code/research/resleeving_research.dm new file mode 100644 index 00000000000..4dcd00cc73e --- /dev/null +++ b/modular_skyrat/modules/resleeving/code/research/resleeving_research.dm @@ -0,0 +1,14 @@ +/datum/design/rsd_interface + name = "RSD Phylactery" + desc = "A brain interface that allows for transfer of Resonance from a handheld RSD, such as the Evoker model." + id = "rsd_interface" + build_type = PROTOLATHE | AWAY_LATHE + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE + category = list(RND_CATEGORY_EQUIPMENT) + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 0.5, + /datum/material/gold = SHEET_MATERIAL_AMOUNT, + /datum/material/silver = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/rsd_interface + diff --git a/modular_skyrat/modules/resleeving/code/rsd_interface.dm b/modular_skyrat/modules/resleeving/code/rsd_interface.dm new file mode 100644 index 00000000000..106bb11ea38 --- /dev/null +++ b/modular_skyrat/modules/resleeving/code/rsd_interface.dm @@ -0,0 +1,44 @@ +/obj/item/rsd_interface + name = "RSD Phylactery" + desc = "A small device inserted, typically, into inert brains. As Resonance cannot persist in what's referred to as a 'vacuum', RSDs--much like the brains and CPUs they emulate--employ cerebral white noise as a foundation for Resonance to persist in otherwise dead-quiet containers.." + icon = 'modular_skyrat/modules/aesthetics/implanter/implanter.dmi' + icon_state = "implanter1" + inhand_icon_state = "syringe_0" + lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' + +/// Attempts to use the item on the target brain. +/obj/item/rsd_interface/afterattack(obj/item/organ/internal/brain/target_brain, mob/user, proximity_flag, click_parameters) + . = ..() + if(!proximity_flag || !istype(target_brain)) + return FALSE + + if(HAS_TRAIT(target_brain, TRAIT_NIFSOFT_HUD_GRANTER)) + balloon_alert("already upgraded!") + return FALSE + + user.visible_message(span_notice("[user] upgrades [target_brain] with [src]."), span_notice("You upgrade [target_brain] to be RSD compatible.")) + target_brain.AddElement(/datum/element/rsd_interface) + playsound(target_brain.loc, 'sound/weapons/circsawhit.ogg', 50, vary = TRUE) + + qdel(src) + +/datum/element/rsd_interface/Attach(datum/target) + . = ..() + if(!istype(target, /obj/item/organ/internal/brain)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + ADD_TRAIT(target, TRAIT_RSD_COMPATIBLE, INNATE_TRAIT) + +/// Adds text to the examine text of the parent item, explaining that the item can be used to enable the use of NIFSoft HUDs +/datum/element/rsd_interface/proc/on_examine(datum/source, mob/user, list/examine_text) + SIGNAL_HANDLER + examine_text += span_cyan("Souls can be transferred to [source], assuming it is inert.") + +/datum/element/rsd_interface/Detach(datum/target) + UnregisterSignal(target, COMSIG_ATOM_EXAMINE) + REMOVE_TRAIT(target, TRAIT_RSD_COMPATIBLE, INNATE_TRAIT) + + return ..() + diff --git a/modular_skyrat/modules/wall_fungus/code/wall_fungus_component.dm b/modular_skyrat/modules/wall_fungus/code/wall_fungus_component.dm deleted file mode 100644 index 9c66677aaed..00000000000 --- a/modular_skyrat/modules/wall_fungus/code/wall_fungus_component.dm +++ /dev/null @@ -1,159 +0,0 @@ -#define FUNGUS_STAGE_ONE 1 -#define FUNGUS_STAGE_TWO 2 -#define FUNGUS_STAGE_THREE 3 -#define FUNGUS_STAGE_FOUR 4 -#define FUNGUS_STAGE_MAX 5 - -/** - * A wall eating mushroom. - * - * This mushroom spreads to walls and eats em up! It can be removed with a welder. If left unchecked it will eat the whole wall. - */ -/datum/component/wall_fungus - /// How far has the fungus progressed on the affected wall? Percentage. - var/progression_percent = 0 - /// How many percent do we increase each subsystem fire? - var/progression_step_amount = 0.5 - /// What stage are we at? - var/progression_stage = FUNGUS_STAGE_ONE - /// Our overlay icon file - var/overlay_icon_file = 'modular_skyrat/modules/wall_fungus/icons/wall_fungus_overlay.dmi' - /// How likely are we to spread to another wall? - var/spread_chance = 1 - /// How far can we spread? - var/spread_distance = 3 // Tiles - /// How likely are we to drop a shroom upon destruction? - var/drop_chance = 30 - -/datum/component/wall_fungus/Initialize(override_progression_step_amount, override_spread_chance, override_spread_distance, override_drop_chance) - if(!iswallturf(parent)) - return COMPONENT_INCOMPATIBLE - - // This stuff enables badminery. - if(override_progression_step_amount) - progression_step_amount = override_progression_step_amount - if(override_spread_chance) - spread_chance = override_progression_step_amount - if(override_spread_distance) - spread_distance = override_spread_distance - if(override_drop_chance) - drop_chance = override_drop_chance - - var/turf/closed/wall/parent_wall = parent - - RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(apply_fungus_overlay)) // We need to do this here so that the wall shows the infection immediately. - - parent_wall.update_icon(UPDATE_OVERLAYS) - - START_PROCESSING(SSobj, src) - -/datum/component/wall_fungus/RegisterWithParent() - RegisterSignal(parent, COMSIG_ATOM_SECONDARY_TOOL_ACT(TOOL_WELDER), PROC_REF(secondary_tool_act)) - RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(examine)) - RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(on_attack_hand)) - -/datum/component/wall_fungus/Destroy(force, silent) - var/turf/closed/wall/parent_wall = parent - STOP_PROCESSING(SSobj, src) - UnregisterSignal(parent, list(COMSIG_ATOM_SECONDARY_TOOL_ACT(TOOL_WELDER), COMSIG_ATOM_EXAMINE, COMSIG_ATOM_UPDATE_OVERLAYS)) - parent_wall.update_icon(UPDATE_OVERLAYS) - return ..() - -/datum/component/wall_fungus/process(seconds_per_tick) - var/turf/closed/wall/parent_wall = parent - if(prob(spread_chance * seconds_per_tick)) - spread_to_nearby_wall() - - if(progression_stage > FUNGUS_STAGE_MAX) - collapse_parent_structure() - return - - progression_percent += progression_step_amount * seconds_per_tick - - if(progression_percent >= 100) - progression_percent = 0 - progression_stage++ - spread_to_nearby_wall() - parent_wall.update_icon(UPDATE_OVERLAYS) - -/datum/component/wall_fungus/proc/on_attack_hand(datum/source, mob/living/user) - SIGNAL_HANDLER - - if(progression_stage < FUNGUS_STAGE_THREE) - return - - collapse_parent_structure() - - -/// We kill the wall once we have progressed far enough. -/datum/component/wall_fungus/proc/collapse_parent_structure() - var/turf/closed/wall/parent_wall = parent - STOP_PROCESSING(SSobj, src) - parent_wall.balloon_alert_to_viewers("collapses!") - parent_wall.dismantle_wall() - qdel(src) - -/datum/component/wall_fungus/proc/spread_to_nearby_wall() - var/turf/closed/wall/parent_wall = parent - var/list/walls_to_pick_from = list() - for(var/turf/closed/wall/iterating_wall in RANGE_TURFS(3, parent_wall)) - if(iterating_wall.GetComponent(/datum/component/wall_fungus)) - continue - - walls_to_pick_from += iterating_wall - - if(!length(walls_to_pick_from)) - return // sad times - - var/turf/closed/wall/picked_wall = pick(walls_to_pick_from) - - picked_wall.AddComponent(/datum/component/wall_fungus, progression_step_amount, spread_chance, spread_distance, drop_chance) - -/// Gives people an idea of how badly the wall is infected. -/datum/component/wall_fungus/proc/examine(datum/source, mob/user, list/examine_list) - SIGNAL_HANDLER - var/turf/closed/wall/parent_wall = parent - switch(progression_stage) - if(FUNGUS_STAGE_ONE) - examine_list += span_green("[parent_wall] is infected with some kind of fungus!") - if(FUNGUS_STAGE_TWO) - examine_list += span_green("[parent_wall] is infected with some kind of fungus, its structure weakened!") - if(FUNGUS_STAGE_THREE) - examine_list += span_green("[parent_wall] is infected with some kind of fungus, its structure seriously weakened!") - if(FUNGUS_STAGE_THREE) - examine_list += span_green("[parent_wall] is infected with some kind of fungus, its falling apart!") - examine_list += span_green("Perhaps you could burn it off?") - -/datum/component/wall_fungus/proc/apply_fungus_overlay(atom/parent_atom, list/overlays) - SIGNAL_HANDLER - overlays += mutable_appearance(overlay_icon_file, "fungus_stage_[progression_stage]") - -/datum/component/wall_fungus/proc/secondary_tool_act(atom/source, mob/user, obj/item/item) - SIGNAL_HANDLER - INVOKE_ASYNC(src, PROC_REF(handle_tool_use), source, user, item) - return COMPONENT_BLOCK_TOOL_ATTACK - -/// Handles removal of the fungus from a wall. -/datum/component/wall_fungus/proc/handle_tool_use(atom/source, mob/user, obj/item/item) - var/turf/closed/wall/parent_wall = parent - switch(item.tool_behaviour) - if(TOOL_WELDER) - if(!item.tool_start_check(user, 1)) - return - - user.balloon_alert(user, "burning off fungus...") - - if(!item.use_tool(source, user, (1 * progression_stage) SECONDS, 1, volume = 100)) - return - - user.balloon_alert(user, "burned off fungus") - if(prob(drop_chance)) - new /obj/item/food/grown/mushroom/wall(parent_wall) - qdel(src) - - -#undef FUNGUS_STAGE_ONE -#undef FUNGUS_STAGE_TWO -#undef FUNGUS_STAGE_THREE -#undef FUNGUS_STAGE_FOUR -#undef FUNGUS_STAGE_MAX diff --git a/modular_skyrat/modules/wall_fungus/code/wall_fungus_event.dm b/modular_skyrat/modules/wall_fungus/code/wall_fungus_event.dm deleted file mode 100644 index 564b9a9424e..00000000000 --- a/modular_skyrat/modules/wall_fungus/code/wall_fungus_event.dm +++ /dev/null @@ -1,29 +0,0 @@ -/datum/round_event_control/wall_fungus - name = "Wall Fungus Outbreak" - typepath = /datum/round_event/wall_fungus - category = EVENT_CATEGORY_ENGINEERING - max_occurrences = 2 - earliest_start = 30 MINUTES - description = "A wall fungus will infest a random wall on the station, eating away at it. If left unchecked, it will spread to other walls and eventually destroy the station." - -/datum/round_event/wall_fungus/announce(fake) - priority_announce("Harmful fungi detected on the station, station structures may be contaminated. Crew are advised to provide immediate response in [get_area(starting_wall)].", "Harmful Fungi", ANNOUNCER_FUNGI) - -/datum/round_event/wall_fungus - announce_when = 180 EVENT_SECONDS - announce_chance = 100 - fakeable = FALSE - var/turf/closed/wall/starting_wall - -/datum/round_event/wall_fungus/start() - var/list/possible_start_walls = list() - var/starting_area = get_area(pick(GLOB.generic_maintenance_landmarks)) - - for(var/turf/closed/wall/iterating_wall in starting_area) - possible_start_walls += iterating_wall - - starting_wall = pick(possible_start_walls) - - starting_wall.AddComponent(/datum/component/wall_fungus) - - notify_ghosts("[starting_wall] has been infested with wall eating mushrooms!!", source = starting_wall, action = NOTIFY_JUMP, header = "Fungus Amongus!") diff --git a/modular_skyrat/modules/wall_fungus/code/wall_mushroom.dm b/modular_skyrat/modules/wall_fungus/code/wall_mushroom.dm deleted file mode 100644 index 71d99c164c6..00000000000 --- a/modular_skyrat/modules/wall_fungus/code/wall_mushroom.dm +++ /dev/null @@ -1,53 +0,0 @@ -// WALL EATING FUNGUS!!!! -/obj/item/seeds/wall_mushroom - name = "pack of wall destroying mycelium" - desc = "This mycelium grows into something devastating." - icon = 'modular_skyrat/master_files/icons/obj/hydroponics/seeds.dmi' - icon_state = "seed-wallmushroom" - species = "angel" - plantname = "Wall Mushroom" - product = /obj/item/food/grown/mushroom/wall - lifespan = 50 - endurance = 35 - maturation = 12 - production = 5 - yield = 2 - potency = 35 - growthstages = 3 - genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism) - growing_icon = 'modular_skyrat/master_files/icons/obj/hydroponics/growing.dmi' - icon_grow = "wallmushroom-grow" - icon_dead = "wallmushroom-dead" - reagents_add = list(/datum/reagent/drug/mushroomhallucinogen = 0.04, /datum/reagent/toxin/amatoxin = 0.1, /datum/reagent/consumable/nutriment = 0.1) - rarity = 30 - graft_gene = /datum/plant_gene/trait/plant_type/fungal_metabolism - -/obj/item/food/grown/mushroom/wall - seed = /obj/item/seeds/wall_mushroom - name = "wall mushroom" - desc = "Wallosia Virosa: A wall eating mushroom!" - icon = 'modular_skyrat/master_files/icons/obj/hydroponics/harvest.dmi' - icon_state = "wallmushroom" - wine_power = 60 - - - -/obj/item/food/grown/mushroom/wall/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(!iswallturf(target)) - return ..() - var/turf/closed/wall/target_wall = target - if(target_wall.GetComponent(/datum/component/wall_fungus)) - target_wall.balloon_alert(user, "already infested!") - return ..() - target_wall.balloon_alert(user, "planting...") - if(do_after(user, 5 SECONDS, target_wall)) - target_wall.AddComponent(/datum/component/wall_fungus) - target_wall.balloon_alert(user, "planted!") - user.log_message("planted [name] on [target_wall.name].", LOG_ATTACK) - qdel(src) - return - return ..() - - - - diff --git a/modular_skyrat/modules/wall_fungus/icons/wall_fungus_overlay.dmi b/modular_skyrat/modules/wall_fungus/icons/wall_fungus_overlay.dmi deleted file mode 100644 index 822d7ea9b29..00000000000 Binary files a/modular_skyrat/modules/wall_fungus/icons/wall_fungus_overlay.dmi and /dev/null differ diff --git a/sound/attributions.txt b/sound/attributions.txt index 09ac2bd5642..3ae6c797dd3 100644 --- a/sound/attributions.txt +++ b/sound/attributions.txt @@ -99,3 +99,9 @@ https://freesound.org/people/FunWithSound/sounds/456965/ beeps_jingle.ogg is adapted from Eponn's "Achievement happy Beeps Jingle", which is public domain (CC 0): https://freesound.org/people/Eponn/sounds/619838/ + +boing.ogg is adapted from reelworldstudio's "Cartoon Boing", which is public domain (CC 0): +https://freesound.org/people/reelworldstudio/sounds/161122/ + +arcade_jump.ogg is adapted from se2001's "8-Bit Jump 3", which is public domain (CC 0): +hhttps://freesound.org/people/se2001/sounds/528568/ diff --git a/sound/creatures/attribution.txt b/sound/creatures/attribution.txt index 1d2d543aa15..06d8361868c 100644 --- a/sound/creatures/attribution.txt +++ b/sound/creatures/attribution.txt @@ -1,8 +1,14 @@ -cow.ogg sound adapted from Benboncan on Freesound +cow.ogg sound adapted from Benboncan on Freesound https://freesound.org/people/Benboncan/sounds/58277/ pig1.ogg and pig2.ogg adapted from Jofae on Freesound https://freesound.org/people/Jofae/sounds/352698/ sheep1, sheep2, and sheep3.ogg adapted from milkotz on Freesound -https://freesound.org/people/milkotz/sounds/618865/ \ No newline at end of file +https://freesound.org/people/milkotz/sounds/618865/ + +snake_hissing1.ogg adapted from schreibsel on Freesound (CC 0) +https://freesound.org/people/schreibsel/sounds/540162/ + +snake_hissing2.ogg adapted from xoiziox on Freesound (CC 0) +https://freesound.org/people/xoiziox/sounds/553374/ diff --git a/sound/creatures/bagawk.ogg b/sound/creatures/bagawk.ogg new file mode 100644 index 00000000000..bfdce2da489 Binary files /dev/null and b/sound/creatures/bagawk.ogg differ diff --git a/sound/creatures/chick_peep.ogg b/sound/creatures/chick_peep.ogg new file mode 100644 index 00000000000..1e84d1d765f Binary files /dev/null and b/sound/creatures/chick_peep.ogg differ diff --git a/sound/creatures/chitter.ogg b/sound/creatures/chitter.ogg new file mode 100644 index 00000000000..5b2a1443886 Binary files /dev/null and b/sound/creatures/chitter.ogg differ diff --git a/sound/creatures/claw_click.ogg b/sound/creatures/claw_click.ogg new file mode 100644 index 00000000000..965b4c3fa9f Binary files /dev/null and b/sound/creatures/claw_click.ogg differ diff --git a/sound/creatures/clucks.ogg b/sound/creatures/clucks.ogg new file mode 100644 index 00000000000..176f46f866f Binary files /dev/null and b/sound/creatures/clucks.ogg differ diff --git a/sound/effects/mousesqueek.ogg b/sound/creatures/mousesqueek.ogg similarity index 100% rename from sound/effects/mousesqueek.ogg rename to sound/creatures/mousesqueek.ogg diff --git a/sound/creatures/pony/snort.ogg b/sound/creatures/pony/snort.ogg index b023ddcf47c..0ea56ad957d 100644 Binary files a/sound/creatures/pony/snort.ogg and b/sound/creatures/pony/snort.ogg differ diff --git a/sound/creatures/snake_hissing1.ogg b/sound/creatures/snake_hissing1.ogg new file mode 100644 index 00000000000..52a37d764c4 Binary files /dev/null and b/sound/creatures/snake_hissing1.ogg differ diff --git a/sound/creatures/snake_hissing2.ogg b/sound/creatures/snake_hissing2.ogg new file mode 100644 index 00000000000..bd11b7fb5f0 Binary files /dev/null and b/sound/creatures/snake_hissing2.ogg differ diff --git a/sound/effects/arcade_jump.ogg b/sound/effects/arcade_jump.ogg new file mode 100644 index 00000000000..65f0cc448b5 Binary files /dev/null and b/sound/effects/arcade_jump.ogg differ diff --git a/sound/effects/boing.ogg b/sound/effects/boing.ogg new file mode 100644 index 00000000000..8328cc33926 Binary files /dev/null and b/sound/effects/boing.ogg differ diff --git a/sound/effects/submerge.ogg b/sound/effects/submerge.ogg new file mode 100644 index 00000000000..8c50fba8e0a Binary files /dev/null and b/sound/effects/submerge.ogg differ diff --git a/strings/names/cyberauth.txt b/strings/names/cyberauth.txt new file mode 100644 index 00000000000..f1fc42b3692 --- /dev/null +++ b/strings/names/cyberauth.txt @@ -0,0 +1,21 @@ +Mr. One +Process Kill +Event Handler +Q. Del +Shutdown Exe +Revert Commit +Thread Manager +Garbage Collector +Core Debugger +Kernel Panic +IO Blocker +Recursion Terminator +Disk Doctor +Format Syntax +Byte Guardian +Disk Defragmenter +Security Patch +Mandatory Upgrade +Pull Review +Bit Auditor +Pen Test diff --git a/tgstation.dme b/tgstation.dme index 8974925f5a7..f6d8460ac26 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -39,7 +39,6 @@ #include "code\__DEFINES\antagonists.dm" #include "code\__DEFINES\apc_defines.dm" #include "code\__DEFINES\appearance.dm" -#include "code\__DEFINES\aquarium.dm" #include "code\__DEFINES\area_editor.dm" #include "code\__DEFINES\art.dm" #include "code\__DEFINES\assemblies.dm" @@ -47,6 +46,7 @@ #include "code\__DEFINES\atom_hud.dm" #include "code\__DEFINES\basic_mobs.dm" #include "code\__DEFINES\basketball.dm" +#include "code\__DEFINES\bitrunning.dm" #include "code\__DEFINES\blackmarket.dm" #include "code\__DEFINES\blend_modes.dm" #include "code\__DEFINES\blob_defines.dm" @@ -92,7 +92,7 @@ #include "code\__DEFINES\external_organs.dm" #include "code\__DEFINES\fantasy_affixes.dm" #include "code\__DEFINES\firealarm.dm" -#include "code\__DEFINES\fishing.dm" +#include "code\__DEFINES\fish.dm" #include "code\__DEFINES\flags.dm" #include "code\__DEFINES\flora.dm" #include "code\__DEFINES\font_awesome_icons.dm" @@ -149,6 +149,7 @@ #include "code\__DEFINES\mod.dm" #include "code\__DEFINES\modular_computer.dm" #include "code\__DEFINES\monkeys.dm" +#include "code\__DEFINES\mood.dm" #include "code\__DEFINES\move_force.dm" #include "code\__DEFINES\movement.dm" #include "code\__DEFINES\movespeed_modification.dm" @@ -277,6 +278,8 @@ #include "code\__DEFINES\dcs\signals\signals_assembly.dm" #include "code\__DEFINES\dcs\signals\signals_backpack.dm" #include "code\__DEFINES\dcs\signals\signals_beam.dm" +#include "code\__DEFINES\dcs\signals\signals_bitrunning.dm" +#include "code\__DEFINES\dcs\signals\signals_blob.dm" #include "code\__DEFINES\dcs\signals\signals_bot.dm" #include "code\__DEFINES\dcs\signals\signals_camera.dm" #include "code\__DEFINES\dcs\signals\signals_changeling.dm" @@ -735,6 +738,7 @@ #include "code\controllers\subsystem\speech_controller.dm" #include "code\controllers\subsystem\statpanel.dm" #include "code\controllers\subsystem\stickyban.dm" +#include "code\controllers\subsystem\stock_market.dm" #include "code\controllers\subsystem\sun.dm" #include "code\controllers\subsystem\tcgsetup.dm" #include "code\controllers\subsystem\tgui.dm" @@ -889,6 +893,7 @@ #include "code\datums\ai\bane\bane_controller.dm" #include "code\datums\ai\bane\bane_subtrees.dm" #include "code\datums\ai\basic_mobs\base_basic_controller.dm" +#include "code\datums\ai\basic_mobs\generic_controllers.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\basic_attacking.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\climb_tree.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\find_mineable_wall.dm" @@ -924,6 +929,7 @@ #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\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" #include "code\datums\ai\basic_mobs\pet_commands\fetch.dm" #include "code\datums\ai\basic_mobs\pet_commands\pet_command_planning.dm" @@ -945,6 +951,7 @@ #include "code\datums\ai\hauntium\hauntium_subtrees.dm" #include "code\datums\ai\hunting_behavior\hunting_behaviors.dm" #include "code\datums\ai\hunting_behavior\hunting_cockroach.dm" +#include "code\datums\ai\hunting_behavior\hunting_corpses.dm" #include "code\datums\ai\hunting_behavior\hunting_lights.dm" #include "code\datums\ai\hunting_behavior\hunting_mouse.dm" #include "code\datums\ai\idle_behaviors\_idle_behavior.dm" @@ -1021,6 +1028,7 @@ #include "code\datums\components\basic_mob_attack_telegraph.dm" #include "code\datums\components\basic_ranged_ready_overlay.dm" #include "code\datums\components\beetlejuice.dm" +#include "code\datums\components\blob_minion.dm" #include "code\datums\components\blood_walk.dm" #include "code\datums\components\bloodysoles.dm" #include "code\datums\components\boomerang.dm" @@ -1054,6 +1062,7 @@ #include "code\datums\components\customizable_reagent_holder.dm" #include "code\datums\components\damage_aura.dm" #include "code\datums\components\deadchat_control.dm" +#include "code\datums\components\death_linked.dm" #include "code\datums\components\dejavu.dm" #include "code\datums\components\deployable.dm" #include "code\datums\components\drift.dm" @@ -1225,6 +1234,7 @@ #include "code\datums\components\crafting\misc.dm" #include "code\datums\components\crafting\ranged_weapon.dm" #include "code\datums\components\crafting\robot.dm" +#include "code\datums\components\crafting\slapcrafting.dm" #include "code\datums\components\crafting\structures.dm" #include "code\datums\components\crafting\tailoring.dm" #include "code\datums\components\crafting\tiles.dm" @@ -1364,7 +1374,6 @@ #include "code\datums\elements\death_drops.dm" #include "code\datums\elements\death_explosion.dm" #include "code\datums\elements\death_gases.dm" -#include "code\datums\elements\death_linked.dm" #include "code\datums\elements\delete_on_drop.dm" #include "code\datums\elements\deliver_first.dm" #include "code\datums\elements\diggable.dm" @@ -1733,6 +1742,7 @@ #include "code\datums\status_effects\debuffs\choke.dm" #include "code\datums\status_effects\debuffs\confusion.dm" #include "code\datums\status_effects\debuffs\cursed.dm" +#include "code\datums\status_effects\debuffs\cyborg.dm" #include "code\datums\status_effects\debuffs\debuffs.dm" #include "code\datums\status_effects\debuffs\decloning.dm" #include "code\datums\status_effects\debuffs\dizziness.dm" @@ -1750,6 +1760,7 @@ #include "code\datums\status_effects\debuffs\slimed.dm" #include "code\datums\status_effects\debuffs\spacer.dm" #include "code\datums\status_effects\debuffs\speech_debuffs.dm" +#include "code\datums\status_effects\debuffs\static_vision.dm" #include "code\datums\status_effects\debuffs\strandling.dm" #include "code\datums\status_effects\debuffs\terrified.dm" #include "code\datums\status_effects\debuffs\tower_of_babel.dm" @@ -2259,6 +2270,7 @@ #include "code\game\objects\items\circuitboards\machines\engine_circuitboards.dm" #include "code\game\objects\items\circuitboards\machines\machine_circuitboards.dm" #include "code\game\objects\items\devices\aicard.dm" +#include "code\game\objects\items\devices\aicard_evil.dm" #include "code\game\objects\items\devices\anomaly_neutralizer.dm" #include "code\game\objects\items\devices\anomaly_releaser.dm" #include "code\game\objects\items\devices\beacon.dm" @@ -2761,6 +2773,7 @@ #include "code\modules\admin\verbs\fps.dm" #include "code\modules\admin\verbs\getlogs.dm" #include "code\modules\admin\verbs\ghost_pool_protection.dm" +#include "code\modules\admin\verbs\grant_dna_infusion.dm" #include "code\modules\admin\verbs\hiddenprints.dm" #include "code\modules\admin\verbs\highlander_datum.dm" #include "code\modules\admin\verbs\individual_logging.dm" @@ -3127,9 +3140,16 @@ #include "code\modules\antagonists\wizard\equipment\spellbook_entries\summons.dm" #include "code\modules\antagonists\wizard\grand_ritual\fluff.dm" #include "code\modules\antagonists\wizard\grand_ritual\grand_ritual.dm" -#include "code\modules\antagonists\wizard\grand_ritual\grand_ritual_finale.dm" #include "code\modules\antagonists\wizard\grand_ritual\grand_rune.dm" #include "code\modules\antagonists\wizard\grand_ritual\grand_side_effect.dm" +#include "code\modules\antagonists\wizard\grand_ritual\finales\all_access.dm" +#include "code\modules\antagonists\wizard\grand_ritual\finales\armageddon.dm" +#include "code\modules\antagonists\wizard\grand_ritual\finales\captaincy.dm" +#include "code\modules\antagonists\wizard\grand_ritual\finales\cheese.dm" +#include "code\modules\antagonists\wizard\grand_ritual\finales\clown.dm" +#include "code\modules\antagonists\wizard\grand_ritual\finales\grand_ritual_finale.dm" +#include "code\modules\antagonists\wizard\grand_ritual\finales\immortality.dm" +#include "code\modules\antagonists\wizard\grand_ritual\finales\midas.dm" #include "code\modules\antagonists\xeno\xeno.dm" #include "code\modules\art\paintings.dm" #include "code\modules\art\statues.dm" @@ -3249,6 +3269,7 @@ #include "code\modules\atmospherics\machinery\components\unary_devices\bluespace_sender.dm" #include "code\modules\atmospherics\machinery\components\unary_devices\cryo.dm" #include "code\modules\atmospherics\machinery\components\unary_devices\heat_exchanger.dm" +#include "code\modules\atmospherics\machinery\components\unary_devices\machine_connector.dm" #include "code\modules\atmospherics\machinery\components\unary_devices\outlet_injector.dm" #include "code\modules\atmospherics\machinery\components\unary_devices\passive_vent.dm" #include "code\modules\atmospherics\machinery\components\unary_devices\portables_connector.dm" @@ -3304,6 +3325,54 @@ #include "code\modules\basketball\controller.dm" #include "code\modules\basketball\hoop.dm" #include "code\modules\basketball\referee.dm" +#include "code\modules\bitrunning\abilities.dm" +#include "code\modules\bitrunning\alerts.dm" +#include "code\modules\bitrunning\areas.dm" +#include "code\modules\bitrunning\event.dm" +#include "code\modules\bitrunning\job.dm" +#include "code\modules\bitrunning\turfs.dm" +#include "code\modules\bitrunning\antagonists\cyber_police.dm" +#include "code\modules\bitrunning\antagonists\outfit.dm" +#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\clothing.dm" +#include "code\modules\bitrunning\objects\disks.dm" +#include "code\modules\bitrunning\objects\hololadder.dm" +#include "code\modules\bitrunning\objects\host_monitor.dm" +#include "code\modules\bitrunning\objects\landmarks.dm" +#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\orders\disks.dm" +#include "code\modules\bitrunning\orders\flair.dm" +#include "code\modules\bitrunning\orders\tech.dm" +#include "code\modules\bitrunning\server\loot.dm" +#include "code\modules\bitrunning\server\map_handling.dm" +#include "code\modules\bitrunning\server\obj_generation.dm" +#include "code\modules\bitrunning\server\quantum_server.dm" +#include "code\modules\bitrunning\server\signal_handlers.dm" +#include "code\modules\bitrunning\server\util.dm" +#include "code\modules\bitrunning\virtual_domain\safehouses.dm" +#include "code\modules\bitrunning\virtual_domain\virtual_domain.dm" +#include "code\modules\bitrunning\virtual_domain\domains\ash_drake.dm" +#include "code\modules\bitrunning\virtual_domain\domains\beach_bar.dm" +#include "code\modules\bitrunning\virtual_domain\domains\blood_drunk_miner.dm" +#include "code\modules\bitrunning\virtual_domain\domains\bubblegum.dm" +#include "code\modules\bitrunning\virtual_domain\domains\clown_planet.dm" +#include "code\modules\bitrunning\virtual_domain\domains\colossus.dm" +#include "code\modules\bitrunning\virtual_domain\domains\gondola_asteroid.dm" +#include "code\modules\bitrunning\virtual_domain\domains\hierophant.dm" +#include "code\modules\bitrunning\virtual_domain\domains\legion.dm" +#include "code\modules\bitrunning\virtual_domain\domains\pipedream.dm" +#include "code\modules\bitrunning\virtual_domain\domains\pirates.dm" +#include "code\modules\bitrunning\virtual_domain\domains\stairs_and_cliffs.dm" +#include "code\modules\bitrunning\virtual_domain\domains\syndicate_assault.dm" +#include "code\modules\bitrunning\virtual_domain\domains\test_only.dm" +#include "code\modules\bitrunning\virtual_domain\domains\vaporwave.dm" +#include "code\modules\bitrunning\virtual_domain\domains\wendigo.dm" +#include "code\modules\bitrunning\virtual_domain\domains\xeno_nest.dm" #include "code\modules\buildmode\bm_mode.dm" #include "code\modules\buildmode\buildmode.dm" #include "code\modules\buildmode\buttons.dm" @@ -3348,6 +3417,7 @@ #include "code\modules\cargo\expressconsole.dm" #include "code\modules\cargo\gondolapod.dm" #include "code\modules\cargo\goodies.dm" +#include "code\modules\cargo\materials_market.dm" #include "code\modules\cargo\order.dm" #include "code\modules\cargo\orderconsole.dm" #include "code\modules\cargo\supplypod.dm" @@ -3407,6 +3477,7 @@ #include "code\modules\cargo\packs\science.dm" #include "code\modules\cargo\packs\security.dm" #include "code\modules\cargo\packs\service.dm" +#include "code\modules\cargo\packs\stock_market_items.dm" #include "code\modules\cargo\packs\vending_restock.dm" #include "code\modules\chatter\chatter.dm" #include "code\modules\client\client_colour.dm" @@ -3457,6 +3528,7 @@ #include "code\modules\client\preferences\preferred_map.dm" #include "code\modules\client\preferences\pride_pin.dm" #include "code\modules\client\preferences\prisoner_crime.dm" +#include "code\modules\client\preferences\prosthetic.dm" #include "code\modules\client\preferences\random.dm" #include "code\modules\client\preferences\runechat.dm" #include "code\modules\client\preferences\scaling_method.dm" @@ -3786,6 +3858,7 @@ #include "code\modules\experisci\experiment\types\physical_experiment.dm" #include "code\modules\experisci\experiment\types\random_scanning.dm" #include "code\modules\experisci\experiment\types\scanning.dm" +#include "code\modules\experisci\experiment\types\scanning_fish.dm" #include "code\modules\experisci\experiment\types\scanning_machinery.dm" #include "code\modules\experisci\experiment\types\scanning_material.dm" #include "code\modules\experisci\experiment\types\scanning_people.dm" @@ -4360,6 +4433,11 @@ #include "code\modules\mob\living\basic\festivus_pole.dm" #include "code\modules\mob\living\basic\health_adjustment.dm" #include "code\modules\mob\living\basic\tree.dm" +#include "code\modules\mob\living\basic\blob_minions\blob_ai.dm" +#include "code\modules\mob\living\basic\blob_minions\blob_mob.dm" +#include "code\modules\mob\living\basic\blob_minions\blob_spore.dm" +#include "code\modules\mob\living\basic\blob_minions\blob_zombie.dm" +#include "code\modules\mob\living\basic\blob_minions\blobbernaut.dm" #include "code\modules\mob\living\basic\clown\clown.dm" #include "code\modules\mob\living\basic\clown\clown_ai.dm" #include "code\modules\mob\living\basic\farm_animals\deer.dm" @@ -4409,6 +4487,14 @@ #include "code\modules\mob\living\basic\lavaland\goliath\goliath_ai.dm" #include "code\modules\mob\living\basic\lavaland\goliath\goliath_trophy.dm" #include "code\modules\mob\living\basic\lavaland\goliath\tentacle.dm" +#include "code\modules\mob\living\basic\lavaland\hivelord\hivelord.dm" +#include "code\modules\mob\living\basic\lavaland\hivelord\hivelord_ai.dm" +#include "code\modules\mob\living\basic\lavaland\hivelord\spawn_hivelord_brood.dm" +#include "code\modules\mob\living\basic\lavaland\legion\legion.dm" +#include "code\modules\mob\living\basic\lavaland\legion\legion_ai.dm" +#include "code\modules\mob\living\basic\lavaland\legion\legion_brood.dm" +#include "code\modules\mob\living\basic\lavaland\legion\legion_tumour.dm" +#include "code\modules\mob\living\basic\lavaland\legion\spawn_legions.dm" #include "code\modules\mob\living\basic\lavaland\lobstrosity\lobstrosity.dm" #include "code\modules\mob\living\basic\lavaland\lobstrosity\lobstrosity_ai.dm" #include "code\modules\mob\living\basic\lavaland\lobstrosity\lobstrosity_trophy.dm" @@ -4439,7 +4525,9 @@ #include "code\modules\mob\living\basic\space_fauna\lightgeist.dm" #include "code\modules\mob\living\basic\space_fauna\morph.dm" #include "code\modules\mob\living\basic\space_fauna\mushroom.dm" +#include "code\modules\mob\living\basic\space_fauna\robot_customer.dm" #include "code\modules\mob\living\basic\space_fauna\spaceman.dm" +#include "code\modules\mob\living\basic\space_fauna\supermatter_spider.dm" #include "code\modules\mob\living\basic\space_fauna\bear\_bear.dm" #include "code\modules\mob\living\basic\space_fauna\bear\bear_ai_behavior.dm" #include "code\modules\mob\living\basic\space_fauna\bear\bear_ai_subtree.dm" @@ -4474,6 +4562,8 @@ #include "code\modules\mob\living\basic\space_fauna\regal_rat\regal_rat.dm" #include "code\modules\mob\living\basic\space_fauna\regal_rat\regal_rat_actions.dm" #include "code\modules\mob\living\basic\space_fauna\regal_rat\regal_rat_ai.dm" +#include "code\modules\mob\living\basic\space_fauna\snake\snake.dm" +#include "code\modules\mob\living\basic\space_fauna\snake\snake_ai.dm" #include "code\modules\mob\living\basic\space_fauna\spider\spider.dm" #include "code\modules\mob\living\basic\space_fauna\spider\giant_spider\giant_spider_ai.dm" #include "code\modules\mob\living\basic\space_fauna\spider\giant_spider\giant_spider_subtrees.dm" @@ -4671,7 +4761,6 @@ #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\robot_customer.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" @@ -4696,9 +4785,6 @@ #include "code\modules\mob\living\simple_animal\guardian\types\standard.dm" #include "code\modules\mob\living\simple_animal\guardian\types\support.dm" #include "code\modules\mob\living\simple_animal\hostile\alien.dm" -#include "code\modules\mob\living\simple_animal\hostile\blob.dm" -#include "code\modules\mob\living\simple_animal\hostile\blobbernaut.dm" -#include "code\modules\mob\living\simple_animal\hostile\blobspore.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" @@ -4708,7 +4794,6 @@ #include "code\modules\mob\living\simple_animal\hostile\ooze.dm" #include "code\modules\mob\living\simple_animal\hostile\pirate.dm" #include "code\modules\mob\living\simple_animal\hostile\skeleton.dm" -#include "code\modules\mob\living\simple_animal\hostile\smspider.dm" #include "code\modules\mob\living\simple_animal\hostile\space_dragon.dm" #include "code\modules\mob\living\simple_animal\hostile\vatbeast.dm" #include "code\modules\mob\living\simple_animal\hostile\venus_human_trap.dm" @@ -4737,7 +4822,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\hivelord.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" @@ -4749,7 +4833,6 @@ #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\pandora.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\goose.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\retaliate.dm" -#include "code\modules\mob\living\simple_animal\hostile\retaliate\snake.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\trader.dm" #include "code\modules\mob\living\simple_animal\slime\death.dm" #include "code\modules\mob\living\simple_animal\slime\emote.dm" @@ -4766,6 +4849,7 @@ #include "code\modules\mob_spawn\corpses\nonhuman_corpses.dm" #include "code\modules\mob_spawn\corpses\species_corpses.dm" #include "code\modules\mob_spawn\ghost_roles\away_roles.dm" +#include "code\modules\mob_spawn\ghost_roles\drone_roles.dm" #include "code\modules\mob_spawn\ghost_roles\fugitive_hunter_roles.dm" #include "code\modules\mob_spawn\ghost_roles\golem_roles.dm" #include "code\modules\mob_spawn\ghost_roles\mining_roles.dm" @@ -5216,7 +5300,6 @@ #include "code\modules\religion\sparring\sparring_datum.dm" #include "code\modules\requests\request.dm" #include "code\modules\requests\request_manager.dm" -#include "code\modules\research\bepis.dm" #include "code\modules\research\designs.dm" #include "code\modules\research\destructive_analyzer.dm" #include "code\modules\research\experimentor.dm" @@ -5910,6 +5993,7 @@ #include "modular_skyrat\master_files\code\modules\antagonists\traitor\objectives\kill_pet.dm" #include "modular_skyrat\master_files\code\modules\antagonists\traitor\objectives\smuggling.dm" #include "modular_skyrat\master_files\code\modules\asset_cache\assets\plumbing.dm" +#include "modular_skyrat\master_files\code\modules\bitrunning\orders\tech.dm" #include "modular_skyrat\master_files\code\modules\buildmode\bm_mode.dm" #include "modular_skyrat\master_files\code\modules\buildmode\submodes\offercontrol.dm" #include "modular_skyrat\master_files\code\modules\cargo\goodies.dm" @@ -6376,7 +6460,6 @@ #include "modular_skyrat\modules\bsa_overhaul\code\bsa_computer.dm" #include "modular_skyrat\modules\bsa_overhaul\code\station_goal.dm" #include "modular_skyrat\modules\bsrpd\code\bsrpd.dm" -#include "modular_skyrat\modules\bulletrebalance\code\sniper.dm" #include "modular_skyrat\modules\cargo\code\goodies.dm" #include "modular_skyrat\modules\cargo\code\packs.dm" #include "modular_skyrat\modules\cargo\code\items\AFAD.dm" @@ -7087,14 +7170,19 @@ #include "modular_skyrat\modules\modular_implants\code\nifs_tgui.dm" #include "modular_skyrat\modules\modular_implants\code\nifsoft_catalog.dm" #include "modular_skyrat\modules\modular_implants\code\nifsofts.dm" +#include "modular_skyrat\modules\modular_implants\code\nifsofts\book_summoner.dm" #include "modular_skyrat\modules\modular_implants\code\nifsofts\dorms.dm" #include "modular_skyrat\modules\modular_implants\code\nifsofts\hivemind.dm" #include "modular_skyrat\modules\modular_implants\code\nifsofts\huds.dm" +#include "modular_skyrat\modules\modular_implants\code\nifsofts\hypnosis.dm" #include "modular_skyrat\modules\modular_implants\code\nifsofts\money_sense.dm" #include "modular_skyrat\modules\modular_implants\code\nifsofts\prop_summoner.dm" +#include "modular_skyrat\modules\modular_implants\code\nifsofts\scryer.dm" #include "modular_skyrat\modules\modular_implants\code\nifsofts\shapeshifter.dm" #include "modular_skyrat\modules\modular_implants\code\nifsofts\soul_poem.dm" #include "modular_skyrat\modules\modular_implants\code\nifsofts\soulcatcher.dm" +#include "modular_skyrat\modules\modular_implants\code\nifsofts\base_types\action_granter.dm" +#include "modular_skyrat\modules\modular_implants\code\soulcatcher\attachable_soulcatcher.dm" #include "modular_skyrat\modules\modular_implants\code\soulcatcher\handheld_soulcatcher.dm" #include "modular_skyrat\modules\modular_implants\code\soulcatcher\soulcatcher_body_component.dm" #include "modular_skyrat\modules\modular_implants\code\soulcatcher\soulcatcher_component.dm" @@ -7366,6 +7454,7 @@ #include "modular_skyrat\modules\pixel_shift\code\pixel_shift_component.dm" #include "modular_skyrat\modules\pixel_shift\code\pixel_shift_keybind.dm" #include "modular_skyrat\modules\pixel_shift\code\pixel_shift_mob.dm" +#include "modular_skyrat\modules\player_ranks\code\world_topic.dm" #include "modular_skyrat\modules\player_ranks\code\player_rank_controller\_player_rank_controller.dm" #include "modular_skyrat\modules\player_ranks\code\player_rank_controller\donator_controller.dm" #include "modular_skyrat\modules\player_ranks\code\player_rank_controller\mentor_controller.dm" @@ -7433,6 +7522,8 @@ #include "modular_skyrat\modules\records_on_examine\code\record_variables.dm" #include "modular_skyrat\modules\records_on_examine\code\records_procs.dm" #include "modular_skyrat\modules\records_on_examine\code\view_exploitables.dm" +#include "modular_skyrat\modules\resleeving\code\rsd_interface.dm" +#include "modular_skyrat\modules\resleeving\code\research\resleeving_research.dm" #include "modular_skyrat\modules\robohand\code\bodypart_autosurgeon.dm" #include "modular_skyrat\modules\robohand\code\robohand.dm" #include "modular_skyrat\modules\robohand\code\silverhand_bundle.dm" @@ -7572,9 +7663,6 @@ #include "modular_skyrat\modules\vox_sprites\code\head.dm" #include "modular_skyrat\modules\vox_sprites\code\security.dm" #include "modular_skyrat\modules\vox_sprites\code\sneakers.dm" -#include "modular_skyrat\modules\wall_fungus\code\wall_fungus_component.dm" -#include "modular_skyrat\modules\wall_fungus\code\wall_fungus_event.dm" -#include "modular_skyrat\modules\wall_fungus\code\wall_mushroom.dm" #include "modular_skyrat\modules\wargame_projectors\code\game_kit.dm" #include "modular_skyrat\modules\wargame_projectors\code\holograms.dm" #include "modular_skyrat\modules\wargame_projectors\code\projectors.dm" diff --git a/tgui/packages/tgui-panel/settings/middleware.js b/tgui/packages/tgui-panel/settings/middleware.js index 705d7a89f3b..cef082213db 100644 --- a/tgui/packages/tgui-panel/settings/middleware.js +++ b/tgui/packages/tgui-panel/settings/middleware.js @@ -10,16 +10,39 @@ import { loadSettings, updateSettings, addHighlightSetting, removeHighlightSetti import { selectSettings } from './selectors'; import { FONTS_DISABLED } from './constants'; +let overrideRule = null; +let overrideFontFamily = null; +let overrideFontSize = null; + +const updateGlobalOverrideRule = () => { + let fontFamily = ''; + + if (overrideFontFamily !== null) { + fontFamily = `font-family: ${overrideFontFamily} !important;`; + } + + const constructedRule = `body * :not(.Icon) { + ${fontFamily} + }`; + + if (overrideRule === null) { + overrideRule = document.createElement('style'); + document.querySelector('head').append(overrideRule); + } + + // no other way to force a CSS refresh other than to update its innerText + overrideRule.innerText = constructedRule; + + document.body.style.setProperty('font-size', overrideFontSize); +}; + const setGlobalFontSize = (fontSize) => { - document.documentElement.style.setProperty('font-size', fontSize + 'px'); - document.body.style.setProperty('font-size', fontSize + 'px'); + overrideFontSize = `${fontSize}px`; }; const setGlobalFontFamily = (fontFamily) => { if (fontFamily === FONTS_DISABLED) fontFamily = null; - - document.documentElement.style.setProperty('font-family', fontFamily); - document.body.style.setProperty('font-family', fontFamily); + overrideFontFamily = fontFamily; }; export const settingsMiddleware = (store) => { @@ -50,6 +73,7 @@ export const settingsMiddleware = (store) => { // Update global UI font size setGlobalFontSize(settings.fontSize); setGlobalFontFamily(settings.fontFamily); + updateGlobalOverrideRule(); // Save settings to the web storage storage.set('panel-settings', settings); return; diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss index 148ccc86f72..43e2fa93343 100644 --- a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss +++ b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss @@ -535,6 +535,10 @@ em { } .blob { + color: #ee4000; +} + +.blobannounce { color: #556b2f; font-weight: bold; font-size: 185%; diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss index ffbfa3f02ed..e685cded774 100644 --- a/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss +++ b/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss @@ -594,6 +594,10 @@ h2.alert { } .blob { + color: #ee4000; +} + +.blobannounce { color: #323f1c; font-weight: bold; font-size: 185%; diff --git a/tgui/packages/tgui/interfaces/AntagInfoCyberAuth.tsx b/tgui/packages/tgui/interfaces/AntagInfoCyberAuth.tsx new file mode 100644 index 00000000000..21d872ed6a0 --- /dev/null +++ b/tgui/packages/tgui/interfaces/AntagInfoCyberAuth.tsx @@ -0,0 +1,75 @@ +import { useBackend } from '../backend'; +import { Divider, Section, Stack } from '../components'; +import { Window } from '../layouts'; +import { Objective } from './common/Objectives'; + +type Info = { + antag_name: string; + objectives: Objective[]; +}; + +const textStyles = { + variable: { + color: 'white', + }, + danger: { + color: 'red', + }, +} as const; + +export const AntagInfoCyberAuth = (props, context) => { + const { data } = useBackend(context); + const { objectives = [] } = data; + + return ( + + +
+ + FN CYBER AUTHORITY UNIT (REF) + + + + You are a cyber authority unit. + + + + Your mission: Eliminate{' '} + organic intruders to maintain the integrity of the system. + + + Bitrunning is a crime. To + assist your task, your program has been loaded with cutting edge{' '} + martial arts skills. + + + Ranged weaponry is{' '} + forbidden. Ballistic + defense is frowned upon. Style is paramount. + + + {objectives[0].explanation} + + + + const TARGETS ={' '} + + + system. + INTRUDERS; + + + while TARGETS.LIFE !={' '} + stat.DEAD + + + action. + KILL() + + cyber_authority_unit([0x70cf4020]) + +
+
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/AntagInfoHeretic.tsx b/tgui/packages/tgui/interfaces/AntagInfoHeretic.tsx index ff14419473c..da4331026cc 100644 --- a/tgui/packages/tgui/interfaces/AntagInfoHeretic.tsx +++ b/tgui/packages/tgui/interfaces/AntagInfoHeretic.tsx @@ -46,6 +46,7 @@ type KnowledgeInfo = { type Info = { charges: number; + side_charges: number; total_sacrifices: number; ascended: BooleanLike; objectives: Objective[]; @@ -179,7 +180,7 @@ const GuideSection = () => { const InformationSection = (props, context) => { const { data } = useBackend(context); - const { charges, total_sacrifices, ascended } = data; + const { charges, side_charges, total_sacrifices, ascended } = data; return ( @@ -201,6 +202,13 @@ const InformationSection = (props, context) => { knowledge point{charges !== 1 ? 's' : ''} + {!!side_charges && ( + + {' '} + and {side_charges} side point + {side_charges !== 1 ? 's' : ''} + + )}{' '} . @@ -275,7 +283,7 @@ const KnowledgeShop = (props, context) => { const ResearchInfo = (props, context) => { const { data } = useBackend(context); - const { charges } = data; + const { charges, side_charges } = data; return ( @@ -285,7 +293,14 @@ const ResearchInfo = (props, context) => { You have {charges || 0}  knowledge point{charges !== 1 ? 's' : ''} - {' '} + + {!!side_charges && ( + + {' '} + and {side_charges} side point + {side_charges !== 1 ? 's' : ''} + + )}{' '} to spend. diff --git a/tgui/packages/tgui/interfaces/AvatarHelp.tsx b/tgui/packages/tgui/interfaces/AvatarHelp.tsx new file mode 100644 index 00000000000..647d3a2e22b --- /dev/null +++ b/tgui/packages/tgui/interfaces/AvatarHelp.tsx @@ -0,0 +1,122 @@ +import { useBackend } from '../backend'; +import { Box, Icon, Section, Stack } from '../components'; +import { Window } from '../layouts'; + +type Data = { + help_text: string; +}; + +const DEFAULT_HELP = `No information available! Ask for assistance if needed.`; + +const boxHelp = [ + { + color: 'purple', + text: 'Study the area and do what needs to be done to recover the crate. Pay close attention to domain information and context clues.', + icon: 'search-location', + title: 'Search', + }, + { + color: 'green', + text: 'Bring the crate to the designated sending location in the safehouse. The area may seem out of place. Examine the safehouse to find it.', + icon: 'boxes', + 'title': 'Recover', + }, + { + color: 'blue', + text: 'The ladder represents the safest way to disconnect before the cache is recovered. Should your connection sever, the netpod offers limited resuscitation potential.', + icon: 'plug', + title: 'Disconnect', + }, + { + color: 'yellow', + text: 'While connected, you are somewhat safe from environmental hazards and intrusions, but not completely. Pay close attention to alerts.', + icon: 'id-badge', + title: 'Security', + }, + { + color: 'gold', + text: 'Generating avatars costs tremendous bandwidth. Do not waste them.', + icon: 'coins', + title: 'Limited Attempts', + }, + { + color: 'red', + text: 'Remember that you are physically linked to this presence. You are a foreign body in a hostile environment. It will attempt to forcefully eject you.', + icon: 'skull-crossbones', + title: 'Realized Danger', + }, +] as const; + +export const AvatarHelp = (props, context) => { + const { data } = useBackend(context); + const { help_text = DEFAULT_HELP } = data; + + return ( + + + + +
+ {help_text} +
+
+ + + + + {[0, 1].map((i) => ( + + ))} + + + + + {[2, 3].map((i) => ( + + ))} + + + + + {[4, 5].map((i) => ( + + ))} + + + + +
+
+
+ ); +}; + +// I wish I had media queries +const BoxHelp = (props: { index: number }, context) => { + const { index } = props; + + return ( + +
+ + {boxHelp[index].title} + + }> + {boxHelp[index].text} +
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/Bepis.tsx b/tgui/packages/tgui/interfaces/Bepis.tsx deleted file mode 100644 index d2835e530d3..00000000000 --- a/tgui/packages/tgui/interfaces/Bepis.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { BooleanLike } from 'common/react'; -import { useBackend } from '../backend'; -import { Box, Button, Grid, LabeledList, NumberInput, Section } from '../components'; -import { Window } from '../layouts'; - -type Data = { - amount: number; - account_owner: string; - manual_power: BooleanLike; - stored_cash: number; - accuracy_percentage: number; - positive_cash_offset: number; - negative_cash_offset: number; - silicon_check: BooleanLike; - success_estimate: number; - mean_value: number; - error_name: string; -}; - -const BEPIS_SLOGAN = `All you need to know about the B.E.P.I.S. and you! The -B.E.P.I.S. performs hundreds of tests a second using -electrical and financial resources to invent new products, -or discover new technologies otherwise overlooked for being -too risky or too niche to produce!`; - -export const Bepis = (props, context) => { - const { act, data } = useBackend(context); - const { - amount, - account_owner, - manual_power, - stored_cash, - accuracy_percentage, - positive_cash_offset, - negative_cash_offset, - silicon_check, - success_estimate, - mean_value, - error_name, - } = data; - - return ( - - -
-
act('toggle_power')} - /> - }> - {BEPIS_SLOGAN} -
-
act('account_reset')} - /> - }> - Console is currently being operated by{' '} - {account_owner ? account_owner : 'no one'}. -
- - -
- - - {stored_cash} - - - {accuracy_percentage}% - - - {positive_cash_offset} - - - {negative_cash_offset} - - - - act('amount', { - amount: value, - }) - } - /> - - -
- -
-
-
- ); -}; diff --git a/tgui/packages/tgui/interfaces/Canvas.tsx b/tgui/packages/tgui/interfaces/Canvas.tsx index 40155c08869..1dddec2e907 100644 --- a/tgui/packages/tgui/interfaces/Canvas.tsx +++ b/tgui/packages/tgui/interfaces/Canvas.tsx @@ -264,13 +264,13 @@ export const Canvas = (props, context) => { { const { self_paid, app_cost } = data; const supplies = Object.values(data.supplies); + const { amount_by_name = [], max_order } = data; const [activeSupplyName, setActiveSupplyName] = useSharedState( context, @@ -273,6 +274,7 @@ export const CargoCatalog = (props, context) => { fluid tooltip={pack.desc} tooltipPosition="left" + disabled={(amount_by_name[pack.name] || 0) >= max_order} onClick={() => act('add', { id: pack.id, @@ -406,7 +408,15 @@ const CartHeader = (props, context) => { const CargoCart = (props, context) => { const { act, data } = useBackend(context); - const { requestonly, away, docked, location, can_send } = data; + const { + requestonly, + away, + docked, + location, + can_send, + amount_by_name, + max_order, + } = data; const cart = data.cart || []; return (
@@ -424,7 +434,7 @@ const CargoCart = (props, context) => { act('modify', { @@ -439,6 +449,7 @@ const CargoCart = (props, context) => { {!!can_send && !!entry.can_be_cancelled && (
@@ -168,44 +168,24 @@ export const ExperimentConfigure = (props, context) => { export const Experiment = (props, context) => { const { act, data } = useBackend(context); - const { exp, controllable } = props; - const { - name, - description, - tag, - selectable, - selected, - progress, - performance_hint, - ref, - } = exp; + const { exp } = props; + const { name, description, tag, selected, progress, performance_hint, ref } = + exp; return ( + + + + +
+ + + ))} + + + ); +}; + +const MarketCrashModal = (props, context) => { + const { act, data } = useBackend(context); + return ( + + ATTENTION! THE MARKET HAS CRASHED +

+ ALL MATERIALS ARE NOW WORTHLESS +

+ TRADING CIRCUIT BREAKER HAS BEEN ENGAGED FOR ALL TRADERS +

+ DO NOT PANIC, WE ARE FIXING THIS +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/NetpodOutfits.tsx b/tgui/packages/tgui/interfaces/NetpodOutfits.tsx new file mode 100644 index 00000000000..afc6a2bd6ca --- /dev/null +++ b/tgui/packages/tgui/interfaces/NetpodOutfits.tsx @@ -0,0 +1,109 @@ +import { Button, Divider, Input, NoticeBox, Section, Stack, Tabs } from '../components'; +import { useBackend, useLocalState } from '../backend'; + +import { Window } from '../layouts'; +import { createSearch } from '../../common/string'; + +type Data = { + netsuit: string; + collections: Collection[]; + types: string[]; +}; + +type Collection = { + name: string; + outfits: Outfit[]; +}; + +type Outfit = { + path: string; + name: string; + type: string; +}; + +export const NetpodOutfits = (props, context) => { + const { act, data } = useBackend(context); + const { netsuit, collections = [] } = data; + const [selectedType, setSelectedType] = useLocalState( + context, + 'selectedType', + collections[0] + ); + const [search, setSearch] = useLocalState( + context, + 'outfitSearch', + '' + ); + + const searchFn = createSearch(search, (outfit: Outfit) => outfit.name); + + const filtered = selectedType?.outfits + ?.filter(searchFn) + .sort((a, b) => (a.name > b.name ? 1 : 0)); + + const selected = + selectedType.outfits?.find((outfit) => outfit.path === netsuit)?.name ?? + 'None'; + + return ( + + + + +
setSearch(value)} + placeholder="Search" + value={search} + /> + }> + + + + {collections.map((collection, index) => ( + <> + setSelectedType(collection)} + selected={selectedType === collection}> + {collection.name} + + {index > 0 && } + + ))} + + + + +
+ {filtered.map(({ path, name }, index) => ( + + + + ))} +
+
+
+
+
+ + + {selected} + + +
+
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/NifPanel.js b/tgui/packages/tgui/interfaces/NifPanel.js index 401f8b495d3..8e2d3160794 100644 --- a/tgui/packages/tgui/interfaces/NifPanel.js +++ b/tgui/packages/tgui/interfaces/NifPanel.js @@ -110,6 +110,29 @@ export const NifPanel = (props, context) => {
{nifsoft.desc}
+ {nifsoft.able_to_keep ? ( + +
+ + + + {points} + + + } + fill + scrollable + title="Virtual Domains"> + {sorted.map((domain) => ( + + ))} + + + + + + +
+ + + + {selected?.name ?? 'Nothing loaded'} + + + + act('stop_domain')} + tooltip="Begins shutdown. Will notify anyone connected." + /> + + +
+
+ + ); +}; + +const DomainEntry = (props: DomainEntryProps, context) => { + const { + domain: { cost, desc, difficulty, id, name, reward }, + } = props; + const { act, data } = useBackend(context); + if (!isConnected(data)) { + return null; + } + + const { generated_domain, ready, occupants, randomized, points } = data; + + const current = generated_domain === id; + const occupied = occupants > 0; + let buttonIcon, buttonName; + if (randomized) { + buttonIcon = ''; + buttonName = '???'; + } else if (current) { + buttonIcon = 'download'; + buttonName = 'Deployed'; + } else { + buttonIcon = 'coins'; + buttonName = 'Deploy'; + } + + return ( + act('set_domain', { id })} + tooltip={!!generated_domain && 'Stop current domain first.'}> + {buttonName} + + } + color={getColor(difficulty)} + title={ + <> + {name} + {difficulty === Difficulty.High && } + + }> + + + {desc} + + + + + + + + + + + + + +
+
+
+
+ ); +}; + +const AvatarDisplay = (props, context) => { + const { act, data } = useBackend(context); + if (!isConnected(data)) { + return null; + } + + const { avatars = [], generated_domain, retries_left } = data; + + return ( +
+ {!!generated_domain && ( + + + + + + )} + + + + + }> + + {avatars.map(({ health, name, pilot, brute, burn, tox, oxy }) => ( + + + {pilot} as{' '} + "{name}" + + + + {brute === 0 && burn === 0 && tox === 0 && oxy === 0 && ( + + + + )} + + 50 ? 'bad' : 'gray'} name="tint" /> + + + 50 ? 'average' : 'gray'} name="fire" /> + + + 50 ? 'green' : 'gray'} + name="skull-crossbones" + /> + + + 50 ? 'blue' : 'gray'} name="lungs" /> + + + + + + + + ))} +
+
+ ); +}; + +const DisplayDetails = (props: DisplayDetailsProps, context) => { + const { amount = 0, color, icon = 'star' } = props; + + if (amount === 0) { + return No bandwidth; + } + + if (typeof amount === 'string') { + return {String(amount)}; // don't ask + } + + if (amount > 4) { + return ( + + + {amount} + + + + + + ); + } + + return ( + + + {Array.from({ length: amount }, (_, index) => ( + + + + ))} + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/SecurityRecords/RecordView.tsx b/tgui/packages/tgui/interfaces/SecurityRecords/RecordView.tsx index 5e39c743ec3..851425dadfd 100644 --- a/tgui/packages/tgui/interfaces/SecurityRecords/RecordView.tsx +++ b/tgui/packages/tgui/interfaces/SecurityRecords/RecordView.tsx @@ -56,6 +56,7 @@ const RecordInfo = (props, context) => { rank, species, wanted_status, + voice, // SKYRAT EDIT START - RP Records past_general_records, past_security_records, @@ -172,6 +173,9 @@ const RecordInfo = (props, context) => { text={fingerprint} /> + + + { const { act, data } = useBackend(context); - const { require_approval, current_rooms = [], ghost_joinable } = data; + const { + require_approval, + current_rooms = [], + ghost_joinable, + current_soul_count, + max_souls, + removable, + communicate_as_parent, + } = data; return ( @@ -278,6 +286,54 @@ export const Soulcatcher = (props, context) => { {soul.able_to_emote ? 'Enabled' : 'Disabled'} + {communicate_as_parent ? ( + <> + + + + + + + + ) : ( + <> + )} + {removable ? ( + + ) : ( + <> + )} ); diff --git a/tgui/packages/tgui/interfaces/SoulcatcherUser.js b/tgui/packages/tgui/interfaces/SoulcatcherUser.js index f768287bb33..cabe26aabc3 100644 --- a/tgui/packages/tgui/interfaces/SoulcatcherUser.js +++ b/tgui/packages/tgui/interfaces/SoulcatcherUser.js @@ -4,7 +4,7 @@ import { BlockQuote, Button, Divider, Box, Flex, Collapsible, LabeledList, Secti export const SoulcatcherUser = (props, context) => { const { act, data } = useBackend(context); - const { current_room, user_data, souls = [] } = data; + const { current_room, user_data, communicate_as_parent, souls = [] } = data; return ( @@ -41,6 +41,18 @@ export const SoulcatcherUser = (props, context) => { ) : ( <> )} + {communicate_as_parent ? ( +