diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cff3b0870901..54ade9af8ca0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,20 +99,42 @@ jobs: tools/ci/generate_maplist.sh DreamMaker -DMULTIINSTANCE -DCIMAP paradise.dme + station_mapload_tests: + name: Station Tests + runs-on: ubuntu-22.04 + strategy: + fail-fast: false # Let all map tests run to completion + matrix: + station: + ['boxstation', 'deltastation', 'metastation', 'cerestation', 'emeraldstation'] + byondtype: ['STABLE', 'BETA'] + steps: + - uses: actions/checkout@v4 + - name: Setup Cache + uses: actions/cache@v4 + with: + path: $HOME/BYOND + key: ${{ runner.os }}-byond + - name: Install RUST_G Deps + run: | + sudo dpkg --add-architecture i386 + sudo apt update || true + sudo apt install zlib1g-dev:i386 + tools/ci/install_rustg.sh + - name: Compile & Run Unit Tests + run: | + tools/ci/install_byond.sh '${{ matrix.byondtype }}' + source $HOME/BYOND/byond/bin/byondsetup + DreamMaker -DMAP_TESTS -DTEST_CONFIG_OVERRIDE=\"unit_tests\" -DMULTIINSTANCE -DCIBUILDING paradise.dme + echo '/datum/map/${{ matrix.station }}' > data/next_map.txt + tools/ci/run_server.sh + unit_tests_and_sql: name: Unit Tests + SQL Validation runs-on: ubuntu-22.04 strategy: - fail-fast: false # Let all map tests run to completion + fail-fast: false matrix: - maptype: - [ - '/datum/map/boxstation', - '/datum/map/deltastation', - '/datum/map/metastation', - '/datum/map/cerestation', - '/datum/map/emeraldstation', - ] byondtype: ['STABLE', 'BETA'] services: mariadb: @@ -144,8 +166,8 @@ jobs: run: | tools/ci/install_byond.sh '${{ matrix.byondtype }}' source $HOME/BYOND/byond/bin/byondsetup - DreamMaker -DMULTIINSTANCE -DCIBUILDING paradise.dme - echo '${{ matrix.maptype }}' > data/next_map.txt + DreamMaker -DGAME_TESTS -DTEST_CONFIG_OVERRIDE=\"unit_tests\" -DMULTIINSTANCE -DCIBUILDING paradise.dme + echo '/datum/map/test_tiny' > data/next_map.txt tools/ci/run_server.sh windows_dll_tests: diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index 9bf589d9dcc5..705d7e1e1203 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -83,6 +83,7 @@ CREATE TABLE `characters` ( `runechat_color` VARCHAR(7) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '#FFFFFF', `cyborg_brain_type` ENUM('MMI', 'Robobrain', 'Positronic') NOT NULL DEFAULT 'MMI', `pda_ringtone` VARCHAR(16) NULL DEFAULT NULL COLLATE 'utf8mb3_general_ci', + `species_subtype` VARCHAR(45) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'None', PRIMARY KEY (`id`), KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=125467 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/SQL/updates/63-64.sql b/SQL/updates/63-64.sql new file mode 100644 index 000000000000..307d0940eb7e --- /dev/null +++ b/SQL/updates/63-64.sql @@ -0,0 +1,5 @@ +# Updates the DB from 63 to 64 ~SpaghettiBit +# Adds a subtype race to be stored on character saves +# Add species_subtype after pda_ringtone +ALTER TABLE `characters` + ADD COLUMN `species_subtype` VARCHAR(45) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'None' AFTER `pda_ringtone`; diff --git a/_maps/__MAP_DEFINES.dm b/_maps/__MAP_DEFINES.dm index 8f55a0aea114..a275d07a744c 100644 --- a/_maps/__MAP_DEFINES.dm +++ b/_maps/__MAP_DEFINES.dm @@ -13,6 +13,8 @@ #define STATION_CONTACT "Station Contact" // A level dedicated to admin use #define ADMIN_LEVEL "Admin Level" + // For Z-levels dedicated to auto-spawning stuff in + #define Z_FLAG_RESERVED "Reserved" // A level that can be navigated to by the crew without admin intervention or the emergency shuttle. #define REACHABLE_BY_CREW "Reachable" // For away missions - used by some consoles diff --git a/_maps/map_files/stations/boxstation.dmm b/_maps/map_files/stations/boxstation.dmm index 4eb1f89aea60..623d38612dc9 100644 --- a/_maps/map_files/stations/boxstation.dmm +++ b/_maps/map_files/stations/boxstation.dmm @@ -35,7 +35,6 @@ "aag" = ( /obj/machinery/hologram/holopad, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plasteel, /area/station/maintenance/incinerator) "aah" = ( @@ -5887,7 +5886,6 @@ "avE" = ( /obj/effect/decal/cleanable/dirt, /obj/item/stack/cable_coil/random, -/mob/living/simple_animal/mouse/white, /turf/simulated/floor/plating, /area/station/maintenance/fpmaint) "avF" = ( @@ -10098,7 +10096,6 @@ /turf/simulated/floor/plating, /area/shuttle/pod_2) "aJW" = ( -/mob/living/simple_animal/mouse, /obj/machinery/atmospherics/pipe/simple/hidden/cyan, /obj/effect/mapping_helpers/turfs/damage, /turf/simulated/floor/wood, @@ -10109,11 +10106,6 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/fpmaint2) -"aJY" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/fpmaint2) "aJZ" = ( /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 4 @@ -11123,10 +11115,6 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/fsmaint) -"aNi" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/fsmaint) "aNj" = ( /obj/structure/table, /turf/simulated/floor/plating, @@ -12254,10 +12242,6 @@ icon_state = "arrival" }, /area/station/hallway/secondary/entry/north) -"aRg" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/fpmaint2) "aRh" = ( /obj/machinery/sleeper{ dir = 4 @@ -21821,11 +21805,6 @@ /obj/item/storage/toolbox/emergency, /turf/simulated/floor/plating, /area/station/public/storage/emergency/port) -"buj" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/gray, -/turf/simulated/floor/plasteel, -/area/station/maintenance/port) "buk" = ( /obj/structure/sign/securearea{ desc = "A warning sign which reads 'KEEP CLEAR OF DOCKING AREA'."; @@ -25808,10 +25787,6 @@ }, /turf/simulated/wall/r_wall, /area/station/maintenance/port) -"bKH" = ( -/mob/living/simple_animal/mouse/gray, -/turf/simulated/floor/plating, -/area/station/maintenance/port) "bKI" = ( /obj/structure/cable{ icon_state = "0-2" @@ -32451,7 +32426,6 @@ /turf/simulated/floor/plating/airless, /area/station/science/toxins/test) "clF" = ( -/mob/living/simple_animal/mouse, /obj/machinery/atmospherics/pipe/simple/hidden/cyan{ dir = 4 }, @@ -33633,7 +33607,6 @@ /area/station/command/office/ntrep) "cqK" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 4 }, @@ -34885,12 +34858,6 @@ /obj/item/stack/rods, /turf/simulated/floor/plasteel, /area/station/maintenance/apmaint) -"cvl" = ( -/mob/living/simple_animal/mouse/gray, -/obj/effect/decal/cleanable/dirt, -/obj/structure/disposalpipe/segment, -/turf/simulated/floor/plasteel, -/area/station/maintenance/port) "cvm" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/suit_storage_unit/expedition, @@ -44097,7 +44064,6 @@ /area/station/maintenance/turbine) "dev" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plasteel, /area/station/maintenance/turbine) "dew" = ( @@ -45625,10 +45591,6 @@ /obj/effect/decal/cleanable/cobweb, /turf/simulated/floor/plating, /area/station/maintenance/aft) -"dkv" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/asmaint) "dky" = ( /obj/machinery/camera{ c_tag = "Central Hallway North-East" @@ -49233,10 +49195,6 @@ }, /turf/simulated/floor/plasteel, /area/station/hallway/primary/port/east) -"egi" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/apmaint) "egq" = ( /obj/structure/closet/secure_closet/brig, /obj/machinery/power/apc/directional/east, @@ -53660,7 +53618,6 @@ /obj/structure/cable{ icon_state = "1-2" }, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plating, /area/station/maintenance/fpmaint2) "gsl" = ( @@ -71961,22 +71918,6 @@ icon_state = "caution" }, /area/station/engineering/break_room) -"pUR" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/cyan{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/asmaint2) "pUU" = ( /obj/structure/filingcabinet, /turf/simulated/floor/carpet, @@ -80364,7 +80305,6 @@ }, /area/station/maintenance/asmaint) "uql" = ( -/mob/living/simple_animal/mouse, /obj/effect/turf_decal/stripes/line{ dir = 4 }, @@ -101858,7 +101798,7 @@ nxX aGn aPW aQb -aRg +aHS aHl aGn rPS @@ -103391,7 +103331,7 @@ bat aDA aEH aEJ -aJY +aHl aIK aGn aHS @@ -103423,7 +103363,7 @@ blM bvq cho bwZ -cvl +pcH bCr pwm cwA @@ -106994,7 +106934,7 @@ aaa aaa loS dEG -aRg +aHS vbm aJX jQt @@ -108053,7 +107993,7 @@ bnK bnK cJV blQ -bKH +bnK bxb bIX bQf @@ -111127,7 +111067,7 @@ bkg blX blQ bsR -buj +svp bvw bDJ blQ @@ -111674,7 +111614,7 @@ bBf wrU nIY cqs -egi +coL xxQ omB coL @@ -131409,7 +131349,7 @@ aGX aQI aGY aGX -aNi +aGY aGY aGX aGX @@ -132253,7 +132193,7 @@ bGG qZN oyY oyY -pUR +upd bGG qZN dQM @@ -137415,7 +137355,7 @@ cNq cga ePu ePu -dkv +csL isD csL jPw diff --git a/_maps/map_files/stations/cerestation.dmm b/_maps/map_files/stations/cerestation.dmm index e87ccdcfcbcc..deb6cb16f765 100644 --- a/_maps/map_files/stations/cerestation.dmm +++ b/_maps/map_files/stations/cerestation.dmm @@ -23636,13 +23636,6 @@ }, /turf/simulated/floor/plating, /area/station/engineering/atmos/distribution) -"deS" = ( -/mob/living/simple_animal/mouse/brown, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" - }, -/area/station/maintenance/port2) "deW" = ( /obj/item/radio/intercom{ pixel_y = 28; @@ -36622,7 +36615,6 @@ /obj/machinery/light/small{ dir = 8 }, -/mob/living/simple_animal/mouse/brown, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/port2) "gtH" = ( @@ -37921,12 +37913,6 @@ }, /turf/simulated/floor/transparent/glass/reinforced, /area/station/maintenance/starboard) -"gLX" = ( -/mob/living/simple_animal/mouse/brown, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" - }, -/area/station/maintenance/fsmaint) "gLY" = ( /obj/machinery/door/poddoor/shutters/preopen{ dir = 8; @@ -38245,15 +38231,6 @@ /obj/machinery/space_heater, /turf/simulated/floor/plating, /area/station/maintenance/disposal/south) -"gRw" = ( -/mob/living/simple_animal/mouse/white, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" - }, -/area/station/maintenance/starboard) "gRz" = ( /obj/effect/decal/cleanable/blood/tracks/mapped, /obj/effect/mapping_helpers/turfs/burn, @@ -38604,10 +38581,6 @@ /obj/effect/spawner/random/maintenance, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/maintcentral) -"gWv" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/port) "gWO" = ( /obj/structure/closet/wardrobe/white, /obj/item/clothing/shoes/jackboots, @@ -41488,7 +41461,6 @@ /obj/machinery/light/small{ dir = 8 }, -/mob/living/simple_animal/mouse/brown, /turf/simulated/floor/plating{ icon_state = "asteroidplating" }, @@ -46695,13 +46667,6 @@ /obj/effect/decal/cleanable/cobweb, /turf/simulated/floor/plating, /area/station/maintenance/disposal/southwest) -"iXy" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/mob/living/simple_animal/mouse/gray, -/turf/simulated/floor/plating/asteroid/ancient, -/area/station/maintenance/starboard) "iXK" = ( /obj/machinery/atmospherics/pipe/simple/hidden{ dir = 10 @@ -53284,14 +53249,6 @@ icon_state = "green" }, /area/station/public/quantum/service) -"kAu" = ( -/mob/living/simple_animal/mouse/gray, -/obj/effect/spawner/random/dirt/often, -/turf/simulated/floor/plasteel{ - dir = 8; - icon_state = "yellow" - }, -/area/station/maintenance/fore) "kAv" = ( /obj/machinery/hologram/holopad, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, @@ -55199,10 +55156,6 @@ /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /turf/simulated/wall, /area/station/hallway/primary/port/south) -"laM" = ( -/mob/living/simple_animal/mouse/brown, -/turf/simulated/floor/plating, -/area/station/maintenance/fore2) "lbf" = ( /obj/structure/cable{ icon_state = "1-2" @@ -62945,10 +62898,6 @@ icon_state = "escape" }, /area/station/maintenance/port2) -"mXW" = ( -/mob/living/simple_animal/mouse/white, -/turf/simulated/floor/plating/asteroid/ancient, -/area/station/maintenance/asmaint) "mYa" = ( /obj/machinery/flasher{ id = "Cell 2"; @@ -63472,7 +63421,6 @@ /area/station/maintenance/fore) "neD" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/white, /obj/effect/turf_decal/delivery/partial{ dir = 4 }, @@ -66193,11 +66141,6 @@ icon_state = "neutralfull" }, /area/station/hallway/primary/fore/west) -"nQU" = ( -/mob/living/simple_animal/mouse/brown, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/plating, -/area/station/maintenance/fore2) "nQW" = ( /obj/machinery/door/airlock/public/glass, /obj/effect/mapping_helpers/airlock/autoname, @@ -68334,7 +68277,6 @@ /area/station/science/test_chamber) "ove" = ( /obj/effect/spawner/random/dirt/frequent, -/mob/living/simple_animal/mouse/gray, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /turf/simulated/floor/plating, @@ -70262,15 +70204,6 @@ }, /turf/simulated/floor/plasteel, /area/station/hallway/primary/fore/east) -"oUR" = ( -/mob/living/simple_animal/mouse/gray, -/obj/machinery/light/small{ - dir = 1 - }, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" - }, -/area/station/maintenance/apmaint) "oVb" = ( /obj/structure/reagent_dispensers/watertank, /turf/simulated/floor/plating, @@ -72741,12 +72674,6 @@ icon_state = "bluered" }, /area/station/hallway/secondary/entry/west) -"pAV" = ( -/mob/living/simple_animal/mouse/gray, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" - }, -/area/station/maintenance/port) "pBh" = ( /obj/structure/cable/orange{ icon_state = "4-8" @@ -76374,13 +76301,6 @@ /obj/structure/flora/ausbushes/sunnybush, /turf/simulated/floor/grass, /area/station/hallway/spacebridge/scidock) -"qvA" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/mob/living/simple_animal/mouse/white, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" - }, -/area/station/maintenance/fore) "qvJ" = ( /obj/structure/lattice/catwalk, /turf/space, @@ -81989,10 +81909,6 @@ icon_state = "asteroidplating" }, /area/station/maintenance/starboard) -"rVL" = ( -/mob/living/simple_animal/mouse/gray, -/turf/simulated/floor/plating/asteroid/ancient, -/area/station/maintenance/apmaint) "rVZ" = ( /obj/machinery/door/firedoor, /obj/machinery/door_control{ @@ -86268,11 +86184,6 @@ icon_state = "cafeteria" }, /area/station/medical/break_room) -"sXA" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/white, -/turf/simulated/floor/plating, -/area/station/maintenance/port2) "sXG" = ( /obj/machinery/light{ dir = 8 @@ -106601,7 +106512,6 @@ /turf/simulated/floor/plating, /area/station/maintenance/fore) "xUz" = ( -/mob/living/simple_animal/mouse/gray, /obj/effect/decal/cleanable/dirt, /obj/structure/disposalpipe/segment/corner, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ @@ -106867,12 +106777,6 @@ }, /turf/simulated/floor/plasteel, /area/station/service/janitor) -"xXN" = ( -/mob/living/simple_animal/mouse/brown, -/turf/simulated/floor/plating{ - icon_state = "asteroidplating" - }, -/area/station/maintenance/starboard) "xXS" = ( /obj/structure/reagent_dispensers/watertank, /turf/simulated/floor/plating, @@ -119133,7 +119037,7 @@ aXn lVV qcE tiE -gWv +jee kZy lVV aXn @@ -121184,7 +121088,7 @@ aXn aXn hvI eTI -pAV +eCI pXy dHZ wzC @@ -121508,7 +121412,7 @@ wms adg fZa fdG -oUR +qlW sKh sKh wIq @@ -128427,7 +128331,7 @@ ueB rXS lSc reB -deS +reB kZd iaF aXn @@ -130608,7 +130512,7 @@ wDs wDs wDs bDo -nQU +vXM vrQ wDs afd @@ -132267,7 +132171,7 @@ rNK lzH rNK cKa -sXA +dQZ dQZ qpx shL @@ -132446,7 +132350,7 @@ wDs wDs uEX tbe -laM +vrQ bJW tbe wDs @@ -132584,7 +132488,7 @@ koR koR dHN xPU -rVL +wsR wsR cWF wIq @@ -138339,7 +138243,7 @@ vPt vPt vPt vPt -laM +vrQ aGg bbc bbc @@ -143460,7 +143364,7 @@ fFd gKc cdz rTz -qvA +bjF bjF bjF bjF @@ -144500,7 +144404,7 @@ bkp bkp mEg scz -kAu +scz vnu qIa qaI @@ -147455,7 +147359,7 @@ plQ plQ plQ rlz -mXW +imG ggK xON mJk @@ -159508,7 +159412,7 @@ xyF sVv yfZ gFg -gRw +xAV tvJ aZN aZM @@ -161292,7 +161196,7 @@ bCq bkH qhP fqw -iXy +bLj gSQ bLj bLj @@ -165357,7 +165261,7 @@ hqL cpC cpC cpC -gLX +cpC rNW gGH pMv @@ -165402,7 +165306,7 @@ vHH wyL gSQ gSQ -xXN +gFg gFg gSQ gSQ diff --git a/_maps/map_files/stations/deltastation.dmm b/_maps/map_files/stations/deltastation.dmm index 20cd6300d0bc..3db4a9ae4a1e 100644 --- a/_maps/map_files/stations/deltastation.dmm +++ b/_maps/map_files/stations/deltastation.dmm @@ -14079,7 +14079,7 @@ }, /area/station/service/kitchen) "aYD" = ( -/obj/machinery/atmospherics/unary/thermomachine/heater/on{ +/obj/machinery/atmospherics/unary/thermomachine/heater{ dir = 4 }, /turf/simulated/floor/plasteel{ @@ -16100,7 +16100,7 @@ /turf/simulated/floor/plasteel{ icon_state = "neutralfull" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bfw" = ( /obj/machinery/light{ dir = 1 @@ -18501,7 +18501,7 @@ }, /obj/effect/spawner/window/reinforced, /turf/simulated/floor/plating, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bmO" = ( /obj/structure/table, /obj/item/storage/box/prisoner, @@ -19413,7 +19413,7 @@ }, /obj/effect/turf_decal/delivery/hollow, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bpS" = ( /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 1 @@ -19924,17 +19924,17 @@ /obj/machinery/space_heater, /obj/effect/turf_decal/delivery/hollow, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "brO" = ( /obj/machinery/atmospherics/portable/canister/sleeping_agent, /obj/effect/turf_decal/delivery/hollow, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "brP" = ( /obj/machinery/atmospherics/portable/canister/nitrogen, /obj/effect/turf_decal/delivery/hollow, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "brR" = ( /obj/machinery/atmospherics/portable/canister/air, /obj/structure/sign/nosmoking_2{ @@ -19942,7 +19942,7 @@ }, /obj/effect/turf_decal/delivery/hollow, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "brS" = ( /turf/simulated/floor/plasteel, /area/station/maintenance/starboard2) @@ -20384,7 +20384,7 @@ }, /obj/effect/turf_decal/delivery, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "btt" = ( /obj/machinery/atmospherics/portable/canister/sleeping_agent, /obj/structure/cable{ @@ -20395,7 +20395,7 @@ }, /obj/effect/turf_decal/delivery/hollow, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "btu" = ( /obj/machinery/atmospherics/portable/canister/nitrogen, /obj/structure/cable{ @@ -20407,17 +20407,17 @@ }, /obj/effect/turf_decal/delivery/hollow, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "btv" = ( /obj/machinery/atmospherics/portable/canister/oxygen, /obj/effect/turf_decal/delivery/hollow, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "btw" = ( /obj/machinery/atmospherics/portable/canister/air, /obj/effect/turf_decal/delivery/hollow, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "btx" = ( /obj/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ @@ -20701,14 +20701,11 @@ dir = 1 }, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "buE" = ( /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/visible/yellow{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/simple/visible/cyan, /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -20717,7 +20714,7 @@ icon_state = "1-4" }, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "buF" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -20740,23 +20737,14 @@ /obj/machinery/firealarm/directional/east, /turf/simulated/floor/plasteel, /area/station/engineering/control) -"buI" = ( -/obj/machinery/atmospherics/pipe/simple/visible/yellow{ - dir = 4 - }, -/turf/simulated/floor/plasteel{ - dir = 1; - icon_state = "yellowcorner" - }, -/area/station/hallway/primary/port/north) "buJ" = ( /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/manifold/visible/yellow{ - dir = 1 - }, /obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/visible/yellow{ + dir = 6 + }, /turf/simulated/floor/plasteel{ icon_state = "neutralfull" }, @@ -21017,15 +21005,18 @@ dir = 8; icon_state = "caution" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bvO" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/visible/yellow{ + dir = 5 + }, /turf/simulated/floor/plasteel{ icon_state = "neutralfull" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bvP" = ( /obj/structure/cable{ icon_state = "1-2" @@ -21034,22 +21025,31 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/visible/yellow{ + dir = 4 + }, /turf/simulated/floor/plasteel{ icon_state = "neutralfull" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bvR" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/visible/yellow{ + dir = 4 + }, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bvT" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/visible/yellow{ + dir = 4 + }, /turf/simulated/floor/plasteel, /area/station/hallway/primary/port/north) "bvV" = ( @@ -21403,14 +21403,14 @@ dir = 8; icon_state = "caution" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bxc" = ( /obj/item/kirbyplants/large, /turf/simulated/floor/plasteel{ dir = 4; icon_state = "caution" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bxe" = ( /obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers, /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ @@ -21858,7 +21858,7 @@ dir = 8; icon_state = "caution" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "byB" = ( /obj/machinery/hologram/holopad, /obj/structure/cable{ @@ -21872,7 +21872,7 @@ /turf/simulated/floor/plasteel{ icon_state = "neutralfull" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "byC" = ( /obj/structure/cable{ icon_state = "4-8" @@ -21883,7 +21883,7 @@ /turf/simulated/floor/plasteel{ icon_state = "neutralfull" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "byD" = ( /obj/structure/chair/office/dark{ dir = 4 @@ -21898,7 +21898,7 @@ dir = 4; icon_state = "caution" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "byF" = ( /obj/machinery/atmospherics/pipe/simple/visible/cyan{ dir = 4 @@ -22349,7 +22349,7 @@ dir = 8; icon_state = "caution" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bzY" = ( /obj/structure/chair/office/dark{ dir = 8 @@ -22357,13 +22357,13 @@ /turf/simulated/floor/plasteel{ icon_state = "neutralfull" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bzZ" = ( /obj/structure/chair/office/dark, /turf/simulated/floor/plasteel{ icon_state = "neutralfull" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bAa" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -22381,7 +22381,7 @@ dir = 4; icon_state = "caution" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bAd" = ( /obj/structure/urinal{ pixel_y = 28 @@ -22856,7 +22856,7 @@ dir = 10; icon_state = "caution" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bBK" = ( /obj/machinery/alarm/directional/south, /obj/machinery/computer/station_alert{ @@ -22865,7 +22865,7 @@ /turf/simulated/floor/plasteel{ icon_state = "caution" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bBL" = ( /obj/machinery/light, /obj/machinery/computer/atmos_alert{ @@ -22875,7 +22875,7 @@ /turf/simulated/floor/plasteel{ icon_state = "caution" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bBM" = ( /obj/structure/table/reinforced, /obj/item/tank/internals/emergency_oxygen, @@ -22886,7 +22886,7 @@ /turf/simulated/floor/plasteel{ icon_state = "caution" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bBN" = ( /obj/structure/table/reinforced, /obj/item/paper_bin, @@ -22899,7 +22899,7 @@ dir = 6; icon_state = "caution" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "bBO" = ( /obj/structure/cable{ icon_state = "1-2" @@ -51173,7 +51173,7 @@ }, /obj/machinery/door/window{ dir = 8; - name = "Atmospherics Desk" + name = "Atmospherics Cannister Storage" }, /obj/effect/mapping_helpers/airlock/windoor/access/any/engineering/atmos{ dir = 8 @@ -51188,7 +51188,7 @@ icon_state = "1-8" }, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "dxD" = ( /obj/structure/cable{ icon_state = "1-2" @@ -51982,6 +51982,10 @@ icon_state = "neutral" }, /area/station/maintenance/apmaint) +"dCK" = ( +/obj/machinery/status_display, +/turf/simulated/wall/r_wall, +/area/station/engineering/atmos/control) "dCU" = ( /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, @@ -58995,6 +58999,10 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/theatre) +"fvB" = ( +/obj/effect/spawner/window/reinforced, +/turf/simulated/floor/plating, +/area/station/engineering/atmos/control) "fvQ" = ( /obj/structure/cable{ icon_state = "1-2" @@ -59878,6 +59886,17 @@ /obj/machinery/alarm/directional/north, /turf/simulated/floor/plasteel/dark, /area/station/engineering/smes) +"fQW" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/cable{ + d2 = 8; + icon_state = "0-8" + }, +/obj/machinery/power/apc/important/directional/east, +/turf/simulated/floor/plasteel, +/area/station/engineering/atmos/control) "fRa" = ( /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/hidden/supply, @@ -59941,12 +59960,10 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/visible/yellow{ - dir = 5 - }, /obj/structure/disposalpipe/sortjunction{ sort_type_txt = "6" }, +/obj/machinery/atmospherics/pipe/manifold/visible/yellow, /turf/simulated/floor/plasteel{ icon_state = "neutralfull" }, @@ -64542,16 +64559,6 @@ /obj/effect/mapping_helpers/turfs/damage, /turf/simulated/floor/wood, /area/station/maintenance/abandonedbar) -"iFv" = ( -/obj/machinery/atmospherics/pipe/simple/visible/yellow{ - dir = 4 - }, -/obj/effect/spawner/window/reinforced/grilled, -/obj/structure/cable{ - icon_state = "0-8" - }, -/turf/simulated/floor/plating, -/area/station/engineering/atmos) "iFB" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -67339,6 +67346,11 @@ /obj/effect/spawner/random/maintenance, /turf/simulated/floor/plating, /area/station/maintenance/aft) +"kmY" = ( +/turf/simulated/floor/plasteel{ + icon_state = "neutralfull" + }, +/area/station/engineering/atmos/control) "kna" = ( /obj/machinery/hologram/holopad, /obj/machinery/atmospherics/pipe/simple/hidden/supply, @@ -69334,8 +69346,11 @@ /obj/effect/mapping_helpers/airlock/windoor/access/any/engineering/atmos{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/visible/yellow{ + dir = 4 + }, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "ltY" = ( /obj/structure/cable{ icon_state = "4-8" @@ -75207,7 +75222,7 @@ "oLu" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/atmos/glass{ - name = "Atmospherics Desk" + name = "Atmospherics Cannister Storage" }, /obj/effect/mapping_helpers/airlock/access/all/engineering/atmos, /obj/structure/cable{ @@ -75217,7 +75232,7 @@ dir = 4 }, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "oLv" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 9 @@ -76956,7 +76971,7 @@ /turf/simulated/floor/plasteel{ icon_state = "neutralfull" }, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "pHd" = ( /obj/structure/closet/emcloset, /turf/simulated/floor/plating, @@ -78930,7 +78945,7 @@ icon_state = "0-2" }, /turf/simulated/floor/plating, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "qQv" = ( /obj/effect/turf_decal/delivery, /obj/machinery/door/firedoor, @@ -79785,9 +79800,6 @@ /turf/simulated/floor/plasteel, /area/station/security/brig) "rke" = ( -/obj/machinery/atmospherics/pipe/simple/visible/yellow{ - dir = 4 - }, /obj/effect/turf_decal/stripes/line{ dir = 1 }, @@ -79795,7 +79807,7 @@ icon_state = "4-8" }, /turf/simulated/floor/plasteel, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "rkt" = ( /obj/machinery/atmospherics/unary/vent_pump/on, /turf/simulated/floor/bluegrid{ @@ -80220,6 +80232,9 @@ icon_state = "dark" }, /area/station/security/prisonershuttle) +"rvv" = ( +/turf/simulated/wall/r_wall, +/area/station/engineering/atmos/control) "rvx" = ( /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 8 @@ -82799,7 +82814,7 @@ /obj/structure/cable, /obj/effect/spawner/window/reinforced/grilled, /turf/simulated/floor/plating, -/area/station/engineering/atmos) +/area/station/engineering/atmos/control) "sIB" = ( /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 1 @@ -83137,13 +83152,6 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/solar_maintenance/aft_starboard) -"sQr" = ( -/mob/living/simple_animal/mouse, -/obj/machinery/light/small{ - dir = 1 - }, -/turf/simulated/floor/plating, -/area/station/maintenance/port) "sQw" = ( /obj/structure/weightmachine/stacklifter, /turf/simulated/floor/plasteel{ @@ -86307,6 +86315,17 @@ /obj/effect/spawner/window/reinforced/grilled, /turf/simulated/floor/plating, /area/station/service/chapel) +"uvO" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/visible/yellow{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + icon_state = "neutralfull" + }, +/area/station/engineering/atmos/control) "uwm" = ( /obj/structure/cable{ icon_state = "4-8" @@ -89263,16 +89282,21 @@ icon_state = "neutralcorner" }, /area/station/hallway/primary/central) +"wbs" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/visible/yellow{ + dir = 10 + }, +/turf/simulated/floor/plasteel, +/area/station/engineering/atmos/control) "wbZ" = ( /obj/machinery/atmospherics/unary/portables_connector, /turf/simulated/floor/plasteel{ icon_state = "whitepurple" }, /area/station/science/toxins/mixing) -"wce" = ( -/mob/living/simple_animal/mouse/white, -/turf/simulated/floor/plating, -/area/station/security/permabrig) "wcu" = ( /obj/machinery/atmospherics/unary/cryo_cell, /turf/simulated/floor/plasteel{ @@ -113466,7 +113490,7 @@ cWl unt lxh cHA -sQr +ddg sZp nCh cHA @@ -120354,17 +120378,17 @@ jgG mzZ osF bmI -aOg -aOg -aOb +rvv +rvv +fvB oLu bmN -aOg -aOg -aOg -aOg -aOg -aOg +rvv +rvv +rvv +rvv +rvv +rvv bFb bGI bIA @@ -120611,7 +120635,7 @@ emu ban osF bmJ -aOg +rvv brN brN bts @@ -120621,7 +120645,7 @@ bxb byz bzX bBJ -aOg +rvv bFc bGH bIF @@ -120868,17 +120892,17 @@ vnK bhp bkN bmK -aOg +rvv brO brO btt -buD +wbs bvO -ban +kmY bzY bzY bBK -aOg +rvv byl kWX byl @@ -121125,7 +121149,7 @@ jJc biZ bkO aQZ -aOg +rvv bpQ brP btu @@ -121135,7 +121159,7 @@ bfv byB bzZ bBL -aOg +rvv bFd bGK bID @@ -121382,17 +121406,17 @@ bhr bja bkP bmM -aOg +rvv btv btv btv rke -bvO -ban +uvO +kmY byC pGT bBM -aOg +rvv bFe bGM kIs @@ -121639,17 +121663,17 @@ rcz qJW aOg keu -aOg +rvv btw brR btw -rke +fQW bvR bxc byD bAb bBN -aOg +rvv bFf bGL bII @@ -121896,17 +121920,17 @@ aSM buX bkQ aOW -aOg -aOg -aOg -bvK -iFv +rvv +rvv +rvv +dCK +rvv ltX qPT dxC sIz -aOg -aOg +rvv +rvv naB xcs mvr @@ -122157,7 +122181,7 @@ bcP bpU bty bty -buI +bty bvT bty byF @@ -147830,7 +147854,7 @@ aaa aaa ygH coI -wce +aQx aQx mtL aKU diff --git a/_maps/map_files/stations/emeraldstation.dmm b/_maps/map_files/stations/emeraldstation.dmm index a68fc3bff64c..9f2849174a69 100644 --- a/_maps/map_files/stations/emeraldstation.dmm +++ b/_maps/map_files/stations/emeraldstation.dmm @@ -2023,6 +2023,10 @@ "ave" = ( /turf/simulated/floor/plasteel, /area/station/supply/storage) +"avi" = ( +/obj/structure/sign/poster/official/random, +/turf/simulated/wall, +/area/station/public/dorms) "avk" = ( /obj/item/cigbutt/roach, /turf/simulated/floor/plating, @@ -14361,11 +14365,6 @@ "cRi" = ( /turf/simulated/wall, /area/station/security/main) -"cRk" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/apmaint2) "cRu" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -15265,6 +15264,12 @@ icon_state = "darkredcorners" }, /area/station/hallway/spacebridge/security/south) +"dbV" = ( +/obj/machinery/firealarm/directional/north, +/turf/simulated/floor/plasteel{ + icon_state = "neutral" + }, +/area/station/public/dorms) "dbY" = ( /obj/machinery/atmospherics/pipe/simple/hidden/purple{ dir = 5 @@ -15571,7 +15576,6 @@ /turf/simulated/floor/plasteel, /area/station/engineering/hardsuitstorage) "dfs" = ( -/mob/living/simple_animal/mouse, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /turf/simulated/floor/wood, /area/station/maintenance/abandoned_office) @@ -22315,7 +22319,6 @@ /obj/structure/cable{ icon_state = "2-8" }, -/mob/living/simple_animal/mouse, /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 4 }, @@ -22647,6 +22650,7 @@ /area/station/service/bar) "eBG" = ( /obj/structure/chair/sofa, +/obj/machinery/firealarm/directional/north, /turf/simulated/floor/carpet, /area/station/public/dorms) "eBM" = ( @@ -27696,6 +27700,9 @@ /obj/machinery/status_display{ pixel_y = 32 }, +/obj/machinery/light{ + dir = 1 + }, /turf/simulated/floor/plasteel{ icon_state = "neutral" }, @@ -37950,7 +37957,6 @@ "hzk" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/generic, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plating, /area/station/maintenance/security/aft_starboard) "hzA" = ( @@ -40382,11 +40388,6 @@ /obj/machinery/atmospherics/meter, /turf/simulated/floor/engine, /area/station/engineering/engine) -"iam" = ( -/obj/effect/spawner/random/oil/maybe, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/security/fore) "iaw" = ( /obj/structure/cable{ icon_state = "1-4" @@ -53384,11 +53385,6 @@ icon_state = "dark" }, /area/station/aisat/atmos) -"kCz" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/apmaint2) "kCA" = ( /turf/simulated/floor/plasteel{ dir = 4; @@ -53530,18 +53526,6 @@ /obj/machinery/hologram/holopad, /turf/simulated/floor/carpet, /area/station/public/vacant_office) -"kGm" = ( -/obj/machinery/light{ - dir = 1 - }, -/obj/structure/extinguisher_cabinet{ - name = "north bump"; - pixel_y = 30 - }, -/turf/simulated/floor/plasteel{ - icon_state = "neutral" - }, -/area/station/public/dorms) "kGu" = ( /obj/structure/table, /obj/machinery/kitchen_machine/microwave{ @@ -55255,11 +55239,6 @@ /obj/machinery/economy/vending/boozeomat, /turf/simulated/floor/wood, /area/station/maintenance/abandonedbar) -"kXa" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/dorms/port) "kXf" = ( /obj/structure/cable{ icon_state = "1-4" @@ -57417,15 +57396,6 @@ /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, /area/station/maintenance/dorms/starboard) -"lut" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan, -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/security/fore) "luC" = ( /obj/effect/decal/cleanable/confetti, /obj/effect/decal/cleanable/dirt, @@ -60029,7 +59999,6 @@ /area/station/supply/lobby) "lWJ" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, /obj/item/trash/spentcasing/shotgun, /turf/simulated/floor/wood, /area/station/maintenance/dorms/starboard) @@ -62111,6 +62080,10 @@ dir = 8 }, /obj/effect/landmark/start/assistant, +/obj/item/radio/intercom{ + name = "east bump"; + pixel_x = 28 + }, /turf/simulated/floor/plasteel{ dir = 8; icon_state = "neutral" @@ -64966,12 +64939,6 @@ /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, /area/station/maintenance/starboard) -"mXx" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/random/oil/maybe, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/apmaint) "mXy" = ( /obj/structure/closet/secure_closet/miner, /obj/machinery/firealarm/directional/north, @@ -67721,14 +67688,6 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/fpmaint) -"nzU" = ( -/mob/living/simple_animal/mouse, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan{ - dir = 4 - }, -/turf/simulated/floor/plasteel, -/area/station/maintenance/apmaint2) "nAc" = ( /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel{ @@ -68402,12 +68361,6 @@ }, /turf/simulated/floor/plating, /area/station/engineering/secure_storage) -"nGt" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/starboard) "nGw" = ( /obj/structure/cable{ icon_state = "4-8" @@ -69417,11 +69370,6 @@ icon_state = "white" }, /area/station/science/toxins/mixing) -"nPx" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/starboard) "nPG" = ( /obj/item/kirbyplants/large, /turf/simulated/floor/plasteel, @@ -69709,11 +69657,6 @@ /obj/effect/spawner/window/reinforced, /turf/simulated/floor/plating, /area/station/medical/virology) -"nSa" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/dorms/fore) "nSe" = ( /turf/simulated/floor/plating/airless, /area/station/aisat/hall) @@ -74339,7 +74282,6 @@ /turf/simulated/wall, /area/station/engineering/tech_storage) "oMl" = ( -/mob/living/simple_animal/mouse/white, /obj/effect/landmark/spawner/nukedisc_respawn, /turf/simulated/floor/plating, /area/station/maintenance/security/fore) @@ -76854,7 +76796,6 @@ /area/station/engineering/break_room/secondary) "piI" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/white, /obj/structure/cable{ icon_state = "4-8" }, @@ -77545,11 +77486,6 @@ /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, /area/station/maintenance/dorms/port) -"pqt" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/fpmaint) "pqI" = ( /obj/structure/chair{ dir = 1 @@ -79200,10 +79136,6 @@ icon_state = "dark" }, /area/station/medical/morgue) -"pHV" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/asmaint) "pHX" = ( /obj/machinery/atmospherics/pipe/simple/visible/yellow{ dir = 4 @@ -81964,11 +81896,6 @@ }, /turf/simulated/floor/plating/airless, /area/station/aisat/hall) -"qmI" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/fpmaint) "qmJ" = ( /obj/machinery/power/apc/directional/south, /obj/structure/cable, @@ -95430,11 +95357,6 @@ "sTG" = ( /turf/simulated/wall, /area/station/science/genetics) -"sTI" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/starboard) "sTJ" = ( /obj/effect/spawner/random/barrier/grille_maybe, /obj/effect/decal/cleanable/dirt, @@ -97280,9 +97202,7 @@ /turf/simulated/floor/plasteel, /area/station/hallway/primary/central/sw) "tlu" = ( -/obj/structure/sign/poster/official/random{ - pixel_x = -32 - }, +/obj/machinery/firealarm/directional/west, /turf/simulated/floor/plasteel{ dir = 4; icon_state = "neutral" @@ -97503,9 +97423,9 @@ /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 8 }, -/obj/item/radio/intercom{ +/obj/structure/extinguisher_cabinet{ name = "east bump"; - pixel_x = 28 + pixel_x = 30 }, /turf/simulated/floor/plasteel{ dir = 8; @@ -104080,6 +104000,13 @@ icon_state = "cult" }, /area/station/legal/lawoffice) +"uDE" = ( +/obj/machinery/firealarm/directional/south, +/turf/simulated/floor/plasteel{ + dir = 1; + icon_state = "neutral" + }, +/area/station/public/dorms) "uDO" = ( /obj/structure/table, /obj/effect/spawner/random/maintenance, @@ -106032,12 +105959,6 @@ icon_state = "cult" }, /area/station/legal/magistrate) -"uWS" = ( -/obj/effect/decal/cleanable/generic, -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/dorms/starboard) "uWU" = ( /obj/item/kirbyplants/large, /turf/simulated/floor/plasteel{ @@ -106416,7 +106337,6 @@ /obj/machinery/atmospherics/pipe/simple/hidden/cyan{ dir = 10 }, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plasteel{ dir = 6; icon_state = "whiteblue" @@ -109607,10 +109527,6 @@ icon_state = "dark" }, /area/station/security/brig) -"vJc" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/aft2) "vJm" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ @@ -112035,7 +111951,6 @@ "whf" = ( /obj/effect/mapping_helpers/turfs/damage, /obj/effect/decal/cleanable/generic, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plating, /area/station/maintenance/security/aft_starboard) "whh" = ( @@ -132942,7 +132857,7 @@ ipM hcH uPm bqU -nzU +xQq bGM xKc rPz @@ -134484,7 +134399,7 @@ mIg eyo opq yiE -cRk +opq xQq fMB aco @@ -138572,7 +138487,7 @@ qXp xrG feI idv -mXx +eBv sqZ mQe lQZ @@ -140149,7 +140064,7 @@ oeh pdx vSD cBD -kCz +fMB lUy eJa sqB @@ -146500,7 +146415,7 @@ ndJ qZs qci lfn -qmI +vWJ gmL nwf nwf @@ -148266,7 +148181,7 @@ aSK wIh qci vWJ -pqt +eMT vWJ vWJ eMT @@ -150115,7 +150030,7 @@ giS giS onz rpb -eUn +tlu eUn eUn qDZ @@ -150359,7 +150274,7 @@ vIv uJr nXW tyb -bvA +dbV njj kgg kgg @@ -151159,7 +151074,7 @@ dsL twa vIV ril -kXa +ewj xmm rxd iSc @@ -154498,7 +154413,7 @@ bQA vAZ vAZ vAZ -vAZ +avi vAZ obO rxd @@ -154743,7 +154658,7 @@ eUn uIz eUn tfk -eUn +tlu xzA eEe vfx @@ -154752,7 +154667,7 @@ eUn eUn eUn neS -tlu +eUn xjx tfk eUn @@ -155495,7 +155410,7 @@ vAZ vAZ vAZ vAZ -kGm +dbV xoK nuI eOw @@ -158608,7 +158523,7 @@ egS gsU fRA oPi -uWS +pIl xmi cPy kcb @@ -158840,7 +158755,7 @@ rjc vAZ xCR urb -sRm +uDE tZO tZO xYm @@ -159084,7 +158999,7 @@ soN dlV iNN syn -nSa +sul ydG rNs rtR @@ -159912,7 +159827,7 @@ lRd snP aIj rWj -vJc +xaN bVp dtF bTR @@ -162123,7 +162038,7 @@ iBy gbl oei iXk -lut +plQ oIH cwI cwI @@ -168812,7 +168727,7 @@ cwI cwI qTH xEt -iam +cuO fsJ lVs vKT @@ -169161,7 +169076,7 @@ mXw tVw dGc qFP -nGt +iPH bpH bpH bpp @@ -172792,7 +172707,7 @@ qDC bNH jnC jnC -pHV +uMS ugn nuJ kTf @@ -172988,7 +172903,7 @@ fIk stp stp oAs -sTI +mXw bnw tlf eDe @@ -174554,7 +174469,7 @@ oTL mXw mIH nWG -nPx +jcy aQl caq pga diff --git a/_maps/map_files/stations/metastation.dmm b/_maps/map_files/stations/metastation.dmm index 4c6a3e2b3c25..fce3b01e5709 100644 --- a/_maps/map_files/stations/metastation.dmm +++ b/_maps/map_files/stations/metastation.dmm @@ -834,11 +834,6 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/solar_maintenance/fore_port) -"ajD" = ( -/mob/living/simple_animal/mouse, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/catwalk, -/area/station/maintenance/fore) "ajE" = ( /obj/structure/cable{ icon_state = "0-4" @@ -12476,7 +12471,6 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/mob/living/simple_animal/mouse, /obj/structure/cable{ icon_state = "2-4" }, @@ -15610,10 +15604,6 @@ /obj/effect/spawner/random/maintenance, /turf/simulated/floor/plating, /area/station/maintenance/fpmaint) -"bmA" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/fpmaint) "bmE" = ( /obj/machinery/newscaster/directional/east, /obj/structure/disposalpipe/segment/corner{ @@ -27082,16 +27072,6 @@ icon_state = "C11" }, /area/station/hallway/primary/central/south) -"cbb" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/mob/living/simple_animal/mouse, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/simulated/floor/plasteel, -/area/station/maintenance/fsmaint) "cbc" = ( /obj/effect/spawner/random/fungus/maybe, /turf/simulated/wall/r_wall, @@ -29744,11 +29724,6 @@ /obj/structure/lattice, /turf/space, /area/space/nearstation) -"clJ" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/turbine) "clK" = ( /obj/structure/closet, /obj/item/extinguisher, @@ -36644,10 +36619,6 @@ }, /turf/simulated/floor/plating/airless, /area/station/science/toxins/test) -"cOU" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/port) "cOV" = ( /obj/machinery/button/windowtint{ dir = 1; @@ -36991,7 +36962,6 @@ "cQt" = ( /obj/effect/mapping_helpers/turfs/burn, /obj/machinery/light/small, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plating, /area/station/maintenance/medmaint) "cQu" = ( @@ -39260,10 +39230,6 @@ icon_state = "whiteblue" }, /area/station/medical/exam_room) -"dbH" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/aft) "dbI" = ( /obj/machinery/atmospherics/pipe/simple/hidden/cyan, /obj/structure/cable{ @@ -47169,10 +47135,6 @@ }, /turf/simulated/floor/plasteel, /area/station/hallway/secondary/exit) -"gof" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/apmaint) "goq" = ( /obj/structure/closet/secure_closet/hos, /obj/item/cartridge/detective, @@ -47934,7 +47896,6 @@ dir = 5 }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plasteel, /area/station/maintenance/starboard2) "gHh" = ( @@ -48677,11 +48638,6 @@ }, /turf/simulated/floor/plasteel, /area/station/maintenance/aft2) -"gWz" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/fsmaint) "gWE" = ( /obj/machinery/atmospherics/pipe/simple/hidden{ dir = 4 @@ -51910,10 +51866,6 @@ }, /turf/simulated/floor/engine, /area/station/engineering/control) -"isf" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/fsmaint) "isB" = ( /obj/machinery/door/airlock/engineering/glass{ autoclose = 0; @@ -57262,10 +57214,6 @@ icon_state = "red" }, /area/station/security/checkpoint/secondary) -"kQF" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/wood, -/area/station/maintenance/starboard) "kRc" = ( /obj/structure/cable{ icon_state = "1-8" @@ -66844,11 +66792,6 @@ }, /turf/simulated/floor/plating, /area/station/medical/virology) -"peg" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/starboard2) "pej" = ( /obj/structure/cable{ icon_state = "1-2" @@ -69577,10 +69520,6 @@ icon_state = "white" }, /area/station/maintenance/aft) -"qoK" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/starboard2) "qoQ" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -70757,7 +70696,6 @@ }, /area/station/security/interrogation) "qRm" = ( -/mob/living/simple_animal/mouse, /obj/effect/spawner/random/oil/maybe, /turf/simulated/floor/plasteel, /area/station/maintenance/fore) @@ -76381,10 +76319,6 @@ icon_state = "whitepurplecorner" }, /area/station/science/research) -"tnW" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/starboard) "toc" = ( /obj/structure/sign/electricshock, /turf/simulated/wall/r_wall, @@ -79948,7 +79882,6 @@ dir = 6 }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, /obj/structure/cable{ icon_state = "2-4" }, @@ -80308,7 +80241,6 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/mob/living/simple_animal/mouse, /obj/machinery/atmospherics/pipe/simple/hidden/cyan{ dir = 4 }, @@ -83377,10 +83309,6 @@ /obj/structure/sign/biohazard, /turf/simulated/wall/r_wall, /area/station/science/research) -"wLB" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/fore) "wMb" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -86663,7 +86591,6 @@ /area/station/engineering/atmos/distribution) "yih" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, -/mob/living/simple_animal/mouse, /obj/machinery/light/small{ dir = 4 }, @@ -86672,10 +86599,6 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/starboard2) -"yiP" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/fore) "yiU" = ( /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -99426,7 +99349,7 @@ qCK aOB aOB adY -bmA +adY aOB aLF aML @@ -103089,7 +103012,7 @@ cpD crG bZP clK -gof +crG crG bZP aaa @@ -104864,7 +104787,7 @@ cdT cdT cdT cdT -cOU +bTY xOy aSM aSM @@ -105587,7 +105510,7 @@ awh hka imw adY -bmA +adY aOB bmK bgA @@ -106196,7 +106119,7 @@ chy tPO eJG czw -dbH +chy bZU abq aaa @@ -118673,7 +118596,7 @@ nEV nEV awp aDY -wLB +alW cnV nVQ whf @@ -119978,7 +119901,7 @@ nSs acL aWv aFj -yiP +fpy bne ajg iGR @@ -121842,7 +121765,7 @@ dtC cte gnS cFB -peg +gSO ipj cmB qub @@ -124109,7 +124032,7 @@ aLl ayv aLl apL -isf +avA eiI aLl bdt @@ -124844,7 +124767,7 @@ aaa aaa aaa ahH -ajD +oTt azu awp air @@ -124869,7 +124792,7 @@ gip nET blB wYm -cbb +blB beF juq apV @@ -124925,7 +124848,7 @@ bPj wdY cte cqE -qoK +cwG dhw dhw bUz @@ -125374,7 +125297,7 @@ air aBZ iAS oyN -gWz +cxr hgU aLl fpk @@ -125410,7 +125333,7 @@ aoG aoG aoG dSv -tnW +asJ nWJ oXK aoG @@ -126462,7 +126385,7 @@ cfL ciu ciH aRQ -clJ +aRQ biB bul clB @@ -126707,7 +126630,7 @@ kbr vud axh cyv -kQF +ovR bZH fTV nXk diff --git a/_maps/map_files220/stations/boxstation.dmm b/_maps/map_files220/stations/boxstation.dmm index 11bc93b7d85c..cf04fd78f2e8 100644 --- a/_maps/map_files220/stations/boxstation.dmm +++ b/_maps/map_files220/stations/boxstation.dmm @@ -31,7 +31,6 @@ "aag" = ( /obj/machinery/hologram/holopad, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plasteel, /area/station/maintenance/incinerator) "aah" = ( @@ -3523,7 +3522,6 @@ dir = 8 }, /obj/machinery/light/small/directional/east, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plating, /area/station/maintenance/fore) "aqu" = ( @@ -4916,7 +4914,6 @@ dir = 1 }, /obj/item/stack/cable_coil/random, -/mob/living/simple_animal/mouse/white, /turf/simulated/floor/plating, /area/station/maintenance/fpmaint) "avF" = ( @@ -7504,7 +7501,6 @@ "aDY" = ( /obj/item/stack/tile/plasteel, /obj/effect/decal/cleanable/dust, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plating, /area/station/maintenance/abandonedbar) "aDZ" = ( @@ -7690,7 +7686,6 @@ /area/station/maintenance/fpmaint2) "aEK" = ( /obj/structure/chair, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/wood/oak, /area/station/maintenance/fpmaint2) "aEL" = ( @@ -8028,7 +8023,6 @@ /area/station/maintenance/fsmaint) "aFN" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/brown, /obj/effect/spawner/random/blood/maybe, /turf/simulated/floor/plasteel{ icon_state = "stage_bleft" @@ -8439,7 +8433,6 @@ "aHd" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/simple/hidden/cyan, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plasteel{ icon_state = "stage_bleft" }, @@ -8780,7 +8773,6 @@ /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 1 }, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plating, /area/station/maintenance/fsmaint) "aIw" = ( @@ -9209,7 +9201,6 @@ /turf/simulated/floor/plating, /area/shuttle/pod_2) "aJW" = ( -/mob/living/simple_animal/mouse, /obj/structure/cable{ icon_state = "1-2" }, @@ -9223,11 +9214,6 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/fpmaint2) -"aJY" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/fpmaint2) "aKa" = ( /obj/structure/closet, /obj/effect/spawner/random/maintenance, @@ -11049,10 +11035,6 @@ icon_state = "arrival" }, /area/station/hallway/secondary/entry) -"aRg" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/fpmaint2) "aRh" = ( /obj/machinery/sleeper{ dir = 4 @@ -21766,10 +21748,6 @@ }, /turf/simulated/wall/r_wall, /area/station/maintenance/port) -"bKH" = ( -/mob/living/simple_animal/mouse/gray, -/turf/simulated/floor/plating, -/area/station/maintenance/port) "bKI" = ( /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 4 @@ -27832,13 +27810,6 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/asmaint2) -"clF" = ( -/mob/living/simple_animal/mouse, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan{ - dir = 4 - }, -/turf/simulated/floor/wood/oak, -/area/station/maintenance/apmaint) "clH" = ( /obj/machinery/camera{ c_tag = "Research Toxins Test Chamber North"; @@ -29057,7 +29028,6 @@ /area/station/engineering/ai_transit_tube) "cqK" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 4 }, @@ -30213,15 +30183,6 @@ /obj/item/stack/rods, /turf/simulated/floor/plasteel, /area/station/maintenance/apmaint) -"cvl" = ( -/mob/living/simple_animal/mouse/gray, -/obj/effect/decal/cleanable/dirt, -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/simulated/floor/plasteel, -/area/station/maintenance/port) "cvm" = ( /obj/item/clothing/gloves/color/rainbow, /obj/item/clothing/shoes/rainbow, @@ -31387,7 +31348,6 @@ /obj/structure/sign/nosmoking_2{ pixel_x = -28 }, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plating, /area/station/maintenance/incinerator) "czJ" = ( @@ -40983,10 +40943,6 @@ icon_state = "purple" }, /area/station/maintenance/fsmaint) -"dkv" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/asmaint) "dky" = ( /obj/machinery/camera{ c_tag = "Central Hallway North-East" @@ -49432,13 +49388,6 @@ }, /turf/simulated/floor/plasteel, /area/station/hallway/secondary/entry) -"fMK" = ( -/mob/living/simple_animal/mouse, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/simulated/floor/plating, -/area/station/maintenance/fpmaint2) "fMM" = ( /obj/structure/flora/grass/jungle, /turf/simulated/floor/grass, @@ -52646,13 +52595,6 @@ icon_state = "neutralfull" }, /area/station/hallway/secondary/exit) -"gUp" = ( -/obj/item/holder/mouse, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan{ - dir = 4 - }, -/turf/simulated/floor/plating, -/area/station/maintenance/apmaint) "gUq" = ( /obj/machinery/light/directional/north, /turf/simulated/floor/plasteel{ @@ -54209,13 +54151,6 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/apmaint) -"hwW" = ( -/obj/effect/decal/cleanable/dust, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/station/security/interrogation) "hxo" = ( /obj/machinery/atmospherics/unary/vent_pump/on, /turf/simulated/floor/plasteel, @@ -56898,10 +56833,6 @@ icon_state = "hydrofloor" }, /area/station/public/toilet/unisex) -"iBM" = ( -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plating, -/area/station/maintenance/asmaint) "iBP" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable{ @@ -57136,10 +57067,6 @@ /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, /area/station/maintenance/asmaint2) -"iFW" = ( -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/wood/oak, -/area/station/maintenance/aft) "iGq" = ( /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 8 @@ -58993,10 +58920,6 @@ icon_state = "neutralfull" }, /area/station/public/dorms) -"jrA" = ( -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plasteel, -/area/station/maintenance/aft) "jrD" = ( /obj/effect/decal/cleanable/dust, /obj/machinery/atmospherics/unary/vent_pump/on{ @@ -60388,13 +60311,6 @@ icon_state = "dark" }, /area/station/security/armory/secure) -"jUn" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/cyan{ - dir = 4 - }, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/wood/oak, -/area/station/maintenance/abandonedbar) "jUq" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -61344,11 +61260,6 @@ /obj/effect/landmark/start/psychiatrist, /turf/simulated/floor/carpet, /area/station/medical/psych) -"koT" = ( -/obj/structure/flora/grass/jungle, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/grass, -/area/station/security/permabrig) "kpx" = ( /obj/structure/closet/secure_closet/engineering_personal, /obj/effect/turf_decal/delivery/hollow, @@ -61684,7 +61595,6 @@ /obj/structure/chair/sofa/pew{ dir = 1 }, -/mob/living/simple_animal/mouse/gray, /obj/effect/turf_decal/siding/wood/oak, /turf/simulated/floor/wood/oak, /area/station/maintenance/abandonedbar) @@ -63133,7 +63043,6 @@ /obj/structure/cable{ icon_state = "1-8" }, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -63674,12 +63583,6 @@ /obj/effect/landmark/start/assistant, /turf/simulated/floor/transparent/glass/reinforced, /area/station/public/dorms) -"lhl" = ( -/obj/item/trash/pistachios, -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plating, -/area/station/maintenance/asmaint) "lhs" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/effect/turf_decal/stripes/corner{ @@ -65232,7 +65135,6 @@ /area/station/maintenance/turbine) "lMP" = ( /obj/structure/sign/poster/contraband/random/north, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/wood/oak, /area/station/maintenance/aft) "lNb" = ( @@ -65871,7 +65773,6 @@ /turf/simulated/floor/wood, /area/station/public/mrchangs) "lXG" = ( -/mob/living/simple_animal/mouse, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -67746,17 +67647,6 @@ icon_state = "neutralfull" }, /area/station/public/dorms) -"mHb" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan{ - dir = 4 - }, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plating, -/area/station/maintenance/fpmaint2) "mHh" = ( /obj/effect/spawner/window/reinforced/polarized/grilled{ id = "hos_room" @@ -69614,10 +69504,6 @@ icon_state = "darkred" }, /area/station/security/brig) -"nte" = ( -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plating, -/area/station/maintenance/aft) "ntg" = ( /mob/living/simple_animal/hostile/retaliate/goat/chef, /obj/structure/disposalpipe/segment, @@ -70582,11 +70468,6 @@ icon_state = "whitepurple" }, /area/station/science/toxins/mixing) -"nMz" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/turbine) "nME" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 10 @@ -74877,11 +74758,6 @@ icon_state = "dark" }, /area/station/security/interrogation) -"pnE" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plating, -/area/station/maintenance/aft) "pnG" = ( /obj/structure/railing, /obj/effect/turf_decal/siding/yellow, @@ -76624,22 +76500,6 @@ /obj/machinery/light_switch/east, /turf/simulated/floor/plasteel, /area/station/supply/office) -"pUR" = ( -/mob/living/simple_animal/mouse, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan{ - dir = 4 - }, -/turf/simulated/floor/plating, -/area/station/maintenance/asmaint2) "pUS" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ @@ -78223,11 +78083,6 @@ }, /turf/simulated/floor/bluegrid, /area/station/turret_protected/ai) -"qyy" = ( -/obj/item/holder/mouse, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/plating, -/area/station/maintenance/apmaint) "qyM" = ( /obj/structure/cable/yellow, /obj/machinery/computer/monitor{ @@ -78431,17 +78286,6 @@ }, /turf/simulated/floor/plasteel, /area/station/maintenance/fpmaint) -"qCJ" = ( -/obj/structure/curtain/open/shower, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/shower{ - pixel_y = 20 - }, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plasteel{ - icon_state = "freezerfloor" - }, -/area/station/maintenance/disposal) "qCM" = ( /obj/machinery/atmospherics/air_sensor{ autolink_id = "sm_sen_cont"; @@ -83058,7 +82902,6 @@ "ssL" = ( /obj/effect/spawner/random/maintenance, /obj/item/clothing/gloves/color/blue, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plasteel{ icon_state = "freezerfloor" }, @@ -83499,13 +83342,6 @@ icon_state = "darkgreen" }, /area/station/procedure/trainer_office) -"sAy" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/cyan{ - dir = 4 - }, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plating, -/area/station/maintenance/fpmaint2) "sAB" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/blood, @@ -85476,11 +85312,6 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply, /turf/simulated/floor/plasteel, /area/station/hallway/primary/central/sw) -"tkN" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plating, -/area/station/maintenance/aft) "tkW" = ( /obj/machinery/atmospherics/pipe/manifold/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ @@ -89912,7 +89743,6 @@ /obj/effect/turf_decal/stripes/line{ dir = 5 }, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plating, /area/station/maintenance/disposal) "uUf" = ( @@ -90155,7 +89985,6 @@ "uYz" = ( /obj/effect/decal/cleanable/dust, /obj/machinery/atmospherics/unary/vent_pump/on, -/mob/living/simple_animal/mouse, /turf/simulated/floor/wood/oak, /area/station/maintenance/abandonedbar) "uYB" = ( @@ -90487,11 +90316,6 @@ icon_state = "rampbottom" }, /area/station/service/bar/atrium) -"veM" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plating, -/area/station/maintenance/asmaint) "veP" = ( /turf/simulated/wall, /area/station/legal/courtroom/gallery) @@ -92415,15 +92239,6 @@ icon_state = "whitebluefull" }, /area/station/medical/storage) -"vON" = ( -/obj/machinery/shower{ - dir = 4 - }, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plasteel{ - icon_state = "freezerfloor" - }, -/area/station/security/permabrig) "vOR" = ( /obj/machinery/atmospherics/unary/vent_pump/on, /turf/simulated/floor/plasteel{ @@ -94299,7 +94114,6 @@ "wAW" = ( /obj/structure/sink/directional/east, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plating, /area/station/maintenance/apmaint) "wBf" = ( @@ -97528,7 +97342,6 @@ dir = 6 }, /obj/effect/spawner/random/blood/maybe, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plating, /area/station/maintenance/fsmaint) "xLj" = ( @@ -113085,14 +112898,14 @@ aEE aFS aHh gnV -fMK +ngO aVa jgi krJ aGn aPW aQb -aRg +aHS aHl aGn rPS @@ -114625,11 +114438,11 @@ bat aDA aEH aEJ -aJY +aHl aIK aGn aHS -mHb +miW aGn aKW aRp @@ -114657,7 +114470,7 @@ blM bvq cho iDG -cvl +jqo wHo pwm ebP @@ -117198,7 +117011,7 @@ oxe wwc uJB uKQ -sAy +jjl aHS aHS aHl @@ -117259,7 +117072,7 @@ puo vKe fGI bCf -qCJ +kwZ dTL cwx cyc @@ -117444,7 +117257,7 @@ oBb rAe luh lEA -vON +luh xPE aaa aaa @@ -118228,7 +118041,7 @@ aaa aaa aII dEG -aRg +aHS aIx aJX nIM @@ -119287,7 +119100,7 @@ bnK dCN pvp blQ -bKH +bnK bxb bIX bQf @@ -119761,7 +119574,7 @@ ayx gMl kkv aEO -koT +fMM avi aEO sFE @@ -121120,7 +120933,7 @@ kdL qwJ cgQ vRG -clF +rhG vyw sJC rMq @@ -121371,7 +121184,7 @@ ctN cMr gYs reE -qyy +cqs gwb xab cgQ @@ -122401,7 +122214,7 @@ cyg cgQ kyh mCA -gUp +gfC egK cgQ coL @@ -123732,7 +123545,7 @@ rix wHB rPd mms -nMz +qEo bFN rzy pUp @@ -136449,7 +136262,7 @@ rlu qFK xHC pTX -hwW +pTX pTX rlu qom @@ -140168,7 +139981,7 @@ xlg sDr chf csK -pnE +cyJ bDr cyJ cAe @@ -140421,7 +140234,7 @@ eGC sug vbQ wtp -tkN +wtp pmR cuc csK @@ -141715,7 +141528,7 @@ cep cDm mlC cep -nte +cep cAv cep czq @@ -142741,12 +142554,12 @@ cyJ uqE qiB chf -jrA +czq eZo qTA eMZ dbr -pnE +cyJ sAB czr mgJ @@ -143248,10 +143061,10 @@ cJK cJK gGQ cxO -nte +cep bop mmB -pnE +cyJ cyJ xxd chf @@ -143487,7 +143300,7 @@ wyU bGG cJQ cuQ -pUR +bcb bGG qZN dQM @@ -144287,7 +144100,7 @@ fbp uGf guQ mrc -iFW +cIm cep cIm chf @@ -144537,7 +144350,7 @@ cyJ hbP cDm vNo -pnE +cyJ uqE chf ntr @@ -145306,7 +145119,7 @@ vIW oJr cKF fyM -iBM +csL ciY ciY vMe @@ -146584,7 +146397,7 @@ vum ojz dci lon -veM +cga xsx reO rCg @@ -146598,7 +146411,7 @@ hyk csL ciY vZV -iBM +csL cHf cBQ aaa @@ -147095,7 +146908,7 @@ osm oJr ksj mdX -veM +cga ciY hWu xvs @@ -147515,7 +147328,7 @@ aab aab aAf aBe -jUn +aVD aBg aBg aFa @@ -147607,7 +147420,7 @@ ciY vBC ePu lcL -lhl +ijg iPb skT xII @@ -148649,7 +148462,7 @@ bVd cga ePu ePu -dkv +csL isD csL jPw @@ -150135,7 +149948,7 @@ ciY rng csL cga -iBM +csL pZe ciY ciY @@ -151703,7 +151516,7 @@ ciY csL fmn qth -iBM +csL oXK isD ciY diff --git a/_maps/map_files220/stations/deltastation.dmm b/_maps/map_files220/stations/deltastation.dmm index 167566e8a71c..1ef63a65f58b 100644 --- a/_maps/map_files220/stations/deltastation.dmm +++ b/_maps/map_files220/stations/deltastation.dmm @@ -10907,7 +10907,6 @@ /turf/simulated/floor/plating, /area/station/maintenance/fore2) "aWJ" = ( -/mob/living/simple_animal/mouse/rat, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dust, /turf/simulated/floor/wood/oak, @@ -35601,14 +35600,6 @@ icon_state = "whiteyellow" }, /area/station/medical/chemistry) -"cRv" = ( -/obj/effect/spawner/random/blood/maybe, -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plasteel{ - icon_state = "showroomfloor" - }, -/area/station/maintenance/old_kitchen) "cRy" = ( /obj/machinery/atmospherics/pipe/simple/heat_exchanging{ dir = 10 @@ -35663,7 +35654,6 @@ /area/station/maintenance/port) "cRI" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plasteel{ dir = 1; icon_state = "neutralcorner" @@ -48628,7 +48618,6 @@ /area/station/maintenance/fsmaint) "ekU" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plasteel{ icon_state = "redyellowfull" }, @@ -51603,10 +51592,6 @@ /obj/effect/spawner/random/maintenance, /turf/simulated/floor/wood/fancy/cherry, /area/station/public/vacant_store) -"fhp" = ( -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/wood/oak, -/area/station/maintenance/electrical_shop) "fhy" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/closet/crate, @@ -52686,7 +52671,6 @@ "fyS" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/alarm/directional/south, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plasteel{ icon_state = "greenblue" }, @@ -52982,11 +52966,6 @@ icon_state = "whiteblue" }, /area/station/medical/surgery/secondary) -"fEd" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/white, -/turf/simulated/floor/plating, -/area/station/maintenance/old_kitchen) "fEi" = ( /obj/effect/turf_decal/delivery, /obj/machinery/plantgenes, @@ -54751,11 +54730,6 @@ /obj/effect/turf_decal/delivery/hollow, /turf/simulated/floor/plasteel/dark, /area/station/public/fitness) -"giU" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/brown, -/turf/simulated/floor/plating, -/area/station/maintenance/starboard2) "giY" = ( /obj/structure/table, /obj/machinery/computer/med_data/laptop{ @@ -57296,13 +57270,6 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/port) -"gZU" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plasteel{ - icon_state = "neutralfull" - }, -/area/station/maintenance/fore) "haa" = ( /obj/structure/sink/directional/north, /obj/effect/decal/cleanable/dirt, @@ -57436,7 +57403,6 @@ /obj/structure/cable{ icon_state = "4-8" }, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/transparent/glass/reinforced, /area/station/maintenance/starboard2) "hcm" = ( @@ -57486,14 +57452,6 @@ icon_state = "dark_large" }, /area/station/security/interrogation) -"hcY" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plasteel{ - dir = 4; - icon_state = "chapel" - }, -/area/station/maintenance/starboard2) "hda" = ( /obj/effect/turf_decal/stripes/white/line{ color = "lightblue" @@ -59491,19 +59449,6 @@ icon_state = "whitepurplefull" }, /area/station/science/lobby) -"hJM" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/mob/living/simple_animal/mouse/white, -/turf/simulated/floor/plating, -/area/station/maintenance/starboard2) "hKc" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/airlock/maintenance, @@ -61632,10 +61577,6 @@ /obj/effect/spawner/window/reinforced/grilled, /turf/simulated/floor/plating, /area/station/security/prisonershuttle) -"irV" = ( -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/wood/oak, -/area/station/maintenance/abandonedbar) "isc" = ( /obj/structure/statue/delta/se, /obj/effect/turf_decal/siding/yellow/end{ @@ -65353,7 +65294,6 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plating, /area/station/maintenance/abandoned_garden) "jym" = ( @@ -67305,10 +67245,6 @@ }, /turf/simulated/floor/wood/oak, /area/station/medical/psych) -"kcd" = ( -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plating, -/area/station/maintenance/old_kitchen) "kcj" = ( /obj/machinery/alarm/directional/east, /turf/simulated/floor/plasteel{ @@ -68235,15 +68171,6 @@ }, /turf/simulated/floor/carpet, /area/station/service/library) -"ksQ" = ( -/obj/machinery/door_control/shutter/west{ - id = "restaurant"; - name = "Restaurant Shutters control" - }, -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/gray, -/turf/simulated/floor/plating, -/area/station/maintenance/old_kitchen) "ksS" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/chair{ @@ -74538,7 +74465,6 @@ /obj/effect/spawner/random/blood/maybe, /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/directional/west, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plasteel{ icon_state = "showroomfloor" }, @@ -75927,17 +75853,6 @@ }, /turf/simulated/floor/plating, /area/station/command/bridge) -"mTK" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/transparent/glass/reinforced, -/area/station/maintenance/starboard2) "mTQ" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -76577,13 +76492,6 @@ icon_state = "yellow" }, /area/station/engineering/hallway) -"ndH" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/gray, -/turf/simulated/floor/plasteel{ - icon_state = "redyellowfull" - }, -/area/station/maintenance/old_kitchen) "ndS" = ( /obj/structure/shelf/security, /obj/effect/turf_decal/delivery/red/hollow, @@ -77338,10 +77246,6 @@ /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, /area/station/supply/sorting) -"noV" = ( -/mob/living/simple_animal/mouse/brown, -/turf/simulated/floor/plating, -/area/station/maintenance/old_kitchen) "noW" = ( /obj/structure/grille/broken, /turf/simulated/floor/engine, @@ -84469,7 +84373,6 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plasteel{ icon_state = "showroomfloor" }, @@ -84961,23 +84864,6 @@ }, /turf/simulated/floor/wood/oak, /area/station/maintenance/library) -"pCj" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/white, -/turf/simulated/floor/plasteel, -/area/station/maintenance/aft) "pCm" = ( /obj/structure/displaycase/labcage, /obj/effect/turf_decal/delivery, @@ -88336,7 +88222,6 @@ /area/station/hallway/primary/central) "qFp" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plasteel{ icon_state = "showroomfloor" }, @@ -88487,12 +88372,6 @@ icon_state = "neutralfull" }, /area/station/hallway/primary/central) -"qHN" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/white, -/obj/effect/mapping_helpers/turfs/damage, -/turf/simulated/floor/wood/oak, -/area/station/maintenance/old_kitchen) "qHO" = ( /obj/structure/bed{ dir = 1 @@ -92731,7 +92610,6 @@ "rXZ" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/nightshifted/south, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plasteel, /area/station/maintenance/abandoned_garden) "rYh" = ( @@ -94315,11 +94193,6 @@ }, /turf/simulated/floor/plasteel, /area/station/engineering/mechanic) -"swI" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plasteel/dark, -/area/station/maintenance/abandonedbar) "swM" = ( /obj/structure/disposalpipe/junction/reversed{ dir = 4 @@ -96309,7 +96182,6 @@ icon_state = "1-4" }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/engine, /area/station/maintenance/incinerator) "tcZ" = ( @@ -97130,7 +97002,6 @@ /area/station/maintenance/fsmaint) "toU" = ( /obj/item/storage/box/donkpockets, -/mob/living/simple_animal/mouse/gray, /turf/simulated/floor/plasteel{ icon_state = "redyellowfull" }, @@ -97241,11 +97112,6 @@ icon_state = "neutralfull" }, /area/station/maintenance/virology_maint) -"tqO" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plating, -/area/station/maintenance/old_kitchen) "tqS" = ( /obj/structure/table, /obj/machinery/kitchen_machine/microwave{ @@ -102611,7 +102477,6 @@ dir = 4 }, /obj/structure/sink/kitchen/north, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/plasteel{ icon_state = "redyellowfull" }, @@ -103144,7 +103009,6 @@ icon_state = "0-8" }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, /turf/simulated/floor/engine, /area/station/maintenance/incinerator) "vmP" = ( @@ -103864,10 +103728,6 @@ /obj/effect/spawner/window/reinforced/polarized/grilled, /turf/simulated/floor/plating, /area/station/public/vacant_office/secondary) -"vBV" = ( -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plating, -/area/station/maintenance/fore) "vCf" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -104340,7 +104200,6 @@ /obj/structure/cable{ icon_state = "4-8" }, -/mob/living/simple_animal/mouse/gray, /turf/simulated/floor/plasteel{ icon_state = "neutralfull" }, @@ -108221,7 +108080,6 @@ icon_state = "1-4" }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plasteel{ icon_state = "neutral" }, @@ -109291,10 +109149,6 @@ icon_state = "whitebluecorner" }, /area/station/medical/medbay2) -"xnq" = ( -/mob/living/simple_animal/mouse/rat, -/turf/simulated/floor/plasteel/dark, -/area/station/maintenance/abandonedbar) "xnx" = ( /turf/simulated/floor/plasteel{ dir = 6; @@ -110505,7 +110359,6 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse/rat, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, @@ -110975,7 +110828,6 @@ /obj/structure/cable{ icon_state = "0-2" }, -/mob/living/simple_animal/mouse/rat, /obj/machinery/light/small/directional/west, /turf/simulated/floor/wood/oak, /area/station/maintenance/old_kitchen) @@ -129328,7 +129180,7 @@ rkv dsr cLz rQi -swI +dnH dcX yeh dYu @@ -129337,7 +129189,7 @@ lTi lTi dYt dnH -swI +dnH dcX dkr dbz @@ -130360,7 +130212,7 @@ uai lTi mAs dcX -swI +dnH yeh dks dcX @@ -131650,7 +131502,7 @@ dja iFl lTi dmQ -irV +lTi dcX drf irt @@ -131898,7 +131750,7 @@ doX xsz cLz dan -xnq +dcX dcW dcX dcX @@ -140023,7 +139875,7 @@ abj apG aqy arr -fhp +ars atg auk apG @@ -140293,7 +140145,7 @@ asq aVK nQL azb -gZU +ayX oDU aCl aCl @@ -146194,7 +146046,7 @@ aqQ aoo azb hoG -vBV +aor tGN oOi fwQ @@ -152990,7 +152842,7 @@ raz klA duk jDc -pCj +dDk nHK dEo abj @@ -157120,7 +156972,7 @@ pnl rzk lCR dqP -mTK +dqP wWV dfQ hkN @@ -160467,7 +160319,7 @@ jyi tpc jyJ wGh -hJM +kwD vzp wwk dpt @@ -163035,7 +162887,7 @@ bws qVD prg cqI -giU +cqI cqI xaX tNU @@ -164324,7 +164176,7 @@ bgs adA mfI eAb -hcY +mfI eAb bws aaa @@ -165568,7 +165420,7 @@ tyW lja uVh pKe -qHN +czX uRC kAm rad @@ -165578,7 +165430,7 @@ niP sIu wOg pAx -cRv +wOg gAT sIu rMZ @@ -166081,12 +165933,12 @@ qpB bfK aXM kAm -noV +uYi nwu wPb qno lHO -ksQ +pfl kAm txG sIu @@ -166607,7 +166459,7 @@ sIu vdF fZf fzE -ndH +fzE fzE jEH uDO @@ -167885,7 +167737,7 @@ maL gPu pgX rtS -fEd +qno xRG kAm wZj @@ -167894,7 +167746,7 @@ ipf qvA fzE uYi -tqO +qno wIZ qPD abj @@ -168142,7 +167994,7 @@ maL maL ddo kue -kcd +uYi jQi azo iHc diff --git a/_maps/map_files220/stations/metastation.dmm b/_maps/map_files220/stations/metastation.dmm index b465d5671234..c851dcffbd31 100644 --- a/_maps/map_files220/stations/metastation.dmm +++ b/_maps/map_files220/stations/metastation.dmm @@ -935,11 +935,6 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/solar_maintenance/fore_port) -"ajD" = ( -/mob/living/simple_animal/mouse, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/catwalk, -/area/station/maintenance/fore) "ajE" = ( /obj/structure/cable/yellow{ icon_state = "0-4" @@ -12523,7 +12518,6 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/mob/living/simple_animal/mouse, /obj/structure/cable/yellow{ icon_state = "1-4" }, @@ -15538,10 +15532,6 @@ /obj/effect/spawner/random/maintenance, /turf/simulated/floor/plating, /area/station/maintenance/fpmaint) -"bmA" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/fpmaint) "bmB" = ( /obj/machinery/door/airlock, /obj/effect/mapping_helpers/airlock/autoname, @@ -15769,11 +15759,6 @@ icon_state = "cautioncorner" }, /area/station/hallway/primary/starboard) -"bng" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/starboard2) "bnh" = ( /obj/machinery/firealarm/directional/north, /obj/machinery/light/directional/north, @@ -27438,13 +27423,6 @@ icon_state = "greenblue" }, /area/station/maintenance/starboard) -"cbb" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/fsmaint) "cbc" = ( /obj/effect/spawner/random/fungus/maybe, /turf/simulated/wall/r_wall, @@ -30341,11 +30319,6 @@ /obj/structure/lattice, /turf/space, /area/space/nearstation) -"clJ" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/turbine) "clK" = ( /obj/structure/closet, /obj/item/extinguisher, @@ -37672,10 +37645,6 @@ }, /turf/simulated/floor/plating/airless, /area/station/science/toxins/test) -"cOU" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/port) "cOV" = ( /obj/machinery/button/windowtint/south{ id = "CHAP2" @@ -38015,7 +37984,6 @@ "cQt" = ( /obj/effect/mapping_helpers/turfs/burn, /obj/machinery/light/small/directional/south, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plating, /area/station/maintenance/medmaint) "cQu" = ( @@ -40301,10 +40269,6 @@ icon_state = "whiteblue" }, /area/station/medical/exam_room) -"dbH" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/aft) "dbI" = ( /obj/effect/spawner/random/maintenance, /turf/simulated/floor/plating, @@ -47343,10 +47307,6 @@ }, /turf/simulated/floor/plasteel, /area/station/hallway/secondary/exit) -"gof" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/apmaint) "goq" = ( /obj/structure/closet/secure_closet/hos, /obj/item/cartridge/detective, @@ -48647,11 +48607,6 @@ icon_state = "white" }, /area/station/science/robotics) -"gWz" = ( -/obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/fsmaint) "gWE" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/delivery/hollow, @@ -50875,10 +50830,6 @@ icon_state = "whitepurple" }, /area/station/science/rnd) -"hYD" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/asmaint) "hYL" = ( /obj/machinery/light/directional/east, /turf/simulated/floor/plasteel{ @@ -51627,10 +51578,6 @@ }, /turf/simulated/floor/engine, /area/station/engineering/control) -"isf" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/fsmaint) "isB" = ( /obj/machinery/door/airlock/engineering/glass{ autoclose = 0; @@ -68497,7 +68444,6 @@ }, /area/station/security/interrogation) "qRm" = ( -/mob/living/simple_animal/mouse, /obj/effect/spawner/random/oil/maybe, /turf/simulated/floor/plasteel, /area/station/maintenance/fore) @@ -69623,7 +69569,6 @@ /area/station/security/armory) "ruY" = ( /obj/machinery/light/small/directional/east, -/mob/living/simple_animal/mouse, /turf/simulated/floor/plating, /area/station/maintenance/starboard2) "ruZ" = ( @@ -76863,7 +76808,6 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/mob/living/simple_animal/mouse, /obj/machinery/atmospherics/pipe/simple/hidden/cyan{ dir = 4 }, @@ -79539,10 +79483,6 @@ /obj/structure/sign/biohazard, /turf/simulated/wall/r_wall, /area/station/science/misc_lab) -"wLB" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plating, -/area/station/maintenance/fore) "wLY" = ( /obj/effect/landmark/start/prisoner, /turf/simulated/floor/plasteel, @@ -82515,10 +82455,6 @@ icon_state = "caution" }, /area/station/engineering/atmos/distribution) -"yiP" = ( -/mob/living/simple_animal/mouse, -/turf/simulated/floor/plasteel, -/area/station/maintenance/fore) "yiU" = ( /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -95340,7 +95276,7 @@ qCK aOB aOB adY -bmA +adY aOB aLF aML @@ -99003,7 +98939,7 @@ cpD crG bZP clK -gof +crG crG bZP aaa @@ -100778,7 +100714,7 @@ cdT cdT cdT cdT -cOU +bTY xOy aSM aSM @@ -101501,7 +101437,7 @@ awh hka aKd adY -bmA +adY aOB bmK bgA @@ -102110,7 +102046,7 @@ chy xxL eJG czw -dbH +chy bZU abq aaa @@ -114587,7 +114523,7 @@ tNe tNe tNe aDY -wLB +alW cnV nVQ whf @@ -115699,7 +115635,7 @@ rJq cwG cwG cwG -bng +kqi nUa kvG cwW @@ -115892,7 +115828,7 @@ nSs acL aWv aFj -yiP +fpy bne ajg iGR @@ -117756,7 +117692,7 @@ cwG cte aYL nUa -bng +kqi cmB cmB qub @@ -118544,7 +118480,7 @@ flh xHr emj emj -hYD +emj cKJ cPc emj @@ -120023,7 +119959,7 @@ aBI bNY aBI apL -isf +avA eiI aLl bdt @@ -120758,7 +120694,7 @@ aaa aaa aaa ahH -ajD +oTt azu oWE air @@ -120783,7 +120719,7 @@ gip tmM blB wYm -cbb +blB beF juq apV @@ -121288,7 +121224,7 @@ air oWE iAS oyN -gWz +cxr hgU aLl fpk @@ -122376,7 +122312,7 @@ cfL ciu ciH aRQ -clJ +aRQ biB bul clB diff --git a/code/__DEFINES/_globals.dm b/code/__DEFINES/_globals.dm index 083abd4108ef..f80661688148 100644 --- a/code/__DEFINES/_globals.dm +++ b/code/__DEFINES/_globals.dm @@ -16,23 +16,41 @@ #define GLOBAL_PROTECT(X) #endif +/// Standard BYOND global, seriously do not use without an earthshakingly good reason #define GLOBAL_REAL_VAR(X) var/global/##X + +/// Standard typed BYOND global, seriously do not use without an earthshakingly good reason #define GLOBAL_REAL(X, Typepath) var/global##Typepath/##X +/// Defines a global var on the controller, do not use #define GLOBAL_RAW(X) /datum/controller/global_vars/var/global##X +/// Create an untyped global with an initializer expression #define GLOBAL_VAR_INIT(X, InitValue) GLOBAL_RAW(/##X); GLOBAL_MANAGED(X, InitValue) +/// Create a global const var, do not use #define GLOBAL_VAR_CONST(X, InitValue) GLOBAL_RAW(/const/##X) = InitValue; GLOBAL_UNMANAGED(X) +/// Create a list global with an initializer expression #define GLOBAL_LIST_INIT(X, InitValue) GLOBAL_RAW(/list/##X); GLOBAL_MANAGED(X, InitValue) +/// Create a list global that is initialized as an empty list #define GLOBAL_LIST_EMPTY(X) GLOBAL_LIST_INIT(X, list()) +/// Create a typed list global with an initializer expression +#define GLOBAL_LIST_INIT_TYPED(X, Typepath, InitValue) GLOBAL_RAW(/list##Typepath/X); GLOBAL_MANAGED(X, InitValue) + +/// Create a typed list global that is initialized as an empty list +#define GLOBAL_LIST_EMPTY_TYPED(X, Typepath) GLOBAL_LIST_INIT_TYPED(X, Typepath, list()) + +/// Create a typed global with an initializer expression #define GLOBAL_DATUM_INIT(X, Typepath, InitValue) GLOBAL_RAW(Typepath/##X); GLOBAL_MANAGED(X, InitValue) +/// Create an untyped null global #define GLOBAL_VAR(X) GLOBAL_RAW(/##X); GLOBAL_UNMANAGED(X) +/// Create a null global list #define GLOBAL_LIST(X) GLOBAL_RAW(/list/##X); GLOBAL_UNMANAGED(X) +/// Create a typed null global #define GLOBAL_DATUM(X, Typepath) GLOBAL_RAW(Typepath/##X); GLOBAL_UNMANAGED(X) diff --git a/code/__DEFINES/dna.dm b/code/__DEFINES/dna.dm index 6f6b03b29ad8..39cd592983d0 100644 --- a/code/__DEFINES/dna.dm +++ b/code/__DEFINES/dna.dm @@ -69,3 +69,5 @@ #define DNA_GENDER_FEMALE 0 #define DNA_GENDER_MALE 1 #define DNA_GENDER_PLURAL 2 + +#define ENCODE_DNA_BLOCK(value) num2hex(value, 3) diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 08c5087b4b09..b1ecfca2fe3d 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -110,9 +110,10 @@ #define HAS_ALT_HEADS (1<<11) #define HAS_WING (1<<12) #define HAS_BODYACC_COLOR (1<<13) -#define BALD (1<<14) -#define ALL_RPARTS (1<<15) -#define SHAVED (1<<16) +#define HAS_SPECIES_SUBTYPE (1<<14) +#define BALD (1<<15) +#define ALL_RPARTS (1<<16) +#define SHAVED (1<<17) //Pre-baked combinations of the above body flags #define HAS_BODY_ACCESSORY (HAS_TAIL | HAS_WING) @@ -144,12 +145,18 @@ #define PASSTAKE (1<<9) #define PASSBARRICADE (1<<10) -//turf-only flags +//turf-only flags, under the flags variable #define BLESSED_TILE (1<<0) #define NO_LAVA_GEN (1<<1) //Blocks lava rivers being generated on the turf #define NO_RUINS (1<<2) #define LAVA_BRIDGE (1<<3) //! This turf has already been reserved for a lavaland bridge placement. +// turf flags, under the turf_flags variable +/// If a turf is an unused reservation turf awaiting assignment +#define UNUSED_RESERVATION_TURF (1<<4) +/// If a turf is a reserved turf +#define RESERVATION_TURF (1<<5) + //ORGAN TYPE FLAGS #define AFFECT_ROBOTIC_ORGAN 1 #define AFFECT_ORGANIC_ORGAN 2 diff --git a/code/__DEFINES/gamemode.dm b/code/__DEFINES/gamemode.dm index 76332f7fb738..a6b8da39714b 100644 --- a/code/__DEFINES/gamemode.dm +++ b/code/__DEFINES/gamemode.dm @@ -80,5 +80,7 @@ #define DYNAMIC_RULESET_BANNED "Banned" #define RULESET_FAILURE_BUDGET "Not enough budget" +#define RULESET_FAILURE_ANTAG_BUDGET "Not enough antag budget" #define RULESET_FAILURE_NO_PLAYERS "No drafted players" +#define RULESET_FAILURE_MUTUAL_RULESET "No banned mutual rulesets" #define RULESET_FAILURE_CHANGELING_SECONDARY_RULESET "Needs a secondary ruleset in rotation" diff --git a/code/__DEFINES/misc_defines.dm b/code/__DEFINES/misc_defines.dm index 227cae67ed84..10d7fab996aa 100644 --- a/code/__DEFINES/misc_defines.dm +++ b/code/__DEFINES/misc_defines.dm @@ -431,7 +431,7 @@ #define INVESTIGATE_HOTMIC "hotmic" // The SQL version required by this version of the code -#define SQL_VERSION 632207 +#define SQL_VERSION 642207 // Vending machine stuff #define CAT_NORMAL (1<<0) diff --git a/code/__DEFINES/rust.dm b/code/__DEFINES/rust.dm index 6ac60f4de08e..a78d48c341f2 100644 --- a/code/__DEFINES/rust.dm +++ b/code/__DEFINES/rust.dm @@ -57,6 +57,8 @@ /proc/byondapi_stack_trace(err) CRASH(err) +// MARK: MILLA + /proc/milla_init_z(z) return RUSTLIB_CALL(milla_initialize, z) @@ -116,6 +118,11 @@ /proc/create_environment(oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b, temperature) return RUSTLIB_CALL(milla_create_environment, oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b, temperature) +/proc/set_zlevel_freeze(z, bool_frozen) + return RUSTLIB_CALL(milla_set_zlevel_frozen, z, bool_frozen) + +// MARK: MapManip + /proc/mapmanip_read_dmm(mapname) return RUSTLIB_CALL(mapmanip_read_dmm_file, mapname) diff --git a/code/__DEFINES/shuttle_defines.dm b/code/__DEFINES/shuttle_defines.dm index 43470086ce22..a656e661a9dd 100644 --- a/code/__DEFINES/shuttle_defines.dm +++ b/code/__DEFINES/shuttle_defines.dm @@ -14,3 +14,5 @@ #define SHUTTLE_DOCKER_LANDING_CLEAR 1 #define SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT 2 #define SHUTTLE_DOCKER_BLOCKED 3 + +#define SHUTTLE_TRANSIT_BORDER 16 diff --git a/code/__DEFINES/turfs.dm b/code/__DEFINES/turfs.dm index f383b4d5540c..f3149bb42aaa 100644 --- a/code/__DEFINES/turfs.dm +++ b/code/__DEFINES/turfs.dm @@ -13,3 +13,10 @@ #define MINERAL_PREVENT_DIG 0 //! A mineral turf should not be changed when mined. #define MINERAL_ALLOW_DIG 1 //! A mineral turf should be dug out when mined. + +/// Returns an outline (neighboring turfs) of the given block +#define CORNER_OUTLINE(corner, width, height) ( \ + CORNER_BLOCK_OFFSET(corner, width + 2, 1, -1, -1) + \ + CORNER_BLOCK_OFFSET(corner, width + 2, 1, -1, height) + \ + CORNER_BLOCK_OFFSET(corner, 1, height, -1, 0) + \ + CORNER_BLOCK_OFFSET(corner, 1, height, width, 0)) diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 47947cb245f1..8ff538f3d37f 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -740,6 +740,19 @@ LAZYINITLIST(lazy_list[key]); \ lazy_list[key] |= value; +///Ensures the length of a list is at least I, prefilling it with V if needed. if V is a proc call, it is repeated for each new index so that list() can just make a new list for each item. +#define LISTASSERTLEN(L, I, V...) \ + if(length(L) < I) { \ + var/_OLD_LENGTH = length(L); \ + L.len = I; \ + /* Convert the optional argument to a if check */ \ + for(var/_USELESS_VAR in list(V)) { \ + for(var/_INDEX_TO_ASSIGN_TO in _OLD_LENGTH+1 to I) { \ + L[_INDEX_TO_ASSIGN_TO] = V; \ + } \ + } \ + } + //same, but returns nothing and acts on list in place /proc/shuffle_inplace(list/L) if(!L) diff --git a/code/__HELPERS/name_helpers.dm b/code/__HELPERS/name_helpers.dm index 8ae3763c85d7..e270b5ff6cc1 100644 --- a/code/__HELPERS/name_helpers.dm +++ b/code/__HELPERS/name_helpers.dm @@ -89,7 +89,7 @@ GLOBAL_VAR(syndicate_name) // Full if(prob(60)) - name += pick("Syndicate", "Consortium", "Collective", "Corporation", "Group", "Holdings", "Biotech", "Industries", "Systems", "Products", "Chemicals", "Enterprises", "Family", "Creations", "International", "Intergalactic", "Interplanetary", "Foundation", "Positronics", "Hive") + name += pick("Syndicate", "Consortium", "Collective", "Corporation", "Group", "Holdings", "Biotech", "Industries", "Systems", "Products", "Chemicals", "Enterprises", "Family", "Creations", "International", "Interstellar", "Interplanetary", "Foundation", "Positronics", "Hive") // Broken else name += pick("Syndi", "Corp", "Bio", "System", "Prod", "Chem", "Inter", "Hive") diff --git a/code/_compile_options.dm b/code/_compile_options.dm index 0990e5bd29c6..6731133b6fbb 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -14,16 +14,17 @@ #ifdef LOCAL_GAME_TESTS #define GAME_TESTS -#endif - -#ifdef CIBUILDING -#define GAME_TESTS +#define MAP_TESTS #endif #if defined(CIBUILDING) && defined(LOCAL_GAME_TESTS) #error CIBUILDING and LOCAL_GAME_TESTS should not be enabled at the same time! #endif +#if defined(GAME_TESTS) || defined(MAP_TESTS) +#define TEST_RUNNER +#endif + /***** All toggles for the GC ref finder *****/ // #define REFERENCE_TRACKING // Uncomment to enable ref finding diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index e165eabdb705..3f1de6a67fde 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -112,6 +112,11 @@ DEFINE_BITFIELD(flags, list( "NO_SCREENTIPS" = NO_SCREENTIPS, )) +DEFINE_BITFIELD(turf_flags, list( + "UNUSED_RESERVATION_TURF" = UNUSED_RESERVATION_TURF, + "RESERVATION_TURF" = RESERVATION_TURF +)) + DEFINE_BITFIELD(flags_2, list( "SLOWS_WHILE_IN_HAND_2" = SLOWS_WHILE_IN_HAND_2, "NO_EMP_WIRES_2" = NO_EMP_WIRES_2, diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index efa225f48b7c..66ce6b862f19 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -18,7 +18,7 @@ GLOBAL_LIST_EMPTY(hierophant_walls) GLOBAL_LIST_EMPTY(pandemics) GLOBAL_LIST_EMPTY(all_areas) -GLOBAL_LIST_EMPTY(all_unique_areas) // List of all unique areas. AKA areas with there_can_be_many = FALSE +GLOBAL_LIST_EMPTY_TYPED(all_unique_areas, /area) // List of all unique areas. AKA areas with there_can_be_many = FALSE GLOBAL_LIST_EMPTY(machines) GLOBAL_LIST_EMPTY(telescreens) /// List of entertainment telescreens connected to the "news" cameranet GLOBAL_LIST_EMPTY(rcd_list) //list of Rapid Construction Devices. diff --git a/code/controllers/configuration/configuration_core.dm b/code/controllers/configuration/configuration_core.dm index 8619c03c26cc..1d11623e9599 100644 --- a/code/controllers/configuration/configuration_core.dm +++ b/code/controllers/configuration/configuration_core.dm @@ -139,13 +139,12 @@ GLOBAL_DATUM_INIT(configuration, /datum/server_configuration, new()) safe_load(asset_cache, "asset_cache_configuration") // Proc to load up instance-specific overrides -/datum/server_configuration/proc/load_overrides() - var/override_file = "config/overrides_[world.port].toml" +/datum/server_configuration/proc/load_overrides(override_file) if(!fexists(override_file)) - DIRECT_OUTPUT(world.log, "Overrides not found for this instance.") + DIRECT_OUTPUT(world.log, "Override file [override_file] not found for this instance.") return - DIRECT_OUTPUT(world.log, "Overrides found for this instance. Loading them.") + DIRECT_OUTPUT(world.log, "Override file [override_file] found. Loading.") var/start = start_watch() // Time tracking raw_data = rustg_read_toml_file(override_file) diff --git a/code/controllers/configuration/sections/database_configuration.dm b/code/controllers/configuration/sections/database_configuration.dm index 73a396c9e29e..94f323ef6539 100644 --- a/code/controllers/configuration/sections/database_configuration.dm +++ b/code/controllers/configuration/sections/database_configuration.dm @@ -21,16 +21,6 @@ var/async_thread_limit = 50 /datum/configuration_section/database_configuration/load_data(list/data) - // UNIT TESTS ARE DEFINED - USE CUSTOM CI VALUES - #ifdef GAME_TESTS - - enabled = TRUE - // This needs to happen in the CI environment to ensure the example SQL version gets updated. - CONFIG_LOAD_NUM(version, data["sql_version"]) - - #else - // Load the normal config. Were not in CI mode - // Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line CONFIG_LOAD_BOOL(enabled, data["sql_enabled"]) CONFIG_LOAD_NUM(version, data["sql_version"]) CONFIG_LOAD_STR(address, data["sql_address"]) @@ -40,4 +30,3 @@ CONFIG_LOAD_STR(db, data["sql_database"]) CONFIG_LOAD_NUM(async_query_timeout, data["async_query_timeout"]) CONFIG_LOAD_NUM(async_thread_limit, data["async_thread_limit"]) - #endif diff --git a/code/controllers/configuration/sections/redis_configuration.dm b/code/controllers/configuration/sections/redis_configuration.dm index b418441e7f99..dc25e88c69de 100644 --- a/code/controllers/configuration/sections/redis_configuration.dm +++ b/code/controllers/configuration/sections/redis_configuration.dm @@ -7,14 +7,5 @@ var/connstring = "redis://127.0.0.1/" /datum/configuration_section/redis_configuration/load_data(list/data) - // UNIT TESTS ARE DEFINED - USE CUSTOM CI VALUES - #ifdef GAME_TESTS - - // enabled = TRUE - - #else - // Load the normal config. Were not in CI mode - // Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line CONFIG_LOAD_BOOL(enabled, data["redis_enabled"]) CONFIG_LOAD_STR(connstring, data["redis_connstring"]) - #endif diff --git a/code/controllers/master.dm b/code/controllers/master.dm index cf8763b32b68..ce39cfb87337 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -83,7 +83,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new /datum/controller/master/New() if(!random_seed) - #ifdef GAME_TESTS + #ifdef TEST_RUNNER random_seed = 29051994 #else random_seed = rand(1, 1e9) diff --git a/code/controllers/subsystem/SSshuttles.dm b/code/controllers/subsystem/SSshuttles.dm index 2065c39026f6..90368fbb8b0a 100644 --- a/code/controllers/subsystem/SSshuttles.dm +++ b/code/controllers/subsystem/SSshuttles.dm @@ -303,7 +303,7 @@ SUBSYSTEM_DEF(shuttle) for(var/obj/machinery/requests_console/console in GLOB.allRequestConsoles) if(console.department != "Cargo Bay") continue - console.createMessage("Messaging and Intergalactic Letters", "New Mail Crates ready to be ordered!", "A new mail crate is able to be shipped alongside your next orders!", RQ_NORMALPRIORITY) + console.createMessage("Nanotrasen Mail and Interstellar Logistics", "New Mail Crates ready to be ordered!", "A new mail crate is able to be shipped alongside your next orders!", RQ_NORMALPRIORITY) if(!length(supply_shuttle_turfs)) for(var/turf/simulated/T in supply.areaInstance) diff --git a/code/controllers/subsystem/SSticker.dm b/code/controllers/subsystem/SSticker.dm index b51569cb54b2..8e923007cc01 100644 --- a/code/controllers/subsystem/SSticker.dm +++ b/code/controllers/subsystem/SSticker.dm @@ -366,10 +366,8 @@ SUBSYSTEM_DEF(ticker) if(GLOB.configuration.general.enable_night_shifts) SSnightshift.check_nightshift(TRUE) - #ifdef GAME_TESTS - // Run map tests first in case unit tests futz with map state - GLOB.test_runner.RunMap() - GLOB.test_runner.Run() + #ifdef TEST_RUNNER + GLOB.test_runner.RunAll() #endif // Do this 10 second after roundstart because of roundstart lag, and make it more visible diff --git a/code/controllers/subsystem/SStimer.dm b/code/controllers/subsystem/SStimer.dm index 9c9bbeed24a0..44191cb87fbd 100644 --- a/code/controllers/subsystem/SStimer.dm +++ b/code/controllers/subsystem/SStimer.dm @@ -134,6 +134,8 @@ SUBSYSTEM_DEF(timer) callBack.InvokeAsync() if(ctime_timer.flags & TIMER_LOOP) + if(QDELETED(ctime_timer)) + continue ctime_timer.spent = 0 ctime_timer.timeToRun = REALTIMEOFDAY + ctime_timer.wait BINARY_INSERT_TG(ctime_timer, clienttime_timers, /datum/timedevent, ctime_timer, timeToRun, COMPARE_KEY) @@ -180,6 +182,8 @@ SUBSYSTEM_DEF(timer) last_invoke_tick = world.time if(timer.flags & TIMER_LOOP) // Prepare looping timers to re-enter the queue + if(QDELETED(timer)) + continue timer.spent = 0 timer.timeToRun = world.time + timer.wait timer.bucketJoin() diff --git a/code/controllers/subsystem/non_firing/SSlate_mapping.dm b/code/controllers/subsystem/non_firing/SSlate_mapping.dm index 65679ca13781..db3111e9a41c 100644 --- a/code/controllers/subsystem/non_firing/SSlate_mapping.dm +++ b/code/controllers/subsystem/non_firing/SSlate_mapping.dm @@ -27,4 +27,45 @@ SUBSYSTEM_DEF(late_mapping) var/duration = stop_watch(watch) log_startup_progress("Generated [mgcount] mazes in [duration]s") + maintenance_mice() + GLOB.spawn_pool_manager.process_pools() + +/** + * Randomly spawns mice in maintenance instead of being purely fixed spawn points + */ +/datum/controller/subsystem/late_mapping/proc/maintenance_mice() + var/watch = start_watch() + log_startup_progress("Populating maintenance with mice...") + + // Looking up for maintenance floors specifically as possible spawn points + var/list/maintenance_turfs = list() + for(var/area/station/maintenance/A in SSmapping.existing_station_areas) + for(var/turf/simulated/floor/F in A) + if(locate(/obj/structure/window) in F) + continue + maintenance_turfs.Add(F) + + if(!length(maintenance_turfs)) + log_debug("No valid turfs has been found for mice.") + return + + // The ratio is based on turfs per mice. Using Boxstation as an example, it would average between 20 to 30 mice. + var/floor_tiles_per_one_mice = rand(125, 200) + var/mice_number = ceil(length(maintenance_turfs) / floor_tiles_per_one_mice) + + // SS220 EDIT START - mouse diversity + var/static/list/mouse_pool = list( + /mob/living/simple_animal/mouse = 1, + /mob/living/simple_animal/mouse/brown = 1, + /mob/living/simple_animal/mouse/gray = 1, + /mob/living/simple_animal/mouse/white = 1, + /mob/living/simple_animal/mouse/rat = 1, + /mob/living/simple_animal/mouse/rat/white = 1, + ) + for(var/i in 1 to mice_number) + var/mouse_type = pickweight(mouse_pool) + new mouse_type(pick_n_take(maintenance_turfs)) + // SS220 EDIT END + + log_debug("Spawned [mice_number] mice over in [stop_watch(watch)]s") diff --git a/code/controllers/subsystem/non_firing/SSmapping.dm b/code/controllers/subsystem/non_firing/SSmapping.dm index feee4abb3452..9d324ac50eba 100644 --- a/code/controllers/subsystem/non_firing/SSmapping.dm +++ b/code/controllers/subsystem/non_firing/SSmapping.dm @@ -1,7 +1,7 @@ SUBSYSTEM_DEF(mapping) name = "Mapping" init_order = INIT_ORDER_MAPPING // 9 - flags = SS_NO_FIRE + /// What map datum are we using var/datum/map/map_datum /// What map will be used next round @@ -31,6 +31,15 @@ SUBSYSTEM_DEF(mapping) /// Ruin placement manager for lavaland levels. var/datum/ruin_placer/lavaland/lavaland_ruins_placer + var/num_of_res_levels = 0 + var/clearing_reserved_turfs = FALSE + var/list/datum/turf_reservations //list of turf reservations + + var/list/turf/unused_turfs = list() //Not actually unused turfs they're unused but reserved for use for whatever requests them. "[zlevel_of_turf]" = list(turfs) + var/list/used_turfs = list() //list of turf = datum/turf_reservation + /// List of lists of turfs to reserve + var/list/lists_to_reserve = list() + // This has to be here because world/New() uses [station_name()], which looks this datum up /datum/controller/subsystem/mapping/PreInit() . = ..() @@ -109,6 +118,8 @@ SUBSYSTEM_DEF(mapping) // Makes a blank space level for the sake of randomness GLOB.space_manager.add_new_zlevel("Empty Area", linkage = CROSSLINKED, traits = empty_z_traits) + // Add a reserved z-level + // add_reservation_zlevel() // CURRENTLY DISABLED, AS NOTHING USES IT. IF YOU WANT TO ADD LAZYLOADING TO ANYTHING, MAKE SURE TO REIMPLEMENT THIS // Setup the Z-level linkage GLOB.space_manager.do_transition_setup() @@ -346,4 +357,120 @@ SUBSYSTEM_DEF(mapping) SSblackbox.record_feedback("nested tally", "keycard_auths", 1, list("emergency station access", "disabled")) /datum/controller/subsystem/mapping/Recover() - flags |= SS_NO_INIT + num_of_res_levels = SSmapping.num_of_res_levels + clearing_reserved_turfs = SSmapping.clearing_reserved_turfs + turf_reservations = SSmapping.turf_reservations + unused_turfs = SSmapping.unused_turfs + used_turfs = SSmapping.used_turfs + lists_to_reserve = SSmapping.lists_to_reserve + +/datum/controller/subsystem/mapping/proc/get_reservation_from_turf(turf/T) + RETURN_TYPE(/datum/turf_reservation) + return used_turfs[T] + +/// Requests a /datum/turf_reservation based on the given width, height. +/datum/controller/subsystem/mapping/proc/request_turf_block_reservation(width, height) + UNTIL(!clearing_reserved_turfs) + log_debug("Reserving [width]x[height] turf reservation") + var/datum/turf_reservation/reserve = new /datum/turf_reservation + for(var/i in levels_by_trait(Z_FLAG_RESERVED)) + if(reserve.reserve(width, height, i)) + return reserve + //If we didn't return at this point, theres a good chance we ran out of room on the exisiting reserved z levels, so lets try a new one + var/z_level_num = add_reservation_zlevel() + if(reserve.reserve(width, height, z_level_num)) + return reserve + qdel(reserve) + +/datum/controller/subsystem/mapping/proc/add_reservation_zlevel() + num_of_res_levels++ + // . here is the z of the just added z-level + . = GLOB.space_manager.add_new_zlevel("Transit/Reserved #[num_of_res_levels]", traits = list(Z_FLAG_RESERVED, BLOCK_TELEPORT, IMPEDES_MAGIC)) + initialize_reserved_level(.) + if(!initialized) + return + if(length(SSidlenpcpool.idle_mobs_by_zlevel) == . || !islist(SSidlenpcpool.idle_mobs_by_zlevel)) // arbitrary chosen from these lists that require the length of the z-levels + return + LISTASSERTLEN(SSidlenpcpool.idle_mobs_by_zlevel, ., list()) + LISTASSERTLEN(SSmobs.clients_by_zlevel, ., list()) + LISTASSERTLEN(SSmobs.dead_players_by_zlevel, ., list()) + +///Sets up a z level as reserved +///This is not for wiping reserved levels, use wipe_reservations() for that. +///If this is called after SSatom init, it will call Initialize on all turfs on the passed z, as its name promises +/datum/controller/subsystem/mapping/proc/initialize_reserved_level(z) + UNTIL(!clearing_reserved_turfs) //regardless, lets add a check just in case. + log_debug("Initializing new reserved Z-level") + clearing_reserved_turfs = TRUE //This operation will likely clear any existing reservations, so lets make sure nothing tries to make one while we're doing it. + if(!check_level_trait(z, Z_FLAG_RESERVED)) + clearing_reserved_turfs = FALSE + CRASH("Invalid z level prepared for reservations.") + var/block = block(SHUTTLE_TRANSIT_BORDER, SHUTTLE_TRANSIT_BORDER, z, world.maxx - SHUTTLE_TRANSIT_BORDER, world.maxy - SHUTTLE_TRANSIT_BORDER) + for(var/turf/T as anything in block) + // No need to empty() these, because they just got created and are already /turf/space. + T.turf_flags |= UNUSED_RESERVATION_TURF + CHECK_TICK + + // Gotta create these suckers if we've not done so already + if(SSatoms.initialized) + SSatoms.InitializeAtoms(block(1, 1, world.maxx, world.maxy, z), FALSE) + + unused_turfs["[z]"] = block + clearing_reserved_turfs = FALSE + +/datum/controller/subsystem/mapping/fire(resumed) + // Cache for sonic speed + var/list/list/turf/unused_turfs = src.unused_turfs + var/list/world_contents = GLOB.all_unique_areas[world.area].contents + // var/list/world_turf_contents_by_z = GLOB.all_unique_areas[world.area].turfs_by_zlevel + var/list/lists_to_reserve = src.lists_to_reserve + var/index = 0 + while(index < length(lists_to_reserve)) + var/list/packet = lists_to_reserve[index + 1] + var/packetlen = length(packet) + while(packetlen) + if(MC_TICK_CHECK) + if(index) + lists_to_reserve.Cut(1, index) + return + var/turf/reserving_turf = packet[packetlen] + reserving_turf.empty(/turf/space) + LAZYINITLIST(unused_turfs["[reserving_turf.z]"]) + if(!(reserving_turf in unused_turfs["[reserving_turf.z]"])) + unused_turfs["[reserving_turf.z]"].Insert(1, reserving_turf) + reserving_turf.turf_flags = UNUSED_RESERVATION_TURF + + world_contents += reserving_turf + packet.len-- + packetlen = length(packet) + + index++ + lists_to_reserve.Cut(1, index) + +/** + * Lazy loads a template on a lazy-loaded z-level + * If you want to use this as non-debug, make sure to uncomment add_reservation_zlevel in /datum/controller/subsystem/mapping/Initialize() + */ +/datum/controller/subsystem/mapping/proc/lazy_load_template(datum/map_template/template) + RETURN_TYPE(/datum/turf_reservation) + + UNTIL(initialized) + var/static/lazy_loading = FALSE + UNTIL(!lazy_loading) + + lazy_loading = TRUE + . = _lazy_load_template(template) + lazy_loading = FALSE + +/datum/controller/subsystem/mapping/proc/_lazy_load_template(datum/map_template/template) + PRIVATE_PROC(TRUE) + var/datum/turf_reservation/reservation = request_turf_block_reservation(template.width, template.height) + if(!istype(reservation)) + return + + template.load(reservation.bottom_left_turf) + return reservation + +/// Schedules a group of turfs to be handed back to the reservation system's control +/datum/controller/subsystem/mapping/proc/unreserve_turfs(list/turfs) + lists_to_reserve += list(turfs) diff --git a/code/datums/diseases/advance/symptoms/hair.dm b/code/datums/diseases/advance/symptoms/hair.dm index 60419bd5b25f..b1f56f177bec 100644 --- a/code/datums/diseases/advance/symptoms/hair.dm +++ b/code/datums/diseases/advance/symptoms/hair.dm @@ -37,13 +37,13 @@ BONUS switch(A.stage) if(1, 2, 3) to_chat(H, "Your scalp itches.") - head_organ.h_style = random_hair_style(H.gender, head_organ.dna.species.name) + head_organ.h_style = random_hair_style(H.gender, head_organ.dna.species.sprite_sheet_name) else to_chat(H, "Hair bursts forth from your scalp!") var/datum/sprite_accessory/tmp_hair_style = GLOB.hair_styles_full_list["Very Long Hair"] - if(head_organ.dna.species.name in tmp_hair_style.species_allowed) //If 'Very Long Hair' is a style the person's species can have, give it to them. + if(head_organ.dna.species.sprite_sheet_name in tmp_hair_style.species_allowed) //If 'Very Long Hair' is a style the person's species can have, give it to them. head_organ.h_style = "Very Long Hair" else //Otherwise, give them a random hair style. - head_organ.h_style = random_hair_style(H.gender, head_organ.dna.species.name) + head_organ.h_style = random_hair_style(H.gender, head_organ.dna.species.sprite_sheet_name) H.update_hair() diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm index 08437daa6097..5858f9b16211 100644 --- a/code/datums/helper_datums/map_template.dm +++ b/code/datums/helper_datums/map_template.dm @@ -51,6 +51,9 @@ // if given a multi-z template // it might need to be adapted for that when that time comes GLOB.space_manager.add_dirt(placement.z) + var/datum/milla_safe/freeze_z_level/milla_freeze = new() + milla_freeze.invoke_async(T.z) + UNTIL(milla_freeze.done) try var/list/bounds = GLOB.maploader.load_map(get_file(), min_x, min_y, placement.z, shouldCropMap = TRUE) if(!bounds) diff --git a/code/datums/outfits/outfit_debug.dm b/code/datums/outfits/outfit_debug.dm index 559c9b8b9a21..f4d2d5ae57f4 100644 --- a/code/datums/outfits/outfit_debug.dm +++ b/code/datums/outfits/outfit_debug.dm @@ -272,6 +272,12 @@ /obj/item/storage/box/debug/debugtools name = "debug tools" +/obj/item/paper/debug_research + name = "debug reseach notes" + desc = "Your brain is melting just from looking at this endless knowledge." + info = "Information written here is beyond your understanding" + origin_tech = "materials=10;engineering=10;plasmatech=10;powerstorage=10;bluespace=10;biotech=10;combat=10;magnets=10;programming=10;toxins=10;syndicate=10;abductor=10" + /obj/item/storage/box/debug/debugtools/populate_contents() new /obj/item/card/emag(src) new /obj/item/rcd/combat/admin(src) @@ -284,6 +290,7 @@ new /obj/item/storage/box/debug/misc_debug(src) new /obj/item/storage/box/centcomofficer(src) new /obj/item/radio/uplink/admin(src) + new /obj/item/paper/debug_research(src) /obj/item/storage/box/debug/material name = "box of materials" diff --git a/code/datums/spells/banana_touch.dm b/code/datums/spells/banana_touch.dm index 165ba07208ef..6fa785eb31aa 100644 --- a/code/datums/spells/banana_touch.dm +++ b/code/datums/spells/banana_touch.dm @@ -72,3 +72,37 @@ if(!(iswizard(src) || (mind && mind.special_role == SPECIAL_ROLE_WIZARD_APPRENTICE))) //Mutations are permanent on non-wizards. Can still be removed by genetics fuckery but not mutadone. dna.default_blocks.Add(GLOB.clumsyblock) dna.default_blocks.Add(GLOB.comicblock) + +/// Like bananatouched, but intended to be used for funny one-off scenarios which aren't meant to permanently cripple someone's round. +/mob/living/carbon/human/proc/bananatouched_harmless() + to_chat(src, "HONK") + Weaken(14 SECONDS) + Stuttering(30 SECONDS) + do_jitter_animation(30 SECONDS) + + var/obj/item/tank/internal_tank = internal + var/obj/item/clothing/mask/gas/clown_hat/clown_mask = new() + var/obj/item/clothing/under/rank/civilian/clown/clown_suit = new() + var/obj/item/clothing/shoes/clown_shoes/clown_shoes = new() + clown_mask.flags |= DROPDEL + clown_suit.flags |= DROPDEL + clown_shoes.flags |= DROPDEL + + drop_item_to_ground(shoes, force = TRUE) + drop_item_to_ground(wear_mask, force = TRUE) + drop_item_to_ground(w_uniform, force = TRUE) + if(isplasmaman(src)) + drop_item_to_ground(head, force = TRUE) + var/obj/item/clothing/head/helmet/space/plasmaman/clown/clown_helmet = new() + clown_suit = new /obj/item/clothing/under/plasmaman/clown + clown_helmet.flags |= DROPDEL + clown_suit.flags |= DROPDEL + equip_to_slot_if_possible(clown_helmet, ITEM_SLOT_HEAD, TRUE, TRUE) + equip_to_slot_if_possible(clown_suit, ITEM_SLOT_JUMPSUIT, TRUE, TRUE) + equip_to_slot_if_possible(clown_shoes, ITEM_SLOT_SHOES, TRUE, TRUE) + equip_to_slot_if_possible(clown_mask, ITEM_SLOT_MASK, TRUE, TRUE) + + // Re-equips the internal tank if present + equip_to_appropriate_slot(internal_tank) + internal = internal_tank + diff --git a/code/game/area/misc_areas.dm b/code/game/area/misc_areas.dm index 1eda79444595..6e5df61490d7 100644 --- a/code/game/area/misc_areas.dm +++ b/code/game/area/misc_areas.dm @@ -64,3 +64,11 @@ /area/syndicate_mothership/jail name = "\improper Syndicate Jail" + +/area/cordon + name = "CORDON" + icon_state = "cordon" + requires_power = FALSE + always_unpowered = TRUE + dynamic_lighting = DYNAMIC_LIGHTING_DISABLED + valid_territory = FALSE diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index 341067b016cf..4bef9732f156 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -259,7 +259,7 @@ GLOBAL_LIST_EMPTY(bad_blocks) // Get a hex-encoded UI block. /datum/dna/proc/GetUIBlock(block) - return EncodeDNABlock(GetUIValue(block)) + return ENCODE_DNA_BLOCK(GetUIValue(block)) // Do not use this unless you absolutely have to. // Set a block from a hex string. This is inefficient. If you can, use SetUIValue(). @@ -356,7 +356,7 @@ GLOBAL_LIST_EMPTY(bad_blocks) // Get hex-encoded SE block. /datum/dna/proc/GetSEBlock(block) - return EncodeDNABlock(GetSEValue(block)) + return ENCODE_DNA_BLOCK(GetSEValue(block)) // Do not use this unless you absolutely have to. // Set a block from a hex string. This is inefficient. If you can, use SetUIValue(). @@ -387,15 +387,11 @@ GLOBAL_LIST_EMPTY(bad_blocks) //testing("SetSESubBlock([block],[subBlock],[newSubBlock],[defer]): [oldBlock] -> [newBlock]") SetSEBlock(block, newBlock, defer) - -/proc/EncodeDNABlock(value) - return num2hex(value, 3) - /datum/dna/proc/UpdateUI() var/list/ui_text_list = list() uni_identity = "" for(var/block in UI) - ui_text_list += EncodeDNABlock(block) + ui_text_list += ENCODE_DNA_BLOCK(block) uni_identity = ui_text_list.Join("") //testing("New UI: [uni_identity]") dirtyUI = 0 @@ -405,7 +401,7 @@ GLOBAL_LIST_EMPTY(bad_blocks) var/list/se_text_list = list() struc_enzymes = "" for(var/block in SE) - se_text_list += EncodeDNABlock(block) + se_text_list += ENCODE_DNA_BLOCK(block) struc_enzymes = se_text_list.Join("") //testing("Old SE: [oldse]") //testing("New SE: [struc_enzymes]") diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 73973a1944db..202e491e1d8c 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -241,7 +241,7 @@ var/list/available = list() for(var/head_accessory in GLOB.head_accessory_styles_list) var/datum/sprite_accessory/S = GLOB.head_accessory_styles_list[head_accessory] - if(!(head_organ.dna.species.name in S.species_allowed)) //If the user's head is not of a species the head accessory style allows, skip it. Otherwise, add it to the list. + if(!(head_organ.dna.species.sprite_sheet_name in S.species_allowed)) //If the user's head is not of a species the head accessory style allows, skip it. Otherwise, add it to the list. continue available += head_accessory var/list/sorted = sortTim(available, GLOBAL_PROC_REF(cmp_text_asc)) diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 417a8c303ff6..92d13eda81bf 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -358,7 +358,7 @@ /obj/machinery/computer/scan_consolenew/proc/all_dna_blocks(list/buffer) var/list/arr = list() for(var/i = 1, i <= length(buffer), i++) - arr += "[i]:[EncodeDNABlock(buffer[i])]" + arr += "[i]:[ENCODE_DNA_BLOCK(buffer[i])]" return arr /obj/machinery/computer/scan_consolenew/proc/setInjectorBlock(obj/item/dnainjector/I, blk, datum/dna2_record/buffer) diff --git a/code/game/gamemodes/dynamic/antag_rulesets.dm b/code/game/gamemodes/dynamic/antag_rulesets.dm index 62293adf6cbf..ce30a5aa50e9 100644 --- a/code/game/gamemodes/dynamic/antag_rulesets.dm +++ b/code/game/gamemodes/dynamic/antag_rulesets.dm @@ -42,7 +42,10 @@ /// If true, the species blacklist is now a species whitelist var/banned_species_only = FALSE - // var/list/banned_mutual_rulesets = list() // UNIMPLEMENTED: could be used to prevent nukies rolling while theres cultists, or wizards, etc + /// Rulesets that cannot be rolled while this ruleset is active. Used to prevent traitors from rolling while theres cultists, etc. + var/list/banned_mutual_rulesets = list( + /datum/ruleset/team/cult, + ) /* This stuff changes, all stuff above is static */ /// How many antagonists to spawn @@ -56,11 +59,17 @@ stack_trace("[src] ([type]) was destroyed.") return ..() -/datum/ruleset/proc/ruleset_possible(ruleset_budget, rulesets) +/datum/ruleset/proc/ruleset_possible(ruleset_budget, rulesets, antag_budget) if(ruleset_budget < ruleset_cost) return RULESET_FAILURE_BUDGET + if(antag_budget < antag_cost) + return RULESET_FAILURE_ANTAG_BUDGET if(!length(SSticker.mode.get_players_for_role(antagonist_type::job_rank))) // this specifically needs to be job_rank not special_rank return RULESET_FAILURE_NO_PLAYERS + if(length(banned_mutual_rulesets) && length(rulesets)) + for(var/datum/ruleset/ruleset in rulesets) + if(ruleset.type in banned_mutual_rulesets) + return RULESET_FAILURE_MUTUAL_RULESET /datum/ruleset/proc/antagonist_possible(budget) return budget >= antag_cost @@ -148,8 +157,8 @@ /datum/ruleset/proc/latespawn(datum/game_mode/dynamic/dynamic) // latespawning is only used by traitors at this point, so we're just going to be naive and allocate all budget when this proc is called. - var/late_antag_amount = floor(dynamic.budget_overflow / antag_cost) - dynamic.budget_overflow -= (late_antag_amount * antag_cost) + var/late_antag_amount = floor(dynamic.antag_budget / antag_cost) + dynamic.antag_budget -= (late_antag_amount * antag_cost) var/list/datum/mind/possible_antags = get_latejoin_players() for(var/i in 1 to late_antag_amount) @@ -158,6 +167,13 @@ log_dynamic("Latespawned [late_antag_amount] [name]s.") +/datum/ruleset/proc/automatic_deduct(budget) + . = antag_cost * antag_amount + log_dynamic("Automatic deduction: +[antag_amount] [name]\s. Remaining budget: [budget - .].") + +/datum/ruleset/proc/declare_completion() + return + /datum/ruleset/traitor name = "Traitor" ruleset_weight = 11 @@ -205,6 +221,7 @@ // This is the fucking worst, but its required to not change functionality with mindflayers. Cannot be rolled normally, this is applied by other methods. /datum/ruleset/implied + name = "BASE IMPLIED RULESET" // These 3 variables should never change ruleset_cost = 0 ruleset_weight = 0 @@ -234,3 +251,57 @@ implier.antag_amount -= 1 antag_amount += 1 was_triggered = TRUE + +/datum/ruleset/team + name = "BASE TEAM RULESET" + ruleset_weight = 0 + /// Whether there should only be one of this kind of team. This could be used for blood-brothers if false. + var/unique_team = TRUE + /// How many players on a team. + var/team_size = 1 + /// Team datum to create. + var/datum/team/team_type + +/datum/ruleset/team/roundstart_post_setup(datum/game_mode/dynamic) + if(unique_team) + new team_type(pre_antags) + return + stack_trace("Undefined behavior for dynamic non-unique teams!") + +/datum/ruleset/team/automatic_deduct(budget) + antag_amount = team_size + . = antag_cost + log_dynamic("Automatic deduction: +[antag_amount] [name]\s. Remaining budget: [budget - .].") + +/datum/ruleset/team/antagonist_possible(budget) + if(unique_team) // we're given our size at the start, no more please! + return FALSE + return ..() + +/datum/ruleset/team/cult + name = "Cultist" + ruleset_cost = 1 + ruleset_weight = 3 + // antag_weight doesnt matter, since we've already allocated our budget for 4 cultists only + antag_cost = 30 + antagonist_type = /datum/antagonist/cultist + banned_mutual_rulesets = list( + /datum/ruleset/traitor, + /datum/ruleset/vampire, + /datum/ruleset/changeling + ) + banned_jobs = list("Cyborg", "AI", "Chaplain", "Head of Personnel") + + team_size = 4 + team_type = /datum/team/cult + +/datum/ruleset/team/cult/declare_completion() + if(SSticker.mode.cult_team.cult_status == NARSIE_HAS_RISEN) + SSticker.mode_result = "cult win - cult win" + to_chat(world, "The cult wins! It has succeeded in summoning [GET_CULT_DATA(entity_name, "their god")]!") + else if(SSticker.mode.cult_team.cult_status == NARSIE_HAS_FALLEN) + SSticker.mode_result = "cult draw - narsie died, nobody wins" + to_chat(world, "Nobody wins! [GET_CULT_DATA(entity_name, "the cult god")] was summoned, but banished!") + else + SSticker.mode_result = "cult loss - staff stopped the cult" + to_chat(world, "The staff managed to stop the cult!") diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index d16bea196080..b75cdc5fca93 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -10,7 +10,7 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) var/list/datum/ruleset/implied_rulesets = list() /// How much budget is left after roundstart antagonists roll - var/budget_overflow = 0 + var/antag_budget = 0 /// Log for what happens in a dynamic round var/list/dynamic_log = list() @@ -27,7 +27,8 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) to_chat(world, "Possible Rulesets: [english_list(possible_rulesets)]") /datum/game_mode/dynamic/proc/allocate_ruleset_budget() - var/ruleset_budget = text2num(GLOB.dynamic_forced_rulesets["budget"] || pickweight(list("0" = 3, "1" = 5, "2" = 12, "3" = 3))) // more likely to or 2 + var/ruleset_budget = text2num(GLOB.dynamic_forced_rulesets["budget"] || pickweight(list("0" = 3, "1" = 8, "2" = 12, "3" = 3))) + antag_budget = num_players() log_dynamic("Allocated gamemode budget: [ruleset_budget]") var/list/possible_rulesets = list() for(var/datum/ruleset/ruleset as anything in subtypesof(/datum/ruleset)) @@ -68,9 +69,9 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) if(!ruleset) return if(!force) - var/failure_reason = ruleset.ruleset_possible(ruleset_budget, rulesets) + var/failure_reason = ruleset.ruleset_possible(ruleset_budget, rulesets, antag_budget) if(failure_reason) - log_dynamic("Failed [ruleset.name] ruleset: [failure_reason]") + log_dynamic("Failed [ruleset.name] ruleset: [failure_reason].") return log_dynamic("Rolled ruleset: [ruleset.name]") rulesets[ruleset] = ruleset.antag_weight @@ -89,33 +90,30 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) if(!length(rulesets)) log_dynamic("No rulesets in play.") return - var/budget = num_players() - log_dynamic("Allocated antagonist budget: [budget].") + log_dynamic("Allocated antagonist budget: [antag_budget].") for(var/datum/ruleset/ruleset in rulesets) ruleset.antag_amount = 1 - budget -= ruleset.antag_cost - log_dynamic("Automatic deduction: +1 [ruleset.name]. Remaining budget: [budget].") + antag_budget -= ruleset.automatic_deduct(antag_budget) log_dynamic("Rulesets in play: [english_list((rulesets + implied_rulesets))]") - apply_antag_budget(budget) + apply_antag_budget() -/datum/game_mode/dynamic/proc/apply_antag_budget(budget) // todo, can be called later in the game to apply more budget. That also means there has to be shit done for latejoins. +/datum/game_mode/dynamic/proc/apply_antag_budget() // todo, can be called later in the game to apply more budget. That also means there has to be shit done for latejoins. var/list/temp_rulesets = rulesets.Copy() - while(budget >= 0) + while(antag_budget >= 0) var/datum/ruleset/ruleset = pickweight(temp_rulesets) if(!ruleset) - log_dynamic("No rulesets remaining. Remaining budget: [budget].") - budget_overflow = budget + log_dynamic("No rulesets remaining. Remaining budget: [antag_budget].") return - if(!ruleset.antagonist_possible(budget)) + if(!ruleset.antagonist_possible(antag_budget)) log_dynamic("Rolled [ruleset.name]: failed, removing [ruleset.name] ruleset.") temp_rulesets -= ruleset continue ruleset.antag_amount++ - budget -= ruleset.antag_cost - log_dynamic("Rolled [ruleset.name]: success, +1 [ruleset.name]. Remaining budget: [budget].") + antag_budget -= ruleset.antag_cost + log_dynamic("Rolled [ruleset.name]: success, +1 [ruleset.name]. Remaining budget: [antag_budget].") log_dynamic("No more antagonist budget remaining.") /datum/game_mode/dynamic/pre_setup() @@ -128,10 +126,10 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) for(var/datum/ruleset/ruleset in (rulesets + implied_rulesets)) // rulesets first, then implied rulesets log_dynamic("Applying [ruleset.antag_amount] [ruleset.name]\s.") - budget_overflow += ruleset.roundstart_pre_setup() + antag_budget += ruleset.roundstart_pre_setup() - log_dynamic("Budget overflow: [budget_overflow].") - // for the future, maybe try readding antagonists with apply_antag_budget(budget_overflow) + log_dynamic("Budget overflow: [antag_budget].") + // for the future, maybe try readding antagonists with apply_antag_budget(antag_budget) log_dynamic("Finished dynamic setup in [stop_watch(watch)]s.") return TRUE @@ -147,19 +145,19 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) /datum/game_mode/dynamic/latespawn(mob) . = ..() - budget_overflow++ + antag_budget++ /datum/game_mode/dynamic/on_mob_cryo(mob/sleepy_mob, obj/machinery/cryopod/cryopod) var/turf/T = get_turf(cryopod) if(!T || is_admin_level(T.z)) return - budget_overflow-- + antag_budget-- if(!sleepy_mob.mind || !length(sleepy_mob.mind.antag_datums)) return for(var/datum/antagonist/antag in sleepy_mob.mind.antag_datums) for(var/datum/ruleset/possible_ruleset as anything in subtypesof(/datum/ruleset)) if(istype(antag, possible_ruleset.antagonist_type)) - budget_overflow += possible_ruleset.antag_cost + antag_budget += possible_ruleset.antag_cost log_dynamic("[possible_ruleset] cryo. +[possible_ruleset.antag_cost] budget.") /datum/game_mode/dynamic/get_webhook_name() @@ -169,6 +167,11 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) implied_and_used += implied return "[name] ([english_list(rulesets + implied_and_used, nothing_text = "Extended")])" +/datum/game_mode/dynamic/declare_completion() + for(var/datum/ruleset/ruleset in rulesets) + ruleset.declare_completion() + . = ..() + /proc/log_dynamic(text) log_game("Dynamic: [text]") var/datum/game_mode/dynamic/dynamic = SSticker.mode diff --git a/code/game/gamemodes/miniantags/tourist/tourist_arrivals.dm b/code/game/gamemodes/miniantags/tourist/tourist_arrivals.dm index f91f1369bc9c..9c3bc0521400 100644 --- a/code/game/gamemodes/miniantags/tourist/tourist_arrivals.dm +++ b/code/game/gamemodes/miniantags/tourist/tourist_arrivals.dm @@ -118,8 +118,8 @@ head_organ.sec_hair_colour = hair_c M.change_eye_color(eye_c) M.s_tone = skin_tone - head_organ.h_style = random_hair_style(M.gender, head_organ.dna.species.name) - head_organ.f_style = random_facial_hair_style(M.gender, head_organ.dna.species.name) + head_organ.h_style = random_hair_style(M.gender, head_organ.dna.species.sprite_sheet_name) + head_organ.f_style = random_facial_hair_style(M.gender, head_organ.dna.species.sprite_sheet_name) M.regenerate_icons() M.update_body() diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index e6b8638e5f05..32d9950aa5a6 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -127,24 +127,28 @@ FIRE ALARM /obj/machinery/firealarm/item_interaction(mob/living/user, obj/item/used, list/modifiers) add_fingerprint(user) - if(wiresexposed) - if(buildstage == FIRE_ALARM_UNWIRED && istype(used, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/coil = used - if(!coil.use(5)) - to_chat(user, "You need a total of five cables to wire [src]!") - return ITEM_INTERACT_COMPLETE - - buildstage = FIRE_ALARM_READY - playsound(get_turf(src), used.usesound, 50, 1) - to_chat(user, "You wire [src]!") - update_icon() - else if(buildstage == FIRE_ALARM_FRAME && istype(used, /obj/item/firealarm_electronics)) - to_chat(user, "You insert the circuit!") - qdel(used) - buildstage = FIRE_ALARM_UNWIRED - update_icon() + if(!wiresexposed) + return ..() + + if(buildstage == FIRE_ALARM_UNWIRED && istype(used, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/coil = used + if(!coil.use(5)) + to_chat(user, "You need a total of five cables to wire [src]!") + return ITEM_INTERACT_COMPLETE + buildstage = FIRE_ALARM_READY + playsound(get_turf(src), used.usesound, 50, TRUE) + to_chat(user, "You wire [src]!") + update_icon() return ITEM_INTERACT_COMPLETE + + if(buildstage == FIRE_ALARM_FRAME && istype(used, /obj/item/firealarm_electronics)) + to_chat(user, "You insert the circuit!") + qdel(used) + buildstage = FIRE_ALARM_UNWIRED + update_icon() + return ITEM_INTERACT_COMPLETE + return ..() /obj/machinery/firealarm/crowbar_act(mob/user, obj/item/I) @@ -198,6 +202,7 @@ FIRE ALARM return if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return + update_icon() WIRECUTTER_SNIP_MESSAGE var/obj/item/stack/cable_coil/new_coil = new /obj/item/stack/cable_coil(drop_location()) new_coil.amount = 5 diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index f6a7070cbfa2..0d7c47d3048a 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -49,7 +49,10 @@ . = ..() . += "The power light is [(stat & NOPOWER) ? "off" : "on"]." . += "The operation light is [emergency_mode ? "off. [src] has detected a forbidden object with its sensors, and has shut down temporarily." : "on. [src] is active."]" - . += "The safety sensor light is [emagged ? "off!" : "on."]" + if(HAS_TRAIT(src, TRAIT_CMAGGED)) + . += "The safety sensor light is RGB." + else + . += "The safety sensor light is [emagged ? "off!" : "on."]" . += "The recycler current accepts items from [dir2text(eat_dir)]." /obj/machinery/recycler/power_change() @@ -77,9 +80,23 @@ if(default_unfasten_wrench(user, I, time = 6 SECONDS)) return TRUE - +/obj/machinery/recycler/cmag_act(mob/user) + if(emagged) + to_chat(user, "The board is completely fried.") + return FALSE + if(!HAS_TRAIT(src, TRAIT_CMAGGED)) + ADD_TRAIT(src, TRAIT_CMAGGED, CLOWN_EMAG) + if(emergency_mode) + emergency_mode = FALSE + update_icon(UPDATE_ICON_STATE) + playsound(src, "sparks", 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + to_chat(user, "You use the jestographic sequencer on [src].") + return TRUE /obj/machinery/recycler/emag_act(mob/user) + if(HAS_TRAIT(src, TRAIT_CMAGGED)) + to_chat(user, "The access panel is coated in yellow ooze...") + return FALSE if(!emagged) emagged = TRUE if(emergency_mode) @@ -127,6 +144,8 @@ else if(isliving(AM)) if(emagged) crush_living(AM) + else if(HAS_TRAIT(src, TRAIT_CMAGGED)) + bananafication(AM) else emergency_stop(AM) else if(isitem(AM)) @@ -165,6 +184,15 @@ emergency_mode = FALSE update_icon(UPDATE_ICON_STATE) +/obj/machinery/recycler/proc/bananafication(mob/living/L) + L.loc = loc + if(!iscarbon(L)) + playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) + return + var/mob/living/carbon/human/victim = L + playsound(src, 'sound/items/AirHorn.ogg', 100, TRUE, -1) + victim.bananatouched_harmless() + /obj/machinery/recycler/proc/crush_living(mob/living/L) L.loc = loc diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 73b80c850722..170fbfd6ba6d 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -561,3 +561,45 @@ if(length(M.equipment) < M.max_equip) return TRUE return FALSE + +/obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam + name = "exosuit medical beamgun" + desc = "Equipment for medical exosuits. A mounted medical nanite projector which will treat patients with a focused beam. Unlike its handheld counterpart, it is incapable of healing internal injuries." + icon_state = "mecha_medigun" + energy_drain = 20 + range = MECHA_MELEE | MECHA_RANGED + equip_cooldown = 0 + origin_tech = "combat=5;materials=6;powerstorage=6;biotech=6" + var/obj/item/gun/medbeam/mech/medigun + materials = list(MAT_METAL = 15000, MAT_GLASS = 8000, MAT_PLASMA = 3000, MAT_GOLD = 8000, MAT_DIAMOND = 2000) + +/obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam/Initialize(mapload) + . = ..() + medigun = new(src) + +/obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam/Destroy() + QDEL_NULL(medigun) + return ..() + +/obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam/process() + if(..()) + return + medigun.process() + +/obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam/action(atom/target) + medigun.process_fire(target, loc) + +/obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam/detach() + if(medigun) + medigun.LoseTarget() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam/can_attach(obj/mecha/medical/M) + if(..()) + for(var/obj/item/beamgun in M) + if(istype(beamgun, /obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam)) + return FALSE //One beamgun per mech + if(istype(M)) + return TRUE + return FALSE diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index d09f84a766f9..baf991f91326 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -211,6 +211,11 @@ delay = 5 SECONDS start_effect_type = /obj/effect/temp_visual/rcd_effect/reverse +/datum/rcd_act/remove_user/can_act(atom/A, obj/item/rcd/rcd) + if(!..()) + return FALSE + return A == rcd.loc + /obj/item/rcd name = "rapid-construction-device (RCD)" desc = "A device used to rapidly build and deconstruct walls, floors and airlocks." @@ -343,11 +348,10 @@ /obj/item/rcd/suicide_act(mob/living/user) user.Immobilize(10 SECONDS) // You cannot move. flags |= NODROP // You cannot drop. You commit to die. - var/turf/suicide_tile = get_turf(src) if(mode == MODE_DECON) user.visible_message("[user] points [src] at [user.p_their()] chest and pulls the trigger. It looks like [user.p_theyre()] trying to commit suicide!") var/datum/rcd_act/remove_user/act = new() - if(!act.try_act(suicide_tile, src, user)) + if(!act.try_act(user, src, user)) flags &= ~NODROP return SHAME user.visible_message("[user] deconstructs [user.p_themselves()] with [src]!") @@ -358,7 +362,7 @@ return OBLITERATION user.visible_message("[user] puts the barrel of [src] into [user.p_their()] mouth and pulls the trigger. It looks like [user.p_theyre()] trying to commit suicide!") - if(!interact_with_atom(suicide_tile, user, TRUE)) + if(!interact_with_atom(get_turf(src), user, TRUE)) flags &= ~NODROP return SHAME user.visible_message("[user] explodes as [src] builds a structure inside [user.p_them()]!") diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm index 88ffb6d24470..a41aacb953c6 100644 --- a/code/game/objects/items/weapons/extinguisher.dm +++ b/code/game/objects/items/weapons/extinguisher.dm @@ -17,12 +17,16 @@ attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed") dog_fashion = /datum/dog_fashion/back resistance_flags = FIRE_PROOF + new_attack_chain = TRUE var/max_water = 50 - var/safety = TRUE - var/refilling = FALSE - /// FALSE by default, turfs picked from a spray are random, set to TRUE to make it always have at least one water effect per row + /// If `TRUE`, using in hand will toggle the extinguisher's safety. This must be set to `FALSE` for extinguishers with different firing modes (i.e. backpacks). + var/has_safety = TRUE + /// If `TRUE`, the extinguisher will not fire. + var/safety_active = TRUE + /// When `FALSE`, turfs picked from a spray are random. When `TRUE`, it always has at least one water effect per row. var/precision = FALSE - var/cooling_power = 2 //Sets the cooling_temperature of the water reagent datum inside of the extinguisher when it is refilled + /// Sets the `cooling_temperature` of the water reagent datum inside of the extinguisher when it is refilled. + var/cooling_power = 2 COOLDOWN_DECLARE(last_use) /obj/item/extinguisher/mini @@ -31,8 +35,8 @@ icon_state = "miniFE0" item_state = "miniFE" base_icon_state = "miniFE" - hitsound = null //it is much lighter, after all. - flags = null //doesn't CONDUCT + hitsound = null // It is much lighter, after all. + flags = null // Non-conductive, not made of metal. throwforce = 2 w_class = WEIGHT_CLASS_SMALL force = 3 @@ -42,8 +46,8 @@ /obj/item/extinguisher/examine(mob/user) . = ..() - . += "The safety is [safety ? "on" : "off"]." - + if(has_safety) + . += "The safety is [safety_active ? "on" : "off"]." /obj/item/extinguisher/Initialize(mapload) . = ..() @@ -52,72 +56,81 @@ reagents.add_reagent("water", max_water) ADD_TRAIT(src, TRAIT_CAN_POINT_WITH, ROUNDSTART_TRAIT) -/obj/item/extinguisher/attack_self__legacy__attackchain(mob/user as mob) - safety = !safety - icon_state = "[base_icon_state][!safety]" - to_chat(user, "You [safety ? "enable" : "disable"] [src]'s safety.") +/obj/item/extinguisher/activate_self(mob/user) + if(..()) + return -/obj/item/extinguisher/attack_obj__legacy__attackchain(obj/O, mob/living/user, params) - if(AttemptRefill(O, user)) - refilling = TRUE - return FALSE - else - return ..() + // Backpack extinguishers have no safety mechanism. + if(!has_safety) + return + + safety_active = !safety_active + icon_state = "[base_icon_state][!safety_active]" + to_chat(user, "You [safety_active ? "enable" : "disable"] [src]'s safety.") + return ITEM_INTERACT_COMPLETE -/obj/item/extinguisher/proc/AttemptRefill(atom/target, mob/user) +/obj/item/extinguisher/interact_with_atom(atom/target, mob/living/user, list/modifiers) + . = ..() + if(attempt_refill(target, user)) + return ITEM_INTERACT_COMPLETE + + if(extinguisher_spray(target, user)) + return ITEM_INTERACT_COMPLETE + +/obj/item/extinguisher/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(extinguisher_spray(target, user)) + return ITEM_INTERACT_COMPLETE + +/obj/item/extinguisher/proc/attempt_refill(atom/target, mob/user) if(!istype(target, /obj/structure/reagent_dispensers/watertank) || !target.Adjacent(user)) return FALSE - var/old_safety = safety - safety = TRUE + if(reagents.total_volume == reagents.maximum_volume) - to_chat(user, "\The [src] is already full!") - safety = old_safety + to_chat(user, "[src] is already full.") return TRUE + var/obj/structure/reagent_dispensers/watertank/W = target var/transferred = W.reagents.trans_to(src, max_water) - if(transferred > 0) - to_chat(user, "\The [src] has been refilled by [transferred] units.") - playsound(loc, 'sound/effects/refill.ogg', 50, TRUE, -6) - for(var/datum/reagent/water/R in reagents.reagent_list) - R.cooling_temperature = cooling_power - else + if(!transferred) to_chat(user, "\The [W] is empty!") - safety = old_safety + return TRUE + + to_chat(user, "[src] has been refilled with [transferred] units.") + playsound(loc, 'sound/effects/refill.ogg', 50, TRUE, -6) + for(var/datum/reagent/water/R in reagents.reagent_list) + R.cooling_temperature = cooling_power return TRUE -/obj/item/extinguisher/afterattack__legacy__attackchain(atom/target, mob/user, flag) - . = ..() - //TODO; Add support for reagents in water. - if(target.loc == user)//No more spraying yourself when putting your extinguisher away - return +/obj/item/extinguisher/proc/extinguisher_spray(atom/A, mob/living/user) + . = TRUE - if(refilling) - refilling = FALSE + // Violence, please! + if(safety_active) + return FALSE + + if(!COOLDOWN_FINISHED(src, last_use)) return - if(safety) - return ..() if(reagents.total_volume < 1) to_chat(user, "[src] is empty.") return - if(!COOLDOWN_FINISHED(src, last_use)) + if(A.loc == user) return COOLDOWN_START(src, last_use, 2 SECONDS) - if(reagents.chem_temp > 300 || reagents.chem_temp < 280) - add_attack_logs(user, target, "Sprayed with superheated or cooled fire extinguisher at Temperature [reagents.chem_temp]K") + add_attack_logs(user, A, "Sprayed with superheated or cooled fire extinguisher at Temperature [reagents.chem_temp]K") playsound(loc, 'sound/effects/extinguish.ogg', 75, TRUE, -3) - var/direction = get_dir(src, target) + var/direction = get_dir(src, A) if(isobj(user.buckled) && !user.buckled.anchored && !istype(user.buckled, /obj/vehicle)) INVOKE_ASYNC(src, PROC_REF(buckled_speed_move), user.buckled, direction) else user.newtonian_move(turn(direction, 180)) - var/turf/T = get_turf(target) + var/turf/T = get_turf(A) var/turf/T1 = get_step(T, turn(direction, 90)) var/turf/T2 = get_step(T, turn(direction, -90)) var/list/the_targets = list(T, T1, T2) diff --git a/code/game/objects/items/weapons/rpd.dm b/code/game/objects/items/weapons/rpd.dm index a7795aff20a3..d85bda11ba25 100644 --- a/code/game/objects/items/weapons/rpd.dm +++ b/code/game/objects/items/weapons/rpd.dm @@ -342,7 +342,7 @@ // If we get here, then we're effectively acting on the turf, probably placing a pipe. if(ranged) //woosh beam if bluespaced at a distance - if(get_dist(src, T) >= (user.client.maxview() + 2)) + if(get_dist(src, T) >= (user.client.maxview() / 2)) message_admins("\[EXPLOIT] [key_name_admin(user)] attempted to place pipes with a BRPD via a camera console. (Attempted range exploit)") playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE) to_chat(user, "ERROR: \The [T] is out of [src]'s range!") diff --git a/code/game/objects/items/weapons/stock_parts.dm b/code/game/objects/items/weapons/stock_parts.dm index 5f8d009af33c..c24f6c4d1c4f 100644 --- a/code/game/objects/items/weapons/stock_parts.dm +++ b/code/game/objects/items/weapons/stock_parts.dm @@ -50,17 +50,16 @@ if(!proximity_flag) if(!works_from_distance) return - if(get_dist(src, M) > (user.client.maxview() + 2)) + if(get_dist(user, M) > (user.client.maxview() / 2)) + message_admins("\[EXPLOIT] [key_name_admin(user)] attempted to upgrade machinery with a BRPED via a camera console (attempted range exploit).") + playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE) + to_chat(user, "ERROR: [M] is out of [src]'s range!") return if(M.component_parts) M.exchange_parts(user, src) if(works_from_distance) user.Beam(M, icon_state="rped_upgrade", icon='icons/effects/effects.dmi', time=5) - else - message_admins("\[EXPLOIT] [key_name_admin(user)] attempted to upgrade machinery with a BRPED via a camera console (attempted range exploit).") - playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE) - to_chat(user, "ERROR: [M] is out of [src]'s range!") /obj/item/storage/part_replacer/tier4/populate_contents() for(var/amount in 1 to 30) @@ -283,9 +282,3 @@ rating = 4 materials = list(MAT_METAL=80) -/obj/item/research//Makes testing much less of a pain -Sieve - name = "research" - icon = 'icons/obj/stock_parts.dmi' - icon_state = "capacitor" - desc = "A debug item for research." - origin_tech = "materials=8;programming=8;magnets=8;powerstorage=8;bluespace=8;combat=8;biotech=8;syndicate=8;engineering=8;plasmatech=8;abductor=8" diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index fb1dcaca5733..5162507e11b7 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -195,7 +195,7 @@ /// 80TC + modules + laser gun /obj/item/storage/box/syndie_kit/bundle/metroid name = "Modsuit Bundle" - desc = "Don the equipment of an intergalactic bounty hunter and blast your way through the station!" + desc = "Don the equipment of an interstellar bounty hunter and blast your way through the station!" items = list( /obj/item/mod/control/pre_equipped/traitor_elite, // 45TC /obj/item/mod/module/visor/thermal, // 15TC diff --git a/code/game/objects/items/weapons/tanks/watertank.dm b/code/game/objects/items/weapons/tanks/watertank.dm index 4722417ad467..d8289c434da4 100644 --- a/code/game/objects/items/weapons/tanks/watertank.dm +++ b/code/game/objects/items/weapons/tanks/watertank.dm @@ -142,7 +142,7 @@ return /proc/check_tank_exists(parent_tank, mob/living/carbon/human/M, obj/O) - if(!parent_tank || !istype(parent_tank, /obj/item/watertank)) //To avoid weird issues from admin spawns + if(!parent_tank || (!istype(parent_tank, /obj/item/watertank) && !istype(parent_tank, /obj/item/mod/module/firefighting_tank))) //To avoid weird issues from admin spawns return FALSE else return TRUE @@ -218,11 +218,12 @@ name = "extinguisher nozzle" desc = "A heavy duty nozzle attached to a firefighter's backpack tank." icon = 'icons/obj/watertank.dmi' - icon_state = "atmos_nozzle" + icon_state = "atmos_nozzle_1" item_state = "nozzleatmos" - safety = 0 + has_safety = FALSE + safety_active = FALSE max_water = 500 - precision = 1 + precision = TRUE cooling_power = 5 w_class = WEIGHT_CLASS_HUGE flags = NODROP //Necessary to ensure that the nozzle and tank never seperate @@ -230,10 +231,23 @@ var/obj/item/watertank/tank /// What mode are we currently in? var/nozzle_mode = EXTINGUISHER - /// Are we overusing the metal synthesizer? can be used 5 times in quick succession, regains 1 use per 10 seconds - var/metal_synthesis_cooldown = 0 - /// Is our nanofrost on cooldown? - var/nanofrost_cooldown = FALSE + /// How many shots of metal foam do we have? + var/metal_synthesis_charge = 5 + /// Time to refill 1 charge of metal foam. + var/metal_regen_time = 2 SECONDS + /// Refire delay for nanofrost chunks. + var/nanofrost_cooldown_time = 2 SECONDS + COOLDOWN_DECLARE(nanofrost_cooldown) + +/obj/item/extinguisher/mini/nozzle/examine(mob/user) + . = ..() + switch(nozzle_mode) + if(EXTINGUISHER) + . += "[src] is currently set to extinguishing mode." + if(NANOFROST) + . += "[src] is currently set to nanofrost mode." + if(METAL_FOAM) + . += "[src] is currently set to metal foam mode." /obj/item/extinguisher/mini/nozzle/Initialize(mapload) if(!check_tank_exists(loc, src)) @@ -255,67 +269,88 @@ if(tank && loc != tank.loc) forceMove(tank) -/obj/item/extinguisher/mini/nozzle/attack_self__legacy__attackchain(mob/user) +/obj/item/extinguisher/mini/nozzle/activate_self(mob/user) + ..() switch(nozzle_mode) if(EXTINGUISHER) nozzle_mode = NANOFROST - tank.icon_state = "waterbackpackatmos_1" to_chat(user, "Swapped to nanofrost launcher") if(NANOFROST) nozzle_mode = METAL_FOAM - tank.icon_state = "waterbackpackatmos_2" to_chat(user, "Swapped to metal foam synthesizer") if(METAL_FOAM) nozzle_mode = EXTINGUISHER - tank.icon_state = "waterbackpackatmos_0" to_chat(user, "Swapped to water extinguisher") + update_icon(UPDATE_ICON_STATE) + return ITEM_INTERACT_COMPLETE + +/obj/item/extinguisher/mini/nozzle/update_icon_state() + switch(nozzle_mode) + if(EXTINGUISHER) + icon_state = "atmos_nozzle_1" + tank.icon_state = "waterbackpackatmos_0" + if(NANOFROST) + icon_state = "atmos_nozzle_2" + tank.icon_state = "waterbackpackatmos_1" + if(METAL_FOAM) + icon_state = "atmos_nozzle_3" + tank.icon_state = "waterbackpackatmos_2" /obj/item/extinguisher/mini/nozzle/dropped(mob/user) ..() + if(istype(tank, /obj/item/mod/module/firefighting_tank)) + return + to_chat(user, "The nozzle snaps back onto the tank!") tank.on = FALSE loc = tank -/obj/item/extinguisher/mini/nozzle/afterattack__legacy__attackchain(atom/target, mob/user) +/obj/item/extinguisher/mini/nozzle/extinguisher_spray(atom/A, mob/living/user) if(nozzle_mode == EXTINGUISHER) - ..() - return - var/Adj = user.Adjacent(target) - if(Adj) - AttemptRefill(target, user) + return ..() + . = TRUE switch(nozzle_mode) if(NANOFROST) - if(Adj) - return //Safety check so you don't blast yourself trying to refill your tank if(reagents.total_volume < 100) - to_chat(user, "You need at least 100 units of water to use the nanofrost launcher!") + to_chat(user, "You need at least 100 units of water to use the nanofrost launcher!") return - if(nanofrost_cooldown) - to_chat(user, "Nanofrost launcher is still recharging.") + + if(COOLDOWN_TIMELEFT(src, nanofrost_cooldown)) + to_chat(user, "The nanofrost launcher is still recharging!") return - nanofrost_cooldown = TRUE + + COOLDOWN_START(src, nanofrost_cooldown, nanofrost_cooldown_time) reagents.remove_any(100) - var/obj/effect/nanofrost_container/A = new /obj/effect/nanofrost_container(get_turf(src)) + var/obj/effect/nanofrost_container/iceball = new /obj/effect/nanofrost_container(get_turf(src)) log_game("[key_name(user)] used Nanofrost at [get_area(user)] ([user.x], [user.y], [user.z]).") playsound(src,'sound/items/syringeproj.ogg', 40, TRUE) - A.throw_at(target, 6, 2, user) + iceball.throw_at(A, 6, 2, user) sleep(2) - A.Smoke() - addtimer(VARSET_CALLBACK(src, nanofrost_cooldown, FALSE)) + iceball.Smoke() + return + if(METAL_FOAM) - if(!Adj) + if(!user.Adjacent(A) || !isturf(A)) return - if(metal_synthesis_cooldown >= 5) - to_chat(user, "Metal foam mix is still being synthesized.") + + if(metal_synthesis_charge <= 0) + to_chat(user, "Metal foam mix is still being synthesized!") return - var/obj/effect/particle_effect/foam/metal/F = new /obj/effect/particle_effect/foam/metal(get_turf(target), TRUE) - F.spread_amount = 0 - metal_synthesis_cooldown++ - addtimer(CALLBACK(src, PROC_REF(metal_cooldown)), 10 SECONDS) -/obj/item/extinguisher/mini/nozzle/proc/metal_cooldown() - metal_synthesis_cooldown-- + if(reagents.total_volume < 10) + to_chat(user, "You need at least 10 units of water to use the metal foam synthesizer!") + return + + var/obj/effect/particle_effect/foam/metal/foam = new /obj/effect/particle_effect/foam/metal(get_turf(A), TRUE) + foam.spread_amount = 0 + reagents.remove_any(10) + metal_synthesis_charge-- + addtimer(CALLBACK(src, PROC_REF(refill_metal_charge)), metal_regen_time) + return + +/obj/item/extinguisher/mini/nozzle/proc/refill_metal_charge() + metal_synthesis_charge++ /obj/effect/nanofrost_container name = "nanofrost container" diff --git a/code/game/objects/mail.dm b/code/game/objects/mail.dm index 86ec5986d279..f0b0171f8cc0 100644 --- a/code/game/objects/mail.dm +++ b/code/game/objects/mail.dm @@ -230,7 +230,7 @@ /obj/item/mail_scanner name = "mail scanner" - desc = "Sponsored by Messaging and Intergalactic Letters, this device allows you to log mail deliveries in exchange for financial compensation." + desc = "A portable mail scanner, this device allows you to log mail deliveries in exchange for financial compensation." force = 0 throwforce = 0 icon = 'icons/obj/device.dmi' @@ -295,5 +295,5 @@ saved = null to_chat(user, "Successful delivery acknowledged! [MAIL_DELIVERY_BONUS] credits added to Supply account!") playsound(loc, 'sound/mail/mailapproved.ogg', 50, TRUE) - GLOB.station_money_database.credit_account(SSeconomy.cargo_account, MAIL_DELIVERY_BONUS, "Mail Delivery Compensation", "Messaging and Intergalactic Letters", supress_log = FALSE) + GLOB.station_money_database.credit_account(SSeconomy.cargo_account, MAIL_DELIVERY_BONUS, "Mail Delivery Compensation", "Nanotrasen Mail and Interstellar Logistics", supress_log = FALSE) SSblackbox.record_feedback("amount", "successful_mail_delivery", 1) diff --git a/code/game/objects/structures/dresser.dm b/code/game/objects/structures/dresser.dm index 5bc31b1d0502..e93f865cc7ed 100644 --- a/code/game/objects/structures/dresser.dm +++ b/code/game/objects/structures/dresser.dm @@ -21,7 +21,7 @@ var/list/valid_underwear = list() for(var/underwear in GLOB.underwear_list) var/datum/sprite_accessory/S = GLOB.underwear_list[underwear] - if(!(H.dna.species.name in S.species_allowed)) + if(!(H.dna.species.sprite_sheet_name in S.species_allowed)) continue valid_underwear[underwear] = GLOB.underwear_list[underwear] var/new_underwear = tgui_input_list(user, "Choose your underwear:", "Changing", valid_underwear) @@ -32,7 +32,7 @@ var/list/valid_undershirts = list() for(var/undershirt in GLOB.undershirt_list) var/datum/sprite_accessory/S = GLOB.undershirt_list[undershirt] - if(!(H.dna.species.name in S.species_allowed)) + if(!(H.dna.species.sprite_sheet_name in S.species_allowed)) continue valid_undershirts[undershirt] = GLOB.undershirt_list[undershirt] var/new_undershirt = tgui_input_list(user, "Choose your undershirt:", "Changing", valid_undershirts) @@ -43,7 +43,7 @@ var/list/valid_sockstyles = list() for(var/sockstyle in GLOB.socks_list) var/datum/sprite_accessory/S = GLOB.socks_list[sockstyle] - if(!(H.dna.species.name in S.species_allowed)) + if(!(H.dna.species.sprite_sheet_name in S.species_allowed)) continue valid_sockstyles[sockstyle] = GLOB.socks_list[sockstyle] var/new_socks = tgui_input_list(user, "Choose your socks:", "Changing", valid_sockstyles) diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index ff4636e30902..7e4b435c254c 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -201,7 +201,7 @@ /obj/structure/sign/greencross name = "medbay" - desc = "The Intergalactic symbol of Medical institutions. You'll probably get help here." + desc = "The universal symbol of medical institutions across the Sector. You'll probably find help here." icon_state = "greencross" /obj/structure/sign/goldenplaque diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 07a9085f4871..fcea2b6c6661 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -34,7 +34,9 @@ var/blocks_air = FALSE - flags = 0 + flags = 0 // TODO, someday move all off the flags here to turf_flags + + var/turf_flags = NONE var/image/obscured //camerachunks @@ -282,8 +284,9 @@ qdel(src) //Just get the side effects and call Destroy var/list/old_comp_lookup = comp_lookup?.Copy() var/list/old_signal_procs = signal_procs?.Copy() - + var/carryover_turf_flags = turf_flags & (RESERVATION_TURF|UNUSED_RESERVATION_TURF) var/turf/W = new path(src) + W.turf_flags |= carryover_turf_flags if(old_comp_lookup) LAZYOR(W.comp_lookup, old_comp_lookup) if(old_signal_procs) diff --git a/code/game/world.dm b/code/game/world.dm index da8dac0955df..cb67ae8829e7 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -1,6 +1,6 @@ GLOBAL_LIST_INIT(map_transition_config, list(CC_TRANSITION_CONFIG)) -#ifdef GAME_TESTS +#ifdef TEST_RUNNER GLOBAL_DATUM(test_runner, /datum/test_runner) #endif @@ -26,7 +26,11 @@ GLOBAL_DATUM(test_runner, /datum/test_runner) GLOB.configuration.load_configuration() // Load up the base config.toml // Load up overrides for this specific instance, based on port // If this instance is listening on port 6666, the server will look for config/overrides_6666.toml - GLOB.configuration.load_overrides() + GLOB.configuration.load_overrides("config/overrides_[world.port].toml") + + #ifdef TEST_CONFIG_OVERRIDE + GLOB.configuration.load_overrides("config/tests/config_[TEST_CONFIG_OVERRIDE].toml") + #endif // Right off the bat, load up the DB SSdbcore.CheckSchemaVersion() // This doesnt just check the schema version, it also connects to the db! This needs to happen super early! I cannot stress this enough! @@ -51,8 +55,8 @@ GLOBAL_DATUM(test_runner, /datum/test_runner) if(TgsAvailable()) world.log = file("[GLOB.log_directory]/dd.log") //not all runtimes trigger world/Error, so this is the only way to ensure we can see all of them. - #ifdef GAME_TESTS - log_world("Unit Tests Are Enabled!") + #ifdef TEST_RUNNER + log_world("Test runner enabled.") #endif if(byond_version < MIN_COMPILER_VERSION || byond_build < MIN_COMPILER_BUILD) @@ -69,7 +73,7 @@ GLOBAL_DATUM(test_runner, /datum/test_runner) Master.Initialize(10, FALSE, TRUE) - #ifdef GAME_TESTS + #ifdef TEST_RUNNER GLOB.test_runner = new GLOB.test_runner.Start() #endif @@ -144,7 +148,7 @@ GLOBAL_LIST_EMPTY(world_topic_handlers) Master.Shutdown() // Shutdown subsystems // If we were running unit tests, finish that run - #ifdef GAME_TESTS + #ifdef TEST_RUNNER GLOB.test_runner.Finalize() return #endif diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 8d1896340311..20975808c4d5 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -159,6 +159,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list( /proc/machine_upgrade, /client/proc/map_template_load, /client/proc/map_template_upload, + /client/proc/map_template_load_lazy, /client/proc/view_runtimes, /client/proc/admin_serialize, /client/proc/uid_log, diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 334c608bbf54..cce16b25c8f3 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1056,7 +1056,7 @@ if(GLOB.master_mode != "dynamic" && !(GLOB.master_mode == "secret" && GLOB.secret_force_mode == "dynamic")) return alert(usr, "The game mode has to be dynamic!", null, null, null, null) var/dat = {"Possible Rulesets:
"} - var/list/rulesets = subtypesof(/datum/ruleset) - typesof(/datum/ruleset/implied) + var/list/rulesets = subtypesof(/datum/ruleset) - typesof(/datum/ruleset/implied) - /datum/ruleset/team dat += {"Budget: [isnull(GLOB.dynamic_forced_rulesets["budget"]) ? "Random" : GLOB.dynamic_forced_rulesets["budget"]]
"} for(var/datum/ruleset/ruleset as anything in rulesets) dat += {"[ruleset.name]: [GLOB.dynamic_forced_rulesets[ruleset] || DYNAMIC_RULESET_NORMAL]
"} diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 559b983db522..2dcf196bce8b 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -121,10 +121,10 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) CRASH("WrapAdminProcCall with no ckey: [target] [procname] [english_list(arguments)]") if(current_caller && current_caller != ckey) if(!GLOB.AdminProcCallSpamPrevention[ckey]) - to_chat(usr, "Another set of admin called procs are still running, your proc will be run after theirs finish.") + to_chat(usr, "Another set of admin called procs are still running, your proc will be run after theirs finish.") GLOB.AdminProcCallSpamPrevention[ckey] = TRUE UNTIL(!GLOB.AdminProcCaller) - to_chat(usr, "Running your proc") + to_chat(usr, "Running your proc") GLOB.AdminProcCallSpamPrevention -= ckey else UNTIL(!GLOB.AdminProcCaller) @@ -135,8 +135,8 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) ++GLOB.AdminProcCallCount try . = world.WrapAdminProcCall(target, procname, arguments) - catch - to_chat(usr, "Your proc call failed to execute, likely from runtimes. You should be out of safety mode. If not, god help you.") + catch(var/exception/e) + to_chat(usr, "Your proc call failed to execute, likely from runtimes. You should be out of safety mode. If not, god help you. Runtime Info: [e.file]:[e.line]: [e.name]") if(--GLOB.AdminProcCallCount == 0) GLOB.AdminProcCaller = null diff --git a/code/modules/admin/verbs/map_template_loadverb.dm b/code/modules/admin/verbs/map_template_loadverb.dm index 80d46e18550d..c05060131fcf 100644 --- a/code/modules/admin/verbs/map_template_loadverb.dm +++ b/code/modules/admin/verbs/map_template_loadverb.dm @@ -56,3 +56,23 @@ message_admins("[key_name_admin(usr)] has uploaded a map template ([map]). Took [stop_watch(timer)]s.") else to_chat(usr, "Map template '[map]' failed to load properly") + +/client/proc/map_template_load_lazy() + set category = "Debug" + set name = "Map template - Lazy Load" + + if(!check_rights(R_DEBUG)) + return + + var/map = input(usr, "Choose a Map Template to place on the lazy load map level.","Place Map Template") as null|anything in GLOB.map_templates + if(!map) + return + var/datum/map_template/template = GLOB.map_templates[map] + + message_admins("[key_name_admin(usr)] is lazyloading the map template ([template.name]).") + var/datum/turf_reservation/reserve = SSmapping.lazy_load_template(template) + if(!istype(reserve)) + message_admins("Lazyloading [template.name] failed! You should report this as a bug.") + return + message_admins("[key_name_admin(usr)] has lazyloaded the map template ([template.name]) at [ADMIN_JMP(reserve.bottom_left_turf)]") + diff --git a/code/modules/antagonists/revolutionary/datum_headrev.dm b/code/modules/antagonists/revolutionary/datum_headrev.dm index 3097fbc02298..64e9311226ed 100644 --- a/code/modules/antagonists/revolutionary/datum_headrev.dm +++ b/code/modules/antagonists/revolutionary/datum_headrev.dm @@ -46,9 +46,9 @@ RESTRICT_TYPE(/datum/antagonist/rev/head) to_chat(revolutionary, "The flash in your [flashloc_name] will help you to persuade the crew to join your cause.") if(give_hud) - var/obj/item/clothing/glasses/hud/security/chameleon/C = new(get_turf(revolutionary)) - var/hudloc_name = revolutionary.equip_in_one_of_slots(C, slots) - to_chat(revolutionary, "The chameleon security HUD in your [hudloc_name] will help you keep track of who is mindshield-implanted, and unable to be recruited.") + var/obj/item/organ/internal/cyberimp/eyes/hud/security/hidden/O = new /obj/item/organ/internal/cyberimp/eyes/hud/security/hidden + O.insert(revolutionary) + to_chat(revolutionary, "The security HUD implant in your head will help you keep track of who is mindshield-implanted, and unable to be recruited.") revolutionary.update_icons() return flashloc_name diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index 636bf12a99e3..50da9a4b15ad 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -1,8 +1,3 @@ -/turf/simulated/Initialize(mapload) - . = ..() - if(!blocks_air) - blind_set_air(get_initial_air()) - /turf/simulated/proc/get_initial_air() var/datum/gas_mixture/air = new() if(!blocks_air) @@ -47,8 +42,12 @@ temperature -= heat/heat_capacity sharer.temperature += heat/sharer.heat_capacity -/turf/simulated/proc/update_visuals() - var/datum/gas_mixture/air = get_readonly_air() +/turf/simulated/proc/update_visuals(use_initial_air = FALSE) + var/datum/gas_mixture/air + if(use_initial_air) + air = get_initial_air() + else + air = get_readonly_air() var/new_overlay_type = tile_graphic(air) if(new_overlay_type == atmos_overlay_type) return @@ -177,6 +176,10 @@ var/list/air = list(oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b, temperature) milla_data = connectivity[1] + list(atmos_mode, SSmapping.environments[atmos_environment]) + air + connectivity[2] +/turf/simulated/Initialize_Atmos(milla_tick) + ..() + update_visuals(TRUE) + /turf/proc/recalculate_atmos_connectivity() var/datum/milla_safe/recalculate_atmos_connectivity/milla = new() milla.invoke_async(src) diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index 5216ac330ebd..fec392083781 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -104,6 +104,9 @@ GLOBAL_LIST_INIT(aalarm_modes, list( var/report_danger_level = TRUE + /// Which MILLA tick were we initialized at? + var/init_tick + /obj/machinery/alarm/monitor report_danger_level = FALSE @@ -232,6 +235,8 @@ GLOBAL_LIST_INIT(aalarm_modes, list( if(!building) first_run() + init_tick = SSair.milla_tick + /obj/machinery/alarm/Destroy() SStgui.close_uis(wires) GLOB.air_alarms -= src @@ -246,7 +251,7 @@ GLOBAL_LIST_INIT(aalarm_modes, list( GLOB.air_alarm_repository.update_cache(src) /obj/machinery/alarm/process() - if((stat & (NOPOWER|BROKEN)) || shorted || buildstage != 2) + if((stat & (NOPOWER|BROKEN)) || shorted || buildstage != 2 || init_tick == SSair.milla_tick) return var/turf/simulated/location = loc diff --git a/code/modules/awaymissions/cordon.dm b/code/modules/awaymissions/cordon.dm new file mode 100644 index 000000000000..4d44766ac668 --- /dev/null +++ b/code/modules/awaymissions/cordon.dm @@ -0,0 +1,32 @@ +/// Turf type that appears to be a world border, completely impassable and non-interactable to all physical (alive) entities. +/turf/cordon + name = "cordon" + icon = 'icons/turf/walls.dmi' + icon_state = "cordon" + invisibility = INVISIBILITY_ABSTRACT + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + explosion_block = 50 + rad_insulation = RAD_FULL_INSULATION + opacity = TRUE + density = TRUE + blocks_air = TRUE + baseturf = /turf/cordon + +// /turf/cordon/rust_heretic_act() +// return FALSE + +/turf/cordon/acid_act(acidpwr, acid_volume, acid_id) + return FALSE + +/turf/cordon/singularity_act() + return FALSE + +/turf/cordon/TerraformTurf(path, list/new_baseturfs, flags) + return + +/turf/cordon/bullet_act(obj/item/projectile/hitting_projectile, def_zone, piercing_hit) + SHOULD_CALL_PARENT(FALSE) // Fuck you + return + +/turf/cordon/Adjacent(atom/neighbor, atom/target, atom/movable/mover) + return FALSE diff --git a/code/modules/awaymissions/mob_spawn.dm b/code/modules/awaymissions/mob_spawn.dm index 3836b267eef1..7914faf17620 100644 --- a/code/modules/awaymissions/mob_spawn.dm +++ b/code/modules/awaymissions/mob_spawn.dm @@ -247,12 +247,12 @@ if(hair_style) D.h_style = hair_style else - D.h_style = random_hair_style(gender, D.dna.species.name) + D.h_style = random_hair_style(gender, D.dna.species.sprite_sheet_name) D.hair_colour = rand_hex_color() if(facial_hair_style) D.f_style = facial_hair_style else - D.f_style = random_facial_hair_style(gender, D.dna.species.name) + D.f_style = random_facial_hair_style(gender, D.dna.species.sprite_sheet_name) D.facial_colour = rand_hex_color() if(skin_tone) H.s_tone = skin_tone diff --git a/code/modules/awaymissions/zlevel_helpers.dm b/code/modules/awaymissions/zlevel_helpers.dm index 749abdf47a57..ca3cc60c1500 100644 --- a/code/modules/awaymissions/zlevel_helpers.dm +++ b/code/modules/awaymissions/zlevel_helpers.dm @@ -13,6 +13,8 @@ * turf in the world */ if(SSair && SSair.initialized) SSair.setup_turfs(bot_left, top_right) + log_debug("Unfreezing atmos.") + set_zlevel_freeze(bot_left.z, FALSE) log_debug("\tTook [stop_watch(subtimer)]s") subtimer = start_watch() @@ -39,3 +41,12 @@ for(var/otherthing in T) qdel(otherthing) T.ChangeTurf(T.baseturf) + +/datum/milla_safe/freeze_z_level + var/done = FALSE + +// Ensures that atmos is frozen before loading +/datum/milla_safe/freeze_z_level/on_run(z) + log_debug("Freezing atmos.") + set_zlevel_freeze(z, TRUE) + done = TRUE diff --git a/code/modules/client/login_processing/20-load_characters.dm b/code/modules/client/login_processing/20-load_characters.dm index 0edf260ae8de..84fd4f15b828 100644 --- a/code/modules/client/login_processing/20-load_characters.dm +++ b/code/modules/client/login_processing/20-load_characters.dm @@ -65,6 +65,7 @@ cyborg_brain_type, body_type, pda_ringtone, + species_subtype, tts_seed FROM characters WHERE ckey=:ckey"}, list( "ckey" = C.ckey diff --git a/code/modules/client/preference/character.dm b/code/modules/client/preference/character.dm index 6649705181da..fd0051dea687 100644 --- a/code/modules/client/preference/character.dm +++ b/code/modules/client/preference/character.dm @@ -37,6 +37,8 @@ var/e_colour = "#000000" //Eye color var/alt_head = "None" //Alt head style. var/species = "Human" + /// Used for DNA species to allow select species to imitate / morph into different species. + var/species_subtype = "None" var/language = "None" //Secondary language var/autohiss_mode = AUTOHISS_OFF //Species autohiss level. OFF, BASIC, FULL. /// If a spawned cyborg should have an MMI, a positronic, or a robobrain. MMI by default @@ -203,6 +205,7 @@ cyborg_brain_type=:cyborg_brain_type, body_type=:body_type, pda_ringtone=:pda_ringtone, + species_subtype=:species_subtype, tts_seed=:tts_seed WHERE ckey=:ckey AND slot=:slot"}, list( @@ -267,6 +270,7 @@ "runechat_color" = runechat_color, "cyborg_brain_type" = cyborg_brain_type, "pda_ringtone" = pda_ringtone, + "species_subtype" = species_subtype, "tts_seed" = tts_seed, // SS220 EDIT ADDITION - TTS220 "ckey" = C.ckey, "slot" = slot_number @@ -308,7 +312,7 @@ player_alt_titles, disabilities, organ_data, rlimb_data, nanotrasen_relation, physique, height, speciesprefs, socks, body_accessory, gear, autohiss, - hair_gradient, hair_gradient_offset, hair_gradient_colour, hair_gradient_alpha, custom_emotes, runechat_color, cyborg_brain_type, body_type, pda_ringtone, tts_seed) + hair_gradient, hair_gradient_offset, hair_gradient_colour, hair_gradient_alpha, custom_emotes, runechat_color, cyborg_brain_type, body_type, pda_ringtone, species_subtype, tts_seed) VALUES (:ckey, :slot, :metadata, :name, :be_random_name, :gender, :age, :species, :language, @@ -335,7 +339,7 @@ :playertitlelist, :disabilities, :organ_list, :rlimb_list, :nanotrasen_relation, :physique, :height, :speciesprefs, :socks, :body_accessory, :gearlist, :autohiss_mode, - :h_grad_style, :h_grad_offset, :h_grad_colour, :h_grad_alpha, :custom_emotes, :runechat_color, :cyborg_brain_type, :body_type, :pda_ringtone, :tts_seed) + :h_grad_style, :h_grad_offset, :h_grad_colour, :h_grad_alpha, :custom_emotes, :runechat_color, :cyborg_brain_type, :body_type, :pda_ringtone, :species_subtype, :tts_seed) "}, list( // This has too many params for anyone to look at this without going insae "ckey" = C.ckey, @@ -400,6 +404,7 @@ "runechat_color" = runechat_color, "cyborg_brain_type" = cyborg_brain_type, "pda_ringtone" = pda_ringtone, + "species_subtype" = species_subtype, "tts_seed" = tts_seed // SS220 EDIT ADDITION - TTS220 )) @@ -425,7 +430,6 @@ age = text2num(query.item[5]) species = query.item[6] language = query.item[7] - h_colour = query.item[8] h_sec_colour = query.item[9] f_colour = query.item[10] @@ -496,7 +500,8 @@ cyborg_brain_type = query.item[59] body_type = query.item[60] pda_ringtone = query.item[61] - tts_seed = query.item[62] // SS220 EDIT ADDITION - TTS220 + species_subtype = query.item[62] + tts_seed = query.item[63] // SS220 EDIT ADDITION - TTS220 //Sanitize var/datum/species/SP = GLOB.all_species[species] @@ -511,6 +516,9 @@ species = "Human" stack_trace("Character doesn't have a species, character name is [real_name]. Defaulting to human.") + if(isnull(species_subtype)) + species_subtype = "None" + if(isnull(language)) language = "None" @@ -834,53 +842,65 @@ //Icon-based species colour. var/coloured_tail if(current_species) - if(current_species.bodyflags & HAS_ICON_SKIN_TONE) //Handling species-specific icon-based skin tones by flagged race. - var/mob/living/carbon/human/fake/H = new - H.dna.species = current_species + var/mob/living/carbon/human/fake/H = new + H.dna.species = current_species + if(species_subtype != "None" && current_species.bodyflags & HAS_SPECIES_SUBTYPE) + var/datum/species/subtype_species = GLOB.all_species[species_subtype] + if(subtype_species) // Take certain attributes from our subtype to apply to our current species. + H.dna.species.updatespeciessubtype(H, subtype_species) + current_species = H.dna.species + else if(current_species.bodyflags & HAS_ICON_SKIN_TONE) //Handling species-specific icon-based skin tones by flagged race. H.s_tone = s_tone H.dna.species.updatespeciescolor(H, 0) //The mob's species wasn't set, so it's almost certainly different than the character's species at the moment. Thus, we need to be owner-insensitive. - var/obj/item/organ/external/chest/C = H.get_organ("chest") - icobase = C.icobase ? C.icobase : C.dna.species.icobase if(H.dna.species.bodyflags & HAS_TAIL) coloured_tail = H.tail ? H.tail : H.dna.species.tail - - qdel(H) - else - icobase = current_species.icobase + icobase = current_species.icobase + qdel(H) else icobase = 'icons/mob/human_races/r_human.dmi' preview_icon = new /icon(icobase, "torso_[g]") preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY) - var/head = "head" - if(alt_head && current_species.bodyflags & HAS_ALT_HEADS) - var/datum/sprite_accessory/alt_heads/H = GLOB.alt_heads_list[alt_head] - if(H.icon_state) - head = H.icon_state - preview_icon.Blend(new /icon(icobase, "[head]_[g]"), ICON_OVERLAY) - for(var/name in list("chest", "groin", "head", "r_arm", "r_hand", "r_leg", "r_foot", "l_leg", "l_foot", "l_arm", "l_hand")) - if(organ_data[name] == "amputated") continue - if(organ_data[name] == "cyborg") + if(organ_data[name] == "amputated") + continue + var/icon/bodypart = new /icon(icobase, "[name]") + if(name == "head") // Head nonsense. + var/head = "head" + if(alt_head && current_species.bodyflags & HAS_ALT_HEADS) + var/datum/sprite_accessory/alt_heads/H = GLOB.alt_heads_list[alt_head] + if(H.icon_state) + head = H.icon_state + bodypart = new /icon(icobase, "[head]_[g]") // head_state _ gender + if(name in list("chest", "groin")) // Groin and Chest nonsense + if(name == "chest") + name = "torso" + bodypart = new /icon(icobase, "[name]_[g]") // groin/torso _ gender + if(organ_data[name] == "cyborg") // Robotic limbs. var/datum/robolimb/R if(rlimb_data[name]) R = GLOB.all_robolimbs[rlimb_data[name]] if(!R) R = GLOB.basic_robolimb if(name == "chest") name = "torso" - preview_icon.Blend(icon(R.icon, "[name]"), ICON_OVERLAY) // This doesn't check gendered_icon. Not an issue while only limbs can be robotic. + if(length(R.sprite_sheets) && R.sprite_sheets[current_species.sprite_sheet_name]) // Species specific augmented limbs + R.icon = R.sprite_sheets[current_species.sprite_sheet_name] + bodypart.Blend(new /icon(R.icon, "[name]"), ICON_OVERLAY) + preview_icon.Blend(bodypart, ICON_OVERLAY) continue - preview_icon.Blend(new /icon(icobase, "[name]"), ICON_OVERLAY) - - // Skin color - if(current_species && (current_species.bodyflags & HAS_SKIN_COLOR)) - preview_icon.Blend(s_colour, ICON_ADD) - - // Skin tone - if(current_species && (current_species.bodyflags & HAS_SKIN_TONE)) - if(s_tone >= 0) - preview_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) + if(istype(current_species, /datum/species/slime) && current_species.species_subtype != "None") // Applies to limbs that are not robotic. + bodypart.GrayScale() + bodypart.Blend("[s_colour]DC", ICON_AND) //DC = 220 alpha. else - preview_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) + // Skin color + if(current_species && (current_species.bodyflags & HAS_SKIN_COLOR)) + bodypart.Blend(s_colour, ICON_ADD) + // Skin tone + if(current_species && (current_species.bodyflags & HAS_SKIN_TONE)) + if(s_tone >= 0) + bodypart.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) + else + bodypart.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) + preview_icon.Blend(bodypart, ICON_OVERLAY) // Body accessory if(current_species && (current_species.bodyflags & HAS_BODY_ACCESSORY)) @@ -1835,6 +1855,11 @@ /datum/character_save/proc/copy_to(mob/living/carbon/human/character) var/datum/species/S = GLOB.all_species[species] character.set_species(S.type, delay_icon_update = TRUE) // Yell at me if this causes everything to melt + var/datum/species/subtype = GLOB.all_species[species_subtype] + if(!isnull(subtype)) + character.dna.species.updatespeciessubtype(character, new subtype.type(), TRUE, FALSE) + else + character.species_subtype = "None" if(be_random_name) real_name = random_name(gender, species) diff --git a/code/modules/client/preference/link_processing.dm b/code/modules/client/preference/link_processing.dm index a26990d2df5a..38f383aca55b 100644 --- a/code/modules/client/preference/link_processing.dm +++ b/code/modules/client/preference/link_processing.dm @@ -3,6 +3,12 @@ return var/datum/species/S = GLOB.all_species[active_character.species] + var/datum/species/subtype = GLOB.all_species[active_character.species_subtype] + if(isnull(subtype)) // Set the subtype to be the same as Species in the case we don't have one, saves alot of headaches when we're checking for valid markings etc. + subtype = S + else + S = new S.type() + S.bodyflags |= subtype.bodyflags if(href_list["preference"] == "job") switch(href_list["task"]) if("close") @@ -197,73 +203,25 @@ to_chat(user, "Invalid species, please pick something else.") return if(prev_species != active_character.species) - active_character.age = clamp(active_character.age, NS.min_age, NS.max_age) - var/datum/robolimb/robohead - if(NS.bodyflags & ALL_RPARTS) - var/head_model = "[!active_character.rlimb_data["head"] ? "Morpheus Cyberkinetics" : active_character.rlimb_data["head"]]" - robohead = GLOB.all_robolimbs[head_model] - //grab one of the valid hair styles for the newly chosen species - active_character.h_style = random_hair_style(active_character.gender, active_character.species, robohead) - - //grab one of the valid facial hair styles for the newly chosen species - active_character.f_style = random_facial_hair_style(active_character.gender, active_character.species, robohead) - - if(NS.bodyflags & HAS_HEAD_ACCESSORY) //Species that have head accessories. - active_character.ha_style = random_head_accessory(active_character.species) - else - active_character.ha_style = "None" // No Vulp ears on Unathi - active_character.hacc_colour = rand_hex_color() - - if(NS.bodyflags & HAS_HEAD_MARKINGS) //Species with head markings. - active_character.m_styles["head"] = random_marking_style("head", active_character.species, robohead, null, active_character.alt_head) - else - active_character.m_styles["head"] = "None" - active_character.m_colours["head"] = "#000000" - - if(NS.bodyflags & HAS_BODY_MARKINGS) //Species with body markings/tattoos. - active_character.m_styles["body"] = random_marking_style("body", active_character.species) - else - active_character.m_styles["body"] = "None" - active_character.m_colours["body"] = "#000000" - - if(NS.bodyflags & HAS_TAIL_MARKINGS) //Species with tail markings. - active_character.m_styles["tail"] = random_marking_style("tail", active_character.species, null, active_character.body_accessory) - else - active_character.m_styles["tail"] = "None" - active_character.m_colours["tail"] = "#000000" - - // Don't wear another species' underwear! - var/datum/sprite_accessory/SA = GLOB.underwear_list[active_character.underwear] - if(!SA || !(active_character.species in SA.species_allowed)) - active_character.underwear = random_underwear(active_character.body_type, active_character.species) - - SA = GLOB.undershirt_list[active_character.undershirt] - if(!SA || !(active_character.species in SA.species_allowed)) - active_character.undershirt = random_undershirt(active_character.body_type, active_character.species) - - SA = GLOB.socks_list[active_character.socks] - if(!SA || !(active_character.species in SA.species_allowed)) - active_character.socks = random_socks(active_character.body_type, active_character.species) - - //reset skin tone and colour - if(NS.bodyflags & (HAS_SKIN_TONE|HAS_ICON_SKIN_TONE)) - random_skin_tone(active_character.species) - else - active_character.s_tone = 0 - - if(!(NS.bodyflags & HAS_SKIN_COLOR)) - active_character.s_colour = "#000000" - - active_character.alt_head = "None" //No alt heads on species that don't have them. - active_character.speciesprefs = 0 //My Vox tank shouldn't change how my future Grey talks. - active_character.body_accessory = random_body_accessory(NS.name, NS.optional_body_accessory) - - //Reset prosthetics. - active_character.organ_data = list() - active_character.rlimb_data = list() - - if(!(NS.autohiss_basic_map)) - active_character.autohiss_mode = AUTOHISS_OFF + S = new NS.type() + active_character.species_subtype = "None" + active_character.age = clamp(active_character.age, S.min_age, S.max_age) + NS = GLOB.all_species[active_character.species_subtype] // Changing species resets subtype. + if(isnull(NS)) + NS = GLOB.all_species[active_character.species] + subtype = new NS.type() + reset_styles(S) + if("species_subtype") + if(S.bodyflags & HAS_SPECIES_SUBTYPE) + var/new_subtype = tgui_input_list(user, "Choose your character's species subtype:", "Character Preference", S.allowed_species_subtypes) + if(isnull(new_subtype) || active_character.species_subtype == new_subtype) + return + active_character.species_subtype = new_subtype + var/datum/species/NS = GLOB.all_species[active_character.species_subtype] + if(isnull(NS)) + NS = GLOB.all_species[active_character.species] + subtype = new NS.type() + reset_styles(subtype, S) if("speciesprefs") active_character.speciesprefs = !active_character.speciesprefs //Starts 0, so if someone clicks the button up top there, this won't be 0 anymore. If they click it again, it'll go back to 0. if("language") @@ -335,7 +293,7 @@ But if the user has a robotic humanoid head and the hairstyle can fit humans, let them use it as a wig. */ valid_hairstyles += hairstyle else //If the user is not a species who can have robotic heads, use the default handling. - if(active_character.species in SA.species_allowed) //If the user's head is of a species the hairstyle allows, add it to the list. + if((active_character.species in SA.species_allowed) || (subtype.name in SA.species_allowed)) //If the user's head is of a species the hairstyle allows, add it to the list. valid_hairstyles += hairstyle sortTim(valid_hairstyles, GLOBAL_PROC_REF(cmp_text_asc)) //this alphabetizes the list @@ -387,7 +345,7 @@ var/list/valid_head_accessory_styles = list() for(var/head_accessory_style in GLOB.head_accessory_styles_list) var/datum/sprite_accessory/H = GLOB.head_accessory_styles_list[head_accessory_style] - if(!(active_character.species in H.species_allowed)) + if(!(active_character.species in H.species_allowed) && !(subtype.name in H.species_allowed)) continue valid_head_accessory_styles += head_accessory_style @@ -404,7 +362,7 @@ var/list/valid_alt_heads = list() for(var/alternate_head in GLOB.alt_heads_list) var/datum/sprite_accessory/alt_heads/head = GLOB.alt_heads_list[alternate_head] - if(!(active_character.species in head.species_allowed)) + if(!(active_character.species in head.species_allowed) && !(subtype.name in head.species_allowed)) continue valid_alt_heads += alternate_head @@ -423,7 +381,7 @@ var/list/valid_markings = list() for(var/markingstyle in GLOB.marking_styles_list) var/datum/sprite_accessory/body_markings/head/M = GLOB.marking_styles_list[markingstyle] - if(!(active_character.species in M.species_allowed)) + if(!(active_character.species in M.species_allowed) && !(subtype.name in M.species_allowed)) continue if(M.marking_location != "head") continue @@ -468,7 +426,7 @@ var/list/valid_markings = list() for(var/markingstyle in GLOB.marking_styles_list) var/datum/sprite_accessory/M = GLOB.marking_styles_list[markingstyle] - if(!(active_character.species in M.species_allowed)) + if(!(active_character.species in M.species_allowed) && !(subtype.name in M.species_allowed)) continue if(M.marking_location != "body") continue @@ -493,7 +451,7 @@ var/datum/sprite_accessory/body_markings/tail/M = GLOB.marking_styles_list[markingstyle] if(M.marking_location != "tail") continue - if(!(active_character.species in M.species_allowed)) + if(!(active_character.species in M.species_allowed) && !(subtype.name in M.species_allowed)) continue if(!active_character.body_accessory) if(M.tails_allowed) @@ -524,7 +482,7 @@ var/datum/body_accessory/accessory = GLOB.body_accessory_by_name[B] if(isnull(accessory)) // None continue - if(active_character.species in accessory.allowed_species) + if((active_character.species in accessory.allowed_species) || (subtype.name in accessory.allowed_species)) possible_body_accessories += B if(S.optional_body_accessory) possible_body_accessories += "None" //the only null entry should be the "None" option @@ -590,7 +548,7 @@ continue if(active_character.body_type == FEMALE && SA.body_type == MALE) continue - if(!(active_character.species in SA.species_allowed)) + if(!(active_character.species in SA.species_allowed) && !(subtype.name in SA.species_allowed)) continue valid_underwear[underwear] = GLOB.underwear_list[underwear] sortTim(valid_underwear, GLOBAL_PROC_REF(cmp_text_asc)) @@ -602,7 +560,7 @@ var/list/valid_undershirts = list() for(var/undershirt in GLOB.undershirt_list) var/datum/sprite_accessory/SA = GLOB.undershirt_list[undershirt] - if(!(active_character.species in SA.species_allowed)) + if(!(active_character.species in SA.species_allowed) && !(subtype.name in SA.species_allowed)) continue if(active_character.body_type == MALE && SA.body_type == FEMALE) continue @@ -619,7 +577,7 @@ var/list/valid_sockstyles = list() for(var/sockstyle in GLOB.socks_list) var/datum/sprite_accessory/SA = GLOB.socks_list[sockstyle] - if(!(active_character.species in SA.species_allowed)) + if(!(active_character.species in SA.species_allowed) && !(subtype.name in SA.species_allowed)) continue if(active_character.body_type == MALE && SA.body_type == FEMALE) continue @@ -1327,3 +1285,74 @@ ShowChoices(user) return TRUE + +/// Reset the styles what is available to the NS (new species) parameter. Parent Species is for subtype changing. +/datum/preferences/proc/reset_styles(datum/species/NS, datum/species/parent_species) + var/datum/robolimb/robohead + if(!isnull(parent_species)) + NS.bodyflags |= parent_species.bodyflags + if(NS.bodyflags & ALL_RPARTS) + var/head_model = "[!active_character.rlimb_data["head"] ? "Morpheus Cyberkinetics" : active_character.rlimb_data["head"]]" + robohead = GLOB.all_robolimbs[head_model] + //grab one of the valid hair styles for the newly chosen species + active_character.h_style = random_hair_style(active_character.gender, NS, robohead) + + //grab one of the valid facial hair styles for the newly chosen species + active_character.f_style = random_facial_hair_style(active_character.gender, NS, robohead) + + if(NS.bodyflags & HAS_HEAD_ACCESSORY) //Species that have head accessories. + active_character.ha_style = random_head_accessory(NS) + else + active_character.ha_style = "None" // No Vulp ears on Unathi + active_character.hacc_colour = rand_hex_color() + + if(NS.bodyflags & HAS_HEAD_MARKINGS) //Species with head markings. + active_character.m_styles["head"] = random_marking_style("head", NS, robohead, null, active_character.alt_head) + else + active_character.m_styles["head"] = "None" + active_character.m_colours["head"] = "#000000" + + if(NS.bodyflags & HAS_BODY_MARKINGS) //Species with body markings/tattoos. + active_character.m_styles["body"] = random_marking_style("body", NS) + else + active_character.m_styles["body"] = "None" + active_character.m_colours["body"] = "#000000" + + if(NS.bodyflags & HAS_TAIL_MARKINGS) //Species with tail markings. + active_character.m_styles["tail"] = random_marking_style("tail", NS, null, active_character.body_accessory) + else + active_character.m_styles["tail"] = "None" + active_character.m_colours["tail"] = "#000000" + + // Don't wear another species' underwear! + var/datum/sprite_accessory/SA = GLOB.underwear_list[active_character.underwear] + if(!SA || !(NS in SA.species_allowed)) + active_character.underwear = random_underwear(active_character.body_type, NS) + + SA = GLOB.undershirt_list[active_character.undershirt] + if(!SA || !(NS in SA.species_allowed)) + active_character.undershirt = random_undershirt(active_character.body_type, NS) + + SA = GLOB.socks_list[active_character.socks] + if(!SA || !(NS in SA.species_allowed)) + active_character.socks = random_socks(active_character.body_type, NS) + + //reset skin tone and colour + if(NS.bodyflags & (HAS_SKIN_TONE|HAS_ICON_SKIN_TONE)) + random_skin_tone(NS) + else + active_character.s_tone = 0 + + if(!(NS.bodyflags & HAS_SKIN_COLOR)) + active_character.s_colour = "#000000" + + active_character.alt_head = "None" //No alt heads on species that don't have them. + active_character.speciesprefs = 0 //My Vox tank shouldn't change how my future Grey talks. + active_character.body_accessory = random_body_accessory(NS.name, NS.optional_body_accessory) + + //Reset prosthetics. + active_character.organ_data = list() + active_character.rlimb_data = list() + + if(!(NS.autohiss_basic_map)) + active_character.autohiss_mode = AUTOHISS_OFF diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index f2315c513511..845164754e8c 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -207,6 +207,8 @@ GLOBAL_LIST_INIT(special_role_times, list( dat += "Возраст: [active_character.age]
" dat += "Тело: (Случайно)
" dat += "Раса: [active_character.species]
" + if(S.bodyflags & HAS_SPECIES_SUBTYPE) + dat += "Подтип расы: [active_character.species_subtype]
" dat += "Пол: [active_character.gender == MALE ? "Male" : (active_character.gender == FEMALE ? "Female" : "Genderless")]
" dat += "Тип тела: [active_character.body_type == MALE ? "Masculine" : "Feminine"]" dat += "
" diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index de04584338be..17285e8e9baa 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -106,10 +106,10 @@ if(H.dna.species) if(exclusive) - if(!(H.dna.species.name in species_restricted)) + if(!(H.dna.species.sprite_sheet_name in species_restricted)) wearable = TRUE else - if(H.dna.species.name in species_restricted) + if(H.dna.species.sprite_sheet_name in species_restricted) wearable = TRUE if(!wearable) diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index eab7f769fb5d..880cd06c900f 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -64,7 +64,7 @@ return var/datum/sprite_accessory/body_markings/tattoo/temp_tatt = GLOB.marking_styles_list[tattoo_icon] - if(!(target.dna.species.name in temp_tatt.species_allowed)) + if(!(target.dna.species.sprite_sheet_name in temp_tatt.species_allowed)) to_chat(user, "You can't think of a way to make the [tattoo_name] design work on [target == user ? "your" : "[target]'s"] body type.") return diff --git a/code/modules/economy/economy_machinery/eftpos.dm b/code/modules/economy/economy_machinery/eftpos.dm index d1f5cf0a956a..67dc65f98860 100644 --- a/code/modules/economy/economy_machinery/eftpos.dm +++ b/code/modules/economy/economy_machinery/eftpos.dm @@ -6,6 +6,7 @@ icon = 'icons/obj/device.dmi' icon_state = "eftpos" w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL = 300, MAT_GLASS = 140) /// Unique identifying name of this EFTPOS for transaction tracking in money accounts var/machine_name = "" /// Whether or not the EFTPOS is locked into a transaction @@ -252,6 +253,7 @@ throw_range = 7 anchored = TRUE w_class = WEIGHT_CLASS_BULKY + materials = list() hitsound = 'sound/weapons/ringslam.ogg' drop_sound = 'sound/items/handling/register_drop.ogg' pickup_sound = 'sound/items/handling/toolbox_pickup.ogg' diff --git a/code/modules/fish/fish_eggs.dm b/code/modules/fish/fish_eggs.dm index 756093fbd013..de9c133aabf0 100644 --- a/code/modules/fish/fish_eggs.dm +++ b/code/modules/fish/fish_eggs.dm @@ -27,7 +27,7 @@ /obj/item/fish_eggs/babycarp name = "baby space carp eggs" - desc = "Eggs from the substantially smaller form of the intergalactic terror." + desc = "Eggs from the substantially smaller form of the spaceborn terror." icon_state = "babycarp_eggs" fish_type = /datum/fish/babycarp diff --git a/code/modules/hallucinations/effects/blind_rush_hallucination.dm b/code/modules/hallucinations/effects/blind_rush_hallucination.dm index 88676e30316c..ab19d0a12da4 100644 --- a/code/modules/hallucinations/effects/blind_rush_hallucination.dm +++ b/code/modules/hallucinations/effects/blind_rush_hallucination.dm @@ -48,16 +48,12 @@ var/rush_timer = null /obj/effect/hallucination/no_delete/blind_rusher/Initialize(mapload, mob/living/carbon/target) - rush_timer = addtimer(CALLBACK(src, PROC_REF(rush)), rush_time, TIMER_LOOP | TIMER_STOPPABLE) + rush_timer = addtimer(CALLBACK(src, PROC_REF(rush)), rush_time, TIMER_LOOP | TIMER_DELETE_ME) if(prob(50)) hallucination_icon = 'icons/mob/simple_human.dmi' hallucination_icon_state = pick("clown", "skeleton_warden", "skeleton_warden_alt") return ..() -/obj/effect/hallucination/no_delete/blind_rusher/Destroy() - deltimer(rush_timer) - return ..() - /obj/effect/hallucination/no_delete/blind_rusher/proc/rush() if(get_dist(src, target) > min_distance) var/direction = get_dir(src, target) //making sure the hallucination is facing the player correctly. diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 18cbb6991cbb..0dc9de25b337 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -389,14 +389,14 @@ continue if(H.dna.species.bodyflags & ALL_RPARTS) //If the user is a species who can have a robotic head... var/datum/robolimb/robohead = GLOB.all_robolimbs[H.model] - if((H.dna.species.name in S.species_allowed) && robohead.is_monitor && ((S.models_allowed && (robohead.company in S.models_allowed)) || !S.models_allowed)) //If this is a hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. + if((H.dna.species.sprite_sheet_name in S.species_allowed) && robohead.is_monitor && ((S.models_allowed && (robohead.company in S.models_allowed)) || !S.models_allowed)) //If this is a hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_hairstyles += hairstyle //Give them their hairstyles if they do. else if(!robohead.is_monitor && ("Human" in S.species_allowed)) /*If the hairstyle is not native to the user's species and they're using a head with an ipc-style screen, don't let them access it. But if the user has a robotic humanoid head and the hairstyle can fit humans, let them use it as a wig. */ valid_hairstyles += hairstyle else //If the user is not a species who can have robotic heads, use the default handling. - if(H.dna.species.name in S.species_allowed) //If the user's head is of a species the hairstyle allows, add it to the list. + if(H.dna.species.sprite_sheet_name in S.species_allowed) //If the user's head is of a species the hairstyle allows, add it to the list. valid_hairstyles += hairstyle return sortTim(valid_hairstyles, GLOBAL_PROC_REF(cmp_text_asc)) @@ -415,15 +415,15 @@ continue if(H.dna.species.bodyflags & ALL_RPARTS) //If the user is a species who can have a robotic head... var/datum/robolimb/robohead = GLOB.all_robolimbs[H.model] - if(H.dna.species.name in S.species_allowed) //If this is a facial hair style native to the user's species... - if((H.dna.species.name in S.species_allowed) && robohead.is_monitor && ((S.models_allowed && (robohead.company in S.models_allowed)) || !S.models_allowed)) //If this is a facial hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. + if(H.dna.species.sprite_sheet_name in S.species_allowed) //If this is a facial hair style native to the user's species... + if((H.dna.species.sprite_sheet_name in S.species_allowed) && robohead.is_monitor && ((S.models_allowed && (robohead.company in S.models_allowed)) || !S.models_allowed)) //If this is a facial hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_facial_hairstyles += facialhairstyle //Give them their facial hairstyles if they do. else if(!robohead.is_monitor && ("Human" in S.species_allowed)) /*If the facial hairstyle is not native to the user's species and they're using a head with an ipc-style screen, don't let them access it. But if the user has a robotic humanoid head and the facial hairstyle can fit humans, let them use it as a wig. */ valid_facial_hairstyles += facialhairstyle else //If the user is not a species who can have robotic heads, use the default handling. - if(H.dna.species.name in S.species_allowed) //If the user's head is of a species the facial hair style allows, add it to the list. + if(H.dna.species.sprite_sheet_name in S.species_allowed) //If the user's head is of a species the facial hair style allows, add it to the list. valid_facial_hairstyles += facialhairstyle return sortTim(valid_facial_hairstyles, GLOBAL_PROC_REF(cmp_text_asc)) @@ -437,7 +437,7 @@ for(var/head_accessory in GLOB.head_accessory_styles_list) var/datum/sprite_accessory/S = GLOB.head_accessory_styles_list[head_accessory] - if(!(H.dna.species.name in S.species_allowed)) //If the user's head is not of a species the head accessory style allows, skip it. Otherwise, add it to the list. + if(!(H.dna.species.sprite_sheet_name in S.species_allowed)) //If the user's head is not of a species the head accessory style allows, skip it. Otherwise, add it to the list. continue valid_head_accessories += head_accessory @@ -456,7 +456,7 @@ continue if(S.marking_location != location) //If the marking isn't for the location we desire, skip. continue - if(!(dna.species.name in S.species_allowed)) //If the user is not of a species the marking style allows, skip it. Otherwise, add it to the list. + if(!(dna.species.sprite_sheet_name in S.species_allowed)) //If the user is not of a species the marking style allows, skip it. Otherwise, add it to the list. continue if(location == "tail") if(!body_accessory) @@ -490,7 +490,7 @@ else if(check_rights(R_ADMIN, FALSE, src)) valid_body_accessories = GLOB.body_accessory_by_name.Copy() break - else if(dna.species.name in A.allowed_species) //If the user is not of a species the body accessory style allows, skip it. Otherwise, add it to the list. + else if(dna.species.sprite_sheet_name in A.allowed_species) //If the user is not of a species the body accessory style allows, skip it. Otherwise, add it to the list. valid_body_accessories += B if(dna.species.optional_body_accessory) valid_body_accessories += "None" @@ -505,7 +505,7 @@ valid_alt_heads["None"] = GLOB.alt_heads_list["None"] //The only null entry should be the "None" option, and there should always be a "None" option. for(var/alternate_head in GLOB.alt_heads_list) var/datum/sprite_accessory/alt_heads/head = GLOB.alt_heads_list[alternate_head] - if(!(H.dna.species.name in head.species_allowed)) + if(!(H.dna.species.sprite_sheet_name in head.species_allowed)) continue valid_alt_heads += alternate_head diff --git a/code/modules/mob/living/carbon/human/body_accessories.dm b/code/modules/mob/living/carbon/human/body_accessories.dm index 364626c0dffb..ca3adfbdcca6 100644 --- a/code/modules/mob/living/carbon/human/body_accessories.dm +++ b/code/modules/mob/living/carbon/human/body_accessories.dm @@ -50,7 +50,7 @@ GLOBAL_LIST_EMPTY(body_accessory_by_species) var/has_behind = FALSE /datum/body_accessory/proc/try_restrictions(mob/living/carbon/human/H) - return (H.dna.species.name in allowed_species) + return (H.dna.species.sprite_sheet_name in allowed_species) /datum/body_accessory/proc/get_animated_icon() //return animated if it has it, return static if it does not. if(animated_icon) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 2762d3e63cfb..7993bcbdbbb4 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -20,6 +20,8 @@ var/list/m_styles = DEFAULT_MARKING_STYLES //All markings set to None. var/s_tone = 0 //Skin tone + /// Species Sub-Type - overrites the species_sheet_name when it's not "None", acts the same as a skin tone. + var/species_subtype = "None" //Skin colour var/skin_colour = "#000000" diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index 69ce8b857ba2..54ac27d05ffa 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -172,9 +172,15 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) var/hulk = HAS_TRAIT(src, TRAIT_HULK) var/skeleton = HAS_TRAIT(src, TRAIT_SKELETONIZED) - if(dna.species && dna.species.bodyflags & HAS_ICON_SKIN_TONE) - dna.species.updatespeciescolor(src) - + if(dna.species) + if(dna.species.bodyflags & HAS_ICON_SKIN_TONE) + dna.species.updatespeciescolor(src) + if(dna.species.bodyflags & HAS_SPECIES_SUBTYPE) + var/datum/species/species_subtype = GLOB.all_species[dna.species.species_subtype] + if(isnull(species_subtype)) + species_subtype = GLOB.all_species[dna.species.name] + if(dna.species.species_subtype != "None" && dna.species.species_subtype != species_subtype.name) + dna.species.updatespeciessubtype(src, new species_subtype.type(), TRUE, FALSE) //CACHING: Generate an index key from visible bodyparts. //0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic. //Create a new, blank icon for our mob to use. @@ -195,7 +201,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) //BEGIN CACHED ICON GENERATION. var/obj/item/organ/external/chest = get_organ("chest") base_icon = chest.get_icon(skeleton) - + var/slimify = istype(src.dna.species, /datum/species/slime) && species_subtype != "None" for(var/obj/item/organ/external/part in bodyparts) var/icon/temp = part.get_icon(skeleton) //That part makes left and right legs drawn topmost and lowermost when human looks WEST or EAST @@ -208,15 +214,19 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) temp2.Insert(new/icon(temp,dir=EAST),dir=EAST) if(!(part.icon_position & RIGHT)) temp2.Insert(new/icon(temp,dir=WEST),dir=WEST) + slimify_limb(part, temp2, slimify) base_icon.Blend(temp2, ICON_OVERLAY) if(part.icon_position & LEFT) temp2.Insert(new/icon(temp,dir=EAST),dir=EAST) if(part.icon_position & RIGHT) temp2.Insert(new/icon(temp,dir=WEST),dir=WEST) + slimify_limb(part, temp2, slimify) base_icon.Blend(temp2, ICON_UNDERLAY) else + slimify_limb(part, temp, slimify) base_icon.Blend(temp, ICON_OVERLAY) + if(!skeleton) if(isgolem(src)) var/datum/species/golem/G = src.dna.species @@ -296,20 +306,26 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) if(chest_organ && m_styles["body"]) var/body_marking = m_styles["body"] var/datum/sprite_accessory/body_marking_style = GLOB.marking_styles_list[body_marking] - if(body_marking_style && body_marking_style.species_allowed && (dna.species.name in body_marking_style.species_allowed)) + if(body_marking_style && body_marking_style.species_allowed && (dna.species.sprite_sheet_name in body_marking_style.species_allowed)) var/icon/b_marking_s = icon("icon" = body_marking_style.icon, "icon_state" = "[body_marking_style.icon_state]_s") if(body_marking_style.do_colouration) b_marking_s.Blend(m_colours["body"], ICON_ADD) + if(istype(src.dna.species, /datum/species/slime)) + b_marking_s.GrayScale() + b_marking_s.Blend("[skin_colour]A0", ICON_AND) markings_standing.Blend(b_marking_s, ICON_OVERLAY) //Head markings. var/obj/item/organ/external/head/head_organ = get_organ("head") if(istype(head_organ) && m_styles["head"]) //If the head is destroyed, forget the head markings. This prevents floating optical markings on decapitated IPCs, for example. var/head_marking = m_styles["head"] var/datum/sprite_accessory/head_marking_style = GLOB.marking_styles_list[head_marking] - if(head_marking_style && head_marking_style.species_allowed && (head_organ.dna.species.name in head_marking_style.species_allowed)) + if(head_marking_style && head_marking_style.species_allowed && (head_organ.dna.species.sprite_sheet_name in head_marking_style.species_allowed)) var/icon/h_marking_s = icon("icon" = head_marking_style.icon, "icon_state" = "[head_marking_style.icon_state]_s") if(head_marking_style.do_colouration) h_marking_s.Blend(m_colours["head"], ICON_ADD) + if(istype(src.dna.species, /datum/species/slime)) + h_marking_s.GrayScale() + h_marking_s.Blend("[skin_colour]A0", ICON_AND) markings_standing.Blend(h_marking_s, ICON_OVERLAY) overlays_standing[MARKINGS_LAYER] = mutable_appearance(markings_standing, layer = -MARKINGS_LAYER) @@ -334,10 +350,13 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) if(head_organ.ha_style && (head_organ.dna.species.bodyflags & HAS_HEAD_ACCESSORY)) var/datum/sprite_accessory/head_accessory/head_accessory_style = GLOB.head_accessory_styles_list[head_organ.ha_style] if(head_accessory_style && head_accessory_style.species_allowed) - if(head_organ.dna.species.name in head_accessory_style.species_allowed) + if(head_organ.dna.species.sprite_sheet_name in head_accessory_style.species_allowed) var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") if(head_accessory_style.do_colouration) head_accessory_s.Blend(head_organ.headacc_colour, ICON_ADD) + if(istype(src.dna.species, /datum/species/slime)) // Slimifies head acc + head_accessory_s.GrayScale() + head_accessory_s.Blend("[skin_colour]A0", ICON_AND) //DC = 160 alpha. if(HAS_TRAIT(src, TRAIT_I_WANT_BRAINS)) head_accessory_s.ColorTone(COLORTONE_DEAD_EXT_ORGAN) head_accessory_s.SetIntensity(0.7) @@ -369,7 +388,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) MA.layer = -HAIR_LAYER if(O.h_style && !(head?.flags & BLOCKHEADHAIR && !ismachineperson(src))) var/datum/sprite_accessory/hair/hair = GLOB.hair_styles_full_list[O.h_style] - if(hair?.species_allowed && ((O.dna.species.name in hair.species_allowed) || (O.dna.species.bodyflags & ALL_RPARTS))) + if(hair?.species_allowed && ((O.dna.species.sprite_sheet_name in hair.species_allowed) || (O.dna.species.bodyflags & ALL_RPARTS))) // Base hair var/icon/hair_icon = new /icon(hair.icon, "[hair.icon_state]_s") if(HAS_TRAIT(src, TRAIT_I_WANT_BRAINS)) @@ -418,8 +437,8 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) return var/species_name = "" - if(dna.species.name in list("Drask", "Grey", "Vox", "Kidan")) - species_name = "_[lowertext(dna.species.name)]" + if(dna.species.sprite_sheet_name in list("Drask", "Grey", "Vox", "Kidan")) + species_name = "_[lowertext(dna.species.sprite_sheet_name)]" var/icon/hands_mask = icon('icons/mob/body_accessory.dmi', "accessory_none_s") //Needs a blank icon, not actually related to markings at all @@ -461,7 +480,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) if(head_organ.f_style) var/datum/sprite_accessory/facial_hair/facial_hair_style = GLOB.facial_hair_styles_list[head_organ.f_style] if(facial_hair_style && facial_hair_style.species_allowed) - if((head_organ.dna.species.name in facial_hair_style.species_allowed) || (head_organ.dna.species.bodyflags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics... + if((head_organ.dna.species.sprite_sheet_name in facial_hair_style.species_allowed) || (head_organ.dna.species.bodyflags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics... var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") if(istype(head_organ.dna.species, /datum/species/slime)) // I am el worstos facial_s.Blend("[skin_colour]A0", ICON_AND) @@ -1369,6 +1388,9 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) if(HAS_TRAIT(src, TRAIT_I_WANT_BRAINS)) wings_icon.ColorTone(COLORTONE_DEAD_EXT_ORGAN) wings_icon.SetIntensity(0.7) + if(istype(src.dna.species, /datum/species/slime)) // Slimifies the wings + wings_icon.GrayScale() + wings_icon.Blend("[skin_colour]A0", ICON_AND) //DC = 160 alpha. var/mutable_appearance/wings = mutable_appearance(wings_icon, layer = -WING_LAYER) wings.pixel_x = body_accessory.pixel_x_offset wings.pixel_y = body_accessory.pixel_y_offset @@ -1379,6 +1401,9 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) if(HAS_TRAIT(src, TRAIT_I_WANT_BRAINS)) under_wing_icon.ColorTone(COLORTONE_DEAD_EXT_ORGAN) under_wing_icon.SetIntensity(0.7) + if(istype(src.dna.species, /datum/species/slime)) // Slimifies the wings + under_wing_icon.GrayScale() + under_wing_icon.Blend("[skin_colour]A0", ICON_AND) //DC = 160 alpha. var/mutable_appearance/under_wing = mutable_appearance(under_wing_icon, layer = -WING_UNDERLIMBS_LAYER) under_wing.pixel_x = body_accessory.pixel_x_offset under_wing.pixel_y = body_accessory.pixel_y_offset @@ -1413,6 +1438,11 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) accessory_s.Blend(skin_colour, body_accessory.blend_mode) if(tail_marking_icon && (body_accessory.name in tail_marking_style.tails_allowed)) accessory_s.Blend(tail_marking_icon, ICON_OVERLAY) + + if(istype(src.dna.species, /datum/species/slime)) // Slimifies the body acc + accessory_s.GrayScale() + accessory_s.Blend("[skin_colour]A0", ICON_AND) //DC = 160 alpha. Less alpha here because the tail is generally stubborn... + if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && dna.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this) // Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway. var/icon/under = new/icon("icon" = 'icons/mob/body_accessory.dmi', "icon_state" = "accessory_none_s") @@ -1451,6 +1481,11 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) tail_s.Blend(skin_colour, ICON_ADD) if(tail_marking_icon && !tail_marking_style.tails_allowed) tail_s.Blend(tail_marking_icon, ICON_OVERLAY) + + if(istype(src.dna.species, /datum/species/slime)) // Slimifies the tail + tail_s.GrayScale() + tail_s.Blend("[skin_colour]A0", ICON_AND) //DC = 160 alpha. + if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && dna.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this) // Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway. var/icon/under = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "blank") @@ -1490,13 +1525,17 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) var/icon/accessory_s = new/icon("icon" = body_accessory.get_animated_icon(), "icon_state" = body_accessory.get_animated_icon_state()) if(dna.species.bodyflags & HAS_SKIN_COLOR) accessory_s.Blend(skin_colour, body_accessory.blend_mode) + if(istype(src.dna.species, /datum/species/slime)) // Slimifies the wings + accessory_s.GrayScale() + accessory_s.Blend("[skin_colour]A0", ICON_AND) //DC = 160 alpha. if(tail_marking_icon && (body_accessory.name in tail_marking_style.tails_allowed)) accessory_s.Blend(tail_marking_icon, ICON_OVERLAY) if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && dna.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this) // Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway. var/icon/under = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "Vulpkanin_tail_delay") - if(body_accessory.allowed_species && (dna.species.name in body_accessory.allowed_species)) - under = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.name]_tail_delay") + + if(body_accessory.allowed_species && (dna.species.sprite_sheet_name in body_accessory.allowed_species)) + under = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.sprite_sheet_name]_tail_delay") under.Insert(new/icon(accessory_s, dir=SOUTH), dir=SOUTH) under.Insert(new/icon(accessory_s, dir=EAST), dir=EAST) under.Insert(new/icon(accessory_s, dir=WEST), dir=WEST) @@ -1508,8 +1547,8 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) // Creates a blank icon, and copies accessory_s' north direction sprite into it before passing that to the tail layer that overlays uniforms and such. var/icon/over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "Vulpkanin_tail_delay") - if(body_accessory.allowed_species && (dna.species.name in body_accessory.allowed_species)) // If the user's species is in the list of allowed species for the currently selected body accessory, use the appropriate animation timing blank - over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.name]_tail_delay") + if(body_accessory.allowed_species && (dna.species.sprite_sheet_name in body_accessory.allowed_species)) // If the user's species is in the list of allowed species for the currently selected body accessory, use the appropriate animation timing blank + over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.sprite_sheet_name]_tail_delay") over.Insert(new/icon(accessory_s, dir=NORTH), dir=NORTH) var/mutable_appearance/tail = mutable_appearance(over, layer = -TAIL_LAYER) @@ -1526,11 +1565,14 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) var/icon/tailw_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[tail]w_s") if(dna.species.bodyflags & HAS_SKIN_COLOR) tailw_s.Blend(skin_colour, ICON_ADD) + if(istype(src.dna.species, /datum/species/slime)) // Slimifies the tail + tailw_s.GrayScale() + tailw_s.Blend("[skin_colour]A0", ICON_AND) //DC = 160 alpha. if(tail_marking_icon && !tail_marking_style.tails_allowed) tailw_s.Blend(tail_marking_icon, ICON_OVERLAY) if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && dna.species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this) // Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway. - var/icon/under = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.name]_tail_delay") + var/icon/under = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.sprite_sheet_name]_tail_delay") under.Insert(new/icon(tailw_s, dir=SOUTH), dir=SOUTH) under.Insert(new/icon(tailw_s, dir=EAST), dir=EAST) under.Insert(new/icon(tailw_s, dir=WEST), dir=WEST) @@ -1538,7 +1580,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) overlays_standing[TAIL_UNDERLIMBS_LAYER] = mutable_appearance(under, layer = -TAIL_UNDERLIMBS_LAYER) // Creates a blank icon, and copies accessory_s' north direction sprite into it before passing that to the tail layer that overlays uniforms and such. - var/icon/over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.name]_tail_delay") + var/icon/over = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[dna.species.sprite_sheet_name]_tail_delay") over.Insert(new/icon(tailw_s, dir=NORTH), dir=NORTH) overlays_standing[TAIL_LAYER] = mutable_appearance(over, layer = -TAIL_LAYER) @@ -1695,3 +1737,10 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) . += "[part.s_tone]" . = "[.][!!husk][!!hulk][!!skeleton]" + +/mob/living/carbon/human/proc/slimify_limb(obj/item/organ/external/L, icon/I, slimify) + if(slimify) // Used for a when slime morphs into another species. Makes them slightly transparent. + if(!L.is_robotic()) + I.GrayScale() + var/color = sanitize_hexcolor(skin_colour) + I.Blend("[color]C8", ICON_AND) //DC = 220 alpha. C8 = 200 diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm index e371ddff8646..30cd8e7c62fa 100644 --- a/code/modules/mob/living/carbon/human/species/_species.dm +++ b/code/modules/mob/living/carbon/human/species/_species.dm @@ -3,6 +3,10 @@ var/name /// Pluralized name (since "[name]s" is not always valid) var/name_plural + /// Sub-type of the species. Used for when slimes imitate a species or when an IPC has augments that look like another species. This will affect sprite_sheet_name + var/species_subtype = "None" + /// List of available sub-types for the species to imitate / morph into (Machine / Slime) + var/allowed_species_subtypes = list() /// The corresponding key for spritesheets var/sprite_sheet_name /// Article to use when referring to an individual of the species, if pronunciation is different from expected. @@ -201,7 +205,9 @@ /datum/species/New() unarmed = new unarmed_type() - if(!sprite_sheet_name) + if(!isnull(species_subtype) && species_subtype != "None") + sprite_sheet_name = species_subtype + else if(!sprite_sheet_name) sprite_sheet_name = name /datum/species/proc/get_random_name(gender) @@ -404,6 +410,17 @@ /datum/species/proc/updatespeciescolor(mob/living/carbon/human/H) //Handles changing icobase for species that have multiple skin colors. return +/** Handles changing icobase for species that can imitate/morph into other species + * Arguments: + * - H: The human of which was are updating. + * - new_subtype: Our imitate species, by datum reference. + * - owner_sensitive: Always leave at TRUE, this is for updating our icon. (change_icobase) + * - reset_styles: If true, resets styles, hair, and other appearance styles. + */ +/// +/datum/species/proc/updatespeciessubtype(mob/living/carbon/human/H, datum/species/new_subtype, owner_sensitive = TRUE, reset_styles = TRUE) + return + // Do species-specific reagent handling here // Return 1 if it should do normal processing too // Return the parent value if processing does not explicitly stop diff --git a/code/modules/mob/living/carbon/human/species/machine.dm b/code/modules/mob/living/carbon/human/species/machine.dm index 58dd3eb2433e..8b971c5dbd81 100644 --- a/code/modules/mob/living/carbon/human/species/machine.dm +++ b/code/modules/mob/living/carbon/human/species/machine.dm @@ -24,7 +24,7 @@ inherent_traits = list(TRAIT_VIRUSIMMUNE, TRAIT_NOBREATH, TRAIT_NOGERMS, TRAIT_NODECAY, TRAIT_NOPAIN, TRAIT_GENELESS) //Computers that don't decay? What a lie! inherent_biotypes = MOB_ROBOTIC | MOB_HUMANOID clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_SKIN_COLOR | HAS_HEAD_MARKINGS | HAS_HEAD_ACCESSORY | ALL_RPARTS | SHAVED + bodyflags = HAS_SKIN_COLOR | HAS_HEAD_MARKINGS | HAS_HEAD_ACCESSORY | ALL_RPARTS | SHAVED | HAS_SPECIES_SUBTYPE dietflags = 0 //IPCs can't eat, so no diet taste_sensitivity = TASTE_SENSITIVITY_NO_TASTE blood_color = COLOR_BLOOD_MACHINE @@ -75,8 +75,65 @@ "is blocking their ventilation port!") plushie_type = /obj/item/toy/plushie/ipcplushie + allowed_species_subtypes = list( + 1 = "None", + 2 = "Vox", + 3 = "Unathi", + 4 = "Tajaran", + 5 = "Nian", + 6 = "Vulpkanin", + 7 = "Kidan", + 8 = "Grey", + 9 = "Drask" + ) + var/static_bodyflags = HAS_SKIN_COLOR | HAS_HEAD_MARKINGS | HAS_HEAD_ACCESSORY | ALL_RPARTS | SHAVED | HAS_SPECIES_SUBTYPE +/datum/species/machine/updatespeciessubtype(mob/living/carbon/human/H, datum/species/new_subtype, owner_sensitive = TRUE, reset_styles = TRUE) //Handling species-subtype and imitation + if(H.dna.species.bodyflags & HAS_SPECIES_SUBTYPE) + var/datum/species/temp_species = new type() + if(isnull(new_subtype) || temp_species.name == new_subtype.name) // Back to our original species. + H.species_subtype = "None" + temp_species.species_subtype = "None" // Update our species subtype to match the Mob's subtype. + var/datum/species/S = GLOB.all_species[temp_species.name] + new_subtype = new S.type() // Resets back to original. We use initial in the case the datum is var edited. + else + H.species_subtype = new_subtype.name + temp_species.species_subtype = H.species_subtype // Update our species subtype to match the Mob's subtype. + + // Copy over new species variables to our temp holder. + temp_species.icobase = new_subtype.icobase + temp_species.tail = new_subtype.tail + temp_species.wing = new_subtype.wing + temp_species.default_headacc = new_subtype.default_headacc + temp_species.default_bodyacc = new_subtype.default_bodyacc + temp_species.bodyflags = new_subtype.bodyflags + temp_species.bodyflags |= static_bodyflags // Add our static bodyflags that slime must always have. + temp_species.sprite_sheet_name = new_subtype.sprite_sheet_name + temp_species.icon_template = new_subtype.icon_template + // Set our DNA to the temp holder. + H.dna.species = temp_species + + for(var/obj/item/organ/external/limb in H.bodyparts) + limb.icobase = temp_species.icobase // update their icobase for when we apply the slimfy effect + limb.dna.species = temp_species // Update limb to match our newly modified species + limb.set_company(limb.model, temp_species.sprite_sheet_name) // Robotic limbs always update to our new subtype. + + // Update misc parts that are stored as reference in species and used on the mob. Also resets stylings to none to prevent anything wacky... + + if(reset_styles) + H.body_accessory = GLOB.body_accessory_by_name[temp_species.default_bodyacc] + H.tail = temp_species.tail + H.wing = temp_species.wing + var/obj/item/organ/external/head/head = H.get_organ("head") + head.h_style = "Bald" + head.f_style = "Shaved" + head.ha_style = "None" + H.s_tone = 0 + H.m_styles = DEFAULT_MARKING_STYLES //Wipes out markings, setting them all to "None". + H.m_colours = DEFAULT_MARKING_COLOURS //Defaults colour to #00000 for all markings. + H.change_head_accessory(GLOB.head_accessory_styles_list[temp_species.default_headacc]) + H.change_icobase(temp_species.icobase, owner_sensitive) //Update the icobase of all our organs, but make sure we don't mess with frankenstein limbs in doing so. /datum/species/machine/on_species_gain(mob/living/carbon/human/H) ..() var/datum/action/innate/change_monitor/monitor = new() @@ -165,7 +222,7 @@ var/list/hair = list() for(var/i in GLOB.hair_styles_public_list) var/datum/sprite_accessory/hair/tmp_hair = GLOB.hair_styles_public_list[i] - if((head_organ.dna.species.name in tmp_hair.species_allowed) && (robohead.company in tmp_hair.models_allowed)) //Populate the list of available monitor styles only with styles that the monitor-head is allowed to use. + if((head_organ.dna.species.sprite_sheet_name in tmp_hair.species_allowed) && (robohead.company in tmp_hair.models_allowed)) //Populate the list of available monitor styles only with styles that the monitor-head is allowed to use. hair += i diff --git a/code/modules/mob/living/carbon/human/species/slimepeople.dm b/code/modules/mob/living/carbon/human/species/slimepeople.dm index 8e97d4f5583e..31fafb60b8a9 100644 --- a/code/modules/mob/living/carbon/human/species/slimepeople.dm +++ b/code/modules/mob/living/carbon/human/species/slimepeople.dm @@ -6,6 +6,8 @@ #define SLIMEPERSON_MINHUNGER 250 #define SLIMEPERSON_REGROWTHDELAY 450 // 45 seconds +#define SLIMEPERSON_MORPH_FORM 10 SECONDS + /datum/species/slime name = "Slime People" name_plural = "Slime People" @@ -36,7 +38,7 @@ species_traits = list(LIPS, NO_CLONESCAN, EXOTIC_COLOR) inherent_traits = list(TRAIT_WATERBREATH, TRAIT_NO_BONES) clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS - bodyflags = HAS_SKIN_COLOR | NO_EYES + bodyflags = HAS_SKIN_COLOR | NO_EYES | HAS_SPECIES_SUBTYPE dietflags = DIET_CARN reagent_tag = PROCESS_ORG @@ -57,7 +59,20 @@ "is ripping out their own core!", "is turning a dull, brown color and melting into a puddle!") + allowed_species_subtypes = list( + 1 = "None", + 2 = "Vox", + 3 = "Unathi", + 4 = "Tajaran", + 5 = "Nian", + 6 = "Vulpkanin", + 7 = "Kidan", + 8 = "Grey", + 9 = "Drask" + ) + var/reagent_skin_coloring = FALSE + var/static_bodyflags = HAS_SKIN_COLOR | NO_EYES | HAS_SPECIES_SUBTYPE plushie_type = /obj/item/toy/plushie/slimeplushie @@ -67,6 +82,8 @@ grow.Grant(H) var/datum/action/innate/slimecolor/recolor = new() recolor.Grant(H) + var/datum/action/innate/morphform/reform = new() + reform.Grant(H) RegisterSignal(H, COMSIG_HUMAN_UPDATE_DNA, PROC_REF(blend)) blend(H) @@ -78,8 +95,63 @@ i.Remove(H) if(istype(i, /datum/action/innate/regrow)) i.Remove(H) + if(istype(i, /datum/action/innate/morphform)) + i.Remove(H) UnregisterSignal(H, COMSIG_HUMAN_UPDATE_DNA) +/datum/species/slime/updatespeciessubtype(mob/living/carbon/human/H, datum/species/new_subtype, owner_sensitive = TRUE, reset_styles = TRUE) //Handling species-subtype and imitation + if(H.dna.species.bodyflags & HAS_SPECIES_SUBTYPE) + var/datum/species/temp_species = new type() + if(isnull(new_subtype) || temp_species.name == new_subtype.name) // Back to our original species. + H.species_subtype = "None" + temp_species.species_subtype = "None" // Update our species subtype to match the Mob's subtype. + var/datum/species/S = GLOB.all_species[temp_species.name] + new_subtype = new S.type() // Resets back to original. We use initial in the case the datum is var edited. + else + H.species_subtype = new_subtype.name + temp_species.species_subtype = H.species_subtype // Update our species subtype to match the Mob's subtype. + + // Copy over new species variables to our current species. + temp_species.icobase = new_subtype.icobase + temp_species.tail = new_subtype.tail + temp_species.wing = new_subtype.wing + temp_species.eyes = new_subtype.eyes + temp_species.scream_verb = new_subtype.scream_verb + temp_species.male_scream_sound = new_subtype.male_scream_sound + temp_species.female_scream_sound = new_subtype.female_scream_sound + temp_species.default_headacc = new_subtype.default_headacc + temp_species.default_bodyacc = new_subtype.default_bodyacc + temp_species.male_cough_sounds = new_subtype.male_cough_sounds + temp_species.female_cough_sounds = new_subtype.female_cough_sounds + temp_species.male_sneeze_sound = new_subtype.male_sneeze_sound + temp_species.female_sneeze_sound = new_subtype.female_sneeze_sound + temp_species.bodyflags = new_subtype.bodyflags + temp_species.bodyflags |= static_bodyflags // Add our static bodyflags that slime must always have. + temp_species.sprite_sheet_name = new_subtype.sprite_sheet_name + temp_species.icon_template = new_subtype.icon_template + H.dna.species = temp_species + + for(var/obj/item/organ/external/limb in H.bodyparts) + limb.icobase = temp_species.icobase // update their icobase for when we apply the slimfy effect + limb.dna.species = temp_species // Update limb to match our newly modified species + limb.set_company(limb.model, temp_species.sprite_sheet_name) // Robotic limbs always update to our new subtype. + + // Update misc parts that are stored as reference in species and used on the mob. Also resets stylings to none to prevent anything wacky... + + if(reset_styles) + H.body_accessory = GLOB.body_accessory_by_name[default_bodyacc] + H.tail = temp_species.tail + H.wing = temp_species.wing + var/obj/item/organ/external/head/head = H.get_organ("head") + head.h_style = "Bald" + head.f_style = "Shaved" + head.ha_style = "None" + H.s_tone = 0 + H.m_styles = DEFAULT_MARKING_STYLES //Wipes out markings, setting them all to "None". + H.m_colours = DEFAULT_MARKING_COLOURS //Defaults colour to #00000 for all markings. + H.change_head_accessory(GLOB.head_accessory_styles_list[default_headacc]) + H.change_icobase(temp_species.icobase, owner_sensitive) //Update the icobase of all our organs, but make sure we don't mess with frankenstein limbs in doing so. + /datum/species/slime/proc/blend(mob/living/carbon/human/H) var/new_color = BlendRGB(H.skin_colour, "#acacac", 0.5) // Blends this to make it work better if(H.dna.species.blood_color != new_color) // Put here, so if it's a roundstart, dyed, or CMA'd slime, their blood changes to match skin @@ -102,8 +174,6 @@ blend(H) ..() - - /datum/species/slime/can_hear(mob/living/carbon/human/H) // fucking snowflakes . = FALSE if(!HAS_TRAIT(H, TRAIT_DEAF)) @@ -201,6 +271,35 @@ else to_chat(H, "You need to hold still in order to regrow a limb!") +/datum/action/innate/morphform + name = "Morph Form" + check_flags = AB_CHECK_CONSCIOUS + button_overlay_icon = 'icons/effects/effects.dmi' + button_overlay_icon_state = "acid" + +/datum/action/innate/morphform/Activate() + + var/mob/living/carbon/human/H = owner + if(H.nutrition < SLIMEPERSON_MINHUNGER) + to_chat(H, "You're too hungry to morph your form!") + return + var/new_subtype = tgui_input_list(H, "Choose a species to imitate", "Select Subtype", H.dna.species.allowed_species_subtypes) + if(H.species_subtype == new_subtype) + return to_chat(H, "You stand there as your body shifts and then returns to its original form.") + H.visible_message("[H] begins to hold still and concentrate on [H.p_their()] form as it begins to shift and contort...", "You begin to focus on changing your form... (This will take [round(SLIMEPERSON_MORPH_FORM/10)] seconds, and you must hold still.)") + if(do_after(H, SLIMEPERSON_MORPH_FORM, FALSE, H, extra_checks = list(CALLBACK(H, TYPE_PROC_REF(/mob/living, IsStunned))), use_default_checks = FALSE)) // Override the check for weakness, only check for stunned + if(H.nutrition < SLIMEPERSON_MINHUNGER) + to_chat(H, "You're too hungry to morph your form!") + return + var/datum/species/species_subtype = GLOB.all_species[new_subtype] + if(isnull(species_subtype)) + species_subtype = GLOB.all_species[H.dna.species.name] + H.dna.species.updatespeciessubtype(H, new species_subtype.type()) + H.regenerate_icons() + H.adjust_nutrition(-SLIMEPERSON_HUNGERCOST) + else + to_chat(H, "You need to hold still in order to shift your form!") + #undef SLIMEPERSON_COLOR_SHIFT_TRIGGER #undef SLIMEPERSON_ICON_UPDATE_PERIOD #undef SLIMEPERSON_BLOOD_SCALING_FACTOR @@ -208,3 +307,5 @@ #undef SLIMEPERSON_HUNGERCOST #undef SLIMEPERSON_MINHUNGER #undef SLIMEPERSON_REGROWTHDELAY + +#undef SLIMEPERSON_MORPH_FORM diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index 3abfbf56dc3f..07b75d1cb4a3 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -120,7 +120,7 @@ /mob/living/simple_animal/pet/dog/corgi/UnarmedAttack(atom/A) if(istype(inventory_back, /obj/item/extinguisher)) var/obj/item/extinguisher/E = inventory_back - if(E.AttemptRefill(A, src)) + if(E.attempt_refill(A, src)) return return ..() diff --git a/code/modules/mod/modules/modules_engineering.dm b/code/modules/mod/modules/modules_engineering.dm index 2efd024af583..c5fcbd9c84d4 100644 --- a/code/modules/mod/modules/modules_engineering.dm +++ b/code/modules/mod/modules/modules_engineering.dm @@ -159,49 +159,31 @@ /// Atmos water tank module +#define EXTINGUISHER 0 +#define NANOFROST 1 +#define METAL_FOAM 2 + /obj/item/mod/module/firefighting_tank name = "MOD firefighting tank" - desc = "A refrigerated and pressurized module tank with an extinguisher nozzle, intended to fight fires. Swaps between extinguisher, nanofrost launcher, and metal foam dispenser for breaches. Nanofrost converts plasma in the air to nitrogen, but only if it is combusting at the time." + desc = "A refrigerated and pressurized module tank with an extinguisher nozzle, intended to fight fires. \ + Swaps between extinguisher, nanofrost launcher, and metal foam dispenser for breaches. Nanofrost converts plasma in the air to nitrogen, but only if it is combusting at the time.\ + The smaller volume compared to a dedicated firefighting backpack means that non-water modes suffer from longer cooldowns." icon_state = "firefighting_tank" module_type = MODULE_ACTIVE complexity = 2 active_power_cost = DEFAULT_CHARGE_DRAIN * 3 - device = /obj/item/extinguisher/mini/mod - -#define EXTINGUISHER 0 -#define NANOFROST 1 -#define METAL_FOAM 2 + incompatible_modules = list(/obj/item/mod/module/firefighting_tank) + device = /obj/item/extinguisher/mini/nozzle/mod + // Used by nozzle code. + var/volume = 500 -/obj/item/extinguisher/mini/mod +/obj/item/extinguisher/mini/nozzle/mod name = "modsuit extinguisher nozzle" desc = "A heavy duty nozzle attached to a modsuit's internal tank." - icon = 'icons/obj/watertank.dmi' - icon_state = "atmos_nozzle_1" - item_state = "nozzleatmos" - safety = 0 - max_water = 500 - precision = 1 - cooling_power = 5 - w_class = WEIGHT_CLASS_HUGE - flags = NODROP // Necessary to ensure that the nozzle and tank never seperate - var/nozzle_mode = EXTINGUISHER - var/metal_synthesis_charge = 5 - COOLDOWN_DECLARE(nanofrost_cooldown) + metal_regen_time = 5 SECONDS + nanofrost_cooldown_time = 10 SECONDS -/obj/item/extinguisher/mini/mod/attack_self__legacy__attackchain(mob/user) - switch(nozzle_mode) - if(EXTINGUISHER) - nozzle_mode = NANOFROST - to_chat(user, "Swapped to nanofrost launcher.") - if(NANOFROST) - nozzle_mode = METAL_FOAM - to_chat(user, "Swapped to metal foam synthesizer.") - if(METAL_FOAM) - nozzle_mode = EXTINGUISHER - to_chat(user, "Swapped to water extinguisher.") - update_icon(UPDATE_ICON_STATE) - -/obj/item/extinguisher/mini/mod/update_icon_state() +/obj/item/extinguisher/mini/nozzle/mod/update_icon_state() switch(nozzle_mode) if(EXTINGUISHER) icon_state = "atmos_nozzle_1" @@ -210,58 +192,6 @@ if(METAL_FOAM) icon_state = "atmos_nozzle_3" -/obj/item/extinguisher/mini/mod/examine(mob/user) - . = ..() - switch(nozzle_mode) - if(EXTINGUISHER) - . += "[src] is currently set to extinguishing mode." - if(NANOFROST) - . += "[src] is currently set to nanofrost mode." - if(METAL_FOAM) - . += "[src] is currently set to metal foam mode." - -/obj/item/extinguisher/mini/mod/afterattack__legacy__attackchain(atom/target, mob/user) - var/is_adjacent = user.Adjacent(target) - if(is_adjacent && AttemptRefill(target, user)) - return - switch(nozzle_mode) - if(EXTINGUISHER) - ..() - - if(NANOFROST) - if(reagents.total_volume < 100) - to_chat(user, "You need at least 100 units of water to use the nanofrost launcher!") - return - if(!COOLDOWN_FINISHED(src, nanofrost_cooldown)) - to_chat(user, "Nanofrost launcher is still recharging.") - return - COOLDOWN_START(src, nanofrost_cooldown, 10 SECONDS) - reagents.remove_any(100) - var/obj/effect/nanofrost_container/A = new /obj/effect/nanofrost_container(get_turf(src)) - log_game("[key_name(user)] used Nanofrost at [get_area(user)] ([user.x], [user.y], [user.z]).") - playsound(src, 'sound/items/syringeproj.ogg', 40, TRUE) - A.throw_at(target, 6, 2, user) - sleep(2) - A.Smoke() - - if(METAL_FOAM) - if(!is_adjacent|| !isturf(target)) - return - if(metal_synthesis_charge <= 0) - to_chat(user, "Metal foam mix is still being synthesized.") - return - if(reagents.total_volume < 10) - to_chat(user, "You need at least 10 units of water to use the metal foam synthesizer!") - return - var/obj/effect/particle_effect/foam/metal/F = new /obj/effect/particle_effect/foam/metal(get_turf(target), TRUE) - F.spread_amount = 0 - reagents.remove_any(10) - metal_synthesis_charge-- - addtimer(CALLBACK(src, PROC_REF(decrease_metal_charge)), 5 SECONDS) - -/obj/item/extinguisher/mini/mod/proc/decrease_metal_charge() - metal_synthesis_charge++ - #undef EXTINGUISHER #undef NANOFROST #undef METAL_FOAM diff --git a/code/modules/projectiles/guns/medbeam.dm b/code/modules/projectiles/guns/medbeam.dm index eb1ab9d1702a..992051934a29 100644 --- a/code/modules/projectiles/guns/medbeam.dm +++ b/code/modules/projectiles/guns/medbeam.dm @@ -12,6 +12,7 @@ var/max_range = 8 var/active = FALSE var/beam_UID = null + var/mounted = FALSE weapon_weight = WEAPON_MEDIUM @@ -43,7 +44,8 @@ current_target = null /obj/item/gun/medbeam/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override) - add_fingerprint(user) + if(isliving(user) && isrobot(user)) + add_fingerprint(user) if(current_target) LoseTarget() @@ -60,7 +62,7 @@ /obj/item/gun/medbeam/process() var/source = loc - if(!ishuman(source) && !isrobot(source)) + if(!mounted && !ishuman(source) && !isrobot(source)) LoseTarget() return @@ -75,20 +77,25 @@ if(get_dist(source,current_target)>max_range || !los_check(source,current_target)) LoseTarget() - to_chat(source, "You lose control of the beam!") + if(ishuman(source) && isrobot(source)) + to_chat(source, "You lose control of the beam!") return if(current_target) on_beam_tick(source, current_target) -/obj/item/gun/medbeam/proc/los_check(mob/user,mob/target) +/obj/item/gun/medbeam/proc/los_check(atom/movable/user, mob/target) var/turf/user_turf = user.loc var/datum/beam/current_beam = locateUID(beam_UID) - if(!istype(user_turf)) + if(mounted) + user_turf = get_turf(user) + else if(!istype(user_turf)) return FALSE var/obj/dummy = new(user_turf) dummy.pass_flags |= PASSTABLE | PASSGLASS | PASSGRILLE | PASSFENCE //Grille/Glass so it can be used through common windows for(var/turf/turf in get_line(user_turf,target)) + if(mounted && turf == user_turf) + continue //Mechs are dense and thus fail the check if(turf.density) qdel(dummy) return FALSE @@ -111,7 +118,7 @@ H.adjustBruteLoss(-4, robotic = TRUE) H.adjustFireLoss(-4, robotic = TRUE) for(var/obj/item/organ/external/E in H.bodyparts) - if(prob(10)) + if(!mounted && prob(10)) E.mend_fracture() E.fix_internal_bleeding() E.fix_burn_wound() @@ -360,3 +367,11 @@ name = "beamgun cell" desc = "A cell that fell out of a beamgun. It cannot be reused until fully charged. Only this brand of battery is compatible with medical beamguns." starting_charge = 0 + +//////////////////////////////Mech Version/////////////////////////////// +/obj/item/gun/medbeam/mech + mounted = TRUE + +/obj/item/gun/medbeam/mech/Initialize(mapload) + . = ..() + STOP_PROCESSING(SSobj, src) //Mech mediguns do not process until installed, and are controlled by the holder obj diff --git a/code/modules/reagents/chemistry/reagents/misc_reagents.dm b/code/modules/reagents/chemistry/reagents/misc_reagents.dm index f39583d7136f..29f8e1964479 100644 --- a/code/modules/reagents/chemistry/reagents/misc_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/misc_reagents.dm @@ -359,8 +359,8 @@ var/obj/item/organ/external/head/head_organ = H.get_organ("head") if(!istype(head_organ)) return ..() - head_organ.h_style = random_hair_style(H.gender, head_organ.dna.species.name) - head_organ.f_style = random_facial_hair_style(H.gender, head_organ.dna.species.name) + head_organ.h_style = random_hair_style(H.gender, head_organ.dna.species.sprite_sheet_name) + head_organ.f_style = random_facial_hair_style(H.gender, head_organ.dna.species.sprite_sheet_name) H.update_hair() H.update_fhair() ..() @@ -383,14 +383,14 @@ var/datum/sprite_accessory/tmp_hair_style = GLOB.hair_styles_full_list["Very Long Hair"] var/datum/sprite_accessory/tmp_facial_hair_style = GLOB.facial_hair_styles_list["Very Long Beard"] - if(head_organ.dna.species.name in tmp_hair_style.species_allowed) //If 'Very Long Hair' is a style the person's species can have, give it to them. + if(head_organ.dna.species.sprite_sheet_name in tmp_hair_style.species_allowed) //If 'Very Long Hair' is a style the person's species can have, give it to them. head_organ.h_style = "Very Long Hair" else //Otherwise, give them a random hair style. - head_organ.h_style = random_hair_style(H.gender, head_organ.dna.species.name) - if(head_organ.dna.species.name in tmp_facial_hair_style.species_allowed) //If 'Very Long Beard' is a style the person's species can have, give it to them. + head_organ.h_style = random_hair_style(H.gender, head_organ.dna.species.sprite_sheet_name) + if(head_organ.dna.species.sprite_sheet_name in tmp_facial_hair_style.species_allowed) //If 'Very Long Beard' is a style the person's species can have, give it to them. head_organ.f_style = "Very Long Beard" else //Otherwise, give them a random facial hair style. - head_organ.f_style = random_facial_hair_style(H.gender, head_organ.dna.species.name) + head_organ.f_style = random_facial_hair_style(H.gender, head_organ.dna.species.sprite_sheet_name) H.update_hair() H.update_fhair() if(!H.wear_mask || H.wear_mask && !istype(H.wear_mask, /obj/item/clothing/mask/fakemoustache)) diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index 41e9955e16e6..24160309477c 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -186,6 +186,7 @@ materials = list(MAT_METAL = 500, MAT_GLASS = 500) build_path = /obj/item/clothing/ears/earmuffs category = list("initial", "Miscellaneous") + /datum/design/painter name = "Modular Painter" id = "mod_painter" @@ -194,6 +195,14 @@ build_path = /obj/item/painter category = list("initial", "Miscellaneous") +/datum/design/eftpos + name = "EFTPOS" + id = "eftpos" + build_type = AUTOLATHE + materials = list(MAT_METAL = 300, MAT_GLASS = 140) + build_path = /obj/item/eftpos + category = list("initial","Miscellaneous") + /datum/design/metal name = "Metal" id = "metal" diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index fb709fa9dc98..a57fcea27ede 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -736,6 +736,16 @@ construction_time = 20 SECONDS category = list("Exosuit Equipment") +/datum/design/mech_medical_beamgun + name = "Exosuit Medical Equipment (Medical Beamgun)" + id = "mech_medi_beam" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam + req_tech = list("combat" = 5, "materials" = 7, "powerstorage" = 7, "biotech" = 7) + materials = list(MAT_METAL=15000,MAT_GLASS=8000,MAT_PLASMA=3000,MAT_GOLD=8000,MAT_DIAMOND=2000) + construction_time = 20 SECONDS + category = list("Exosuit Equipment") + /datum/design/mech_mop name = "Exosuit Janitorial Equipment (Mega Mop)" id = "mech_mop" diff --git a/code/modules/response_team/ert.dm b/code/modules/response_team/ert.dm index 85e276091210..0217b23f5a25 100644 --- a/code/modules/response_team/ert.dm +++ b/code/modules/response_team/ert.dm @@ -196,8 +196,8 @@ GLOBAL_LIST_EMPTY(ert_request_messages) M.change_eye_color(eye_c) M.s_tone = skin_tone head_organ.headacc_colour = pick("#1f138b", "#272525", "#07a035", "#8c00ff", "#a80c0c") - head_organ.h_style = random_hair_style(M.gender, head_organ.dna.species.name) - head_organ.f_style = random_facial_hair_style(M.gender, head_organ.dna.species.name) + head_organ.h_style = random_hair_style(M.gender, head_organ.dna.species.sprite_sheet_name) + head_organ.f_style = random_facial_hair_style(M.gender, head_organ.dna.species.sprite_sheet_name) M.rename_character(null, "[pick("Капрал", "Сержант", "Старший Сержант", "Сержант 1-го Класса", "Мастер-Сержант", "Сержант-Майор")] [pick(GLOB.last_names)]") M.age = rand(23,35) diff --git a/code/modules/security_levels/keycard_authentication.dm b/code/modules/security_levels/keycard_authentication.dm index a93f3dc1c2f8..f42e7eda4524 100644 --- a/code/modules/security_levels/keycard_authentication.dm +++ b/code/modules/security_levels/keycard_authentication.dm @@ -205,7 +205,7 @@ return ERT_Announce(ert_reason, triggered_by, repeat_warning = FALSE) - addtimer(CALLBACK(src, PROC_REF(remind_admins), ert_reason, triggered_by), 15 MINUTES) + addtimer(CALLBACK(src, PROC_REF(remind_admins), ert_reason, triggered_by), 5 MINUTES) ert_reason = null /obj/machinery/keycard_auth/proc/remind_admins(old_reason, the_triggerer) // im great at naming variables diff --git a/code/modules/space_management/heap_space_level.dm b/code/modules/space_management/heap_space_level.dm deleted file mode 100644 index 666bfa9fa821..000000000000 --- a/code/modules/space_management/heap_space_level.dm +++ /dev/null @@ -1,62 +0,0 @@ -// This represents a level we can carve up as we please, and hand out -// chunks of to whatever requests it -/datum/space_level/heap - name = "Heap level #ERROR" - var/datum/space_chunk/top - linkage = UNAFFECTED - -/datum/space_level/heap/New(z, name, transition_type, traits) - ..(z, "Heap level #[z]", UNAFFECTED, traits) - top = new(1, 1, zpos, world.maxx, world.maxy) - flags = traits - -/datum/space_level/heap/proc/request(width, height) - return top.can_fit_space(width, height) - -// Returns a space chunk datum for some nerd to work with - tells them what's safe to write into, and such -/datum/space_level/heap/proc/allocate(width, height) - if(!request(width, height)) - return null - - var/datum/space_chunk/C = top.get_optimal_chunk(width, height) - if(!C) - return null - C.children.Cut() - - if(C.width == width && C.height == height && C.is_empty) - C.set_occupied(TRUE) - return C - - // Split the chunk into 4 pieces - var/datum/space_chunk/return_chunk = new(C.x, C.y, C.zpos, width, height) - C.children += return_chunk - C.children += new /datum/space_chunk(C.x+width, C.y, C.zpos, C.width-width, height) - C.children += new /datum/space_chunk(C.x, C.y+height, C.zpos, width, C.height-height) - C.children += new /datum/space_chunk(C.x+width, C.y+height, C.zpos, C.width-width, C.height-height) - - for(var/datum/space_chunk/C2 in C.children) - C2.parent = C - return_chunk.set_occupied(TRUE) - return return_chunk - -/datum/space_level/heap/proc/free(datum/space_chunk/C) - if(!istype(C)) - return - if(C.zpos != zpos) - return - C.set_occupied(FALSE) - for(var/turf/T in block(C.x, C.y, C.zpos, C.x + C.width - 1, C.y + C.height - 1, C.zpos)) - for(var/atom/movable/M in T) - if(isobserver(M)) - continue - M.loc = null - qdel(M, TRUE) - T.ChangeTurf(T.baseturf) - var/datum/space_chunk/last_empty_parent = C - while(last_empty_parent.parent && last_empty_parent.parent.is_empty) - last_empty_parent = last_empty_parent.parent - // Prevent a self-qdel from killing this proc - src = null - for(var/datum/space_chunk/child in last_empty_parent.children) - qdel(child) - last_empty_parent.children.Cut() diff --git a/code/modules/space_management/level_traits.dm b/code/modules/space_management/level_traits.dm index 0634d9299902..aa02bdaa44c1 100644 --- a/code/modules/space_management/level_traits.dm +++ b/code/modules/space_management/level_traits.dm @@ -28,6 +28,8 @@ /proc/level_boosts_signal(z) return check_level_trait(z, BOOSTS_SIGNAL) +#define is_reserved_level(z) check_level_trait(z, ZTRAIT_RESERVED) + // Used for the nuke disk, or for checking if players survived through xenos /proc/is_secure_level(z) var/secure = check_level_trait(z, STATION_LEVEL) diff --git a/code/modules/space_management/turf_reservation.dm b/code/modules/space_management/turf_reservation.dm new file mode 100644 index 000000000000..febe4b34bba4 --- /dev/null +++ b/code/modules/space_management/turf_reservation.dm @@ -0,0 +1,153 @@ +/* + * Turf reservations are used to reserve specific areas of the reserved z-levels for various purposes, typically for late-loading maps. + * It ensures that reserved turfs are properly managed and can be released when no longer needed. + * Reservations are not automatically released, so they must be manually released when no longer needed. + * + * Usage: + * - To create a new reservation, call the `request_turf_block_reservation(width, height)` method from the mapping subsystem. + * - This will return a new instance of /datum/turf_reservation if the reservation is successful. + * + * Releasing: + * - Call the `Release` method on the /datum/turf_reservation instance to release the reserved turfs and cordon turfs. + * - This will return the used turfs to the mapping subsystem to allow for reuse of the turfs. + */ + +/datum/turf_reservation + /// All turfs that we've reserved + var/list/reserved_turfs = list() + + /// Turfs around the reservation for cordoning + var/list/cordon_turfs = list() + + /// Area of turfs next to the cordon to fill with pre_cordon_area's + var/list/pre_cordon_turfs = list() + + /// The width of the reservation + var/width = 0 + + /// The height of the reservation + var/height = 0 + + /// Bottom left turf of the reservation + var/turf/bottom_left_turf + + /// Top right turf of the reservation + var/turf/top_right_turf + + /// The turf type the reservation is initially made with + var/turf_type = /turf/space + +/datum/turf_reservation/New() + LAZYADD(SSmapping.turf_reservations, src) + +/datum/turf_reservation/Destroy() + Release() + LAZYREMOVE(SSmapping.turf_reservations, src) + return ..() + +/datum/turf_reservation/proc/Release() + bottom_left_turf = null + top_right_turf = null + + var/list/reserved_copy = reserved_turfs.Copy() + SSmapping.used_turfs -= reserved_turfs + reserved_turfs = list() + + var/list/cordon_copy = cordon_turfs.Copy() + SSmapping.used_turfs -= cordon_turfs + cordon_turfs = list() + + var/release_turfs = reserved_copy + cordon_copy + + SSmapping.unreserve_turfs(release_turfs) + +/// Attempts to calaculate and store a list of turfs around the reservation for cordoning. Returns whether a valid cordon was calculated +/datum/turf_reservation/proc/calculate_cordon_turfs(turf/bottom_left, turf/top_right) + if(bottom_left.x < 2 || bottom_left.y < 2 || top_right.x > (world.maxx - 2) || top_right.y > (world.maxy - 2)) + return FALSE // no space for a cordon here + + var/list/possible_turfs = CORNER_OUTLINE(bottom_left, width, height) + // if they're our cordon turfs, accept them + possible_turfs -= cordon_turfs + for(var/turf/cordon_turf as anything in possible_turfs) + // if we changed this to check reservation turf instead of not unused, we could have overlapping cordons. + // Unfortunately, that means adding logic for cordons not being removed if they have multiple edges and I'm lazy + if(!(cordon_turf.turf_flags & UNUSED_RESERVATION_TURF)) + return FALSE + cordon_turfs |= possible_turfs + + return TRUE + +/// Actually generates the cordon around the reservation, and marking the cordon turfs as reserved +/datum/turf_reservation/proc/generate_cordon() + for(var/turf/cordon_turf as anything in cordon_turfs) + var/area/cordon/cordon_area = GLOB.all_unique_areas[/area/cordon] || new /area/cordon + + cordon_area.contents += cordon_turf + + // Its no longer unused, but its also not "used" + cordon_turf.turf_flags &= ~UNUSED_RESERVATION_TURF + cordon_turf.empty(/turf/cordon) + SSmapping.unused_turfs["[cordon_turf.z]"] -= cordon_turf + // still gets linked to us though + SSmapping.used_turfs[cordon_turf] = src + +/// Internal proc which handles reserving the area for the reservation. +/datum/turf_reservation/proc/_reserve_area(width, height, zlevel) + src.width = width + src.height = height + if(width > world.maxx || height > world.maxy || width < 1 || height < 1) + return FALSE + var/list/avail = SSmapping.unused_turfs["[zlevel]"] + var/turf/bottom_left + var/turf/top_right + var/list/turf/final_turfs = list() + var/passing = FALSE + for(var/i in avail) + CHECK_TICK + bottom_left = i + if(!(bottom_left.turf_flags & UNUSED_RESERVATION_TURF)) + continue + if(bottom_left.x + width > world.maxx || bottom_left.y + height > world.maxy) + continue + top_right = locate(bottom_left.x + width - 1, bottom_left.y + height - 1, bottom_left.z) + if(!(top_right.turf_flags & UNUSED_RESERVATION_TURF)) + continue + final_turfs = block(bottom_left, top_right) + if(!final_turfs) + continue + passing = TRUE + for(var/I in final_turfs) + var/turf/checking = I + if(!(checking.turf_flags & UNUSED_RESERVATION_TURF)) + passing = FALSE + break + if(passing) // found a potentially valid area, now try to calculate its cordon + passing = calculate_cordon_turfs(bottom_left, top_right) + if(!passing) + continue + break + if(!passing || !istype(bottom_left) || !istype(top_right)) + return FALSE + for(var/turf/T as anything in final_turfs) + reserved_turfs |= T + SSmapping.unused_turfs["[T.z]"] -= T + SSmapping.used_turfs[T] = src + T.turf_flags = (T.turf_flags | RESERVATION_TURF) & ~UNUSED_RESERVATION_TURF + T.empty(turf_type) + + bottom_left_turf = bottom_left + top_right_turf = top_right + return TRUE + +/datum/turf_reservation/proc/reserve(width, height, z_reservation) + + if(!_reserve_area(width, height, z_reservation)) + log_debug("Failed turf reservation: releasing") + Release() + return FALSE + + log_debug("Turf reservation successful, generating cordon") + generate_cordon() + return TRUE + diff --git a/code/modules/space_management/zlevel_manager.dm b/code/modules/space_management/zlevel_manager.dm index d2364652ee6a..4887257493c9 100644 --- a/code/modules/space_management/zlevel_manager.dm +++ b/code/modules/space_management/zlevel_manager.dm @@ -134,42 +134,3 @@ GLOBAL_DATUM_INIT(space_manager, /datum/zlev_manager, new()) z_list.Remove(S) qdel(S) world.maxz-- - - -// An internally-used proc used for heap-zlevel management -/datum/zlev_manager/proc/add_new_heap() - world.maxz++ - var/our_z = world.maxz - var/datum/space_level/yup = new /datum/space_level/heap(our_z, traits = list(BLOCK_TELEPORT, ADMIN_LEVEL)) - z_list["[our_z]"] = yup - return yup - -// This is what you can call to allocate a section of space -// Later, I'll add an argument to let you define the flags on the region -/datum/zlev_manager/proc/allocate_space(width, height) - if(width > world.maxx || height > world.maxy) - throw EXCEPTION("Too much space requested! \[[width],[height]\]") - if(!length(heaps)) - heaps.len++ - heaps[length(heaps)] = add_new_heap() - var/datum/space_level/heap/our_heap - var/weve_got_vacancy = 0 - for(our_heap in heaps) - weve_got_vacancy = our_heap.request(width, height) - if(weve_got_vacancy) - break // We're sticking with the present value of `our_heap` - it's got room - // This loop will also run out if no vacancies are found - - if(!weve_got_vacancy) - heaps.len++ - our_heap = add_new_heap() - heaps[length(heaps)] = our_heap - return our_heap.allocate(width, height) - -/datum/zlev_manager/proc/free_space(datum/space_chunk/C) - if(!istype(C)) - return - var/datum/space_level/heap/heap = z_list["[C.zpos]"] - if(!istype(heap)) - throw EXCEPTION("Attempted to free chunk at invalid z-level ([C.x],[C.y],[C.zpos]) [C.width]x[C.height]") - heap.free(C) diff --git a/code/modules/surgery/organs/augments_eyes.dm b/code/modules/surgery/organs/augments_eyes.dm index a26301260540..5ff41d62e2b0 100644 --- a/code/modules/surgery/organs/augments_eyes.dm +++ b/code/modules/surgery/organs/augments_eyes.dm @@ -61,6 +61,9 @@ HUD_type = DATA_HUD_SECURITY_ADVANCED examine_extensions = list(EXAMINE_HUD_SECURITY_READ) +/obj/item/organ/internal/cyberimp/eyes/hud/security/hidden + stealth_level = 4 // Only surgery or a body scanner with the highest tier of stock parts can detect this. + /obj/item/organ/internal/cyberimp/eyes/hud/jani name = "Janitor HUD implant" desc = "These cybernetic eye implants will display a filth HUD over everything you see." diff --git a/code/modules/surgery/organs/organ_icon.dm b/code/modules/surgery/organs/organ_icon.dm index 7704c6707c54..86a1bf4b5675 100644 --- a/code/modules/surgery/organs/organ_icon.dm +++ b/code/modules/surgery/organs/organ_icon.dm @@ -108,7 +108,7 @@ var/head_marking = owner.m_styles["head"] if(head_marking) var/datum/sprite_accessory/head_marking_style = GLOB.marking_styles_list[head_marking] - if(head_marking_style && head_marking_style.species_allowed && (dna.species.name in head_marking_style.species_allowed) && head_marking_style.marking_location == "head") + if(head_marking_style && head_marking_style.species_allowed && (dna.species.sprite_sheet_name in head_marking_style.species_allowed) && head_marking_style.marking_location == "head") var/icon/h_marking_s = new /icon("icon" = head_marking_style.icon, "icon_state" = "[head_marking_style.icon_state]_s") if(head_marking_style.do_colouration) h_marking_s.Blend(owner.m_colours["head"], ICON_ADD) @@ -117,7 +117,7 @@ if(!((owner.head && (owner.head.flags & BLOCKHAIR)) || (owner.wear_mask && (owner.wear_mask.flags & BLOCKHAIR)))) //Common restriction for all the below features. if(ha_style) var/datum/sprite_accessory/head_accessory_style = GLOB.head_accessory_styles_list[ha_style] - if(head_accessory_style && head_accessory_style.species_allowed && (dna.species.name in head_accessory_style.species_allowed)) + if(head_accessory_style && head_accessory_style.species_allowed && (dna.species.sprite_sheet_name in head_accessory_style.species_allowed)) var/icon/head_accessory_s = new /icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") if(head_accessory_style.do_colouration) head_accessory_s.Blend(headacc_colour, ICON_ADD) @@ -125,7 +125,7 @@ if(f_style) var/datum/sprite_accessory/facial_hair_style = GLOB.facial_hair_styles_list[f_style] - if(facial_hair_style && ((facial_hair_style.species_allowed && (dna.species.name in facial_hair_style.species_allowed)) || (dna.species.bodyflags & ALL_RPARTS))) + if(facial_hair_style && ((facial_hair_style.species_allowed && (dna.species.sprite_sheet_name in facial_hair_style.species_allowed)) || (dna.species.bodyflags & ALL_RPARTS))) var/icon/facial_s = new /icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") if(istype(dna.species, /datum/species/slime)) // I am el worstos facial_s.Blend("[owner.skin_colour]A0", ICON_AND) //A0 = 160 alpha. @@ -136,7 +136,7 @@ if(h_style) if(!ismachineperson(owner) || (ismachineperson(owner) && ((owner.head && (owner.head.flags & BLOCKHEADHAIR)) || (owner.wear_mask && (owner.wear_mask.flags & BLOCKHEADHAIR))))) var/datum/sprite_accessory/hair_style = GLOB.hair_styles_full_list[h_style] - if(hair_style && ((dna.species.name in hair_style.species_allowed) || (dna.species.bodyflags & ALL_RPARTS))) + if(hair_style && ((dna.species.sprite_sheet_name in hair_style.species_allowed) || (dna.species.bodyflags & ALL_RPARTS))) var/icon/hair_s = new /icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") if(istype(dna.species, /datum/species/slime)) // I am el worstos hair_s.Blend("[owner.skin_colour]A0", ICON_AND) //A0 = 160 alpha. diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index ab38b16f36ff..07fb8745987a 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -750,13 +750,32 @@ else if(!target.Adjacent(user)) to_chat(user, "The multitool is out of range! Please try again.") return SURGERY_STEP_INCOMPLETE + + var/new_subtype = tgui_input_list(user, "Choose a species look-alike for this machine", "Select Subtype", target.dna.species.allowed_species_subtypes) + if(isnull(new_subtype)) + to_chat(user, "You must choose a subtype! Please try again.") + return SURGERY_STEP_INCOMPLETE + else if(!target.Adjacent(user)) + to_chat(user, "The multitool is out of range! Please try again.") + return SURGERY_STEP_INCOMPLETE + var/new_gender = gender_list[gender_key] var/old_name = target.real_name target.real_name = new_name target.gender = new_gender user.visible_message( - "[user] edits [old_name]'s identity parameters with [tool]; [target.p_they()] [target.p_are()] now known as [new_name].", - "You alter [old_name]'s identity parameters with [tool]; [target.p_they()] [target.p_are()] now known as [new_name].", + "[user] edits [old_name]'s identity parameters with [tool], changing their appearance; [target.p_they()] [target.p_are()] now known as [new_name].", + "You alter [old_name]'s identity parameters with [tool], changing their appearance; [target.p_they()] [target.p_are()] now known as [new_name].", chat_message_type = MESSAGE_TYPE_COMBAT ) + + if(!isnull(target.dna)) + var/datum/species/subtype = GLOB.all_species[new_subtype] + if(isnull(subtype)) + subtype = GLOB.all_species[target.dna.species.name] + target.dna.species.updatespeciessubtype(target, new subtype.type()) + for(var/obj/item/organ/external/limb in target.bodyparts) // Update robotic limbs to match new sub species + limb.set_company(limb.model, target.dna.species.sprite_sheet_name) // Update the limbs to properly use their new sprite sheet. + target.regenerate_icons() + return SURGERY_STEP_CONTINUE diff --git a/code/modules/tgui/modules/appearance_changer.dm b/code/modules/tgui/modules/appearance_changer.dm index cacf106a7913..d82fcec4efb8 100644 --- a/code/modules/tgui/modules/appearance_changer.dm +++ b/code/modules/tgui/modules/appearance_changer.dm @@ -17,9 +17,13 @@ var/list/whitelist var/list/blacklist + /// Temporary holder when we first initialize the TGUI, we store this as our owner's previous subtype so we can tell when it updates. + var/owner_subtype + /datum/ui_module/appearance_changer/New(datum/host, mob/living/carbon/human/H, check_species_whitelist = TRUE, list/species_whitelist = list(), list/species_blacklist = list()) ..() owner = H + owner_subtype = owner.dna.species.species_subtype head_organ = owner.get_organ("head") check_whitelist = check_species_whitelist whitelist = species_whitelist @@ -214,7 +218,11 @@ ui.open() /datum/ui_module/appearance_changer/ui_data(mob/user) - generate_data(check_whitelist, whitelist, blacklist) + if(user.dna.species.species_subtype != owner_subtype) + owner_subtype = user.dna.species.species_subtype + cut_and_generate_data() + else + generate_data(check_whitelist, whitelist, blacklist) var/list/data = list() data["specimen"] = owner.dna.species.name diff --git a/code/tests/_map_per_tile_test.dm b/code/tests/_map_per_tile_test.dm new file mode 100644 index 000000000000..db596d855178 --- /dev/null +++ b/code/tests/_map_per_tile_test.dm @@ -0,0 +1,20 @@ +/** + * Map per-tile test. + * + * Per-tile map tests iterate over each tile of a map to perform a check, and + * fails the test if a tile does not pass the check. A new test can be + * written by extending /datum/map_per_tile_test, and implementing the check + * in CheckTile. + */ +/datum/map_per_tile_test + var/succeeded = TRUE + var/list/fail_reasons + var/failure_count = 0 + +/datum/map_per_tile_test/proc/CheckTile(turf/T) + Fail("CheckTile() called parent or not implemented") + +/datum/map_per_tile_test/proc/Fail(turf/T, reason) + succeeded = FALSE + LAZYADD(fail_reasons, "[T.x],[T.y],[T.z]: [reason]") + failure_count++ diff --git a/code/tests/game_tests.dm b/code/tests/game_tests.dm index d482918253ff..81b45121d889 100644 --- a/code/tests/game_tests.dm +++ b/code/tests/game_tests.dm @@ -1,9 +1,14 @@ //include game test files in this module in this ifdef //Keep this sorted alphabetically -#ifdef GAME_TESTS +#ifdef TEST_RUNNER #include "_game_test_puppeteer.dm" #include "_game_test.dm" +#include "_map_per_tile_test.dm" +#include "test_runner.dm" +#endif + +#ifdef GAME_TESTS #include "atmos\test_ventcrawl.dm" #include "attack_chain\test_attack_chain_cult_dagger.dm" #include "attack_chain\test_attack_chain_machinery.dm" @@ -13,7 +18,6 @@ #include "jobs\test_job_globals.dm" #include "test_aicard_icons.dm" #include "test_announcements.dm" -#include "test_areas_apcs.dm" #include "test_components.dm" #include "test_config_sanity.dm" #include "test_crafting_lists.dm" @@ -22,12 +26,10 @@ #include "test_init_sanity.dm" #include "test_log_format.dm" #include "test_map_templates.dm" -#include "test_map_tests.dm" #include "test_missing_icons.dm" #include "test_origin_tech.dm" #include "test_purchase_reference_test.dm" #include "test_reagent_id_typos.dm" -#include "test_runner.dm" #include "test_rustg_version.dm" #include "test_spawn_humans.dm" #include "test_spell_targeting_test.dm" @@ -37,3 +39,8 @@ #include "test_subsystem_metric_sanity.dm" #include "test_timer_sanity.dm" #endif + +#ifdef MAP_TESTS +#include "test_areas_apcs.dm" +#include "test_map_tests.dm" +#endif diff --git a/code/tests/test_map_tests.dm b/code/tests/test_map_tests.dm index c4d756390bf2..76d1416ac7f6 100644 --- a/code/tests/test_map_tests.dm +++ b/code/tests/test_map_tests.dm @@ -1,24 +1,3 @@ -/** - * Map per-tile test. - * - * Per-tile map tests iterate over each tile of a map to perform a check, and - * fails the test if a tile does not pass the check. A new test can be - * written by extending /datum/map_per_tile_test, and implementing the check - * in CheckTile. - */ -/datum/map_per_tile_test - var/succeeded = TRUE - var/list/fail_reasons - var/failure_count = 0 - -/datum/map_per_tile_test/proc/CheckTile(turf/T) - Fail("CheckTile() called parent or not implemented") - -/datum/map_per_tile_test/proc/Fail(turf/T, reason) - succeeded = FALSE - LAZYADD(fail_reasons, "[T.x],[T.y],[T.z]: [reason]") - failure_count++ - /** * Check to ensure that APCs have a cable node on their tile. */ diff --git a/code/tests/test_runner.dm b/code/tests/test_runner.dm index 206d31a2205d..1bd2cf287812 100644 --- a/code/tests/test_runner.dm +++ b/code/tests/test_runner.dm @@ -22,38 +22,18 @@ // Running the tests is part of the ticker's start function, because I cant think of any better place to put it SSticker.force_start = TRUE - -/datum/test_runner/proc/RunMap(z_level = 2) - CHECK_TICK - - var/list/tests = list() - - for(var/I in subtypesof(/datum/map_per_tile_test)) - tests += new I - test_logs[I] = list() - durations[I] = 0 - - for(var/turf/T in block(1, 1, z_level, world.maxx, world.maxy, z_level)) - for(var/datum/map_per_tile_test/test in tests) - if(test.failure_count < MAX_MAP_TEST_FAILURE_COUNT) - var/duration = REALTIMEOFDAY - test.CheckTile(T) - durations[test.type] += REALTIMEOFDAY - duration - - if(test.failure_count >= MAX_MAP_TEST_FAILURE_COUNT) - test.Fail(T, "failure threshold reached at this tile") - - CHECK_TICK - - for(var/datum/map_per_tile_test/test in tests) - if(!test.succeeded) - failed_any_test = TRUE - test_logs[test.type] += test.fail_reasons - - QDEL_LIST_CONTENTS(tests) - +/datum/test_runner/proc/RunAll() + #ifdef MAP_TESTS + // Run map tests first in case unit tests futz with map state + RunMap() + #endif + #ifdef GAME_TESTS + Run() + #endif + SSticker.reboot_helper("Unit Test Reboot", "tests ended", 0) /datum/test_runner/proc/Run() + log_world("Test runner: game tests.") CHECK_TICK for(var/I in subtypesof(/datum/game_test)) @@ -84,10 +64,38 @@ CHECK_TICK - SSticker.reboot_helper("Unit Test Reboot", "tests ended", 0) +/datum/test_runner/proc/RunMap(z_level = 2) + log_world("Test runner: map tests.") + CHECK_TICK + + var/list/tests = list() + + for(var/I in subtypesof(/datum/map_per_tile_test)) + tests += new I + test_logs[I] = list() + durations[I] = 0 + + for(var/turf/T in block(1, 1, z_level, world.maxx, world.maxy, z_level)) + for(var/datum/map_per_tile_test/test in tests) + if(test.failure_count < MAX_MAP_TEST_FAILURE_COUNT) + var/duration = REALTIMEOFDAY + test.CheckTile(T) + durations[test.type] += REALTIMEOFDAY - duration + if(test.failure_count >= MAX_MAP_TEST_FAILURE_COUNT) + test.Fail(T, "failure threshold reached at this tile") + + CHECK_TICK + + for(var/datum/map_per_tile_test/test in tests) + if(!test.succeeded) + failed_any_test = TRUE + test_logs[test.type] += test.fail_reasons + + QDEL_LIST_CONTENTS(tests) /datum/test_runner/proc/Finalize(emit_failures = FALSE) + log_world("Test runner: finalizing.") var/time = world.timeofday set waitfor = FALSE diff --git a/config/example/config.toml b/config/example/config.toml index 014e63b393d5..161868b5fba5 100644 --- a/config/example/config.toml +++ b/config/example/config.toml @@ -41,7 +41,6 @@ ################################################################ - [admin_configuration] # This section contains all information regarding admin setup. This includes ranks, rights, and if you are using the database-backed admin system @@ -73,70 +72,68 @@ enable_localhost_autoadmin = true # +MAINTAINER = Access to super dangerous debug verbs that can break an entire round. Use sparingly. # +DEV_TEAM = Access to dev team chat admin_ranks = [ - # Format: {name = "My Rank", rights = ["+LIST", "+OF", "+RIGHTS"]} - { name = "Mentor", rights = [ - "+MENTOR", - ] }, - { name = "Trial Admin", rights = [ - "+ADMIN", - "+BAN", - "+STEALTH", - "+REJUVINATE", - ] }, - { name = "Game Admin", rights = [ - "+ADMIN", - "+BAN", - "+STEALTH", - "+REJUVINATE", - "+DEBUG", - "+BUILDMODE", - "+EVENT", - "+SERVER", - "+POSSESS", - "+PROCCALL", - "+VAREDIT", - "+SOUND", - "+SPAWN", - ] }, - { name = "Head of Staff", rights = [ - "+EVERYTHING", - ] }, - { name = "Hosting Provider", rights = [ - "+EVERYTHING", - ] }, - { name = "Maintainers", rights = [ - "+EVERYTHING", - ] }, - { name = "Developer", rights = [ - "+DEV_TEAM", - ] }, + # Format: {name = "My Rank", rights = ["+LIST", "+OF", "+RIGHTS"]} + {name = "Mentor", rights = [ + "+MENTOR", + ]}, + {name = "Trial Admin", rights = [ + "+ADMIN", + "+BAN", + "+STEALTH", + "+REJUVINATE", + ]}, + {name = "Game Admin", rights = [ + "+ADMIN", + "+BAN", + "+STEALTH", + "+REJUVINATE", + "+DEBUG", + "+BUILDMODE", + "+EVENT", + "+SERVER", + "+POSSESS", + "+PROCCALL", + "+VAREDIT", + "+SOUND", + "+SPAWN", + ]}, + {name = "Head of Staff", rights = [ + "+EVERYTHING", + ]}, + {name = "Hosting Provider", rights = [ + "+EVERYTHING", + ]}, + {name = "Maintainers", rights = [ + "+EVERYTHING", + ]}, + {name = "Developer", rights = [ + "+DEV_TEAM", + ]}, ] # List of people and the admin rank they are assigned to admin_assignments = [ - #{ckey = "Your Name Here", rank = "Hosting Provider"} + #{ckey = "Your Name Here", rank = "Hosting Provider"} ] # Allow admins to set their own OOC colour allow_admin_ooc_colour = true # Map of admin rank colours to their respective rank. Note you can use hex or colour name here. admin_rank_colour_map = [ - { name = "Head of Staff", colour = "#e74c3c" }, - { name = "Maintainer", colour = "#992d22" }, - { name = "Server Dev", colour = "#1abc9c" }, - { name = "Community Manager", colour = "#e91e63" }, - { name = "Game Admin", colour = "#238afa" }, - { name = "Trial Admin", colour = "#7fb6fc" }, - { name = "Developer", colour = "#61b413" }, - { name = "Mentor", colour = "#f1c40f" }, + {name = "Head of Staff", colour = "#e74c3c"}, + {name = "Maintainer", colour = "#992d22"}, + {name = "Server Dev", colour = "#1abc9c"}, + {name = "Community Manager", colour = "#e91e63"}, + {name = "Game Admin", colour = "#238afa"}, + {name = "Trial Admin", colour = "#7fb6fc"}, + {name = "Developer", colour = "#61b413"}, + {name = "Mentor", colour = "#f1c40f"}, ] # Map of common CIDs that should not be banned, plus their reasons common_cid_map = [ - { cid = "3923664137", reason = "Mass-Match related to Walmart branded prebuilt PCs" }, + {cid = "3923664137", reason = "Mass-Match related to Walmart branded prebuilt PCs"}, ] - ################################################################ - [afk_configuration] # This section contains options for the auto AFK cryo system @@ -149,10 +146,8 @@ afk_auto_despawn_minutes = 21 # Amount of time before SSD people are auto cryo'd ssd_auto_cryo_minutes = 15 - ################################################################ - [custom_sprites_configuration] # This section contains a list of information for people with custom sprites for mobs, if they donated # It is split by mob type, and screens have their own system @@ -168,16 +163,14 @@ ai_hologram = ["ckeyhere"] pai_holoform = ["ckeyhere"] # List of dictionary entries for ckeys with a custom IPC screean ipc_screens = [ - { ckey = "ckeyhere", screens = [ - "Icon State 1", - "Icon State 2", - ] }, + {ckey = "ckeyhere", screens = [ + "Icon State 1", + "Icon State 2", + ]}, ] - ################################################################ - [database_configuration] # This section contains all the settings for the ingame database # If you are running in production, you will want to be using a database @@ -185,7 +178,7 @@ ipc_screens = [ # Enable/disable the database on a whole sql_enabled = false # SQL version. If this is a mismatch, round start will be delayed -sql_version = 632207 +sql_version = 642207 # SQL server address. Can be an IP or DNS name sql_address = "127.0.0.1" # SQL server port @@ -201,10 +194,8 @@ async_query_timeout = 10 # How many threads is the async SQL engine allowed to open. 50 is normal. Trust me. async_thread_limit = 50 - ################################################################ - [discord_configuration] # This section contains all the information related to Discord webhook sending from the code # If you are using webhooks, please fill out this section in full @@ -214,8 +205,8 @@ enable_discord_webhooks = false main_webhook_urls = ["https://webhook.one", "https://webhook.two"] # List of all webhook URLs for the mentor feed (mentorhelps relay) mentor_webhook_urls = [ - "https://mentor.webhook.one", - "https://mentor.webhook.two", + "https://mentor.webhook.one", + "https://mentor.webhook.two", ] # List of all webhook URLs for the admin feed (round alerts, ahelps, etc) admin_webhook_urls = ["https://admin.webhook.one", "https://admin.webhook.two"] @@ -233,31 +224,28 @@ new_round_waiting_role_id = "" ################################################################ - [event_configuration] # This section contains settings for ingame random events # Disable this to disable all random events allow_random_events = true # Map of lower bounds for event delays. In minutes. -event_delay_lower_bounds = { mundane = 10, moderate = 30, major = 50 } +event_delay_lower_bounds = {mundane = 10, moderate = 30, major = 50} # Map of upper bounds for event delays. In minutes. -event_delay_upper_bounds = { mundane = 15, moderate = 45, major = 70 } +event_delay_upper_bounds = {mundane = 15, moderate = 45, major = 70} # Expected round length in minutes. Changes event weights expected_round_length = 120 # Initial delays for the first events firing off. If any of these are commented, a random value based on above thresholds is used. # You must specify an upper and lower bound, or the code cries a lot. The events system is so bad good god. # Values are in minutes event_initial_delays = [ - #{severity = "mundane", lower_bound = 10, upper_bound = 15}, - { severity = "moderate", lower_bound = 25, upper_bound = 40 }, - { severity = "major", lower_bound = 55, upper_bound = 75 }, + #{severity = "mundane", lower_bound = 10, upper_bound = 15}, + {severity = "moderate", lower_bound = 25, upper_bound = 40}, + {severity = "major", lower_bound = 55, upper_bound = 75}, ] - ################################################################ - [gamemode_configuration] # This section contains setups for the gamemodes, as well as their probabilities @@ -267,7 +255,7 @@ antag_account_age_restrictions = false gamemode_probabilities = [ { gamemode = "abduction", probability = 0 }, { gamemode = "changeling", probability = 0 }, - { gamemode = "cult", probability = 3 }, + { gamemode = "cult", probability = 0 }, { gamemode = "extend-a-traitormongous", probability = 2 }, # Autotraitor { gamemode = "extended", probability = 0 }, { gamemode = "nuclear", probability = 2 }, @@ -296,10 +284,8 @@ enable_gamemode_player_limit = true # Enable to generate zero or more random station traits on game start. add_random_station_traits = false - ################################################################ - [general_configuration] # General setup for the server (branding, options, etc) @@ -391,10 +377,8 @@ random_ai_lawset = true # Enable weather events initialized by SSweather. New weather events can still be added during the round if this is disabled. enable_default_weather_events = true - ################################################################ - [lighting_effects_configuration] # Settings that allow you to change light effects (bloom / exposure intensity) @@ -415,10 +399,8 @@ exposure_contrast_base = 9.5 # Contrast of exposure effect that depends on light_power exposure_contrast_power = 0 - ################################################################ - [ipintel_configuration] # This section contains all the information for IPIntel (The Anti VPN system) @@ -441,10 +423,8 @@ playtime_ignore_threshold = 10 # Details URL for more info on an IP (such as ASN). IP is tacked on the end. details_url = "https://iphub.info/?ip=" - ################################################################ - [job_configuration] # This section contains information on job configuartion, as well as the jon amounts @@ -473,55 +453,45 @@ assistant_security_ratio = 2 enable_job_amount_overrides = true # Job slot amount map. These are overrides. If you dont specify a value here, the code will be used as default. -1 is infinite job_slot_amounts = [ - # Commmand - { name = "Captain", lowpop = 1, highpop = 1 }, - { name = "Head of Personnel", lowpop = 1, highpop = 1 }, - { name = "Head of Security", lowpop = 1, highpop = 1 }, - { name = "Chief Engineer", lowpop = 1, highpop = 1 }, - { name = "Research Director", lowpop = 1, highpop = 1 }, - { name = "Chief Medical Officer", lowpop = 1, highpop = 1 }, - # Engineering - { name = "Life Support Specialist", lowpop = 3, highpop = 4 }, - { name = "Station Engineer", lowpop = 5, highpop = 6 }, - { name = "Trainee Engineer", lowpop = 0, highpop = 0 }, - # Medical - { name = "Chemist", lowpop = 2, highpop = 2 }, - { name = "Geneticist", lowpop = 2, highpop = 2 }, - { name = "Medical Doctor", lowpop = 5, highpop = 6 }, - { name = "Medical Intern", lowpop = 0, highpop = 0 }, - { name = "Virologist", lowpop = 1, highpop = 1 }, - # Science - { name = "Roboticist", lowpop = 2, highpop = 2 }, - { name = "Scientist", lowpop = 6, highpop = 7 }, - { name = "Student Scientist", lowpop = 0, highpop = 0 }, - # Security - { name = "Detective", lowpop = 1, highpop = 1 }, - { name = "Security Officer", lowpop = 8, highpop = 9 }, - { name = "Security Cadet", lowpop = 0, highpop = 0 }, - { name = "Warden", lowpop = 1, highpop = 1 }, - { name = "Internal Affairs Agent", lowpop = 2, highpop = 2 }, - # Service - { name = "Bartender", lowpop = 1, highpop = 1 }, - { name = "Botanist", lowpop = 2, highpop = 2 }, - { name = "Chaplain", lowpop = 1, highpop = 1 }, - { name = "Chef", lowpop = 1, highpop = 1 }, - { name = "Janitor", lowpop = 1, highpop = 2 }, - { name = "Librarian", lowpop = 1, highpop = 1 }, - # Cargo/Supply - { name = "Quartermaster", lowpop = 1, highpop = 1 }, - { name = "Shaft Miner", lowpop = 6, highpop = 6 }, - { name = "Cargo Technician", lowpop = 3, highpop = 4 }, - # Silicon - { name = "AI", lowpop = 1, highpop = 1 }, - { name = "Cyborg", lowpop = 1, highpop = 1 }, - # Misc - { name = "Assistant", lowpop = -1, highpop = -1 }, + # Commmand + {name = "Captain", lowpop = 1, highpop = 1}, + {name = "Head of Personnel", lowpop = 1, highpop = 1}, + {name = "Head of Security", lowpop = 1, highpop = 1}, + {name = "Chief Engineer", lowpop = 1, highpop = 1}, + {name = "Research Director", lowpop = 1, highpop = 1}, + {name = "Chief Medical Officer", lowpop = 1, highpop = 1}, # Engineering + {name = "Life Support Specialist", lowpop = 3, highpop = 4}, + {name = "Station Engineer", lowpop = 5, highpop = 6}, + {name = "Trainee Engineer", lowpop = 0, highpop = 0}, # Medical + {name = "Chemist", lowpop = 2, highpop = 2}, + {name = "Geneticist", lowpop = 2, highpop = 2}, + {name = "Medical Doctor", lowpop = 5, highpop = 6}, + {name = "Medical Intern", lowpop = 0, highpop = 0}, + {name = "Virologist", lowpop = 1, highpop = 1}, # Science + {name = "Roboticist", lowpop = 2, highpop = 2}, + {name = "Scientist", lowpop = 6, highpop = 7}, + {name = "Student Scientist", lowpop = 0, highpop = 0}, # Security + {name = "Detective", lowpop = 1, highpop = 1}, + {name = "Security Officer", lowpop = 8, highpop = 9}, + {name = "Security Cadet", lowpop = 0, highpop = 0}, + {name = "Warden", lowpop = 1, highpop = 1}, + {name = "Internal Affairs Agent", lowpop = 2, highpop = 2}, # Service + {name = "Bartender", lowpop = 1, highpop = 1}, + {name = "Botanist", lowpop = 2, highpop = 2}, + {name = "Chaplain", lowpop = 1, highpop = 1}, + {name = "Chef", lowpop = 1, highpop = 1}, + {name = "Janitor", lowpop = 1, highpop = 2}, + {name = "Librarian", lowpop = 1, highpop = 1}, # Cargo/Supply + {name = "Quartermaster", lowpop = 1, highpop = 1}, + {name = "Shaft Miner", lowpop = 6, highpop = 6}, + {name = "Cargo Technician", lowpop = 3, highpop = 4}, # Silicon + {name = "AI", lowpop = 1, highpop = 1}, + {name = "Cyborg", lowpop = 1, highpop = 1}, # Misc + {name = "Assistant", lowpop = -1, highpop = -1}, ] - ################################################################ - [logging_configuration] # Configuration for all things related to logging data to disk # If you are in production you will want most of these on @@ -559,10 +529,8 @@ enable_adminchat_logging = true # Log debug messages enable_debug_logging = true - ################################################################ - [metrics_configuration] # This section contains values for all metrics storing. # This is designed for ElasticSearch but you might be able to make it work with other things. @@ -575,10 +543,8 @@ metrics_endpoint = "http://elastic-host:9200/your_index/_doc" # Metrics API token. Placed into the auth header metrics_api_token = "your_base64_encoded_thingy==" - ################################################################ - [mc_configuration] # This section is settings for the MC # Dont change these unless you know what you are doing @@ -596,10 +562,8 @@ mc_highpop_threshold_enable = 65 # Threshold to disable MC highpop mode mc_highpop_threshold_disable = 60 - ################################################################ - [movement_configuration] # This section contains values for all mob movement stuff. # We suggest VVing ingame till you get values you like. @@ -622,10 +586,8 @@ slime_delay = 1.5 # Move delay for other simple animals animal_delay = 2.5 - ################################################################ - [overflow_configuration] # This contains information for re-routing players to an overflow server # We dont use this in production, but you may find it useful @@ -644,7 +606,6 @@ reservation_time = 10 ################################################################ - [redis_configuration] # This section contains all the settings for using redis. # This is heavily tied into the Paradise production architecture and you probably dont need it. @@ -654,10 +615,8 @@ redis_enabled = false # Redis connection string. Include your passphrase if needed redis_connstring = "redis://127.0.0.1/" - ################################################################ - [ruin_configuration] # This section contains configuration for all space ruins and lava ruins @@ -680,130 +639,110 @@ lavaland_ruin_budget_max = 325 # List of all space ruins that can generate in the world # Commenting something out in here DISABLES IT FROM SPAWNING active_space_ruins = [ - "_maps/map_files/RandomRuins/SpaceRuins/way_home.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/asteroid1.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/asteroid2.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/asteroid3.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/asteroid4.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/asteroid5.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/derelict1.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/derelict2.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/derelict3.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/derelict4.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/derelict5.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/spacebar.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/emptyshell.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/intactemptyship.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/meatpackers.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/turretedoutpost.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/debris1.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/debris2.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/debris3.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/moonoutpost19.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/syndiecakesfactory.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/wizardcrash.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/voyager.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/wreckedcargoship.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/abandoned_engi_sat.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/casino.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/rocky_motel.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/abandoned_sec_shuttle.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/freighter.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/unathi_skiff.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/clockwork_monastery.dmm", - ## SS220 Ruins - "_maps/map_files220/RandomRuins/SpaceRuins/mechtransport_new.dmm", - "_maps/map_files220/RandomRuins/SpaceRuins/destroyed_infiltrator.dmm", - "_maps/map_files220/RandomRuins/SpaceRuins/transit_bar.dmm", - "_maps/map_files220/RandomRuins/SpaceRuins/infected_ship.dmm", - "_maps/map_files220/RandomRuins/SpaceRuins/convoy_ambush.dmm", - "_maps/map_files220/RandomRuins/SpaceRuins/voxraiders_1.dmm", - "_maps/map_files220/RandomRuins/SpaceRuins/spacehotel.dmm", - "_maps/map_files220/RandomRuins/SpaceRuins/sierra_1_4.dmm", - - ### The following ruins are based from past pre-spawned Zlevel content ### - "_maps/map_files/RandomRuins/SpaceRuins/abandonedtele.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/blowntcommsat.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/clownmime.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/dj.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/syndicatedruglab.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/syndie_space_base.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/ussp_tele.dmm", - "_maps/map_files/RandomRuins/SpaceRuins/ussp.dmm", - - - # The following is the white ship ruin. Its force-spawned and is required to stop SSshuttle runtiming on startup - # Its also important incase a white-ship console is ever built midround - # DO NOT DISABLE THIS UNLESS YOU HAVE A GOOD REASON - "_maps/map_files220/RandomRuins/SpaceRuins/whiteship.dmm", - - # The following is a force-spawned ruin consisting mostly of empty space with a shuttle docking port for the free golem shuttle - # Disabling it will lead to the free golem shuttle sometimes being stuck on lavaland. - "_maps/map_files/RandomRuins/SpaceRuins/golemtarget.dmm", -] # List of all space ruins that can generate in the world -# Commenting something out in here DISABLES IT FROM SPAWNING + "_maps/map_files/RandomRuins/SpaceRuins/way_home.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/asteroid1.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/asteroid2.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/asteroid3.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/asteroid4.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/asteroid5.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/derelict1.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/derelict2.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/derelict3.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/derelict4.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/derelict5.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/spacebar.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/emptyshell.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/intactemptyship.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/meatpackers.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/turretedoutpost.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/debris1.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/debris2.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/debris3.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/moonoutpost19.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/syndiecakesfactory.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/wizardcrash.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/voyager.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/wreckedcargoship.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/abandoned_engi_sat.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/casino.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/rocky_motel.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/abandoned_sec_shuttle.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/freighter.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/unathi_skiff.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/clockwork_monastery.dmm", ### The following ruins are based from past pre-spawned Zlevel content ### + ## SS220 Ruins + "_maps/map_files220/RandomRuins/SpaceRuins/mechtransport_new.dmm", + "_maps/map_files220/RandomRuins/SpaceRuins/destroyed_infiltrator.dmm", + "_maps/map_files220/RandomRuins/SpaceRuins/transit_bar.dmm", + "_maps/map_files220/RandomRuins/SpaceRuins/infected_ship.dmm", + "_maps/map_files220/RandomRuins/SpaceRuins/convoy_ambush.dmm", + "_maps/map_files220/RandomRuins/SpaceRuins/voxraiders_1.dmm", + "_maps/map_files220/RandomRuins/SpaceRuins/spacehotel.dmm", + "_maps/map_files220/RandomRuins/SpaceRuins/sierra_1_4.dmm", + + "_maps/map_files/RandomRuins/SpaceRuins/abandonedtele.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/blowntcommsat.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/clownmime.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/dj.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/syndicatedruglab.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/syndie_space_base.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/ussp_tele.dmm", + "_maps/map_files/RandomRuins/SpaceRuins/ussp.dmm", # The following is the white ship ruin. Its force-spawned and is required to stop SSshuttle runtiming on startup # Its also important incase a white-ship console is ever built midround # DO NOT DISABLE THIS UNLESS YOU HAVE A GOOD REASON + "_maps/map_files220/RandomRuins/SpaceRuins/whiteship.dmm", # The following is a force-spawned ruin consisting mostly of empty space with a shuttle docking port for the free golem shuttle + # Disabling it will lead to the free golem shuttle sometimes being stuck on lavaland. + "_maps/map_files/RandomRuins/SpaceRuins/golemtarget.dmm", +] # List of all ruins that can generate on lavaland # Commenting something out in here DISABLES IT FROM SPAWNING active_lava_ruins = [ - ##BIODOMES - "_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_winter.dmm", - ##RESPAWN - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_hermit.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm", - ##SIN - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_envy.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_gluttony.dmm", - # Greed blacklisted on production because its reward (dice) has a 1/20 chance of making you a wizard - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_greed.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_pride.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_sloth.dmm", - ##MEGAFAUNA - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_blooddrunk1.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_blooddrunk2.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_blooddrunk3.dmm", - # Re-removed 7/24/2020, I ran a month-long test of hierophant Jun-Jul and the staff was still too strong. https://github.com/ParadiseSS13/Paradise/pull/13542 - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_hierophant.dmm", - - ##MISC - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_althland_excavation.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_althland_facility.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_cultaltar.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_dead_ratvar.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_elite_tumor.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_fountain_hall.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_monster_nest.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_pizzaparty.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_puzzle.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_random_ripley.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_shuttlecrash.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_survivalpod.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_ufo_crash.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_watcher_grave.dmm", - "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_xeno_nest.dmm", - "_maps/map_files220/RandomRuins/LavaRuins/scp_facility.dmm", - "_maps/map_files220/RandomRuins/LavaRuins/cheesus_temple.dmm", - "_maps/map_files220/RandomRuins/LavaRuins/ash_old.dmm", - "_maps/map_files220/RandomRuins/LavaRuins/old_outpost.dmm", + ##BIODOMES + "_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_winter.dmm", ##RESPAWN + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_hermit.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm", ##SIN + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_envy.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_gluttony.dmm", # Greed blacklisted on production because its reward (dice) has a 1/20 chance of making you a wizard + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_greed.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_pride.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_sloth.dmm", ##MEGAFAUNA + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_blooddrunk1.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_blooddrunk2.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_blooddrunk3.dmm", # Re-removed 7/24/2020, I ran a month-long test of hierophant Jun-Jul and the staff was still too strong. https://github.com/ParadiseSS13/Paradise/pull/13542 + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_hierophant.dmm", ##MISC + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_althland_excavation.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_althland_facility.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_cultaltar.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_dead_ratvar.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_elite_tumor.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_fountain_hall.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_monster_nest.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_pizzaparty.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_puzzle.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_random_ripley.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_shuttlecrash.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_survivalpod.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_ufo_crash.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_watcher_grave.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_xeno_nest.dmm", + "_maps/map_files220/RandomRuins/LavaRuins/scp_facility.dmm", + "_maps/map_files220/RandomRuins/LavaRuins/cheesus_temple.dmm", + "_maps/map_files220/RandomRuins/LavaRuins/ash_old.dmm", + "_maps/map_files220/RandomRuins/LavaRuins/old_outpost.dmm", ] -# Budget for lavaland ruins. A higher number means more will spawn -lavaland_ruin_budget = 100 - ################################################################ - [system_configuration] # This contains stuff that the host should fill out, relating to backend stuff @@ -840,15 +779,13 @@ external_tos_handler = false # This is not for separate DD instances per region, but if you have a geo-routing setup deployed to optimise routing for players # I am 99.9% certain you will never need to fill this out regional_servers = [ - #{name = "UK", ip = "byond://uk.paradisestation.org:6666"}, + #{name = "UK", ip = "byond://uk.paradisestation.org:6666"}, ] # Send a toast on server init completion. You probably dont need this on in production toast_on_init_complete = true - ################################################################ - [url_configuration] # Configuration for all the URLs used by the server # If you are in production you will want to tweak these to your servers @@ -888,10 +825,8 @@ centcomm_ban_db_url = "https://centcom.melonmesa.com/ban/search/" # URL for the game stats page, if applicable. Round ID is appended right on the end. Include a trailing slash if necessary. #round_stats_url = "https://affectedarc07.github.io/ParaStats/#/round/" - ################################################################ - [voting_configuration] # This section contains all settings relating to the ingame voting system @@ -919,19 +854,17 @@ non_repeating_maps = true # - "FPTP" = A vote that excludes the map from the current round, and last round, then uses a weighted pick on the remaining maps, from preferences. # If you dont enter one correctly, it will whine on startup map_vote_day_types = [ - { day_number = 1, rotation_type = "Vote" }, # Monday - { day_number = 2, rotation_type = "Random" }, # Tuesday - { day_number = 3, rotation_type = "FPTP" }, # Wednesday - { day_number = 4, rotation_type = "Random" }, # Thursday - { day_number = 5, rotation_type = "Vote" }, # Friday - { day_number = 6, rotation_type = "FPTP" }, # Saturday - { day_number = 7, rotation_type = "FPTP" }, # Sunday + {day_number = 1, rotation_type = "Vote"}, # Monday + {day_number = 2, rotation_type = "Random"}, # Tuesday + {day_number = 3, rotation_type = "FPTP"}, # Wednesday + {day_number = 4, rotation_type = "Random"}, # Thursday + {day_number = 5, rotation_type = "Vote"}, # Friday + {day_number = 6, rotation_type = "FPTP"}, # Saturday + {day_number = 7, rotation_type = "FPTP"}, # Sunday ] - ################################################################ - [asset_cache_configuration] # Browser assets are any file included in interfaces. css, images, javascript, etc. # This handles configuring how we get these to the player so interfaces can access them. @@ -950,7 +883,6 @@ asset_simple_preload = true # if you want to test this locally, you simpily run the `localhost-asset-webroot-server.py` python3 script to host assets stored in `data/asset-store/` via http://localhost:58715/ # asset_cdn_url = "http://localhost:58715/" - # Congratulations. You reached the end. heres a cookie. # And some SS220 configs ratge. diff --git a/config/tests/config_unit_tests.toml b/config/tests/config_unit_tests.toml new file mode 100644 index 000000000000..dee4ef090fc4 --- /dev/null +++ b/config/tests/config_unit_tests.toml @@ -0,0 +1,11 @@ +[ruin_configuration] +enable_lavaland = false +enable_space_ruins = false +minimum_zlevels = 0 +maximum_zlevels = 0 + +[redis_configuration] +enabled = false + +[database_configuration] +enabled = true diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md index af8bc67a6938..d2cd183798c8 100644 --- a/docs/CODE_OF_CONDUCT.md +++ b/docs/CODE_OF_CONDUCT.md @@ -58,11 +58,6 @@ made by people actually in-touch with the server atmosphere. ### PR Expectations -Contributors may only have a maximum of **2** feature or balance Pull Requests -open at any given time. Any additional Pull Requests beyond this limit will be -closed at the discretion of the Headcoders. The Headcoders may grant an -exemption to this limit on a case-by-case basis, as the need arises. - All Pull Requests are expected to be tested prior to submission. If a submitted Pull Request fails to pass CI checks, the likelihood of it being merged will be significantly lower. If you can't take the time to compile/test your Pull diff --git a/docs/references/autodoc.md b/docs/references/autodoc.md index bb1278becf86..3eff9a7501fe 100644 --- a/docs/references/autodoc.md +++ b/docs/references/autodoc.md @@ -17,33 +17,33 @@ reference. [dmdoc]: https://github.com/SpaceManiac/SpacemanDMM/tree/master/crates/dmdoc ## Documenting Code On Paradise -We use block comments to document procs and classes, and we use `///` line +We use block comments to document procs and types, and we use `///` line comments when documenting individual variables. Documentation is not required at Paradise, but it is highly recommended that all new code be covered with DMdoc code, according to the [Specifications](#specification). -We also recommend that when you touch older code, you document the functions that you +We also recommend that when you touch older code, you document the procs that you have touched in the process of updating that code ### Specification -A class *should* always be auto-documented, and all public functions *should* be +A type *should* always be auto-documented, and all public procs *should* be documented. -All class level defined variables *should* be documented. +All type level defined variables *should* be documented. -Internal functions *can* be documented, but may not be. +Internal procs *can* be documented, but may not be. -A public function is any function that a developer might reasonably call while using -or interacting with your object. Internal functions are helper functions that your -public functions rely on to implement logic. +A public proc is any function that a developer might reasonably call while using +or interacting with your object. Internal procs are helper functions that your +public procs rely on to implement logic. ### Documenting a proc When documenting a proc, we give a short one line description (as this is shown next to the proc definition in the list of all procs for a type or global namespace), then a longer paragraph which will be shown when the user clicks on -the proc to jump to it's definition +the proc to jump to its definition ```dm /** @@ -57,36 +57,36 @@ the proc to jump to it's definition */ ``` -### Documenting Classes -We first give the name of the class as a header, this can be omitted if the name -is just going to be the typepath of the class, as dmdoc uses that by default. -Then we give a short one-line description of the class. Finally we give a longer -multi paragraph description of the class and it's details. +### Documenting types +We first give the name of the type as a header, this can be omitted if the name +is just going to be the typepath of the type, as dmdoc uses that by default. +Then we give a short one-line description of the type. Finally we give a longer +multi paragraph description of the type and its details. ```dm /** - * # Classname (Can be omitted if it's just going to be the typepath) + * # type name (Can be omitted if it's just going to be the typepath) * * The short overview * * A longer - * paragraph of functionality about the class + * paragraph of functionality about the type * including any assumptions/special cases * */ ``` ### Documenting a variable/define -Give a short explanation of what the variable, in the context of the class, or define is. +Give a short explanation of what the variable, in the context of the type, or define is. ```dm -/// Type path of item to go in suit slot +/// Typepath of item to go in suit slot var/suit = null ``` ## Module level description of code Modules are the best way to describe the structure/intent of a package of code -where you don't want to be tied to the formal layout of the class structure. +where you don't want to be tied to the formal layout of the type structure. On Paradise we do this by adding markdown files inside the `code` directory that will also be rendered and added to the modules tree. The structure for @@ -98,10 +98,10 @@ You can use certain special template variables in DM DOC comments and they will be expanded. - `[DEFINE_NAME]` expands to a link to the define definition if documented. -- `[/mob]` expands to a link to the docs for the /mob class. -- `[/mob/proc/Dizzy]` expands to a link that will take you to the /mob class and +- `[/mob]` expands to a link to the docs for the /mob type. +- `[/mob/proc/Dizzy]` expands to a link that will take you to the /mob type and anchor you to the dizzy proc docs. -- `[/mob/var/stat]` expands to a link that will take you to the /mob class and +- `[/mob/var/stat]` expands to a link that will take you to the /mob type and anchor you to the stat var docs You can customise the link name by using `[link name][link shorthand]`. diff --git a/icons/_nanomaps/DeltaStation_nanomap_z1.png b/icons/_nanomaps/DeltaStation_nanomap_z1.png index 30e35087458b..2f0f2991c768 100644 Binary files a/icons/_nanomaps/DeltaStation_nanomap_z1.png and b/icons/_nanomaps/DeltaStation_nanomap_z1.png differ diff --git a/icons/mecha/mecha_equipment.dmi b/icons/mecha/mecha_equipment.dmi index f26012f32596..3771518bb5e5 100644 Binary files a/icons/mecha/mecha_equipment.dmi and b/icons/mecha/mecha_equipment.dmi differ diff --git a/icons/mob/accessories.dmi b/icons/mob/accessories.dmi index 40f038739aee..87a9713317e5 100644 Binary files a/icons/mob/accessories.dmi and b/icons/mob/accessories.dmi differ diff --git a/icons/mob/clothing/belt.dmi b/icons/mob/clothing/belt.dmi index 0e34c8a1d89a..e81e06ad10a5 100644 Binary files a/icons/mob/clothing/belt.dmi and b/icons/mob/clothing/belt.dmi differ diff --git a/icons/obj/abductor.dmi b/icons/obj/abductor.dmi index 0dda8c42a910..2752a947e897 100644 Binary files a/icons/obj/abductor.dmi and b/icons/obj/abductor.dmi differ diff --git a/icons/obj/clothing/accessories.dmi b/icons/obj/clothing/accessories.dmi index ac7094fea86e..6aba3c61e03a 100644 Binary files a/icons/obj/clothing/accessories.dmi and b/icons/obj/clothing/accessories.dmi differ diff --git a/icons/obj/clothing/accessories_overlay.dmi b/icons/obj/clothing/accessories_overlay.dmi index f667b8dc04e9..62a4c3baaa53 100644 Binary files a/icons/obj/clothing/accessories_overlay.dmi and b/icons/obj/clothing/accessories_overlay.dmi differ diff --git a/icons/obj/clothing/belts.dmi b/icons/obj/clothing/belts.dmi index 336c85dedd7a..d0cbf2deb20f 100644 Binary files a/icons/obj/clothing/belts.dmi and b/icons/obj/clothing/belts.dmi differ diff --git a/icons/turf/areas.dmi b/icons/turf/areas.dmi index d27c76b49de6..69aca13c76e9 100755 Binary files a/icons/turf/areas.dmi and b/icons/turf/areas.dmi differ diff --git a/icons/turf/walls.dmi b/icons/turf/walls.dmi index d8d4d8fdd790..fb71d66c556c 100644 Binary files a/icons/turf/walls.dmi and b/icons/turf/walls.dmi differ diff --git a/modular_ss220/camera_nanomap/code/camera.dm b/modular_ss220/camera_nanomap/code/camera.dm index bb903e6d06d6..d657c88f306e 100644 --- a/modular_ss220/camera_nanomap/code/camera.dm +++ b/modular_ss220/camera_nanomap/code/camera.dm @@ -3,10 +3,12 @@ /obj/machinery/camera/Initialize(mapload, should_add_to_cameranet) . = ..() +#if !defined(MAP_TESTS) && !defined(GAME_TESTS) if(z == level_name_to_num(MAIN_STATION)) nanomap_png = "[SSmapping.map_datum.technical_name]_nanomap_z1.png" else if(z == level_name_to_num(MINING)) nanomap_png = "[MINING]_nanomap_z1.png" +#endif /obj/machinery/computer/security var/list/z_levels = list() // Assoc list, "z_level":"nanomap.png" diff --git a/paradise.dme b/paradise.dme index fbcdb95bfce4..007fd9c82c7e 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1696,6 +1696,7 @@ #include "code\modules\atmospherics\machinery\portable\portable_atmospherics.dm" #include "code\modules\atmospherics\machinery\portable\portable_pump.dm" #include "code\modules\atmospherics\machinery\portable\scrubber.dm" +#include "code\modules\awaymissions\cordon.dm" #include "code\modules\awaymissions\mob_spawn.dm" #include "code\modules\awaymissions\zlevel_helpers.dm" #include "code\modules\awaymissions\maploader\dmm_suite.dm" @@ -2878,12 +2879,12 @@ #include "code\modules\shuttle\shuttle_rotate.dm" #include "code\modules\shuttle\supply.dm" #include "code\modules\shuttle\syndicate_shuttles.dm" -#include "code\modules\space_management\heap_space_level.dm" #include "code\modules\space_management\level_check.dm" #include "code\modules\space_management\level_traits.dm" #include "code\modules\space_management\space_chunk.dm" #include "code\modules\space_management\space_level.dm" #include "code\modules\space_management\space_transition.dm" +#include "code\modules\space_management\turf_reservation.dm" #include "code\modules\space_management\zlevel_manager.dm" #include "code\modules\station_goals\bluespace_tap.dm" #include "code\modules\station_goals\bluespace_tap_events.dm" diff --git a/rust/src/milla/api.rs b/rust/src/milla/api.rs index 8239cfc1d955..a92b648732eb 100644 --- a/rust/src/milla/api.rs +++ b/rust/src/milla/api.rs @@ -703,6 +703,27 @@ fn milla_get_tick_time() -> eyre::Result { )) } +/// BYOND API for freezing a specific z-level. +#[byondapi::bind] +fn milla_set_zlevel_frozen( + byond_z: ByondValue, + byond_frozen: ByondValue, +) -> eyre::Result { + let z = f32::try_from(byond_z)? as i32 - 1; + let frozen = bool::try_from(byond_frozen)?; + let buffers = BUFFERS.get().ok_or(eyre!("BUFFERS not initialized."))?; + let active = buffers.get_active().read().unwrap(); + let maybe_z_level = active.0[z as usize].try_write(); + if maybe_z_level.is_err() { + return Err(eyre!( + "Tried to freeze or unfreeze during asynchronous, read-only atmos. Use a /datum/milla_safe/..." + )); + } + let mut z_level = maybe_z_level.unwrap(); + z_level.frozen = frozen; + Ok(ByondValue::null()) +} + // Yay, tests! #[cfg(test)] mod tests { diff --git a/rust/src/milla/constants.rs b/rust/src/milla/constants.rs index d0f4d8b9160e..057af66f7fab 100644 --- a/rust/src/milla/constants.rs +++ b/rust/src/milla/constants.rs @@ -1,6 +1,5 @@ /// How many Z levels we allow before being suspicious that the wrong number was sent. -pub(crate) const MAX_Z_LEVELS: i32 = 14; - +pub(crate) const MAX_Z_LEVELS: i32 = 19; // SS220 EDIT - upstream value +4 /// How big is the map? Assumed square. pub(crate) const MAP_SIZE: usize = 255; @@ -120,7 +119,7 @@ pub(crate) const PLASMA_BURN_MIN_TEMP: f32 = 100.0 + T0C; pub(crate) const PLASMA_BURN_OPTIMAL_TEMP: f32 = 1370.0 + T0C; /// How much of the plasma are we willing to burn each tick? -pub(crate) const PLASMA_BURN_MAX_RATIO: f32 = 0.05; +pub(crate) const PLASMA_BURN_MAX_RATIO: f32 = 0.01; /// How much of the plasma do we burn anyway if the ratio would make it really small? pub(crate) const PLASMA_BURN_MIN_MOLES: f32 = 0.001; @@ -148,10 +147,10 @@ pub(crate) const TEST_TOLERANCE: f32 = 0.1; pub(crate) const SPACE_COOLING_THRESHOLD: f32 = T20C; /// Lose this amount of heat energy per tick if above SPACE_COOLING_THRESHOLD. -pub(crate) const SPACE_COOLING_FLAT: f32 = 2000.0; +pub(crate) const SPACE_COOLING_FLAT: f32 = 200.0; -/// Lose this ratio of heat energy per tick if above SPACE_COOLING_THRESHOLD. -pub(crate) const SPACE_COOLING_RATIO: f32 = 0.002; +/// Lose this ratio of heat energy per Kelvin per tick if above SPACE_COOLING_THRESHOLD. +pub(crate) const SPACE_COOLING_TEMPERATURE_RATIO: f32 = 0.4; /// Tiles with less than this much gas will become empty. pub(crate) const MINIMUM_NONZERO_MOLES: f32 = 0.1; diff --git a/rust/src/milla/model.rs b/rust/src/milla/model.rs index 4b7ac10036eb..838bb090cce2 100644 --- a/rust/src/milla/model.rs +++ b/rust/src/milla/model.rs @@ -401,6 +401,7 @@ impl From<&InterestingTile> for Vec { pub(crate) struct ZLevel { tiles: Box<[Tile; MAP_SIZE * MAP_SIZE]>, pub(crate) active_pressure_chunks: HashSet<(u8, u8)>, + pub(crate) frozen: bool, } impl ZLevel { @@ -412,6 +413,7 @@ impl ZLevel { ZLevel { tiles: unbuilt.into_boxed_slice().try_into().unwrap(), active_pressure_chunks: HashSet::new(), + frozen: false, } } @@ -455,6 +457,7 @@ impl ZLevel { self.tiles[i].copy_from(&other.tiles[i]); } self.active_pressure_chunks = other.active_pressure_chunks.clone(); + self.frozen = other.frozen; } } diff --git a/rust/src/milla/simulate.rs b/rust/src/milla/simulate.rs index befff52558eb..2cdc5ab964d1 100644 --- a/rust/src/milla/simulate.rs +++ b/rust/src/milla/simulate.rs @@ -681,7 +681,7 @@ pub(crate) fn apply_tile_mode( if my_next_tile.temperature() > SPACE_COOLING_THRESHOLD { let excess_thermal_energy = my_next_tile.thermal_energy - SPACE_COOLING_THRESHOLD * my_next_tile.heat_capacity(); - let cooling = (SPACE_COOLING_FLAT + SPACE_COOLING_RATIO * excess_thermal_energy) + let cooling = (SPACE_COOLING_FLAT + SPACE_COOLING_TEMPERATURE_RATIO * my_next_tile.temperature()) .min(excess_thermal_energy); my_next_tile.thermal_energy -= cooling; } diff --git a/rust/src/milla/tick.rs b/rust/src/milla/tick.rs index ee197e5788fb..ca0f126beae6 100644 --- a/rust/src/milla/tick.rs +++ b/rust/src/milla/tick.rs @@ -95,12 +95,14 @@ pub(crate) fn tick_z_level( // Initialize the new frame as a copy of the old one. next.copy_from(&prev); - simulate::find_walls(&mut next); - simulate::update_wind(&prev, &mut next); - simulate::flow_air(&prev, &mut next)?; - simulate::post_process(&prev, &mut next, &environments, new_interesting_tiles, z)?; + if !prev.frozen { + simulate::find_walls(&mut next); + simulate::update_wind(&prev, &mut next); + simulate::flow_air(&prev, &mut next)?; + simulate::post_process(&prev, &mut next, &environments, new_interesting_tiles, z)?; - next.active_pressure_chunks.clear(); + next.active_pressure_chunks.clear(); + } Ok(()) } diff --git a/rustlibs.dll b/rustlibs.dll index fd0fde8a12b5..3f6c5876c8d5 100644 Binary files a/rustlibs.dll and b/rustlibs.dll differ diff --git a/rustlibs_prod.dll b/rustlibs_prod.dll index e91053a07f08..f24ea8c3c993 100644 Binary files a/rustlibs_prod.dll and b/rustlibs_prod.dll differ diff --git a/tgui/packages/tgui/interfaces/Autolathe.js b/tgui/packages/tgui/interfaces/Autolathe.js index 89950bbc6217..5e60f91c1ca6 100644 --- a/tgui/packages/tgui/interfaces/Autolathe.js +++ b/tgui/packages/tgui/interfaces/Autolathe.js @@ -123,7 +123,7 @@ export const Autolathe = (props, context) => { }) } > - {toTitleCase(recipe.name)} + {recipe.name} {recipe.max_multiplier >= 10 && (