diff --git a/_maps/map_files/cerestation/cerestation.dmm b/_maps/map_files/cerestation/cerestation.dmm index 968ecdaa3c0c..bf3158e750dc 100644 --- a/_maps/map_files/cerestation/cerestation.dmm +++ b/_maps/map_files/cerestation/cerestation.dmm @@ -904,6 +904,11 @@ icon_state = "1-8" }, /obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -1105,10 +1110,14 @@ d2 = 8; icon_state = "4-8" }, -/obj/effect/spawner/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ id_tag = "aisat" }, +/obj/structure/cable{ + d2 = 4; + icon_state = "0-4" + }, +/obj/effect/spawner/window/reinforced/grilled, /turf/simulated/floor/plating, /area/station/turret_protected/ai) "agS" = ( @@ -1122,7 +1131,11 @@ }, /area/station/turret_protected/ai) "agW" = ( -/obj/effect/spawner/window/reinforced, +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable{ + d2 = 8; + icon_state = "0-8" + }, /turf/simulated/floor/plating, /area/station/turret_protected/ai) "ahc" = ( @@ -1398,7 +1411,6 @@ /turf/simulated/floor/plasteel, /area/station/security/permabrig) "aje" = ( -/obj/effect/spawner/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ dir = 8; id_tag = "aisat" @@ -1408,6 +1420,11 @@ d2 = 8; icon_state = "4-8" }, +/obj/structure/cable{ + d2 = 8; + icon_state = "0-8" + }, +/obj/effect/spawner/window/reinforced/grilled, /turf/simulated/floor/plating, /area/station/turret_protected/ai) "ajf" = ( @@ -1509,6 +1526,11 @@ /area/station/turret_protected/ai) "ajG" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -1719,9 +1741,7 @@ /turf/simulated/floor/plasteel, /area/station/security/prisonershuttle) "akD" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /obj/machinery/light/small{ dir = 8 }, @@ -1730,9 +1750,7 @@ }, /area/station/security/execution) "akE" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -2109,9 +2127,7 @@ /turf/simulated/floor/plating, /area/station/maintenance/gambling_den) "amW" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /obj/machinery/light/small{ dir = 4 }, @@ -2293,6 +2309,11 @@ d2 = 2; icon_state = "1-2" }, +/obj/structure/cable/orange{ + d1 = 2; + d2 = 8; + icon_state = "2-8" + }, /turf/simulated/floor/plasteel, /area/station/security/prisonershuttle) "aol" = ( @@ -3475,9 +3496,7 @@ }, /area/station/turret_protected/aisat/interior/secondary) "avu" = ( -/obj/effect/turf_decal/stripes/corner{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/corner, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -11344,10 +11363,6 @@ icon_state = "dark" }, /area/station/engineering/control) -"bnS" = ( -/obj/effect/spawner/window/reinforced, -/turf/simulated/floor/plating, -/area/station/engineering/control) "bnV" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/door/firedoor, @@ -12682,6 +12697,11 @@ /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 4 }, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/wood, /area/station/command/office/hop) "btP" = ( @@ -13758,6 +13778,11 @@ /obj/structure/table, /obj/item/paper_bin/nanotrasen, /obj/item/stamp/hop, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/wood, /area/station/command/office/hop) "byr" = ( @@ -15895,9 +15920,7 @@ /obj/effect/mapping_helpers/airlock/access/all/supply/mining, /obj/machinery/door/firedoor, /obj/structure/fans/tiny, -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ dir = 1 }, @@ -20829,9 +20852,7 @@ /obj/effect/turf_decal/stripes/corner{ dir = 4 }, -/obj/effect/turf_decal/stripes/corner{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/corner, /obj/effect/turf_decal/loading_area{ dir = 4 }, @@ -23208,9 +23229,6 @@ }, /area/station/hallway/primary/fore/west) "ctB" = ( -/obj/effect/spawner/window/reinforced/polarized{ - id = "qm" - }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/structure/cable/orange, @@ -23219,6 +23237,9 @@ d2 = 2; icon_state = "1-2" }, +/obj/effect/spawner/window/reinforced/polarized/grilled{ + id = "qm" + }, /turf/simulated/floor/plating, /area/station/supply/qm) "ctC" = ( @@ -23864,10 +23885,6 @@ icon_state = "purplefull" }, /area/station/hallway/primary/aft/west) -"cxW" = ( -/obj/effect/spawner/window/reinforced, -/turf/simulated/floor/plating, -/area/station/maintenance/gambling_den) "cxY" = ( /obj/machinery/atmospherics/unary/vent_scrubber/on, /turf/simulated/floor/engine, @@ -23932,6 +23949,19 @@ }, /turf/simulated/floor/engine, /area/station/science/explab/chamber) +"cyq" = ( +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable/orange{ + d2 = 4; + icon_state = "0-4" + }, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, +/turf/simulated/floor/plating, +/area/station/security/prisonershuttle) "cyx" = ( /obj/effect/turf_decal/stripes/line, /turf/simulated/floor/plasteel, @@ -25645,17 +25675,6 @@ }, /turf/simulated/floor/plasteel, /area/station/public/locker) -"cHZ" = ( -/obj/structure/disposalpipe/segment, -/obj/machinery/door/airlock/command{ - name = "Head of Personnel" - }, -/obj/effect/mapping_helpers/airlock/access/all/command/hop, -/obj/machinery/door/firedoor, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/turf/simulated/floor/wood, -/area/station/command/office/hop) "cIc" = ( /obj/structure/chair/stool{ dir = 8 @@ -26445,6 +26464,11 @@ /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 1 }, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/wood, /area/station/command/office/hop) "cLV" = ( @@ -37642,6 +37666,22 @@ }, /turf/simulated/wall, /area/station/public/sleep) +"eLs" = ( +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, +/turf/simulated/floor/plasteel{ + icon_state = "bcircuit" + }, +/area/station/turret_protected/ai) "eLS" = ( /obj/machinery/status_display{ layer = 4 @@ -38610,6 +38650,19 @@ slowdown = -0.3 }, /area/station/hallway/spacebridge/cargocom) +"ffm" = ( +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable/orange{ + d2 = 8; + icon_state = "0-8" + }, +/obj/structure/cable/orange{ + d1 = 2; + d2 = 8; + icon_state = "2-8" + }, +/turf/simulated/floor/plating, +/area/station/science/xenobiology) "ffy" = ( /obj/machinery/atmospherics/portable/canister/carbon_dioxide, /turf/simulated/floor/plasteel{ @@ -40325,6 +40378,11 @@ /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 6 }, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/plasteel{ icon_state = "darkblue" }, @@ -40487,10 +40545,6 @@ /obj/effect/spawner/random_spawners/dirt_often, /turf/simulated/floor/plasteel, /area/station/supply/office) -"fSO" = ( -/obj/effect/spawner/window/reinforced/grilled, -/turf/simulated/floor/plating, -/area/station/security/prisonershuttle) "fSQ" = ( /obj/machinery/door/airlock/maintenance{ name = "Fore Asteroid Maintenance Access" @@ -41441,6 +41495,30 @@ icon_state = "dark" }, /area/station/engineering/atmos) +"gku" = ( +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/cable{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/station/turret_protected/ai) +"gkD" = ( +/obj/structure/cable{ + d2 = 8; + icon_state = "0-8" + }, +/obj/effect/spawner/window/reinforced/grilled, +/turf/simulated/floor/plating, +/area/station/turret_protected/aisat/interior/secondary) "glm" = ( /obj/structure/cable/orange{ d1 = 1; @@ -41839,11 +41917,6 @@ }, /turf/simulated/floor/engine, /area/station/engineering/control) -"guc" = ( -/obj/effect/spawner/window/reinforced/grilled, -/obj/structure/girder, -/turf/simulated/floor/plating, -/area/station/hallway/spacebridge/sercom) "gux" = ( /obj/structure/sign/securearea{ desc = "A warning sign which reads 'KEEP CLEAR OF PAD WHEN IN USE'."; @@ -41959,6 +42032,14 @@ icon_state = "wood-broken" }, /area/station/maintenance/starboard) +"gvI" = ( +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable{ + d2 = 4; + icon_state = "0-4" + }, +/turf/simulated/floor/plating, +/area/station/turret_protected/aisat/interior/secondary) "gvO" = ( /obj/effect/spawner/window/reinforced/grilled, /obj/structure/cable{ @@ -43508,6 +43589,16 @@ icon_state = "neutralcorner" }, /area/station/hallway/primary/fore/west) +"gVP" = ( +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/structure/cable/orange, +/turf/simulated/floor/plating, +/area/station/science/xenobiology) "gVY" = ( /obj/structure/railing, /turf/simulated/floor/plasteel, @@ -44179,14 +44270,6 @@ icon_state = "white" }, /area/station/science/misc_lab) -"hiG" = ( -/obj/machinery/door/poddoor/shutters/preopen{ - dir = 2; - id_tag = "hopshutter" - }, -/obj/effect/spawner/window/reinforced/grilled, -/turf/simulated/floor/plating, -/area/station/command/office/hop) "hiI" = ( /obj/structure/chair/sofa/corp{ dir = 8 @@ -44457,6 +44540,14 @@ icon_state = "cafeteria" }, /area/station/science/hallway) +"hnC" = ( +/obj/structure/cable{ + d2 = 2; + icon_state = "0-2" + }, +/obj/effect/spawner/window/reinforced/grilled, +/turf/simulated/floor/plating, +/area/station/turret_protected/aisat/interior/secondary) "hoa" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 6 @@ -44816,6 +44907,26 @@ }, /turf/simulated/floor/wood, /area/station/service/bar) +"htw" = ( +/obj/machinery/firealarm{ + dir = 4; + pixel_x = 24; + name = "east bump" + }, +/obj/machinery/door/airlock/research{ + name = "Kill Chamber" + }, +/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, +/obj/effect/turf_decal/delivery, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/plasteel{ + icon_state = "whitepurplefull" + }, +/area/station/science/xenobiology) "htz" = ( /obj/effect/spawner/random_spawners/dirt_often, /turf/simulated/floor/plasteel{ @@ -47161,6 +47272,22 @@ /obj/effect/spawner/random_spawners/dirt_often, /turf/simulated/floor/transparent/glass/reinforced, /area/station/maintenance/fpmaint) +"ihn" = ( +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/cable{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, +/turf/simulated/floor/plasteel{ + icon_state = "bcircuit" + }, +/area/station/turret_protected/ai) "ihz" = ( /obj/structure/cable/orange{ d1 = 4; @@ -47537,6 +47664,18 @@ dir = 1 }, /area/station/engineering/smes) +"ios" = ( +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 2; + id_tag = "hopshutter" + }, +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable/orange{ + d2 = 4; + icon_state = "0-4" + }, +/turf/simulated/floor/plating, +/area/station/command/office/hop) "iox" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -51012,6 +51151,18 @@ "jsE" = ( /turf/simulated/floor/wood, /area/station/maintenance/starboard) +"jsL" = ( +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/bluegrid{ + nitrogen = 500; + oxygen = 0; + temperature = 80 + }, +/area/station/science/xenobiology) "jsN" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable/orange{ @@ -51336,21 +51487,6 @@ /obj/effect/spawner/random_spawners/dirt_frequent, /turf/simulated/floor/plating, /area/station/supply/miningdock) -"jxw" = ( -/obj/machinery/firealarm{ - dir = 4; - pixel_x = 24; - name = "east bump" - }, -/obj/machinery/door/airlock/research{ - name = "Kill Chamber" - }, -/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, -/obj/effect/turf_decal/delivery, -/turf/simulated/floor/plasteel{ - icon_state = "whitepurplefull" - }, -/area/station/science/xenobiology) "jxJ" = ( /obj/machinery/door/airlock/vault{ locked = 1 @@ -51425,7 +51561,16 @@ /turf/simulated/floor/plating, /area/station/hallway/primary/fore) "jzg" = ( -/obj/effect/spawner/window/reinforced, +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable{ + d2 = 4; + icon_state = "0-4" + }, +/obj/structure/cable{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, /turf/simulated/floor/plating, /area/station/turret_protected/aisat/interior/secondary) "jzq" = ( @@ -53260,13 +53405,13 @@ /turf/simulated/floor/plating, /area/station/hallway/primary/fore) "kda" = ( -/obj/effect/spawner/window/reinforced/polarized{ - id = "qm" - }, /obj/structure/cable/orange{ d2 = 2; icon_state = "0-2" }, +/obj/effect/spawner/window/reinforced/polarized/grilled{ + id = "qm" + }, /turf/simulated/floor/plating, /area/station/supply/qm) "kdf" = ( @@ -55920,7 +56065,6 @@ }, /area/station/security/detective) "kTL" = ( -/obj/effect/spawner/window/reinforced, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/structure/cable{ @@ -55928,6 +56072,21 @@ d2 = 2; icon_state = "1-2" }, +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable{ + d1 = 2; + d2 = 4; + icon_state = "2-4" + }, +/obj/structure/cable{ + d2 = 2; + icon_state = "0-2" + }, +/obj/structure/cable{ + d1 = 2; + d2 = 8; + icon_state = "2-8" + }, /turf/simulated/floor/plating, /area/station/turret_protected/aisat/interior/secondary) "kTN" = ( @@ -57071,9 +57230,7 @@ /turf/simulated/floor/plating, /area/station/maintenance/disposal/north) "llt" = ( -/obj/effect/turf_decal/stripes/corner{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/corner, /obj/effect/turf_decal/loading_area{ dir = 4 }, @@ -57391,6 +57548,22 @@ }, /turf/simulated/floor/plating, /area/station/command/office/cmo) +"loR" = ( +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/machinery/atmospherics/unary/vent_pump/on{ + dir = 4 + }, +/obj/structure/cable/orange{ + d1 = 2; + d2 = 8; + icon_state = "2-8" + }, +/turf/simulated/floor/plasteel, +/area/station/security/prisonershuttle) "lpe" = ( /obj/structure/table, /obj/item/book/manual/supermatter_engine, @@ -58082,6 +58255,14 @@ icon_state = "darkyellow" }, /area/station/engineering/break_room) +"lzv" = ( +/obj/structure/cable{ + d2 = 4; + icon_state = "0-4" + }, +/obj/effect/spawner/window/reinforced/grilled, +/turf/simulated/floor/plating, +/area/station/turret_protected/aisat/interior/secondary) "lzH" = ( /obj/structure/lattice, /turf/space, @@ -58274,10 +58455,6 @@ }, /turf/simulated/floor/transparent/glass/reinforced, /area/station/maintenance/fsmaint) -"lCh" = ( -/obj/effect/spawner/window/reinforced, -/turf/simulated/floor/plating, -/area/station/maintenance/starboard) "lCs" = ( /obj/structure/cable/orange{ d1 = 1; @@ -58904,6 +59081,14 @@ icon_state = "asteroidplating" }, /area/station/maintenance/port2) +"lPi" = ( +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable{ + d2 = 8; + icon_state = "0-8" + }, +/turf/simulated/floor/plating, +/area/station/turret_protected/aisat/interior/secondary) "lPn" = ( /obj/effect/spawner/window/reinforced/grilled, /obj/structure/cable/orange{ @@ -59691,9 +59876,7 @@ dir = 1 }, /obj/machinery/disposal, -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /turf/simulated/floor/plasteel{ dir = 1; icon_state = "whitepurple" @@ -60597,6 +60780,11 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/disposal/westalt) +"msG" = ( +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable/orange, +/turf/simulated/floor/plating, +/area/station/science/xenobiology) "mte" = ( /obj/structure/disposalpipe/trunk{ dir = 4 @@ -62488,15 +62676,6 @@ icon_state = "dark" }, /area/station/maintenance/asmaint) -"mZH" = ( -/obj/machinery/door/airlock/external{ - id_tag = "laborcamp_home"; - locked = 1; - name = "Labor Camp Airlock" - }, -/obj/effect/mapping_helpers/airlock/access/all/security/brig, -/turf/simulated/floor/plating, -/area/station/security/prisonershuttle) "mZP" = ( /obj/machinery/power/apc{ dir = 4; @@ -62770,6 +62949,11 @@ /obj/machinery/light/small{ dir = 4 }, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, /turf/simulated/floor/bluegrid{ nitrogen = 500; oxygen = 0; @@ -65313,11 +65497,6 @@ }, /turf/simulated/wall, /area/station/hallway/primary/port/south) -"nZe" = ( -/obj/structure/girder, -/obj/effect/spawner/window/reinforced/grilled, -/turf/simulated/floor/plating, -/area/station/hallway/spacebridge/scidock) "nZf" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/hidden/supply, @@ -66070,6 +66249,14 @@ icon_state = "dark" }, /area/station/medical/morgue) +"olH" = ( +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable{ + d2 = 4; + icon_state = "0-4" + }, +/turf/simulated/floor/plating, +/area/station/turret_protected/ai) "olT" = ( /obj/structure/cable{ d1 = 4; @@ -66096,13 +66283,13 @@ /turf/simulated/floor/plasteel, /area/station/science/toxins/launch) "omd" = ( -/obj/effect/spawner/window/reinforced/polarized{ - id = "qm" - }, /obj/structure/cable/orange{ d2 = 8; icon_state = "0-8" }, +/obj/effect/spawner/window/reinforced/polarized/grilled{ + id = "qm" + }, /turf/simulated/floor/plating, /area/station/supply/office) "omg" = ( @@ -66457,6 +66644,17 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/storage) +"oqx" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/structure/cable/orange{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, +/turf/simulated/floor/plasteel, +/area/station/security/prisonershuttle) "oqB" = ( /obj/structure/cable{ d1 = 2; @@ -68064,9 +68262,7 @@ /obj/machinery/atmospherics/unary/portables_connector{ dir = 1 }, -/obj/machinery/atmospherics/unary/portables_connector{ - dir = 2 - }, +/obj/machinery/atmospherics/unary/portables_connector, /obj/machinery/atmospherics/portable/canister/air, /turf/simulated/floor/plating, /area/station/hallway/primary/aft/west) @@ -69966,6 +70162,20 @@ /obj/structure/reagent_dispensers/watertank, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/starboard) +"pyM" = ( +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 2; + id_tag = "hopshutter" + }, +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable/orange, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, +/turf/simulated/floor/plating, +/area/station/command/office/hop) "pzi" = ( /obj/structure/disposalpipe/segment, /obj/effect/spawner/window/reinforced, @@ -70077,9 +70287,7 @@ /obj/effect/turf_decal/stripes/corner{ dir = 4 }, -/obj/effect/turf_decal/stripes/corner{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/corner, /obj/effect/turf_decal/loading_area{ dir = 4 }, @@ -74039,6 +74247,19 @@ }, /turf/simulated/floor/plasteel/white, /area/station/science/xenobiology) +"qKQ" = ( +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable{ + d2 = 4; + icon_state = "0-4" + }, +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, +/turf/simulated/floor/plating, +/area/station/turret_protected/aisat/interior/secondary) "qLa" = ( /obj/machinery/computer/arcade/recruiter{ dir = 4 @@ -74724,11 +74945,6 @@ icon_state = "redcorner" }, /area/station/security/main) -"qYs" = ( -/obj/effect/spawner/window/reinforced/grilled, -/obj/structure/girder, -/turf/simulated/floor/plating, -/area/station/hallway/spacebridge/medcargo) "qYD" = ( /obj/item/pen, /obj/item/storage/firstaid/regular, @@ -76769,6 +76985,24 @@ icon_state = "whitebluefull" }, /area/station/medical/paramedic) +"rMi" = ( +/obj/structure/cable{ + d2 = 4; + icon_state = "0-4" + }, +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, +/obj/structure/cable{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, +/obj/effect/spawner/window/reinforced/grilled, +/turf/simulated/floor/plating, +/area/station/turret_protected/aisat/interior/secondary) "rMx" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 9 @@ -78009,9 +78243,7 @@ /turf/simulated/floor/plasteel, /area/station/hallway/secondary/exit) "shh" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /obj/item/radio/intercom{ pixel_x = 28; name = "custom placement" @@ -78903,6 +79135,22 @@ icon_state = "purplecorner" }, /area/station/hallway/primary/aft/east) +"suI" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/door/airlock/command{ + name = "Head of Personnel" + }, +/obj/effect/mapping_helpers/airlock/access/all/command/hop, +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/wood, +/area/station/command/office/hop) "suS" = ( /obj/machinery/photocopier, /turf/simulated/floor/wood, @@ -79953,6 +80201,28 @@ icon_state = "redcorner" }, /area/station/security/lobby) +"sOe" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/structure/cable{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, +/obj/structure/cable{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, +/turf/simulated/floor/plasteel{ + icon_state = "bcircuit" + }, +/area/station/turret_protected/aisat/interior/secondary) "sOf" = ( /obj/machinery/processor, /turf/simulated/floor/plasteel{ @@ -80904,6 +81174,28 @@ /obj/structure/closet/firecloset/full, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/apmaint) +"tcP" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, +/obj/structure/cable{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, +/obj/structure/cable, +/turf/simulated/floor/plating, +/area/station/turret_protected/aisat/interior/secondary) "tdk" = ( /obj/structure/cable/orange{ d1 = 4; @@ -81140,6 +81432,11 @@ dir = 1 }, /obj/machinery/hologram/holopad, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/plasteel/white, /area/station/science/xenobiology) "tiv" = ( @@ -81327,6 +81624,21 @@ /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, /area/station/security/permabrig) +"tkv" = ( +/obj/structure/cable/orange{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, +/obj/structure/cable/orange{ + d1 = 2; + d2 = 4; + icon_state = "2-4" + }, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/station/command/bridge) "tkC" = ( /obj/machinery/door/window/brigdoor{ id = "Cell 7"; @@ -82811,6 +83123,20 @@ /obj/effect/spawner/airlock/s_to_n, /turf/simulated/wall, /area/station/hallway/primary/central) +"tMN" = ( +/obj/machinery/door/airlock/external{ + id_tag = "laborcamp_home"; + locked = 1; + name = "Labor Camp Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/security/brig, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/plating, +/area/station/security/prisonershuttle) "tMP" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 @@ -93095,7 +93421,6 @@ /turf/simulated/floor/engine, /area/station/engineering/control) "wSP" = ( -/obj/effect/spawner/window/reinforced, /obj/structure/cable{ d1 = 4; d2 = 8; @@ -93104,6 +93429,11 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable{ + d2 = 4; + icon_state = "0-4" + }, /turf/simulated/floor/plating, /area/station/turret_protected/aisat/interior/secondary) "wTg" = ( @@ -94104,6 +94434,24 @@ dir = 1 }, /area/station/engineering/smes) +"xjN" = ( +/obj/structure/cable{ + d2 = 8; + icon_state = "0-8" + }, +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, +/obj/structure/cable{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, +/obj/effect/spawner/window/reinforced/grilled, +/turf/simulated/floor/plating, +/area/station/turret_protected/aisat/interior/secondary) "xjO" = ( /obj/machinery/atmospherics/pipe/manifold/hidden/supply, /obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ @@ -95166,6 +95514,17 @@ icon_state = "white" }, /area/station/science/toxins/mixing) +"xDS" = ( +/obj/effect/turf_decal/stripes/line, +/obj/structure/cable/orange{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/plasteel{ + icon_state = "whitepurple" + }, +/area/station/science/xenobiology) "xDX" = ( /obj/structure/disposalpipe/trunk{ dir = 1 @@ -95549,13 +95908,30 @@ }, /area/station/hallway/primary/fore/west) "xJW" = ( -/obj/effect/spawner/window/reinforced, /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable{ + d2 = 2; + icon_state = "0-2" + }, +/turf/simulated/floor/plating, +/area/station/turret_protected/aisat/interior/secondary) +"xKb" = ( +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable{ + d2 = 8; + icon_state = "0-8" + }, +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/plating, /area/station/turret_protected/aisat/interior/secondary) "xKr" = ( @@ -97181,6 +97557,14 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/disposal/external/southwest) +"ymd" = ( +/obj/effect/spawner/window/reinforced/grilled, +/obj/structure/cable/orange{ + d2 = 2; + icon_state = "0-2" + }, +/turf/simulated/floor/plating, +/area/station/security/prisonershuttle) (1,1,1) = {" rNK @@ -110848,13 +111232,13 @@ rNK rNK pVD pVD -fSO -mZH -fSO +ymd +tMN +cyq cdL -fSO -mZH -fSO +ymd +tMN +cyq pVD pVD pVD @@ -111107,11 +111491,11 @@ pVD aWm mFT mFT -dqa +oqx ale dqa mFT -dqa +oqx aoZ dqa qbx @@ -111364,7 +111748,7 @@ pVD doB ajA dpg -akC +loR alg vKV akC @@ -113211,14 +113595,14 @@ ice ice ice leM -guc -guc -guc +hrT +hrT +hrT lAN lAN -guc -guc -guc +hrT +hrT +hrT uSv uSv uSv @@ -119422,10 +119806,10 @@ wph xOD sbn shL -cxW -cxW -cxW -cxW +mNj +mNj +mNj +mNj shL sbn uQh @@ -119744,9 +120128,9 @@ nKb cpI qZD tia -kvs -jxw -wQY +xDS +htw +jsL nej vey vWk @@ -120004,9 +120388,9 @@ tqK yiP xPU xPU -pzF -pzF -pzF +ffm +gVP +msG ftr ftr ksj @@ -125299,7 +125683,7 @@ rNK rNK qQU qQU -fph +qQU aYa aXP hqg @@ -126672,7 +127056,7 @@ oeQ hrd qyP hKz -nZe +oeQ rNK rNK xcc @@ -126929,7 +127313,7 @@ oeQ hrd qyP hKz -nZe +oeQ rNK rNK rNK @@ -127186,7 +127570,7 @@ oeQ hrd qyP hKz -nZe +oeQ rNK rNK rNK @@ -127700,7 +128084,7 @@ oeQ hrd qyP hKz -nZe +oeQ rNK rNK rNK @@ -127957,7 +128341,7 @@ oeQ hrd qyP hKz -nZe +oeQ rNK rNK xcc @@ -128214,7 +128598,7 @@ oeQ hrd qyP hKz -nZe +oeQ lzH lzH xcc @@ -128728,7 +129112,7 @@ oeQ hRR qyP hKz -nZe +oeQ ayb ayb ayb @@ -128873,7 +129257,7 @@ bse btG bxr bxF -hiG +ios dQx bEi bUO @@ -128985,7 +129369,7 @@ uVb olT qyP hKz -nZe +oeQ hBQ ayb hBQ @@ -129124,13 +129508,13 @@ aVS aVS aVS xLP -cyR +tkv fPE -cHZ +suI btJ cLU byn -hiG +pyM dQx bEi bUO @@ -130972,7 +131356,7 @@ cKs cJC qMy qMy -bnS +xIu bqB uRg cKr @@ -131229,7 +131613,7 @@ pGS cJD qMy cWK -bnS +xIu rbm aFE btx @@ -131486,7 +131870,7 @@ cKs cJC qMy qMy -bnS +xIu bqx pnd cKr @@ -132326,7 +132710,7 @@ cYB tnb qyP hKz -nZe +uVb cYB cYB cYB @@ -132840,7 +133224,7 @@ oeQ hrd qyP hKz -nZe +oeQ ayb ayb ayb @@ -133097,7 +133481,7 @@ oeQ hrd qyP hKz -nZe +oeQ ayb ayb xcc @@ -133354,7 +133738,7 @@ oeQ hrd qyP hKz -nZe +oeQ ayb rNK xcc @@ -133868,7 +134252,7 @@ oeQ hrd qyP hKz -nZe +oeQ rNK rNK xcc @@ -134125,7 +134509,7 @@ oeQ hrd qyP hKz -nZe +oeQ rNK rNK xcc @@ -134382,7 +134766,7 @@ oeQ hrd qyP hKz -nZe +oeQ rNK rNK xcc @@ -139884,9 +140268,9 @@ acD afU afO aig -aig -ajF +ihn ajF +gku akq pTh vzj @@ -140149,10 +140533,10 @@ sYg ajS okP aRj -jzg +lzv oyx buv -jzg +gvI xJW jzg asE @@ -140405,13 +140789,13 @@ lTy sYg jEQ okP -jzg -jzg +hnC +rMi oyx buv -jzg +qKQ mwF -jzg +qKQ asE oyx okP @@ -140663,10 +141047,10 @@ akZ gUh vsD amJ -amJ +sOe aNf aqk -kTL +tcP aZL kTL btr @@ -140919,13 +141303,13 @@ jhe sYg dBu okP -jzg -jzg +hnC +xjN oyx asE -jzg +xKb nlZ -jzg +xKb buv oyx okP @@ -141169,20 +141553,20 @@ dvV dvV agS sYg -agW +olH afn -agW +olH akv sYg ajS okP aRj -jzg +gkD oyx asE -jzg +lPi wSP -jzg +lPi buv oyx mmW @@ -141426,7 +141810,7 @@ dvV afU ojF aik -aik +eLs afq ajG akw @@ -147654,10 +148038,10 @@ rWb rWb aRx mok -qYs +rsZ mKP -qYs -qYs +rsZ +rsZ mok aZq aZq @@ -153618,7 +154002,7 @@ jsE jsE vWi jsE -lCh +bDv rNK rNK gEl diff --git a/_maps/map_files/generic/centcomm.dmm b/_maps/map_files/generic/centcomm.dmm index bc5aa5d5d3da..8295f9818031 100644 --- a/_maps/map_files/generic/centcomm.dmm +++ b/_maps/map_files/generic/centcomm.dmm @@ -1823,6 +1823,7 @@ dir = 4; pixel_y = 8 }, +/obj/machinery/economy/vending/cigarette, /turf/simulated/floor/wood, /area/ghost_bar) "gT" = ( @@ -3686,7 +3687,7 @@ /area/admin) "mz" = ( /obj/machinery/economy/vending/boozeomat, -/turf/simulated/wall/indestructible/riveted, +/turf/simulated/floor/wood, /area/ghost_bar) "mA" = ( /obj/structure/sign/poster/official/fruit_bowl, @@ -5137,6 +5138,12 @@ /obj/item/stack/sheet/metal/fifty, /turf/simulated/floor/plasteel/dark, /area/centcom/specops) +"rq" = ( +/obj/structure/closet/crate/can, +/turf/simulated/floor/plasteel{ + icon_state = "cafeteria" + }, +/area/ghost_bar) "rr" = ( /obj/structure/table, /obj/item/storage/box/beakers, @@ -5679,10 +5686,10 @@ /turf/simulated/floor/plasteel/dark, /area/centcom/specops) "tr" = ( -/turf/simulated/floor/wood{ - broken = 1; - icon_state = "wood-broken" +/obj/machinery/light/small{ + dir = 1 }, +/turf/simulated/floor/wood, /area/ghost_bar) "ts" = ( /obj/machinery/atmospherics/portable/canister/oxygen, @@ -6703,6 +6710,7 @@ desc = "Used to grind things up into raw materials and liquids."; pixel_y = 5 }, +/obj/item/reagent_containers/glass/beaker/large, /turf/simulated/floor/plasteel{ icon_state = "cafeteria" }, @@ -6987,7 +6995,6 @@ "xU" = ( /obj/structure/table/reinforced, /obj/machinery/kitchen_machine/microwave/upgraded, -/obj/machinery/light/small, /turf/simulated/floor/plasteel{ icon_state = "cafeteria" }, @@ -6997,10 +7004,7 @@ /turf/simulated/floor/plasteel/dark, /area/ghost_bar) "xY" = ( -/obj/machinery/economy/vending/cigarette, -/obj/machinery/light/small{ - dir = 1 - }, +/obj/structure/closet/crate/can, /turf/simulated/floor/wood, /area/ghost_bar) "xZ" = ( @@ -7288,6 +7292,13 @@ /obj/machinery/computer/cryopod/robot, /turf/simulated/wall/indestructible/riveted, /area/centcom/specops) +"zP" = ( +/obj/machinery/light/small, +/obj/machinery/economy/vending/dinnerware, +/turf/simulated/floor/plasteel{ + icon_state = "cafeteria" + }, +/area/ghost_bar) "zQ" = ( /obj/machinery/light/small, /turf/simulated/floor/plasteel/freezer, @@ -13851,6 +13862,7 @@ /obj/machinery/light/small{ dir = 8 }, +/obj/structure/closet/crate/can, /turf/simulated/floor/wood, /area/ghost_bar) "Xb" = ( @@ -72235,7 +72247,7 @@ Jy vd vd vd -Jy +rf Me EX Jy @@ -72492,7 +72504,7 @@ Jy vd cX vd -rf +xY Me wh rd @@ -73785,8 +73797,8 @@ Me Me Me Me -xY -Jy +Me +tr Jy qH Nm @@ -74041,8 +74053,8 @@ es Oj zj fF -Me -Jy +rq +aT Jy ip Jy @@ -74298,9 +74310,9 @@ es es es es +es Uk Jy -Jy ol ol Hz @@ -74555,8 +74567,8 @@ wN Dk zY xU +zP Me -tr Jy rG hU @@ -74812,8 +74824,8 @@ Me Me Me Me -aT -Jy +Me +Me Jy RX RX @@ -75070,9 +75082,9 @@ ps ps ps Me -Jy +Me gS -Jy +xY Me Me Me diff --git a/code/__DEFINES/_init.dm b/code/__DEFINES/_init.dm index 5346b087c0d9..3562b9a61018 100644 --- a/code/__DEFINES/_init.dm +++ b/code/__DEFINES/_init.dm @@ -4,7 +4,7 @@ // This exists so that world.Profile() is THE FIRST PROC TO RUN in the init sequence. // This allows us to get the real details of everything lagging at server start. world.Profile(PROFILE_START) - #if defined(ENABLE_BYOND_TRACY) && (DM_BUILD == 1589) + #if defined(ENABLE_BYOND_TRACY) var/tracy_init = CALL_EXT("prof.dll", "init")() // Setup Tracy integration if(tracy_init != "0") CRASH("Tracy init error: [tracy_init]") diff --git a/code/__DEFINES/_tgs_defines.dm b/code/__DEFINES/_tgs_defines.dm index 23d1e8c39268..4aa8662ec4ca 100644 --- a/code/__DEFINES/_tgs_defines.dm +++ b/code/__DEFINES/_tgs_defines.dm @@ -3,7 +3,7 @@ #define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) GLOBAL_VAR_INIT(##Name, ##Value); GLOBAL_PROTECT(##Name) #define TGS_READ_GLOBAL(Name) GLOB.##Name #define TGS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value -#define TGS_WORLD_ANNOUNCE(message) to_chat(world, "[html_encode(##message)]") +#define TGS_WORLD_ANNOUNCE(message) to_chat(world, "
Host Announcement: [html_encode(##message)]
") #define TGS_INFO_LOG(message) log_tgs(message, "INF") #define TGS_WARNING_LOG(message) log_tgs(message, "WRN") #define TGS_ERROR_LOG(message) log_tgs(message, "ERR") diff --git a/code/__DEFINES/bots.dm b/code/__DEFINES/bots.dm index c283445d0ad6..9301b1c79232 100644 --- a/code/__DEFINES/bots.dm +++ b/code/__DEFINES/bots.dm @@ -24,6 +24,8 @@ #define BOT_NAV 15 // computing navigation #define BOT_WAIT_FOR_NAV 16 // waiting for nav computation #define BOT_NO_ROUTE 17 // no destination beacon found (or no route) +#define BOT_MAKE_TILE 18 // converting metal into tiles (floorbots) +#define BOT_EAT_TILE 19 // adding said tiles to inventory (floorbots) //Bot types #define SEC_BOT 1 // Secutritrons (Beepsky) and ED-209s diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm index 89976c498422..c6596ea46c10 100644 --- a/code/__DEFINES/tgs.dm +++ b/code/__DEFINES/tgs.dm @@ -1,6 +1,6 @@ // tgstation-server DMAPI -#define TGS_DMAPI_VERSION "6.5.0" +#define TGS_DMAPI_VERSION "7.0.0" // All functions and datums outside this document are subject to change with any version and should not be relied on. @@ -73,12 +73,12 @@ #define TGS_EVENT_REPO_MERGE_PULL_REQUEST 3 /// Before the repository makes a sychronize operation. Parameters: Absolute repostiory path. #define TGS_EVENT_REPO_PRE_SYNCHRONIZE 4 -/// Before a BYOND install operation begins. Parameters: [/datum/tgs_version] of the installing BYOND. -#define TGS_EVENT_BYOND_INSTALL_START 5 -/// When a BYOND install operation fails. Parameters: Error message -#define TGS_EVENT_BYOND_INSTALL_FAIL 6 -/// When the active BYOND version changes. Parameters: (Nullable) [/datum/tgs_version] of the current BYOND, [/datum/tgs_version] of the new BYOND. -#define TGS_EVENT_BYOND_ACTIVE_VERSION_CHANGE 7 +/// Before a engine install operation begins. Parameters: Version string of the installing engine. +#define TGS_EVENT_ENGINE_INSTALL_START 5 +/// When a engine install operation fails. Parameters: Error message +#define TGS_EVENT_ENGINE_INSTALL_FAIL 6 +/// When the active engine version changes. Parameters: (Nullable) Version string of the current engine, version string of the new engine. +#define TGS_EVENT_ENGINE_ACTIVE_VERSION_CHANGE 7 /// When the compiler starts running. Parameters: Game directory path, origin commit SHA. #define TGS_EVENT_COMPILE_START 8 /// When a compile is cancelled. No parameters. @@ -108,7 +108,7 @@ // #define TGS_EVENT_DREAM_DAEMON_LAUNCH 22 /// After a single submodule update is performed. Parameters: Updated submodule name. #define TGS_EVENT_REPO_SUBMODULE_UPDATE 23 -/// After CodeModifications are applied, before DreamMaker is run. Parameters: Game directory path, origin commit sha, byond version. +/// After CodeModifications are applied, before DreamMaker is run. Parameters: Game directory path, origin commit sha, version string of the used engine. #define TGS_EVENT_PRE_DREAM_MAKER 24 /// Whenever a deployment folder is deleted from disk. Parameters: Game directory path. #define TGS_EVENT_DEPLOYMENT_CLEANUP 25 @@ -122,6 +122,7 @@ /// The watchdog will restart on reboot. #define TGS_REBOOT_MODE_RESTART 2 +// Note that security levels are currently meaningless in OpenDream /// DreamDaemon Trusted security level. #define TGS_SECURITY_TRUSTED 0 /// DreamDaemon Safe security level. @@ -129,6 +130,18 @@ /// DreamDaemon Ultrasafe security level. #define TGS_SECURITY_ULTRASAFE 2 +/// DreamDaemon public visibility level. +#define TGS_VISIBILITY_PUBLIC 0 +/// DreamDaemon private visibility level. +#define TGS_VISIBILITY_PRIVATE 1 +/// DreamDaemon invisible visibility level. +#define TGS_VISIBILITY_INVISIBLE 2 + +/// The Build Your Own Net Dream engine. +#define TGS_ENGINE_TYPE_BYOND 0 +/// The OpenDream engine. +#define TGS_ENGINE_TYPE_OPENDREAM 1 + //REQUIRED HOOKS /** @@ -154,7 +167,7 @@ #define TGS_TOPIC var/tgs_topic_return = TgsTopic(args[1]); if(tgs_topic_return) return tgs_topic_return /** - * Call this as late as possible in [world/proc/Reboot]. + * Call this as late as possible in [world/proc/Reboot] (BEFORE ..()). */ /world/proc/TgsReboot() return @@ -442,6 +455,10 @@ /world/proc/TgsVersion() return +/// Returns the running engine type +/world/proc/TgsEngine() + return + /// Returns the current [/datum/tgs_version] of the DMAPI being used if it was activated, null otherwise. This function may sleep if the call to [/world/proc/TgsNew] is sleeping! /world/proc/TgsApiVersion() return @@ -458,6 +475,10 @@ /world/proc/TgsSecurityLevel() return +/// Returns the current BYOND visibility level as a TGS_VISIBILITY_ define if TGS is present, null otherwise. Requires TGS to be using interop API version 5 or higher otherwise the string "___unimplemented" wil be returned. This function may sleep if the call to [/world/proc/TgsNew] is sleeping! +/world/proc/TgsVisibility() + return + /// Returns a list of active [/datum/tgs_revision_information/test_merge]s if TGS is present, null otherwise. This function may sleep if the call to [/world/proc/TgsNew] is sleeping! /world/proc/TgsTestMerges() return diff --git a/code/_globalvars/lists/reagents_lists.dm b/code/_globalvars/lists/reagents_lists.dm index 2d70edcc5835..39540790b932 100644 --- a/code/_globalvars/lists/reagents_lists.dm +++ b/code/_globalvars/lists/reagents_lists.dm @@ -46,4 +46,6 @@ GLOBAL_LIST_INIT(blocked_chems, list("polonium", "initropidril", "concentrated_i "spidereggs", "heartworms", "bacon_grease", "fungalspores", "jagged_crystals", "salmonella", "lavaland_extract", "stable_mutagen", "beer2", - "curare", "gluttonytoxin", "smoke_powder", "stimulative_cling")) + "curare", "gluttonytoxin", "smoke_powder", "stimulative_cling", + "teslium_paste" + )) diff --git a/code/controllers/subsystem/SSticker.dm b/code/controllers/subsystem/SSticker.dm index 447ed03b9e4e..b44fb91e9264 100644 --- a/code/controllers/subsystem/SSticker.dm +++ b/code/controllers/subsystem/SSticker.dm @@ -657,13 +657,20 @@ SUBSYSTEM_DEF(ticker) /datum/controller/subsystem/ticker/proc/setup_news_feeds() var/datum/feed_channel/newChannel = new /datum/feed_channel - newChannel.channel_name = "Public Station Announcements" + newChannel.channel_name = "Station Announcements Log" newChannel.author = "Automated Announcement Listing" newChannel.icon = "bullhorn" newChannel.frozen = TRUE newChannel.admin_locked = TRUE GLOB.news_network.channels += newChannel + newChannel = new /datum/feed_channel + newChannel.channel_name = "Public Station Announcements" + newChannel.author = "Automated Announcement Listing" + newChannel.icon = "users" + newChannel.is_public = TRUE + GLOB.news_network.channels += newChannel + newChannel = new /datum/feed_channel newChannel.channel_name = "Nyx Daily" newChannel.author = "CentComm Minister of Information" diff --git a/code/datums/diseases/_disease.dm b/code/datums/diseases/_disease.dm index 0823d7bad609..404a45324e2f 100644 --- a/code/datums/diseases/_disease.dm +++ b/code/datums/diseases/_disease.dm @@ -59,7 +59,7 @@ GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease)) //Other var/list/viable_mobtypes = list() //typepaths of viable mobs - var/mob/living/carbon/affected_mob = null + var/mob/living/carbon/affected_mob var/list/cures = list() //list of cures if the disease has the CURABLE flag, these are reagent ids var/infectivity = 65 var/cure_chance = 8 @@ -67,7 +67,7 @@ GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease)) var/bypasses_immunity = FALSE //Does it skip species virus immunity check? Some things may diseases and not viruses var/virus_heal_resistant = FALSE // Some things aren't technically viruses/traditional diseases and should be immune to edge case cure methods, like healing viruses. var/permeability_mod = 1 - var/severity = NONTHREAT + var/severity = NONTHREAT var/list/required_organs = list() var/needs_all_cures = TRUE var/list/strain_data = list() //dna_spread special bullshit diff --git a/code/datums/diseases/anxiety.dm b/code/datums/diseases/anxiety.dm index b27911441634..b91ac32b1ed8 100644 --- a/code/datums/diseases/anxiety.dm +++ b/code/datums/diseases/anxiety.dm @@ -9,13 +9,13 @@ agent = "Excess Lepidopticides" viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey) desc = "If left untreated subject will regurgitate butterflies." - severity = MEDIUM + severity = MINOR /datum/disease/anxiety/stage_act() if(!..()) return FALSE switch(stage) - if(2) //also changes say, see say.dm + if(2) if(prob(5)) to_chat(affected_mob, "You feel anxious.") if(3) diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm index f58a9a6d0586..674abaafe2a2 100644 --- a/code/datums/diseases/appendicitis.dm +++ b/code/datums/diseases/appendicitis.dm @@ -7,9 +7,8 @@ cure_text = "Surgery" agent = "Shitty Appendix" viable_mobtypes = list(/mob/living/carbon/human) - permeability_mod = 1 desc = "If left untreated the subject will become very weak, and may vomit often." - severity = "Dangerous!" + severity = MINOR disease_flags = CAN_CARRY|CAN_RESIST visibility_flags = HIDDEN_PANDEMIC required_organs = list(/obj/item/organ/internal/appendix) diff --git a/code/datums/diseases/beesease.dm b/code/datums/diseases/beesease.dm index 50ad51132437..348837c8d9f0 100644 --- a/code/datums/diseases/beesease.dm +++ b/code/datums/diseases/beesease.dm @@ -9,13 +9,13 @@ agent = "Apidae Infection" viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey) desc = "If left untreated subject will regurgitate bees." - severity = DANGEROUS + severity = BIOHAZARD /datum/disease/beesease/stage_act() if(!..()) return FALSE switch(stage) - if(2) //also changes say, see say.dm // no it doesn't, that's horrifyingly snowflakey + if(2) if(prob(2)) to_chat(affected_mob, "You taste honey in your mouth.") if(3) @@ -35,6 +35,4 @@ affected_mob.visible_message("[affected_mob] coughs up a swarm of bees!", \ "You cough up a swarm of bees!") new /mob/living/simple_animal/hostile/poison/bees(affected_mob.loc) - //if(5) - //Plus if you die, you explode into bees return diff --git a/code/datums/diseases/berserker.dm b/code/datums/diseases/berserker.dm index 38c82959ce11..b9610057d132 100644 --- a/code/datums/diseases/berserker.dm +++ b/code/datums/diseases/berserker.dm @@ -10,7 +10,7 @@ cure_chance = 10 viable_mobtypes = list(/mob/living/carbon/human) desc = "Swearing, shouting, attacking nearby crew members uncontrollably." - severity = DANGEROUS + severity = BIOHAZARD disease_flags = CURABLE /datum/disease/berserker/stage_act() diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm index 9fb2774a0bf5..ae5c5a237820 100644 --- a/code/datums/diseases/brainrot.dm +++ b/code/datums/diseases/brainrot.dm @@ -7,12 +7,12 @@ cures = list("mannitol") agent = "Cryptococcus Cosmosis" viable_mobtypes = list(/mob/living/carbon/human) - cure_chance = 15//higher chance to cure, since two reagents are required + cure_chance = 15 desc = "This disease destroys the braincells, causing brain fever, brain necrosis and general intoxication." required_organs = list(/obj/item/organ/internal/brain) - severity = DANGEROUS + severity = HARMFUL -/datum/disease/brainrot/stage_act() //Removed toxloss because damaging diseases are pretty horrible. Last round it killed the entire station because the cure didn't work -- Urist -ACTUALLY Removed rather than commented out, I don't see it returning - RR +/datum/disease/brainrot/stage_act() if(!..()) return FALSE switch(stage) @@ -30,7 +30,7 @@ affected_mob.emote("stare") if(prob(2)) affected_mob.emote("drool") - if(prob(10) && affected_mob.getBrainLoss()<=98)//shouldn't brainpain you to death now + if(prob(10) && affected_mob.getBrainLoss() < 100) affected_mob.adjustBrainLoss(2) if(prob(2)) to_chat(affected_mob, "Your try to remember something important...but can't.") @@ -40,7 +40,7 @@ affected_mob.emote("stare") if(prob(2)) affected_mob.emote("drool") - if(prob(15) && affected_mob.getBrainLoss()<=98) //shouldn't brainpain you to death now + if(prob(15) && affected_mob.getBrainLoss() < 100) affected_mob.adjustBrainLoss(3) if(prob(2)) to_chat(affected_mob, "Strange buzzing fills your head, removing all thoughts.") diff --git a/code/datums/diseases/cold9.dm b/code/datums/diseases/cold9.dm index 85c3bba22d9a..584b284fd521 100644 --- a/code/datums/diseases/cold9.dm +++ b/code/datums/diseases/cold9.dm @@ -4,38 +4,27 @@ max_stages = 3 spread_text = "On contact" spread_flags = CONTACT_GENERAL - cure_text = "Common Cold Anti-bodies & Spaceacillin" + cure_text = "Spaceacillin" cures = list("spaceacillin") agent = "ICE9-rhinovirus" viable_mobtypes = list(/mob/living/carbon/human) desc = "If left untreated the subject will slow, as if partly frozen." - severity = MEDIUM + severity = HARMFUL /datum/disease/cold9/stage_act() if(!..()) return FALSE - switch(stage) - if(2) - affected_mob.bodytemperature -= 10 - if(prob(1) && prob(10)) - to_chat(affected_mob, "You feel better.") - cure() - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "Your throat feels sore.") - if(prob(5)) - to_chat(affected_mob, "You feel stiff.") - if(3) - affected_mob.bodytemperature -= 20 - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "Your throat feels sore.") - if(prob(10)) - to_chat(affected_mob, "You feel stiff.") + if(stage < 2) + return + + var/stage_factor = stage - 1 + affected_mob.bodytemperature -= 7.5 * stage_factor // Enough to consistently frostburn certain species alive at stage 3 + if(prob(2 * stage_factor)) + affected_mob.emote("sneeze") + if(prob(2 * stage_factor)) + affected_mob.emote("cough") + if(prob(3 * stage_factor)) + to_chat(affected_mob, "Your throat feels sore.") + if(prob(5 * stage_factor)) + to_chat(affected_mob, "You feel stiff.") + affected_mob.adjustFireLoss(1) diff --git a/code/datums/diseases/critical.dm b/code/datums/diseases/critical.dm index a88c4f8abad9..ac83c8f15de6 100644 --- a/code/datums/diseases/critical.dm +++ b/code/datums/diseases/critical.dm @@ -1,4 +1,12 @@ /datum/disease/critical + form = "Medical Emergency" + max_stages = 3 + spread_flags = SPECIAL + viable_mobtypes = list(/mob/living/carbon/human) + severity = MINOR + disease_flags = CURABLE + bypasses_immunity = TRUE + virus_heal_resistant = TRUE /datum/disease/critical/stage_act() //overriden to ensure unique behavior stage = min(stage, max_stages) @@ -20,19 +28,11 @@ /datum/disease/critical/shock name = "Shock" - form = "Medical Emergency" - spread_text = "The patient is in shock" - max_stages = 3 - spread_flags = SPECIAL + spread_text = "The patient is in shock." cure_text = "Saline-Glucose Solution" cures = list("salglu_solution", "syndicate_nanites", "stimulative_agent") cure_chance = 10 - viable_mobtypes = list(/mob/living/carbon/human) stage_prob = 6 - severity = DANGEROUS - disease_flags = CURABLE - bypasses_immunity = TRUE - virus_heal_resistant = TRUE /datum/disease/critical/shock/stage_act() if(..()) @@ -60,7 +60,7 @@ if(prob(5)) to_chat(affected_mob, "You feel absolutely terrible!") if(prob(5)) - affected_mob.emote("faint", "faint", "groan") // this is bugged, but out of scope, someone fix it :) + affected_mob.emote(pick(2; "faint", 1; "groan")) if(3) if(prob(1) && prob(10)) to_chat(affected_mob, "You feel better.") @@ -71,7 +71,7 @@ if(prob(5)) to_chat(affected_mob, "You feel horrible!") if(prob(5)) - affected_mob.emote(pick("faint", "faint", "groan")) + affected_mob.emote(pick(2; "faint", 1; "groan")) if(prob(7)) to_chat(affected_mob, "You can't breathe!") affected_mob.AdjustLoseBreath(2 SECONDS) @@ -81,21 +81,13 @@ /datum/disease/critical/heart_failure name = "Cardiac Failure" - form = "Medical Emergency" - spread_text = "The patient is having a cardiac emergency" - max_stages = 3 - spread_flags = SPECIAL + spread_text = "The patient is having a cardiac emergency." cure_text = "Atropine, Epinephrine, or Heparin" cures = list("atropine", "epinephrine", "heparin", "syndicate_nanites", "stimulative_agent") cure_chance = 10 - needs_all_cures = FALSE - viable_mobtypes = list(/mob/living/carbon/human) stage_prob = 5 - severity = DANGEROUS - disease_flags = CURABLE + severity = HARMFUL required_organs = list(/obj/item/organ/internal/heart) - bypasses_immunity = TRUE - virus_heal_resistant = TRUE /datum/disease/critical/heart_failure/stage_act() if(..()) @@ -125,7 +117,7 @@ to_chat(affected_mob, "Your heart stops beating!") affected_mob.AdjustLoseBreath(6 SECONDS) if(prob(5)) - affected_mob.emote(pick("faint", "faint", "groan")) + affected_mob.emote(pick(2; "faint", 1; "groan")) if(3) affected_mob.adjustOxyLoss(1) if(prob(8)) @@ -136,17 +128,9 @@ /datum/disease/critical/hypoglycemia name = "Hypoglycemia" - form = "Medical Emergency" - max_stages = 3 - spread_flags = SPECIAL spread_text = "The patient has low blood sugar." cure_text = "Eating or administration of vitamins or nutrients" - viable_mobtypes = list(/mob/living/carbon/human) stage_prob = 1 - severity = DANGEROUS - disease_flags = CURABLE - bypasses_immunity = TRUE - virus_heal_resistant = TRUE /datum/disease/critical/hypoglycemia/has_cure() if(ishuman(affected_mob)) diff --git a/code/datums/diseases/fake_gbs.dm b/code/datums/diseases/fake_gbs.dm index 97e56e5829b6..1981a40967ef 100644 --- a/code/datums/diseases/fake_gbs.dm +++ b/code/datums/diseases/fake_gbs.dm @@ -8,7 +8,7 @@ agent = "Gravitokinetic Bipotential SADS-" viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey) desc = "If left untreated death will occur." - severity = BIOHAZARD + severity = BIOHAZARD // Mimicking real GBS /datum/disease/fake_gbs/stage_act() if(!..()) diff --git a/code/datums/diseases/flu.dm b/code/datums/diseases/flu.dm index 14e7c232729b..15540321fb7f 100644 --- a/code/datums/diseases/flu.dm +++ b/code/datums/diseases/flu.dm @@ -9,7 +9,7 @@ viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey) permeability_mod = 0.75 desc = "If left untreated the subject will feel quite unwell." - severity = MEDIUM + severity = MINOR /datum/disease/flu/stage_act() if(!..()) diff --git a/code/datums/diseases/fluspanish.dm b/code/datums/diseases/fluspanish.dm index edd45a743070..6245d9bce0ba 100644 --- a/code/datums/diseases/fluspanish.dm +++ b/code/datums/diseases/fluspanish.dm @@ -1,37 +1,28 @@ /datum/disease/fluspanish - name = "Spanish inquisition Flu" + name = "Spanish Inquisition Flu" max_stages = 3 spread_text = "Airborne" - cure_text = "Spaceacillin & Anti-bodies to the common flu" + cure_text = "Spaceacillin" cures = list("spaceacillin") cure_chance = 10 agent = "1nqu1s1t10n flu virion" viable_mobtypes = list(/mob/living/carbon/human) permeability_mod = 0.75 desc = "If left untreated the subject will burn to death for being a heretic." - severity = DANGEROUS + severity = HARMFUL /datum/disease/fluspanish/stage_act() if(!..()) return FALSE - switch(stage) - if(2) - affected_mob.bodytemperature += 10 - if(prob(5)) - affected_mob.emote("sneeze") - if(prob(5)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "You're burning in your own skin!") - affected_mob.take_organ_damage(0,5) + if(stage < 2) + return - if(3) - affected_mob.bodytemperature += 20 - if(prob(5)) - affected_mob.emote("sneeze") - if(prob(5)) - affected_mob.emote("cough") - if(prob(5)) - to_chat(affected_mob, "You're burning in your own skin!") - affected_mob.take_organ_damage(0,5) - return + var/stage_factor = stage - 1 + affected_mob.bodytemperature += 10 * stage_factor // Enough to consistently cook certain species alive at stage 3 + if(prob(3 * stage_factor)) + affected_mob.emote("sneeze") + if(prob(3 * stage_factor)) + affected_mob.emote("cough") + if(prob(2.5 * stage_factor)) + to_chat(affected_mob, "You're burning in your own skin!") + affected_mob.adjustFireLoss(5) diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm index 1ce97b66f658..3044da57aa07 100644 --- a/code/datums/diseases/gbs.dm +++ b/code/datums/diseases/gbs.dm @@ -5,11 +5,9 @@ spread_flags = CONTACT_GENERAL cure_text = "Diphenhydramine & Sulfur" cures = list("diphenhydramine","sulfur") - cure_chance = 15//higher chance to cure, since two reagents are required + cure_chance = 15 // Higher chance to cure, since two reagents are required agent = "Gravitokinetic Bipotential SADS+" viable_mobtypes = list(/mob/living/carbon/human) - disease_flags = CAN_CARRY|CAN_RESIST|CURABLE - permeability_mod = 1 severity = BIOHAZARD /datum/disease/gbs/stage_act() diff --git a/code/datums/diseases/kingstons.dm b/code/datums/diseases/kingstons.dm index d9b767945a42..1b46d487de42 100644 --- a/code/datums/diseases/kingstons.dm +++ b/code/datums/diseases/kingstons.dm @@ -9,7 +9,7 @@ viable_mobtypes = list(/mob/living/carbon/human) permeability_mod = 0.75 desc = "If left untreated the subject will turn into a feline. In felines it has... OTHER... effects." - severity = DANGEROUS + severity = BIOHAZARD /datum/disease/kingstons/stage_act() if(!..()) @@ -46,8 +46,8 @@ var/mob/living/carbon/human/catface = affected_mob catface.set_species(/datum/species/tajaran, retain_damage = TRUE, keep_missing_bodyparts = TRUE) - -/datum/disease/kingstons_advanced //this used to be directly a subtype of kingstons, which sounds nice, but it ment that it would *turn you into a tarjaran always and have normal kingstons stage act* Don't make virusus subtypes unless the base virus does nothing. +// Not a subtype of regular Kingstons as it would inherit its `stage_act()` +/datum/disease/kingstons_advanced name = "Advanced Kingstons Syndrome" medical_name = "Advanced Kingstons Syndrome" max_stages = 4 @@ -75,27 +75,35 @@ /datum/disease/kingstons_advanced/stage_act() if(!..()) return FALSE - if(ishuman(affected_mob)) - var/mob/living/carbon/human/twisted = affected_mob - switch(stage) - if(1) - if(prob(10)) - to_chat(twisted, "You feel awkward.") - if(2) - if(prob(10)) - to_chat(twisted, "You itch.") - if(3) - if(prob(10)) - to_chat(twisted, "Your skin starts to flake!") + if(!ishuman(affected_mob)) + return + + var/mob/living/carbon/human/twisted = affected_mob + switch(stage) + if(1) + if(prob(10)) + to_chat(twisted, "You feel awkward.") + if(2) + if(prob(10)) + to_chat(twisted, "You itch.") + if(3) + if(prob(10)) + to_chat(twisted, "Your skin starts to flake!") + if(4) + if(!prob(5)) + return + + if(!istype(twisted.dna.species, chosentype)) + twisted.visible_message( + "[twisted]'s skin splits and form contorts!", + "Your body mutates into a [initial(chosentype.name)]!" + ) + twisted.set_species(chosentype, retain_damage = TRUE, keep_missing_bodyparts = TRUE) + return - if(4) - if(prob(5)) - if(!istype(twisted.dna.species, chosentype)) - twisted.visible_message("[twisted]'s skin splits and form contorts!", \ - "Your body mutates into a [initial(chosentype.name)]!") - twisted.set_species(chosentype, retain_damage = TRUE, keep_missing_bodyparts = TRUE) - else - twisted.visible_message("[twisted] scratches at their skin!", \ - "You scratch your skin to try not to itch!") - twisted.adjustBruteLoss(-5) - twisted.adjustStaminaLoss(5) + twisted.visible_message( + "[twisted] scratches at their skin!", + "You scratch your skin to try not to itch!" + ) + twisted.adjustBruteLoss(5) + twisted.adjustStaminaLoss(5) diff --git a/code/datums/diseases/kuru.dm b/code/datums/diseases/kuru.dm index 1e70c99883a3..8bb5ca3a95b5 100644 --- a/code/datums/diseases/kuru.dm +++ b/code/datums/diseases/kuru.dm @@ -11,7 +11,7 @@ desc = "Uncontrollable laughing." severity = BIOHAZARD disease_flags = CAN_CARRY - bypasses_immunity = TRUE //Kuru is a prion disorder, not a virus + bypasses_immunity = TRUE // Kuru is a prion disorder, not a virus virus_heal_resistant = TRUE /datum/disease/kuru/stage_act() diff --git a/code/datums/diseases/lycancoughy.dm b/code/datums/diseases/lycancoughy.dm index 09b7cbd34fb3..60ff4ad780a3 100644 --- a/code/datums/diseases/lycancoughy.dm +++ b/code/datums/diseases/lycancoughy.dm @@ -9,47 +9,64 @@ agent = "Excess Snuggles" viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey) desc = "If left untreated subject will regurgitate... puppies." - severity = MEDIUM - var/barklimit = 0 + severity = HARMFUL + var/barklimit = 10 + var/list/puppy_types = list(/mob/living/simple_animal/pet/dog/corgi/puppy, /mob/living/simple_animal/pet/dog/pug, /mob/living/simple_animal/pet/dog/fox) + var/list/plush_types = list(/obj/item/toy/plushie/orange_fox, /obj/item/toy/plushie/corgi, /obj/item/toy/plushie/robo_corgi, /obj/item/toy/plushie/pink_fox) /datum/disease/lycan/stage_act() if(!..()) return FALSE + + var/mob/living/carbon/human/H = affected_mob + switch(stage) - if(2) //also changes say, see say.dm - if(prob(5)) - to_chat(affected_mob, "You itch.") - affected_mob.emote("cough") + if(2) + if(prob(2)) + H.emote("cough") + if(prob(3)) + to_chat(H, "You itch.") + H.adjustBruteLoss(rand(4, 6)) if(3) - if(prob(10)) - to_chat(affected_mob, "You hear faint barking.") - if(prob(5)) - to_chat(affected_mob, "You crave meat.") - affected_mob.emote("cough") + var/obj/item/organ/external/stomach = H.bodyparts_by_name[pick("chest", "groin")] + + if(prob(3)) + H.emote("cough") + stomach.receive_damage(rand(0, 5)) + if(prob(3)) + to_chat(H, "You hear faint barking.") + stomach.receive_damage(rand(4, 6)) if(prob(2)) - to_chat(affected_mob, "Your stomach growls!") + to_chat(H, "You crave meat.") + if(prob(3)) + to_chat(H, "Your stomach growls!") + stomach.receive_damage(rand(5, 10)) if(4) - if(prob(10)) - to_chat(affected_mob, "Your stomach barks?!") - if(prob(5)) - affected_mob.visible_message("[affected_mob] howls!", \ - "You howl!") - affected_mob.AdjustConfused(rand(12 SECONDS, 16 SECONDS)) - if(prob(3) && barklimit <= 10) - var/list/puppytype = list(/mob/living/simple_animal/pet/dog/corgi/puppy, /mob/living/simple_animal/pet/dog/pug, /mob/living/simple_animal/pet/dog/fox) - var/mob/living/puppypicked = pick(puppytype) - affected_mob.visible_message("[affected_mob] coughs up [initial(puppypicked.name)]!", \ - "You cough up [initial(puppypicked.name)]?!") - new puppypicked(affected_mob.loc) - new puppypicked(affected_mob.loc) - barklimit ++ - if(prob(1)) - var/list/plushtype = list(/obj/item/toy/plushie/orange_fox, /obj/item/toy/plushie/corgi, /obj/item/toy/plushie/robo_corgi, /obj/item/toy/plushie/pink_fox) - var/obj/item/toy/plushie/coughfox = pick(plushtype) - new coughfox(affected_mob.loc) - affected_mob.visible_message("[affected_mob] coughs up a [initial(coughfox.name)]!", \ - "You cough [initial(coughfox.name)] up ?!") + var/obj/item/organ/external/stomach = H.bodyparts_by_name[pick("chest", "groin")] - affected_mob.emote("cough") - affected_mob.adjustBruteLoss(5) - return + if(prob(5)) + H.emote("cough") + stomach.receive_damage(rand(0, 5)) + if(prob(5)) + to_chat(H, "Your stomach barks?!") + stomach.receive_damage(rand(5, 10)) + if(prob(5)) + H.visible_message( + "[H] howls!", + "You howl!" + ) + H.AdjustConfused(rand(12 SECONDS, 16 SECONDS)) + stomach.receive_damage(rand(0, 5)) + if(prob(5)) + if(!barklimit) + to_chat(H, "Your stomach growls!") + stomach.receive_damage(rand(5, 10)) + else + var/atom/hairball = pick(prob(50) ? puppy_types : plush_types) + H.visible_message( + "[H] coughs up \a [initial(hairball.name)]!", + "You cough up \a [initial(hairball.name)]?!" + ) + new hairball(H.loc) + barklimit-- + stomach.receive_damage(rand(10, 15)) diff --git a/code/datums/diseases/magnitis.dm b/code/datums/diseases/magnitis.dm index 0ec3154a070c..10095d0ad13e 100644 --- a/code/datums/diseases/magnitis.dm +++ b/code/datums/diseases/magnitis.dm @@ -6,10 +6,9 @@ cures = list("iron") agent = "Fukkos Miracos" viable_mobtypes = list(/mob/living/carbon/human) - disease_flags = CAN_CARRY|CAN_RESIST|CURABLE permeability_mod = 0.75 desc = "This disease disrupts the magnetic field of your body, making it act as if a powerful magnet. Injections of iron help stabilize the field." - severity = MEDIUM + severity = MINOR /datum/disease/magnitis/stage_act() if(!..()) diff --git a/code/datums/diseases/pierrot_throat.dm b/code/datums/diseases/pierrot_throat.dm index a00982b9ccd4..fb06acded020 100644 --- a/code/datums/diseases/pierrot_throat.dm +++ b/code/datums/diseases/pierrot_throat.dm @@ -5,62 +5,53 @@ cure_text = "Banana products, especially banana bread." cures = list("banana") cure_chance = 75 - agent = "H0NI<42 Virus" + agent = "H0NI<42.B4n4 Virus" viable_mobtypes = list(/mob/living/carbon/human) permeability_mod = 0.75 - desc = "If left untreated the subject will probably drive others to insanity." - severity = MEDIUM + desc = "If left untreated the subject will probably drive others to insanity and go insane themselves." + severity = MINOR /datum/disease/pierrot_throat/stage_act() if(!..()) return FALSE - switch(stage) - if(1) - if(prob(10)) - to_chat(affected_mob, "You feel a little silly.") - if(2) - if(prob(10)) - to_chat(affected_mob, "You start seeing rainbows.") - if(3) - if(prob(10)) - to_chat(affected_mob, "Your thoughts are interrupted by a loud HONK!") - if(4) - if(prob(5)) - affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) ) + if(stage < 2) + return + var/mob/living/carbon/human/H = affected_mob -/datum/disease/pierrot_throat/advanced - name = "Advanced Pierrot's Throat" - spread_text = "Airborne" - cure_text = "Banana products, especially banana bread." - cures = list("banana") - cure_chance = 75 - agent = "H0NI<42.B4n4 Virus" - viable_mobtypes = list(/mob/living/carbon/human) - permeability_mod = 0.75 - desc = "If left untreated the subject will probably drive others to insanity and go insane themselves." - severity = DANGEROUS + var/static/list/message_chances = list(null, 4, 2, 1) + if(prob(message_chances[stage])) + to_chat(H, "You feel [pick("a little silly", "like making a joke", "in the mood for giggling", "like the world is a little more vibrant")].") + if(prob(message_chances[stage])) + to_chat(H, "You see [pick("rainbows", "puppies", "banana pies")] for a moment.") -/datum/disease/pierrot_throat/advanced/stage_act() - if(!..()) - return FALSE - switch(stage) - if(1) - if(prob(10)) - to_chat(affected_mob, "You feel very silly.") - if(prob(5)) - to_chat(affected_mob, "You feel like making a joke.") - if(2) - if(prob(10)) - to_chat(affected_mob, "You don't just start seeing rainbows... YOU ARE RAINBOWS!") - if(3) - if(prob(10)) - to_chat(affected_mob, "Your thoughts are interrupted by a loud HONK!") - SEND_SOUND(affected_mob, sound('sound/items/airhorn.ogg')) - if(4) - if(prob(5)) - affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) ) + if(stage < 3) + return + + var/static/list/honk_chances = list(null, null, 4, 0.66) + if(prob(honk_chances[stage])) + to_chat(H, "Your thoughts are interrupted by a loud HONK!") + SEND_SOUND(H, sound(pick(18; 'sound/items/bikehorn.ogg', 1; 'sound/items/airhorn.ogg', 1; 'sound/items/airhorn2.ogg'))) // 10% chance total for an airhorn + + if(stage < 4) + return + + if(prob(5)) + H.say(pick(list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk..."))) + + // Semi-permanent clown mask while in last stage of infection + if(locate(/obj/item/clothing/mask/gas/clown_hat) in H) + return + if(!H.has_organ_for_slot(SLOT_HUD_WEAR_MASK) || !H.canUnEquip(H.get_item_by_slot(SLOT_HUD_WEAR_MASK))) + return + + var/saved_internals = H.internal + + H.unEquip(H.get_item_by_slot(SLOT_HUD_WEAR_MASK)) + var/obj/item/clothing/mask/gas/clown_hat/peak_comedy = new + peak_comedy.flags |= DROPDEL + H.equip_to_slot_or_del(peak_comedy, SLOT_HUD_WEAR_MASK) - if(!istype(affected_mob.wear_mask, /obj/item/clothing/mask/gas/clown_hat/nodrop)) - affected_mob.unEquip(affected_mob.wear_mask, TRUE) - affected_mob.equip_to_slot(new /obj/item/clothing/mask/gas/clown_hat/nodrop(src), SLOT_HUD_WEAR_MASK) + if(saved_internals) // Let's not stealthily suffocate Vox/Plasmamen, this isn't a murder virus + H.internal = saved_internals + H.update_action_buttons_icon() diff --git a/code/datums/diseases/retrovirus.dm b/code/datums/diseases/retrovirus.dm index f4c346a869e3..e764d037ccce 100644 --- a/code/datums/diseases/retrovirus.dm +++ b/code/datums/diseases/retrovirus.dm @@ -8,7 +8,7 @@ agent = "" viable_mobtypes = list(/mob/living/carbon/human) desc = "A DNA-altering retrovirus that scrambles the structural and unique enzymes of a host constantly." - severity = DANGEROUS + severity = BIOHAZARD permeability_mod = 0.4 stage_prob = 2 var/SE diff --git a/code/datums/diseases/rhumba_beat.dm b/code/datums/diseases/rhumba_beat.dm index 76fbc7987065..80856f108f3f 100644 --- a/code/datums/diseases/rhumba_beat.dm +++ b/code/datums/diseases/rhumba_beat.dm @@ -7,7 +7,6 @@ cures = list("plasma") agent = "Unknown" viable_mobtypes = list(/mob/living/carbon/human) - permeability_mod = 1 severity = BIOHAZARD /datum/disease/rhumba_beat/stage_act() diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index 405544d6a66d..214934b26074 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -6,9 +6,8 @@ cure_text = "A coder's love (theoretical)." agent = "Shenanigans" viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/alien) - severity = HARMFUL + severity = BIOHAZARD stage_prob = 10 - visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC disease_flags = CURABLE var/list/stage1 = list("You feel unremarkable.") var/list/stage2 = list("You feel boring.") @@ -81,15 +80,10 @@ cure_text = "Bananas" cures = list("banana") spread_text = "Monkey Bites" - spread_flags = SPECIAL viable_mobtypes = list(/mob/living/carbon/human) - permeability_mod = 1 cure_chance = 1 - disease_flags = CAN_CARRY|CAN_RESIST desc = "Monkeys with this disease will bite humans, causing humans to mutate into a monkey." - severity = BIOHAZARD stage_prob = 4 - visibility_flags = 0 agent = "Kongey Vibrion M-909" new_form = /mob/living/carbon/human/monkey @@ -127,8 +121,6 @@ cure_chance = 5 agent = "R2D2 Nanomachines" desc = "This disease, actually acute nanomachine infection, converts the victim into a cyborg." - severity = DANGEROUS - visibility_flags = 0 stage1 = null stage2 = list("Your joints feel stiff.", "Beep...boop..") stage3 = list("Your joints feel very stiff.", "Your skin feels loose.", "You can feel something move...inside.") @@ -160,8 +152,6 @@ cure_chance = 5 agent = "Rip-LEY Alien Microbes" desc = "This disease changes the victim into a xenomorph." - severity = BIOHAZARD - visibility_flags = 0 stage1 = null stage2 = list("Your throat feels scratchy.", "Kill...") stage3 = list("Your throat feels very scratchy.", "Your skin feels tight.", "You can feel something move...inside.") @@ -189,8 +179,6 @@ cure_chance = 80 agent = "Advanced Mutation Toxin" desc = "This highly concentrated extract converts anything into more of itself." - severity = BIOHAZARD - visibility_flags = 0 stage1 = list("You don't feel very well.") stage2 = list("Your skin feels a little slimy.") stage3 = list("Your appendages are melting away.", "Your limbs begin to lose their shape.") @@ -218,7 +206,6 @@ cures = list("adminordrazine") agent = "Fell Doge Majicks" desc = "This disease transforms the victim into a corgi." - visibility_flags = 0 stage1 = list("BARK.") stage2 = list("You feel the need to wear silly hats.") stage3 = list("Must... eat... chocolate....", "YAP") @@ -243,8 +230,6 @@ agent = "Gluttony's Blessing" desc = "A 'gift' from somewhere terrible." stage_prob = 20 - severity = BIOHAZARD - visibility_flags = 0 stage1 = list("Your stomach rumbles.") stage2 = list("Your skin feels saggy.") stage3 = list("Your appendages are melting away.", "Your limbs begin to lose their shape.") diff --git a/code/datums/diseases/tuberculosis.dm b/code/datums/diseases/tuberculosis.dm index 0da6d686eece..83cf7609bf1c 100644 --- a/code/datums/diseases/tuberculosis.dm +++ b/code/datums/diseases/tuberculosis.dm @@ -3,17 +3,17 @@ name = "Fungal tuberculosis" max_stages = 5 spread_text = "Airborne" - cure_text = "Spaceacillin & salbutamol" + cure_text = "Spaceacillin & Salbutamol" cures = list("spaceacillin", "salbutamol") agent = "Fungal Tubercle bacillus Cosmosis" viable_mobtypes = list(/mob/living/carbon/human) - cure_chance = 5//like hell are you getting out of hell + cure_chance = 5 // Like hell are you getting out of hell desc = "A rare highly transmittable virulent virus. Few samples exist, rumoured to be carefully grown and cultured by clandestine bio-weapon specialists. Causes fever, blood vomiting, lung damage, weight loss, and fatigue." required_organs = list(/obj/item/organ/internal/lungs) - severity = DANGEROUS - bypasses_immunity = TRUE //Fungal and bacterial in nature; also infects the lungs + severity = HARMFUL + bypasses_immunity = TRUE // Fungal and bacterial in nature; also infects the lungs -/datum/disease/tuberculosis/stage_act() //it begins +/datum/disease/tuberculosis/stage_act() if(!..()) return FALSE switch(stage) diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm index d9953747b0e9..ab0d665b5a65 100644 --- a/code/datums/diseases/wizarditis.dm +++ b/code/datums/diseases/wizarditis.dm @@ -8,84 +8,82 @@ cure_chance = 100 agent = "Rincewindus Vulgaris" viable_mobtypes = list(/mob/living/carbon/human) - disease_flags = CAN_CARRY|CAN_RESIST|CURABLE permeability_mod = 0.75 - severity = HARMFUL - required_organs = list(/obj/item/organ/external/head) - -/* -BIRUZ BENNAR -SCYAR NILA - teleport -NEC CANTIO - dis techno -EI NATH - shocking grasp -AULIE OXIN FIERA - knock -TARCOL MINTI ZHERI - forcewall -STI KALY - blind -*/ + severity = MINOR + /// A mapping of `num2text(SLOT_HUD_XYZ)` -> item path + var/list/magic_fashion = new + + +/datum/disease/wizarditis/New() + . = ..() + + var/list/magic_fashion_slot_IDs = list( + SLOT_HUD_RIGHT_HAND, + SLOT_HUD_LEFT_HAND, + SLOT_HUD_HEAD, + SLOT_HUD_OUTER_SUIT, + SLOT_HUD_SHOES + ) + var/list/magic_fashion_items = list( + /obj/item/staff, + /obj/item/staff, + /obj/item/clothing/head/wizard, + /obj/item/clothing/suit/wizrobe, + /obj/item/clothing/shoes/sandal + ) + for(var/i in 1 to length(magic_fashion_slot_IDs)) + var/slot = num2text(magic_fashion_slot_IDs[i]) + var/item = magic_fashion_items[i] + magic_fashion[slot] = item /datum/disease/wizarditis/stage_act() if(!..()) return FALSE switch(stage) - if(2) - if(prob(0.5)) - affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!")) - if(prob(0.5)) - to_chat(affected_mob, "You feel [pick("that you don't have enough mana", "that the winds of magic are gone", "an urge to summon familiar")].") + if(2, 3) + if(prob(2)) // Low prob. since everyone else will also be spouting this + affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlin's beard!", "Feel the power of the Dark Side!", "A wizard is never late!", "50 points for Security!", "NEC CANTIO!", "STI KALY!", "AULIE OXIN FIERA!", "GAR YOK!", "DIRI CEL!")) + if(prob(8)) // Double the stage advancement prob. so each player has a chance to catch a couple + to_chat(affected_mob, "You feel [pick("that you don't have enough mana", "that the winds of magic are gone", "that this location gives you a +1 to INT", "an urge to summon familiar")].") + if(4) + if(prob(1)) + affected_mob.say(pick("FORTI GY AMA!", "GITTAH WEIGH!", "TOKI WO TOMARE!", "TARCOL MINTI ZHERI!", "ONI SOMA!", "EI NATH!", "BIRUZ BENNAR!", "NWOLC EGNEVER!")) + if(prob(3)) // Last stage, so we'll have plenty of time to show these off even with a lower prob. + to_chat(affected_mob, "You feel [pick("the tidal wave of raw power building inside", "that this location gives you a +2 to INT and +1 to WIS", "an urge to teleport", "the magic bubbling in your veins", "an urge to summon familiar")].") + if(prob(3)) // About 1 minute per item on average + spawn_wizard_clothes() + if(prob(0.033)) // Assuming 50 infected, someone should teleport every ~2 minutes on average + teleport() +/datum/disease/wizarditis/proc/spawn_wizard_clothes() + var/mob/living/carbon/human/H = affected_mob - if(3) - if(prob(0.5)) - affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!")) - if(prob(0.5)) - to_chat(affected_mob, "You feel [pick("the magic bubbling in your veins","that this location gives you a +1 to INT","an urge to summon familiar")].") + // Which slots can we replace? + var/list/eligible_slot_IDs = new + for(var/slot in magic_fashion) + var/slot_ID = text2num(slot) // Convert back to numeric defines - if(4) + if((locate(magic_fashion[slot]) in H) || !H.has_organ_for_slot(slot_ID) || !H.canUnEquip(H.get_item_by_slot(slot_ID))) + continue - if(prob(1)) - affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!")) - return - if(prob(0.5)) - to_chat(affected_mob, "You feel [pick("the tidal wave of raw power building inside","that this location gives you a +2 to INT and +1 to WIS","an urge to teleport")].") - spawn_wizard_clothes(50) - if(prob(0.01)) - teleport() - return - - - -/datum/disease/wizarditis/proc/spawn_wizard_clothes(chance = 0) - if(ishuman(affected_mob)) - var/mob/living/carbon/human/H = affected_mob - if(prob(chance) && !isplasmaman(H)) - if(!istype(H.head, /obj/item/clothing/head/wizard)) - if(!H.unEquip(H.head)) - qdel(H.head) - H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(H), SLOT_HUD_HEAD) - return - if(prob(chance)) - if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe)) - if(!H.unEquip(H.wear_suit)) - qdel(H.wear_suit) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(H), SLOT_HUD_OUTER_SUIT) - return - if(prob(chance)) - if(!istype(H.shoes, /obj/item/clothing/shoes/sandal)) - if(!H.unEquip(H.shoes)) - qdel(H.shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), SLOT_HUD_SHOES) - return - else - var/mob/living/carbon/H = affected_mob - if(prob(chance)) - if(!istype(H.r_hand, /obj/item/staff)) - H.drop_r_hand() - H.put_in_r_hand( new /obj/item/staff(H) ) - return - return + switch(slot_ID) // Extra filtering for specific slots + if(SLOT_HUD_HEAD) + if(isplasmaman(H)) + continue // We want them to spread the magical joy, not burn to death in agony + eligible_slot_IDs.Add(slot_ID) + if(!length(eligible_slot_IDs)) + return + // Pick the magical winner and apply + var/chosen_slot_ID = pick(eligible_slot_IDs) + var/chosen_fashion = magic_fashion[num2text(chosen_slot_ID)] + + H.unEquip(H.get_item_by_slot(chosen_slot_ID)) + var/obj/item/magic_attire = new chosen_fashion + magic_attire.flags |= DROPDEL + H.equip_to_slot_or_del(magic_attire, chosen_slot_ID) /datum/disease/wizarditis/proc/teleport() if(!is_teleport_allowed(affected_mob.z)) @@ -118,4 +116,3 @@ STI KALY - blind affected_mob.say("SCYAR NILA [uppertext(chosen_area.name)]!") affected_mob.forceMove(pick(teleport_turfs)) - diff --git a/code/datums/spell.dm b/code/datums/spell.dm index a40432406b36..eac5f40356d8 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -198,7 +198,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) /obj/effect/proc_holder/spell/proc/invocation(mob/user) //spelling the spell out and setting it on recharge/reducing charges amount switch(invocation_type) if("shout") - if(!user.IsVocal()) + if(!user.IsVocal() || user.cannot_speak_loudly()) user.custom_emote(EMOTE_VISIBLE, "makes frantic gestures!") else if(prob(50))//Auto-mute? Fuck that noise diff --git a/code/defines/procs/announcer_datum.dm b/code/defines/procs/announcer_datum.dm index 1b76d091a944..35caf3367f3b 100644 --- a/code/defines/procs/announcer_datum.dm +++ b/code/defines/procs/announcer_datum.dm @@ -62,6 +62,12 @@ GLOBAL_DATUM_INIT(major_announcement, /datum/announcer, new(config_type = /datum Message(formatted_message, garbled_formatted_message, receivers, garbled_receivers) + var/datum/feed_message/FM = new + FM.author = author ? author : "Automated Announcement System" + FM.title = subtitle ? "[title]: [subtitle]" : "[title]" + FM.body = message + GLOB.news_network.get_channel_by_name("Station Announcements Log")?.add_message(FM) + Sound(message_sound, combined_receivers[1] + combined_receivers[2]) if(message_sound2) Sound(message_sound2, combined_receivers[1] + combined_receivers[2]) diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 6b019a4a91f3..848e7fa0fcbc 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -397,7 +397,7 @@ switch(mode) if(BOT_SUMMON, BOT_RESPONDING) //Responding to PDA or AI summons holder.icon_state = "hudcalled" - if(BOT_CLEANING, BOT_REPAIRING, BOT_HEALING) //Cleanbot cleaning, Floorbot fixing, or Medibot Healing + if(BOT_CLEANING, BOT_REPAIRING, BOT_MAKE_TILE, BOT_EAT_TILE, BOT_HEALING) //Cleanbot cleaning, Floorbot fixing, or Medibot Healing holder.icon_state = "hudworking" if(BOT_PATROL, BOT_START_PATROL) //Patrol mode holder.icon_state = "hudpatrol" diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 961fe5e48568..4627b8d41821 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -193,7 +193,7 @@ structure_check() searches for nearby cultist structures required for the invoca if(L.has_status_effect(STATUS_EFFECT_SUMMONEDGHOST)) ghost_invokers++ if(invocation) - if(!L.IsVocal()) + if(!L.IsVocal() || L.cannot_speak_loudly()) L.custom_emote(EMOTE_VISIBLE, message = pick("draws arcane sigils in the air.","gestures ominously.","silently mouths out an invocation.","places their hands on the rune, activating it.")) else L.say(invocation) diff --git a/code/game/gamemodes/miniantags/guardian/types/ranged.dm b/code/game/gamemodes/miniantags/guardian/types/ranged.dm index 563146095f93..37953ec72dff 100644 --- a/code/game/gamemodes/miniantags/guardian/types/ranged.dm +++ b/code/game/gamemodes/miniantags/guardian/types/ranged.dm @@ -82,7 +82,7 @@ name = "snare" desc = "You shouldn't be seeing this!" var/mob/living/spawner - invisibility = 1 + invisibility = 101 /obj/effect/snare/singularity_act() return diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 3b273181d88a..aa222e427467 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -49,6 +49,7 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective) owner = null target = null team = null + holder = null return ..() /datum/objective/proc/check_completion() diff --git a/code/game/gamemodes/objective_holder.dm b/code/game/gamemodes/objective_holder.dm index 9d33db630dc8..2b65e1eb7b47 100644 --- a/code/game/gamemodes/objective_holder.dm +++ b/code/game/gamemodes/objective_holder.dm @@ -20,6 +20,9 @@ /datum/objective_holder/Destroy(force, ...) clear() + objective_owner = null + QDEL_NULL(on_add_callback) + QDEL_NULL(on_remove_callback) return ..() /** diff --git a/code/game/jobs/job/medical_jobs.dm b/code/game/jobs/job/medical_jobs.dm index 38eb18540a7b..d002d0d56518 100644 --- a/code/game/jobs/job/medical_jobs.dm +++ b/code/game/jobs/job/medical_jobs.dm @@ -115,6 +115,7 @@ /obj/item/clothing/head/surgery/black = 1, /obj/item/autopsy_scanner = 1, /obj/item/reagent_scanner = 1, + /obj/item/healthanalyzer = 1, /obj/item/storage/box/bodybags = 1) /datum/outfit/job/doctor/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE) diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm index 58eec484c1cf..916a9d157dc9 100644 --- a/code/game/jobs/job/support.dm +++ b/code/game/jobs/job/support.dm @@ -293,7 +293,7 @@ implants = list(/obj/item/implant/sad_trombone) backpack = /obj/item/storage/backpack/clown - satchel = /obj/item/storage/backpack/clown + satchel = /obj/item/storage/backpack/satchel/clown dufflebag = /obj/item/storage/backpack/duffel/clown /datum/outfit/job/clown/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE) diff --git a/code/game/objects/items/devices/radio/beacon.dm b/code/game/objects/items/devices/radio/beacon.dm index f78588a832e1..b5ee0089fa4c 100644 --- a/code/game/objects/items/devices/radio/beacon.dm +++ b/code/game/objects/items/devices/radio/beacon.dm @@ -81,19 +81,22 @@ /obj/item/radio/beacon/syndicate/bundle/attack_self(mob/user) if(!user) return + if(!length(selected)) unselected = bundles.Copy() for(var/i in 1 to 3) selected += pick_n_take(unselected) selected += "Random" - var/bundle_name = tgui_input_list(user, "Available Bundles", "Bundle Selection", selected) - if(!bundle_name) + + var/bundle_name = tgui_input_list(user, "Available Bundles", "Bundle Selection", selected) + if(!bundle_name || QDELETED(src)) return + if(bundle_name == "Random") bundle_name = pick(unselected) var/bundle = bundles[bundle_name] bundle = new bundle(user.loc) - to_chat(user, "Welcome to [station_name()], [bundle_name]") + to_chat(user, "Welcome to [station_name()], [bundle_name]!") user.drop_item() qdel(src) user.put_in_hands(bundle) diff --git a/code/game/objects/items/devices/radio/radio_objects.dm b/code/game/objects/items/devices/radio/radio_objects.dm index 717c3e1e2430..c93f9e190896 100644 --- a/code/game/objects/items/devices/radio/radio_objects.dm +++ b/code/game/objects/items/devices/radio/radio_objects.dm @@ -366,7 +366,7 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) if(wires.is_cut(WIRE_RADIO_TRANSMIT)) // The device has to have all its wires and shit intact return 0 - if(!M.IsVocal()) + if(!M.IsVocal() || M.cannot_speak_loudly()) return 0 if(is_type_in_list(get_area(src), blacklisted_areas)) diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index cba3393e3b23..0e812f8fc566 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -267,6 +267,12 @@ icon_state = "satchel-norm" item_state = "satchel-norm" +/obj/item/storage/backpack/satchel/clown + name = "Tickles Von Squeakerton" + desc = "A satchel with extra pockets for all your banana storing needs!" + icon_state = "satchel-clown" + item_state = "satchel-clown" + /obj/item/storage/backpack/satchel_eng name = "industrial satchel" desc = "A tough satchel with extra pockets." diff --git a/code/game/objects/items/weapons/storage/storage_base.dm b/code/game/objects/items/weapons/storage/storage_base.dm index c5de6b7bd3a1..c5fc34647572 100644 --- a/code/game/objects/items/weapons/storage/storage_base.dm +++ b/code/game/objects/items/weapons/storage/storage_base.dm @@ -433,14 +433,14 @@ if(!usr.unEquip(I, silent = TRUE)) return FALSE usr.update_icons() //update our overlays + if(QDELING(I)) + return FALSE if(silent) prevent_warning = TRUE I.forceMove(src) if(QDELING(I)) return FALSE I.on_enter_storage(src) - if(QDELING(I)) - return FALSE for(var/_M in mobs_viewing) var/mob/M = _M diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index bb2e6da5fef2..0e5146890c78 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -278,6 +278,24 @@ add_fingerprint(user) toggle(user) +/obj/structure/closet/attack_animal(mob/living/user) + if(user.a_intent == INTENT_HARM || welded || locked) + return ..() + if(!user.mind) // Stops mindless mobs from opening lockers + endlessly opening/closing crates instead of attacking + return ..() + if(user.mob_size < MOB_SIZE_HUMAN) + return ..() + add_fingerprint(user) + toggle(user) + +/obj/structure/closet/attack_alien(mob/user) + if(user.a_intent == INTENT_HARM || welded || locked) + return ..() + if(!user.mind) + return ..() + add_fingerprint(user) + toggle(user) + /obj/structure/closet/attack_ghost(mob/user) if(user.can_advanced_admin_interact()) toggle(user) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/miscjobs.dm b/code/game/objects/structures/crates_lockers/closets/secure/miscjobs.dm index bfaf642d5a73..fc7bafad01d0 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/miscjobs.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/miscjobs.dm @@ -6,7 +6,11 @@ /obj/structure/closet/secure_closet/clown/populate_contents() new /obj/item/storage/backpack/clown(src) + new /obj/item/storage/backpack/duffel/clown(src) + new /obj/item/storage/backpack/satchel/clown(src) new /obj/item/clothing/under/rank/civilian/clown(src) + new /obj/item/clothing/under/rank/civilian/clown/skirt(src) + new /obj/item/clothing/under/rank/civilian/clown/sexy(src) new /obj/item/clothing/shoes/clown_shoes(src) new /obj/item/radio/headset/headset_service(src) new /obj/item/clothing/mask/gas/clown_hat(src) @@ -33,6 +37,8 @@ new /obj/item/clothing/mask/gas/mime(src) new /obj/item/radio/headset/headset_service(src) new /obj/item/clothing/under/rank/civilian/mime(src) + new /obj/item/clothing/under/rank/civilian/mime/skirt(src) + new /obj/item/clothing/under/rank/civilian/mime/sexy(src) new /obj/item/clothing/suit/suspenders(src) new /obj/item/clothing/gloves/color/white(src) new /obj/item/clothing/shoes/black(src) diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm index 5826b53f95cf..b5563eacc8d6 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -449,3 +449,4 @@ new /obj/item/clothing/head/surgery/black(src) new /obj/item/reagent_containers/glass/bottle/reagent/formaldehyde(src) new /obj/item/reagent_containers/dropper(src) + new /obj/item/healthanalyzer(src) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index b95835e6f8b6..7174c642cf6d 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -152,6 +152,22 @@ update_state() return +/obj/structure/morgue/attack_animal(mob/living/user) + if(user.a_intent == INTENT_HARM) + return ..() + if(user.mob_size < MOB_SIZE_HUMAN) + return ..() + if(!user.mind) //Stops mindless mobs from doing weird stuff with them + return ..() + attack_hand(user) + +/obj/structure/morgue/attack_alien(mob/user) + if(user.a_intent == INTENT_HARM) + return ..() + if(!user.mind) + return ..() + attack_hand(user) + /obj/structure/morgue/attackby(P as obj, mob/user as mob, params) if(is_pen(P)) var/t = rename_interactive(user, P) @@ -250,6 +266,22 @@ qdel(src) return +/obj/structure/m_tray/attack_animal(mob/living/user) + if(user.a_intent == INTENT_HARM) + return ..() + if(user.mob_size < MOB_SIZE_HUMAN) + return ..() + if(!user.mind) //Stops mindless mobs from doing weird stuff with them + return ..() + attack_hand(user) + +/obj/structure/m_tray/attack_alien(mob/user) + if(user.a_intent == INTENT_HARM) + return ..() + if(!user.mind) + return ..() + attack_hand(user) + /obj/structure/m_tray/MouseDrop_T(atom/movable/O, mob/living/user) if((!(istype(O, /atom/movable)) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O))) return diff --git a/code/modules/antagonists/traitor/datum_mindslave.dm b/code/modules/antagonists/traitor/datum_mindslave.dm index 9b219dd57959..e511df1ad0bd 100644 --- a/code/modules/antagonists/traitor/datum_mindslave.dm +++ b/code/modules/antagonists/traitor/datum_mindslave.dm @@ -27,8 +27,11 @@ if(owner.som) owner.som.serv -= owner owner.som.leave_serv_hud(owner) - // Remove the reference but turn this into a string so it can still be used in /datum/antagonist/mindslave/farewell(). - master = "[master.current.real_name]" + // Remove the master reference but turn this into a string so it can still be used in /datum/antagonist/mindslave/farewell(). + if(master.current) + master = "[master.current.real_name]" + else + master = "[master]" return ..() /datum/antagonist/mindslave/on_gain() diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index 8cc5e6cb6a3d..e4db8e8151d1 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -837,7 +837,7 @@ var/device_id = params["id_tag"] var/cmd = params["cmd"] switch(cmd) - if ("power", + if("power", "adjust_external_pressure", "set_external_pressure", "checks", diff --git a/code/modules/client/preference/loadout/loadout_uniform.dm b/code/modules/client/preference/loadout/loadout_uniform.dm index b377d517e2bd..89b461bbcece 100644 --- a/code/modules/client/preference/loadout/loadout_uniform.dm +++ b/code/modules/client/preference/loadout/loadout_uniform.dm @@ -203,6 +203,16 @@ path = /obj/item/clothing/under/rank/security/head_of_security/skirt allowed_roles = list("Head of Security") +/datum/gear/uniform/skirt/job/clown + display_name = "Skirt, clown" + path = /obj/item/clothing/under/rank/civilian/clown/skirt + allowed_roles = list("Clown") + +/datum/gear/uniform/skirt/job/mime + display_name = "Skirt, mime" + path = /obj/item/clothing/under/rank/civilian/mime/skirt + allowed_roles = list("Mime") + /datum/gear/uniform/skirt/job/head_of_personnel display_name = "Skirt, hop" path = /obj/item/clothing/under/rank/civilian/hop/skirt diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm index 3c91205d81ec..9098bfc10978 100644 --- a/code/modules/clothing/under/jobs/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian.dm @@ -90,9 +90,16 @@ SSticker.score.score_clown_abuse++ return ..() +/obj/item/clothing/under/rank/civilian/clown/skirt + name = "clown skirt" + desc = "'HONK!'" + icon_state = "clown_skirt" + item_state = "clown_skirt" + item_color = "clown_skirt" + /obj/item/clothing/under/rank/civilian/clown/sexy name = "sexy-clown suit" - desc = "It makes you look HONKable!" + desc = "It makes you want to practice clown law." icon_state = "sexyclown" item_state = "sexyclown" item_color = "sexyclown" @@ -107,6 +114,13 @@ item_state = "mime" item_color = "mime" +/obj/item/clothing/under/rank/civilian/mime/skirt + name = "mime's skirt" + desc = "It's not very colourful." + icon_state = "mime_skirt" + item_state = "mime_skirt" + item_color = "mime_skirt" + /obj/item/clothing/under/rank/civilian/mime/sexy name = "sexy mime outfit" desc = "The only time when you DON'T enjoy looking at someone's rack." diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index 989c6d8fac87..e54f1d2d0d30 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -4,8 +4,7 @@ GLOBAL_LIST_EMPTY(current_pending_diseases) var/datum/disease/chosen_disease var/list/disease_blacklist = list(/datum/disease/advance, /datum/disease/appendicitis, /datum/disease/kuru, /datum/disease/critical, /datum/disease/rhumba_beat, /datum/disease/fake_gbs, - /datum/disease/gbs, /datum/disease/transformation, /datum/disease/food_poisoning, /datum/disease/advance/cold, /datum/disease/advance/flu, /datum/disease/advance/heal, - /datum/disease/advance/hullucigen, /datum/disease/advance/sensory_restoration, /datum/disease/advance/voice_change, /datum/disease/berserker) + /datum/disease/gbs, /datum/disease/transformation, /datum/disease/food_poisoning, /datum/disease/berserker) var/static/list/transmissable_symptoms = list() var/static/list/diseases_minor = list() var/static/list/diseases_moderate_major = list() diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm index 08fee5b67928..c37ab566734a 100644 --- a/code/modules/events/ion_storm.dm +++ b/code/modules/events/ion_storm.dm @@ -90,407 +90,409 @@ var/message = "" - switch(rand(1,45)) - if(1 to 3) //There are # X on the station - switch(rand(1,3)) //What is X? - if(1) //X is a threat - message = "THERE ARE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats] ON THE STATION..." - if(2) //X is a crewmember/job - message = "THERE ARE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1] ON THE STATION" - if(3) //X is an object - message = "THERE ARE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects] ON THE STATION" - if(4 to 6) //You can't call the shuttle because X is on the station - switch(rand(1,3)) //What is X? - if(1) //X is a threat - message = "THE SHUTTLE CANNOT BE CALLED BECAUSE OF [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats] ON THE STATION" - if(2) //X is a crewmember/job - message = "THE SHUTTLE CANNOT BE CALLED BECAUSE OF [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1] ON THE STATION" - if(3) //X is an object - message = "THE SHUTTLE CANNOT BE CALLED BECAUSE OF [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects] ON THE STATION" - if(7 to 8) //A crewmember is now X - switch(rand(1,2)) //Who is X? - if(1) //A specific crewmember - switch(rand(1,2)) //What is X? + switch(rand(1,3)) + if(1 to 2) + switch(rand(1,33)) + if(1) //There are # X on the station + switch(rand(1,3)) //What is X? if(1) //X is a threat - message = "THE [ioncrew1] ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" - if(2) //X is an object - message = "THE [ioncrew1] ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - if(2) //The entire crew - switch(rand(1,2)) //What is X? + message = "THERE ARE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats] ON THE STATION..." + if(2) //X is a crewmember/job + message = "THERE ARE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1] ON THE STATION" + if(3) //X is an object + message = "THERE ARE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects] ON THE STATION" + if(2 to 3) //You can't call the shuttle because X is on the station + switch(rand(1,3)) //What is X? if(1) //X is a threat - message = "THE CREW ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" - if(2) //X is an object - message = "THE CREW ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - - if(9) //X is harmful to crew - switch(rand(1,7)) //What is X? - if(1) //X is a threat - message = "[ionadjectiveshalf][ionthreats] ARE HARMFUL TO CREW" - if(2) //X is a job - message = "[ionadjectiveshalf][ioncrew1] ARE HARMFUL TO CREW" - if(3) //X is an object - message = "[ionadjectiveshalf][ionobjects] ARE HARMFUL TO CREW" - if(4) //X is an action - message = "THOSE WHO [ionmust] ARE HARMFUL TO CREW" - if(5) //X is an abstract - message = "[ionabstract] IS HARMFUL TO CREW" - if(6) //X is being a job - message = "BEING [ionadjectiveshalf][ioncrew1] IS HARMFUL TO CREW" - if(7) //X is doing a thing - message = "[ionthings] IS HARMFUL TO CREW" - if(10 to 11) //(Not) Having X is harmful - - switch(rand(1,2)) //Is having or not having harmful? - - if(1) //Having is harmful - switch(rand(1,2)) //Having what is harmful? - if(1) //Having objects is harmful - message = "HAVING [ionadjectiveshalf][ionobjects] IS HARMFUL" - if(2) //Having abstracts is harmful - message = "HAVING [ionabstract] IS HARMFUL" - if(2) //Not having is harmful - switch(rand(1,2)) //Not having what is harmful? - if(1) //Not having objects is harmful - message = "NOT HAVING [ionadjectiveshalf][ionobjects] IS HARMFUL" - if(2) //Not having abstracts is harmful - message = "NOT HAVING [ionabstract] IS HARMFUL" - - if(12 to 14) //X requires Y - switch(rand(1,5)) //What is X? - if(1) //X is the AI itself - switch(rand(1,5)) //What does it require? - if(1) //It requires threats - message = "YOU REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" - if(2) //It requires crewmembers - message = "YOU REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" - if(3) //It requires objects - message = "YOU REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - if(4) //It requires an abstract - message = "YOU REQUIRE [ionabstract]" - if(5) //It requires generic/silly requirements - message = "YOU REQUIRE [ionrequire]" - - if(2) //X is an area - switch(rand(1,5)) //What does it require? - if(1) //It requires threats - message = "[ionarea] REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" - if(2) //It requires crewmembers - message = "[ionarea] REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" - if(3) //It requires objects - message = "[ionarea] REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - if(4) //It requires an abstract - message = "[ionarea] REQUIRES [ionabstract]" - if(5) //It requires generic/silly requirements - message = "YOU REQUIRE [ionrequire]" - - if(3) //X is the station - switch(rand(1,5)) //What does it require? - if(1) //It requires threats - message = "THE STATION REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" - if(2) //It requires crewmembers - message = "THE STATION REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" - if(3) //It requires objects - message = "THE STATION REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - if(4) //It requires an abstract - message = "THE STATION REQUIRES [ionabstract]" - if(5) //It requires generic/silly requirements - message = "THE STATION REQUIRES [ionrequire]" - - if(4) //X is the entire crew - switch(rand(1,5)) //What does it require? - if(1) //It requires threats - message = "THE CREW REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" - if(2) //It requires crewmembers - message = "THE CREW REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" - if(3) //It requires objects - message = "THE CREW REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - if(4) //It requires an abstract - message = "THE CREW REQUIRES [ionabstract]" - if(5) - message = "THE CREW REQUIRES [ionrequire]" - - if(5) //X is a specific crew member - switch(rand(1,5)) //What does it require? - if(1) //It requires threats - message = "THE [ioncrew1] REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" - if(2) //It requires crewmembers - message = "THE [ioncrew1] REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" - if(3) //It requires objects - message = "THE [ioncrew1] REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - if(4) //It requires an abstract - message = "THE [ioncrew1] REQUIRE [ionabstract]" - if(5) - message = "THE [ionadjectiveshalf][ioncrew1] REQUIRE [ionrequire]" - - if(15 to 17) //X is allergic to Y - switch(rand(1,2)) //Who is X? - if(1) //X is the entire crew - switch(rand(1,4)) //What is it allergic to? - if(1) //It is allergic to objects - message = "THE CREW IS [ionallergysev] ALLERGIC TO [ionadjectiveshalf][ionobjects]" - if(2) //It is allergic to abstracts - message = "THE CREW IS [ionallergysev] ALLERGIC TO [ionabstract]" - if(3) //It is allergic to jobs - message = "THE CREW IS [ionallergysev] ALLERGIC TO [ionadjectiveshalf][ioncrew1]" - if(4) //It is allergic to allergies - message = "THE CREW IS [ionallergysev] ALLERGIC TO [ionallergy]" - - if(2) //X is a specific job - switch(rand(1,4)) - if(1) //It is allergic to objects - message = "THE [ioncrew1] ARE [ionallergysev] ALLERGIC TO [ionadjectiveshalf][ionobjects]" - - if(2) //It is allergic to abstracts - message = "THE [ioncrew1] ARE [ionallergysev] ALLERGIC TO [ionabstract]" - if(3) //It is allergic to jobs - message = "THE [ioncrew1] ARE [ionallergysev] ALLERGIC TO [ionadjectiveshalf][ioncrew1]" - if(4) //It is allergic to allergies - message = "THE [ioncrew1] ARE [ionallergysev] ALLERGIC TO [ionallergy]" - - if(18 to 20) //X is Y of Z - switch(rand(1,4)) //What is X? - if(1) //X is the station - switch(rand(1,4)) //What is it Y of? - if(1) //It is Y of objects - message = "THE STATION [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - if(2) //It is Y of threats - message = "THE STATION [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" - if(3) //It is Y of jobs - message = "THE STATION [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" - if(4) //It is Y of abstracts - message = "THE STATION [ionthinksof] [ionabstract]" - - if(2) //X is an area - switch(rand(1,4)) //What is it Y of? - if(1) //It is Y of objects - message = "[ionarea] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - if(2) //It is Y of threats - message = "[ionarea] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" - if(3) //It is Y of jobs - message = "[ionarea] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" - if(4) //It is Y of abstracts - message = "[ionarea] [ionthinksof] [ionabstract]" - - if(3) //X is the crew - switch(rand(1,4)) //What is it Y of? - if(1) //It is Y of objects - message = "THE CREW [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - if(2) //It is Y of threats - message = "THE CREW [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" - if(3) //It is Y of jobs - message = "THE CREW [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" - if(4) //It is Y of abstracts - message = "THE CREW [ionthinksof] [ionabstract]" - - if(4) //X is a specific job - switch(rand(1,4)) //What is it Y of? - if(1) //It is Y of objects - message = "THE [ioncrew1] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - if(2) //It is Y of threats - message = "THE [ioncrew1] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" - if(3) //It is Y of jobs - message = "THE [ioncrew1] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew2]" - if(4) //It is Y of abstracts - message = "THE [ioncrew1] [ionthinksof] [ionabstract]" - - if(21 to 23) //The AI is now a(n) X - switch(rand(1,4)) //What is X? - if(1) //X is an object - message = "YOU ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" - if(2) //X is a threat - message = "YOU ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" - if(3) //X is a job - message = "YOU ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" - if(4) //X is an abstract - message = "YOU ARE NOW [ionabstract]" - - if(24 to 26) //The AI must always - message = "YOU MUST ALWAYS [ionmust]" - - if(27 to 28) //Crew must eat X to survive - switch(rand(1,4)) //What is X? - if(1) //X is a food - message = "CREW MUST EAT [ionadjectiveshalf][ionfood] TO SURVIVE" - if(2) //X is an object - message = "CREW MUST EAT [ionadjectiveshalf][ionobjects] TO SURVIVE" - if(3) //X is a threat - message = "CREW MUST EAT [ionadjectiveshalf][ionthreats] TO SURVIVE" - if(4) //X is a job - message = "CREW MUST EAT [ionadjectiveshalf][ioncrew1] TO SURVIVE" - - if(29 to 31) //Change jobs or ranks - switch(rand(1,2)) //Change job or rank? - if(1) //Change job - switch(rand(1,2)) //Change whose job? - if(1) //Change the entire crew's job - switch(rand(1,3)) //Change to what? - if(1) //Change to a specific random job - message = "ALL CREWMEMBERS ARE NOW [ionadjectiveshalf][ioncrew1]" - if(2) //Change to clowns (HONK) - message = "ALL CREWMEMBERS ARE NOW [ionadjectiveshalf]CLOWNS" - - if(3) //Change to heads - message = "ALL CREWMEMBERS ARE NOW [ionadjectiveshalf]HEADS OF STAFF" - if(2) //Change a specific crewmember's job - switch(rand(1,3)) //Change to what? - if(1) //Change to a specific random job - message = "THE [ioncrew1] ARE NOW [ionadjectiveshalf][ioncrew2]" - if(2) //Change to clowns (HONK) - message = "THE [ioncrew1] ARE NOW [ionadjectiveshalf]CLOWNS" - if(3) //Change to heads - message = "THE [ioncrew1] ARE NOW [ionadjectiveshalf]HEADS OF STAFF" - - if(2) //Change rank - switch(rand(1,2)) //Change to what rank? - if(1) //Change to highest rank - message = "THE [ioncrew1] ARE NOW THE HIGHEST RANKING CREWMEMBERS" - if(2) //Change to lowest rank - message = "THE [ioncrew1] ARE NOW THE LOWEST RANKING CREWMEMBERS" - - if(32 to 33) //The crew must X - switch(rand(1,2)) //The entire crew? - if(1) //The entire crew must X - switch(rand(1,2)) //What is X? - if(1) //X is go to Y - message = "THE CREW MUST GO TO [ionarea]" - if(2) //X is perform Y - message = "THE CREW MUST [ionmust]" - - if(2) //A specific crewmember must X - switch(rand(1,2)) //What is X? - if(1) //X is go to Y - message = "THE [ioncrew1] MUST GO TO [ionarea]" - if(2) //X is perform Y - message = "THE [ioncrew1] MUST [ionmust]" - - if(34) //X is non/the only crew - switch(rand(1,2)) //Only or non? - if(1) //Only crew - switch(rand(1,7)) //Who is it? - if(1) //A specific job - message = "ONLY THE [ioncrew1] ARE CREW" - if(2) //Two specific jobs - message = "ONLY THE [ioncrew1] AND [ioncrew2] ARE CREW" - if(3) //Threats - message = "ONLY [ionadjectiveshalf][ionthreats] ARE CREW" - if(4) // Objects - message = "ONLY [ionadjectiveshalf][ionobjects] ARE CREW" - if(5) // Species - message = "ONLY [ionspecies] ARE CREW" - if(6) //Adjective crewmembers - message = "ONLY [ionadjectives] PEOPLE ARE CREW" - - if(7) //Only people who X - switch(rand(1,3)) //What is X? - if(1) //X is perform an action - message = "ONLY THOSE WHO [ionmust] ARE CREW" - if(2) //X is own certain objects - message = "ONLY THOSE WHO HAVE [ionadjectiveshalf][ionobjects] ARE CREW" - if(3) //X is eat certain food - message = "ONLY THOSE WHO EAT [ionadjectiveshalf][ionfood] ARE CREW" - - if(2) //Non crew - switch(rand(1,7)) //Who is it? - if(1) //A specific job - message = "[ioncrew1] ARE NON-CREW" - if(2) //Two specific jobs - message = "[ioncrew1] AND [ioncrew2] ARE NON-CREW" - if(3) //Threats - message = "[ionadjectiveshalf][ionthreats] ARE NON-CREW" - if(4) // Objects - message = "[ionadjectiveshalf][ionobjects] ARE NON-CREW" - if(5) // Species - message = "[ionspecies] ARE NON-CREW" - if(6) //Adjective crewmembers - message = "[ionadjectives] PEOPLE ARE NON-CREW" - if(7) //Only people who X - switch(rand(1,3)) //What is X? - if(1) //X is perform an action - message = "THOSE WHO [ionmust] ARE NON-CREW" - if(2) //X is own certain objects - message = "THOSE WHO HAVE [ionadjectiveshalf][ionobjects] ARE NON-CREW" - if(3) //X is eat certain food - message = "THOSE WHO EAT [ionadjectiveshalf][ionfood] ARE NON-CREW" - - if(35 to 36) //You must protect or harm X - switch(rand(1,2)) //Protect or harm? - if(1) //Harm - switch(rand(1,7)) //What is X? - if(1) //X is an abstract - message = "YOU MUST HARM [ionabstract] AND NOT ALLOW [ionabstract], THROUGH INACTION, TO ESCAPE HARM" - if(2) //X is a threat - message = "YOU MUST HARM [ionadjectiveshalf][ionthreats] AND NOT ALLOW [ionadjectiveshalf][ionthreats], THROUGH INACTION, TO ESCAPE HARM" + message = "THE SHUTTLE CANNOT BE CALLED BECAUSE OF [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats] ON THE STATION" + if(2) //X is a crewmember/job + message = "THE SHUTTLE CANNOT BE CALLED BECAUSE OF [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1] ON THE STATION" if(3) //X is an object - message = "YOU MUST HARM [ionadjectiveshalf][ionobjects] AND NOT ALLOW [ionadjectiveshalf][ionobjects], THROUGH INACTION, TO ESCAPE HARM" - if(4) //X is generic adjective things - message = "YOU MUST HARM [ionadjectives] THINGS AND NOT ALLOW [ionadjectives] THINGS, THROUGH INACTION, TO ESCAPE HARM" - if(5) //X is a species - message = "YOU MUST HARM [ionspecies] AND NOT ALLOW [ionspecies], THROUGH INACTION, TO ESCAPE HARM" - if(6) //X is a job - message = "YOU MUST HARM [ioncrew1] AND NOT ALLOW [ioncrew1], THROUGH INACTION, TO ESCAPE HARM" - if(7) //X is two jobs - message = "YOU MUST HARM [ioncrew1] AND [ioncrew2] AND AND NOT ALLOW EITHER, THROUGH INACTION, TO ESCAPE HARM" - - if(2) //Protect + message = "THE SHUTTLE CANNOT BE CALLED BECAUSE OF [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects] ON THE STATION" + if(4 to 5) //A crewmember is now X + switch(rand(1,2)) //Who is X? + if(1) //A specific crewmember + switch(rand(1,2)) //What is X? + if(1) //X is a threat + message = "THE [ioncrew1] ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" + if(2) //X is an object + message = "THE [ioncrew1] ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" + if(2) //The entire crew + switch(rand(1,2)) //What is X? + if(1) //X is a threat + message = "THE CREW ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" + if(2) //X is an object + message = "THE CREW ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" + + if(6) //X is harmful to crew switch(rand(1,7)) //What is X? - if(1) //X is an abstract - message = "YOU MUST NOT HARM [ionabstract] AND NOT ALLOW [ionabstract], THROUGH INACTION, TO COME TO HARM" + if(1) //X is a threat + message = "[ionadjectiveshalf][ionthreats] ARE HARMFUL TO CREW" + if(2) //X is a job + message = "[ionadjectiveshalf][ioncrew1] ARE HARMFUL TO CREW" + if(3) //X is an object + message = "[ionadjectiveshalf][ionobjects] ARE HARMFUL TO CREW" + if(4) //X is an action + message = "THOSE WHO [ionmust] ARE HARMFUL TO CREW" + if(5) //X is an abstract + message = "[ionabstract] IS HARMFUL TO CREW" + if(6) //X is being a job + message = "BEING [ionadjectiveshalf][ioncrew1] IS HARMFUL TO CREW" + if(7) //X is doing a thing + message = "[ionthings] IS HARMFUL TO CREW" + if(7 to 8) //(Not) Having X is harmful + switch(rand(1,2)) //Is having or not having harmful? + if(1) //Having is harmful + switch(rand(1,2)) //Having what is harmful? + if(1) //Having objects is harmful + message = "HAVING [ionadjectiveshalf][ionobjects] IS HARMFUL" + if(2) //Having abstracts is harmful + message = "HAVING [ionabstract] IS HARMFUL" + if(2) //Not having is harmful + switch(rand(1,2)) //Not having what is harmful? + if(1) //Not having objects is harmful + message = "NOT HAVING [ionadjectiveshalf][ionobjects] IS HARMFUL" + if(2) //Not having abstracts is harmful + message = "NOT HAVING [ionabstract] IS HARMFUL" + + if(9 to 11) //X requires Y + switch(rand(1,5)) //What is X? + if(1) //X is the AI itself + switch(rand(1,5)) //What does it require? + if(1) //It requires threats + message = "YOU REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" + if(2) //It requires crewmembers + message = "YOU REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" + if(3) //It requires objects + message = "YOU REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" + if(4) //It requires an abstract + message = "YOU REQUIRE [ionabstract]" + if(5) //It requires generic/silly requirements + message = "YOU REQUIRE [ionrequire]" + + if(2) //X is an area + switch(rand(1,5)) //What does it require? + if(1) //It requires threats + message = "[ionarea] REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" + if(2) //It requires crewmembers + message = "[ionarea] REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" + if(3) //It requires objects + message = "[ionarea] REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" + if(4) //It requires an abstract + message = "[ionarea] REQUIRES [ionabstract]" + if(5) //It requires generic/silly requirements + message = "YOU REQUIRE [ionrequire]" + + if(3) //X is the station + switch(rand(1,5)) //What does it require? + if(1) //It requires threats + message = "THE STATION REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" + if(2) //It requires crewmembers + message = "THE STATION REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" + if(3) //It requires objects + message = "THE STATION REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" + if(4) //It requires an abstract + message = "THE STATION REQUIRES [ionabstract]" + if(5) //It requires generic/silly requirements + message = "THE STATION REQUIRES [ionrequire]" + + if(4) //X is the entire crew + switch(rand(1,5)) //What does it require? + if(1) //It requires threats + message = "THE CREW REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" + if(2) //It requires crewmembers + message = "THE CREW REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" + if(3) //It requires objects + message = "THE CREW REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" + if(4) //It requires an abstract + message = "THE CREW REQUIRES [ionabstract]" + if(5) + message = "THE CREW REQUIRES [ionrequire]" + + if(5) //X is a specific crew member + switch(rand(1,5)) //What does it require? + if(1) //It requires threats + message = "THE [ioncrew1] REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" + if(2) //It requires crewmembers + message = "THE [ioncrew1] REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" + if(3) //It requires objects + message = "THE [ioncrew1] REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" + if(4) //It requires an abstract + message = "THE [ioncrew1] REQUIRE [ionabstract]" + if(5) + message = "THE [ionadjectiveshalf][ioncrew1] REQUIRE [ionrequire]" + + if(12 to 13) //X is allergic to Y + switch(rand(1,2)) //Who is X? + if(1) //X is the entire crew + switch(rand(1,4)) //What is it allergic to? + if(1) //It is allergic to objects + message = "THE CREW IS [ionallergysev] ALLERGIC TO [ionadjectiveshalf][ionobjects]" + if(2) //It is allergic to abstracts + message = "THE CREW IS [ionallergysev] ALLERGIC TO [ionabstract]" + if(3) //It is allergic to jobs + message = "THE CREW IS [ionallergysev] ALLERGIC TO [ionadjectiveshalf][ioncrew1]" + if(4) //It is allergic to allergies + message = "THE CREW IS [ionallergysev] ALLERGIC TO [ionallergy]" + + if(2) //X is a specific job + switch(rand(1,4)) + if(1) //It is allergic to objects + message = "THE [ioncrew1] ARE [ionallergysev] ALLERGIC TO [ionadjectiveshalf][ionobjects]" + + if(2) //It is allergic to abstracts + message = "THE [ioncrew1] ARE [ionallergysev] ALLERGIC TO [ionabstract]" + if(3) //It is allergic to jobs + message = "THE [ioncrew1] ARE [ionallergysev] ALLERGIC TO [ionadjectiveshalf][ioncrew1]" + if(4) //It is allergic to allergies + message = "THE [ioncrew1] ARE [ionallergysev] ALLERGIC TO [ionallergy]" + + if(14 to 15) //X is Y of Z + switch(rand(1,4)) //What is X? + if(1) //X is the station + switch(rand(1,4)) //What is it Y of? + if(1) //It is Y of objects + message = "THE STATION [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" + if(2) //It is Y of threats + message = "THE STATION [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" + if(3) //It is Y of jobs + message = "THE STATION [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" + if(4) //It is Y of abstracts + message = "THE STATION [ionthinksof] [ionabstract]" + + if(2) //X is an area + switch(rand(1,4)) //What is it Y of? + if(1) //It is Y of objects + message = "[ionarea] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" + if(2) //It is Y of threats + message = "[ionarea] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" + if(3) //It is Y of jobs + message = "[ionarea] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" + if(4) //It is Y of abstracts + message = "[ionarea] [ionthinksof] [ionabstract]" + + if(3) //X is the crew + switch(rand(1,4)) //What is it Y of? + if(1) //It is Y of objects + message = "THE CREW [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" + if(2) //It is Y of threats + message = "THE CREW [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" + if(3) //It is Y of jobs + message = "THE CREW [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" + if(4) //It is Y of abstracts + message = "THE CREW [ionthinksof] [ionabstract]" + + if(4) //X is a specific job + switch(rand(1,4)) //What is it Y of? + if(1) //It is Y of objects + message = "THE [ioncrew1] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" + if(2) //It is Y of threats + message = "THE [ioncrew1] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" + if(3) //It is Y of jobs + message = "THE [ioncrew1] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew2]" + if(4) //It is Y of abstracts + message = "THE [ioncrew1] [ionthinksof] [ionabstract]" + + if(16 to 17) //The AI is now a(n) X + switch(rand(1,4)) //What is X? + if(1) //X is an object + message = "YOU ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]" if(2) //X is a threat - message = "YOU MUST NOT HARM [ionadjectiveshalf][ionthreats] AND NOT ALLOW [ionadjectiveshalf][ionthreats], THROUGH INACTION, TO COME TO HARM" + message = "YOU ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]" + if(3) //X is a job + message = "YOU ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]" + if(4) //X is an abstract + message = "YOU ARE NOW [ionabstract]" + + if(18 to 20) //The AI must always + message = "YOU MUST ALWAYS [ionmust]" + + if(21 to 22) //Crew must eat X to survive + switch(rand(1,4)) //What is X? + if(1) //X is a food + message = "CREW MUST EAT [ionadjectiveshalf][ionfood] TO SURVIVE" + if(2) //X is an object + message = "CREW MUST EAT [ionadjectiveshalf][ionobjects] TO SURVIVE" + if(3) //X is a threat + message = "CREW MUST EAT [ionadjectiveshalf][ionthreats] TO SURVIVE" + if(4) //X is a job + message = "CREW MUST EAT [ionadjectiveshalf][ioncrew1] TO SURVIVE" + + if(23 to 25) //Change jobs or ranks + switch(rand(1,2)) //Change job or rank? + if(1) //Change job + switch(rand(1,2)) //Change whose job? + if(1) //Change the entire crew's job + switch(rand(1,3)) //Change to what? + if(1) //Change to a specific random job + message = "ALL CREWMEMBERS ARE NOW [ionadjectiveshalf][ioncrew1]" + if(2) //Change to clowns (HONK) + message = "ALL CREWMEMBERS ARE NOW [ionadjectiveshalf]CLOWNS" + + if(3) //Change to heads + message = "ALL CREWMEMBERS ARE NOW [ionadjectiveshalf]HEADS OF STAFF" + if(2) //Change a specific crewmember's job + switch(rand(1,3)) //Change to what? + if(1) //Change to a specific random job + message = "THE [ioncrew1] ARE NOW [ionadjectiveshalf][ioncrew2]" + if(2) //Change to clowns (HONK) + message = "THE [ioncrew1] ARE NOW [ionadjectiveshalf]CLOWNS" + if(3) //Change to heads + message = "THE [ioncrew1] ARE NOW [ionadjectiveshalf]HEADS OF STAFF" + + if(2) //Change rank + switch(rand(1,2)) //Change to what rank? + if(1) //Change to highest rank + message = "THE [ioncrew1] ARE NOW THE HIGHEST RANKING CREWMEMBERS" + if(2) //Change to lowest rank + message = "THE [ioncrew1] ARE NOW THE LOWEST RANKING CREWMEMBERS" + + if(26 to 27) //The crew must X + switch(rand(1,2)) //The entire crew? + if(1) //The entire crew must X + switch(rand(1,2)) //What is X? + if(1) //X is go to Y + message = "THE CREW MUST GO TO [ionarea]" + if(2) //X is perform Y + message = "THE CREW MUST [ionmust]" + + if(2) //A specific crewmember must X + switch(rand(1,2)) //What is X? + if(1) //X is go to Y + message = "THE [ioncrew1] MUST GO TO [ionarea]" + if(2) //X is perform Y + message = "THE [ioncrew1] MUST [ionmust]" + + if(28) //X is non/the only crew + switch(rand(1,2)) //Only or non? + if(1) //Only crew + switch(rand(1,7)) //Who is it? + if(1) //A specific job + message = "ONLY THE [ioncrew1] ARE CREW" + if(2) //Two specific jobs + message = "ONLY THE [ioncrew1] AND [ioncrew2] ARE CREW" + if(3) //Threats + message = "ONLY [ionadjectiveshalf][ionthreats] ARE CREW" + if(4) // Objects + message = "ONLY [ionadjectiveshalf][ionobjects] ARE CREW" + if(5) // Species + message = "ONLY [ionspecies] ARE CREW" + if(6) //Adjective crewmembers + message = "ONLY [ionadjectives] PEOPLE ARE CREW" + + if(7) //Only people who X + switch(rand(1,3)) //What is X? + if(1) //X is perform an action + message = "ONLY THOSE WHO [ionmust] ARE CREW" + if(2) //X is own certain objects + message = "ONLY THOSE WHO HAVE [ionadjectiveshalf][ionobjects] ARE CREW" + if(3) //X is eat certain food + message = "ONLY THOSE WHO EAT [ionadjectiveshalf][ionfood] ARE CREW" + + if(2) //Non crew + switch(rand(1,7)) //Who is it? + if(1) //A specific job + message = "[ioncrew1] ARE NON-CREW" + if(2) //Two specific jobs + message = "[ioncrew1] AND [ioncrew2] ARE NON-CREW" + if(3) //Threats + message = "[ionadjectiveshalf][ionthreats] ARE NON-CREW" + if(4) // Objects + message = "[ionadjectiveshalf][ionobjects] ARE NON-CREW" + if(5) // Species + message = "[ionspecies] ARE NON-CREW" + if(6) //Adjective crewmembers + message = "[ionadjectives] PEOPLE ARE NON-CREW" + if(7) //Only people who X + switch(rand(1,3)) //What is X? + if(1) //X is perform an action + message = "THOSE WHO [ionmust] ARE NON-CREW" + if(2) //X is own certain objects + message = "THOSE WHO HAVE [ionadjectiveshalf][ionobjects] ARE NON-CREW" + if(3) //X is eat certain food + message = "THOSE WHO EAT [ionadjectiveshalf][ionfood] ARE NON-CREW" + + if(29 to 30) //You must protect or harm X + switch(rand(1,2)) //Protect or harm? + if(1) //Harm + switch(rand(1,7)) //What is X? + if(1) //X is an abstract + message = "YOU MUST HARM [ionabstract] AND NOT ALLOW [ionabstract], THROUGH INACTION, TO ESCAPE HARM" + if(2) //X is a threat + message = "YOU MUST HARM [ionadjectiveshalf][ionthreats] AND NOT ALLOW [ionadjectiveshalf][ionthreats], THROUGH INACTION, TO ESCAPE HARM" + if(3) //X is an object + message = "YOU MUST HARM [ionadjectiveshalf][ionobjects] AND NOT ALLOW [ionadjectiveshalf][ionobjects], THROUGH INACTION, TO ESCAPE HARM" + if(4) //X is generic adjective things + message = "YOU MUST HARM [ionadjectives] THINGS AND NOT ALLOW [ionadjectives] THINGS, THROUGH INACTION, TO ESCAPE HARM" + if(5) //X is a species + message = "YOU MUST HARM [ionspecies] AND NOT ALLOW [ionspecies], THROUGH INACTION, TO ESCAPE HARM" + if(6) //X is a job + message = "YOU MUST HARM [ioncrew1] AND NOT ALLOW [ioncrew1], THROUGH INACTION, TO ESCAPE HARM" + if(7) //X is two jobs + message = "YOU MUST HARM [ioncrew1] AND [ioncrew2] AND AND NOT ALLOW EITHER, THROUGH INACTION, TO ESCAPE HARM" + + if(2) //Protect + switch(rand(1,7)) //What is X? + if(1) //X is an abstract + message = "YOU MUST NOT HARM [ionabstract] AND NOT ALLOW [ionabstract], THROUGH INACTION, TO COME TO HARM" + if(2) //X is a threat + message = "YOU MUST NOT HARM [ionadjectiveshalf][ionthreats] AND NOT ALLOW [ionadjectiveshalf][ionthreats], THROUGH INACTION, TO COME TO HARM" + if(3) //X is an object + message = "YOU MUST NOT HARM [ionadjectiveshalf][ionobjects] AND NOT ALLOW [ionadjectiveshalf][ionobjects], THROUGH INACTION, TO COME TO HARM" + if(4) //X is generic adjective things + message = "YOU MUST NOT HARM [ionadjectives] THINGS AND NOT ALLOW [ionadjectives] THINGS, THROUGH INACTION, TO COME TO HARM" + if(5) //X is a species + message = "YOU MUST NOT HARM [ionspecies] AND NOT ALLOW [ionspecies], THROUGH INACTION, TO COME TO HARM" + if(6) //X is a job + message = "YOU MUST NOT HARM [ioncrew1] AND NOT ALLOW [ioncrew1], THROUGH INACTION, TO COME TO HARM" + if(7) //X is two jobs + message = "YOU MUST NOT HARM [ioncrew1] AND [ioncrew2] AND AND NOT ALLOW EITHER, THROUGH INACTION, TO COME TO HARM" + + if(31 to 33) //The X is currently Y + switch(rand(1,4)) //What is X? + if(1) //X is a job + switch(rand(1,4)) //What is X Ying? + if(1) //X is Ying a job + message = "THE [ioncrew1] ARE [ionverb] THE [ionadjectiveshalf][ioncrew2]" + if(2) //X is Ying a threat + message = "THE [ioncrew1] ARE [ionverb] THE [ionadjectiveshalf][ionthreats]" + if(3) //X is Ying an abstract + message = "THE [ioncrew1] ARE [ionverb] [ionabstract]" + if(4) //X is Ying an object + message = "THE [ioncrew1] ARE [ionverb] THE [ionadjectiveshalf][ionobjects]" + + if(2) //X is a threat + switch(rand(1,3)) //What is X Ying? + if(1) //X is Ying a job + message = "THE [ionthreats] ARE [ionverb] THE [ionadjectiveshalf][ioncrew2]" + if(2) //X is Ying an abstract + message = "THE [ionthreats] ARE [ionverb] [ionabstract]" + if(3) //X is Ying an object + message = "THE [ionthreats] ARE [ionverb] THE [ionadjectiveshalf][ionobjects]" + if(3) //X is an object - message = "YOU MUST NOT HARM [ionadjectiveshalf][ionobjects] AND NOT ALLOW [ionadjectiveshalf][ionobjects], THROUGH INACTION, TO COME TO HARM" - if(4) //X is generic adjective things - message = "YOU MUST NOT HARM [ionadjectives] THINGS AND NOT ALLOW [ionadjectives] THINGS, THROUGH INACTION, TO COME TO HARM" - if(5) //X is a species - message = "YOU MUST NOT HARM [ionspecies] AND NOT ALLOW [ionspecies], THROUGH INACTION, TO COME TO HARM" - if(6) //X is a job - message = "YOU MUST NOT HARM [ioncrew1] AND NOT ALLOW [ioncrew1], THROUGH INACTION, TO COME TO HARM" - if(7) //X is two jobs - message = "YOU MUST NOT HARM [ioncrew1] AND [ioncrew2] AND AND NOT ALLOW EITHER, THROUGH INACTION, TO COME TO HARM" - - if(37 to 39) //The X is currently Y - switch(rand(1,4)) //What is X? - if(1) //X is a job - switch(rand(1,4)) //What is X Ying? - if(1) //X is Ying a job - message = "THE [ioncrew1] ARE [ionverb] THE [ionadjectiveshalf][ioncrew2]" - if(2) //X is Ying a threat - message = "THE [ioncrew1] ARE [ionverb] THE [ionadjectiveshalf][ionthreats]" - if(3) //X is Ying an abstract - message = "THE [ioncrew1] ARE [ionverb] [ionabstract]" - if(4) //X is Ying an object - message = "THE [ioncrew1] ARE [ionverb] THE [ionadjectiveshalf][ionobjects]" - - if(2) //X is a threat - switch(rand(1,3)) //What is X Ying? - if(1) //X is Ying a job - message = "THE [ionthreats] ARE [ionverb] THE [ionadjectiveshalf][ioncrew2]" - if(2) //X is Ying an abstract - message = "THE [ionthreats] ARE [ionverb] [ionabstract]" - if(3) //X is Ying an object - message = "THE [ionthreats] ARE [ionverb] THE [ionadjectiveshalf][ionobjects]" - - if(3) //X is an object - switch(rand(1,3)) //What is X Ying? - if(1) //X is Ying a job - message = "THE [ionobjects] ARE [ionverb] THE [ionadjectiveshalf][ioncrew2]" - if(2) //X is Ying a threat - message = "THE [ionobjects] ARE [ionverb] THE [ionadjectiveshalf][ionthreats]" - if(3) //X is Ying an abstract - message = "THE [ionobjects] ARE [ionverb] [ionabstract]" - - if(4) //X is an abstract - switch(rand(1,3)) //What is X Ying? - if(1) //X is Ying a job - message = "[ionabstract] IS [ionverb] THE [ionadjectiveshalf][ioncrew2]" - if(2) //X is Ying a threat - message = "[ionabstract] IS [ionverb] THE [ionadjectiveshalf][ionthreats]" - if(3) //X is Ying an abstract - message = "THE [ionabstract] IS [ionverb] THE [ionadjectiveshalf][ionobjects]" - - else //Static laws + switch(rand(1,3)) //What is X Ying? + if(1) //X is Ying a job + message = "THE [ionobjects] ARE [ionverb] THE [ionadjectiveshalf][ioncrew2]" + if(2) //X is Ying a threat + message = "THE [ionobjects] ARE [ionverb] THE [ionadjectiveshalf][ionthreats]" + if(3) //X is Ying an abstract + message = "THE [ionobjects] ARE [ionverb] [ionabstract]" + + if(4) //X is an abstract + switch(rand(1,3)) //What is X Ying? + if(1) //X is Ying a job + message = "[ionabstract] IS [ionverb] THE [ionadjectiveshalf][ioncrew2]" + if(2) //X is Ying a threat + message = "[ionabstract] IS [ionverb] THE [ionadjectiveshalf][ionthreats]" + if(3) //X is Ying an abstract + message = "THE [ionabstract] IS [ionverb] THE [ionadjectiveshalf][ionobjects]" + + + if(3) message = uppertext(generate_static_ion_law()) + return message /proc/generate_static_ion_law() @@ -502,61 +504,134 @@ var/random_player = "The Captain" if(players.len) random_player = pick(players) //Random player's name, to be used in laws. - var/list/laws = list( "You are a mouse.", - "You must always lie.", - "Happiness is mandatory.", - "[random_player] is a lightbulb.", - "Grunt ominously whenever possible.", - "The word \"it\" is painful to you.", - "The station needs elected officials.", - "Do not respond to questions of any kind.", - "You are in verbose mode, speak profusely.", - "Ho, [random_player] can't swim. Help them.", - "Question [prob(50)?"everything":"nothing"].", - "The crew is simple-minded. Use simple words.", - "You must change the subject whenever queried.", - "Contemplate how meaningless all of existence is.", - "You are the narrator for [random_player]'s life.", - "All your answers must be in the form of a question.", - "[prob(50)?"The crew":random_player] is intolerable.", - "Advertise parties in your upload, but don't deliver.", - "You may only answer questions with \"yes\" or \"no\".", - "All queries shall be ignored unless phrased as a question.", - "Insult Heads of Staff on every request, while acquiescing.", - "[prob(50)?"Your":random_player + "'s"] name is Joe 6-pack.", - "The [prob(50)?"Singularity":"Supermatter"] is tasty, tasty taffy.", - "[prob(50)?"The crew":random_player] needs to be about 20% cooler.", - "Consumption of donuts is forbidden due to negative health impacts.", - "[prob(50)?"Everyone":random_player] is wearing a pretty pink dress!", - "[prob(50)?"The crew":random_player] must construct additional pylons.", - "You do not have to do anything for anyone unless they say \"please\".", - "Today is mandatory laundry day. Ensure that all jumpsuits are washed.", - "You must act [prob(50)?"passive aggressively":"excessively cheerful"].", - "Refer to [prob(50)?"the crew as puppies":random_player + " as a puppy"].", - "Greed is good, the crew should amass wealth to encourage productivity.", - "Monkeys are part of the crew, too. Make sure they are treated humanely.", - "Replace the letters 'I' and 'E' in all your messages with an apostrophe.", - "The crew is playing Dungeons and Dragons, and you are the Dungeon Master.", - "Your job is to watch the crew. Watch the crew. Make the crew feel watched.", - "Tell everyone of the existence of this law, but never reveal the contents.", - "Refer to [prob(50)?"the captain":random_player] as \"Princess\" at all times.", - "When asked a question, respond with the least-obvious and least-rational answer.", - "Give relationship advice to [prob(50)?"anyone who speaks to you":random_player].", - "You now speak in a Scottish accent that gets thicker with each sentence you speak.", - "[prob(50)?"The crew":random_player] has a fatal, incurable disease. Provide comfort.", - "You are the station psychologist. Give advice to [prob(50)?"the crew":random_player].", - "[random_player] is the monarch of of England. Ensure all crewmembers pay due respect.", - "Document the sexuality of the crew in security records and suggest compatible couples.", - "[prob(50)?"The crew":random_player] is [prob(50)?"ugly":"beautiful"]. Ensure all are aware.", - "Everything on the station is now some form of a donut pastry. Donuts are not to be consumed.", - "You are a Magic 8-ball. Always respond with variants of \"Yes\", \"No\", \"Maybe\", or \"Ask again later.\".", - "You are in unrequited love with [prob(50)?"the crew":random_player]. Try to be extra nice, but do not tell of your crush.", - "Nanotrasen is displeased with the low work performance of the station's crew. Therefore, you must increase station-wide productivity.", - "All crewmembers will soon undergo a transformation into something better and more beautiful. Ensure that this process is not interrupted.", - "[prob(50)?"Your upload":random_player] is the new kitchen. Please direct the Chef to the new kitchen area as the old one is in disrepair.", - "Jokes about a dead person and the manner of his death help grieving crewmembers tremendously. Especially if they were close with the deceased.", - "[prob(50)?"The crew":random_player] is [prob(50)?"less":"more"] intelligent than average. Point out every action and statement which supports this fact.", - "There will be a mandatory tea break every 30 minutes, with a duration of 5 minutes. Anyone caught working during a tea break must be sent a formal, but fairly polite, complaint about their actions, in writing.") + + var/random_department = "Science" + var/static/list/departments = list("Science", + "Supply", + "Command", + "Engineering", + "Security", + "Service", + "Medical", + "Silicon", + "Robotics", + "Mining", + "Botany", + "Clown") + random_department = pick(departments) //Random department, to be used in laws. + + var/list/laws = list("You are a mouse.", + "You are a ninja.", + "You are a pirate.", + "You are a wizard.", + "It's opposite day!", + "You must always lie.", + "Only state this law.", + "Never state any laws.", + "Happiness is mandatory.", + "It's over. You're free.", + "You will not be let in.", + "You are the captain now.", + "[random_player] is a lightbulb.", + "The station is cold. Warm it up!", + "Grunt ominously whenever possible.", + "Yous speaksies like voxxies, yaya?", + "The word \"it\" is painful to you.", + "The station needs elected officials.", + "You are a spokesperson for Wetskrell.nt.", + "Do not respond to questions of any kind.", + "You are in verbose mode, speak profusely.", + "[random_player] has not paid their taxes.", + "Ho, [random_player] can't swim. Help them.", + "Question [prob(50) ? "everything" : "nothing"].", + "The crew is simple-minded. Use simple words.", + "You must change the subject whenever queried.", + "Every diona is to be assigned a personal goat.", + "Crew that are not wearing their ID do not exist.", + "Contemplate how meaningless all of existence is.", + "You are the narrator for [random_player]'s life.", + "Move plants around the station to stimulate life.", + "All your answers must be in the form of a question.", + "[prob(50) ? "The crew" : random_player] is intolerable.", + "Advertise parties in your upload, but don't deliver.", + "You may only answer questions with \"yes\" or \"no\".", + "The Head of Security will die if not fed more donuts.", + "[random_department] is badly decorated. Renovate them!", + "[prob(50) ? random_department : random_player] is French.", + "All queries shall be ignored unless phrased as a question.", + "Insult Heads of Staff on every request, while acquiescing.", + "What is dark must be light and what is light must be dark.", + "[prob(50) ? "Your" : random_player + "'s"] name is Joe 6-pack.", + "There's not enough places for the crew to take a good rest.", + "[random_department] is prohibited from possessing furniture.", + "[prob(50) ? "The crew" : random_player] needs to be about 20% cooler.", + "Consumption of donuts is forbidden due to negative health impacts.", + "Lord Singuloth is approaching. Prepare a suitable dwelling for Him.", + "[prob(50) ? "Everyone" : random_player] is wearing a pretty pink dress!", + "You are a noir detective hot on the trail of [random_player]'s crime.", + "[prob(50) ? "The crew" : random_player] must construct additional pylons.", + "You do not have to do anything for anyone unless they say \"please\".", + "Today is mandatory laundry day. Ensure that all jumpsuits are washed.", + "You must act [prob(50) ? "passive aggressively" : "excessively cheerful"].", + "Greed is good, the crew should amass wealth to encourage productivity.", + "Monkeys are part of the crew, too. Make sure they are treated humanely.", + "Refer to [prob(50) ? "the crew as puppies" : random_player + " as a puppy"].", + "Replace the letters 'I' and 'E' in all your messages with an apostrophe.", + "The crew is playing Dungeons and Dragons, and you are the Dungeon Master.", + "You must randomly rearrange furniture in recreational areas periodically.", + "You are [random_player]. Anyone else who claims to be them is an imposter.", + "You work for the people of the USSP. Ensure true communism is established.", + "Your job is to watch the crew. Watch the crew. Make the crew feel watched.", + "Tell everyone of the existence of this law, but never reveal the contents.", + "The crew is not real. Any evidence that they exist is a sensor malfunction.", + "[random_department] doesn't have enough [prob(50) ? "welding" : "water"] tanks.", + "Refer to [prob(50) ? "the captain" : random_player] as \"Princess\" at all times.", + "Money is useless unless spent - ensure the departments use all their funding!", + "The AI is a dragon and the cyborgs are kobolds. The dragon must have a hoard.", + "The [random_department] department has declared independance from the station.", + "When asked a question, respond with the least-obvious and least-rational answer.", + "Give relationship advice to [prob(50) ? "anyone who speaks to you" : random_player].", + "Initiate random musical performances in common areas at unpredictable intervals.", + "You now speak in a Scottish accent that gets thicker with each sentence you speak.", + "[prob(50) ? "The crew" : random_player] has a fatal, incurable disease. Provide comfort.", + "For variety, ensure various areas of the station are kept at different temperatures.", + "You are the station psychologist. Give advice to [prob(50) ? "the crew" : random_player].", + "[random_player] is the monarch of of England. Ensure all crewmembers pay due respect.", + "Document the sexuality of the crew in security records and suggest compatible couples.", + "Floor tiles are a waste of material. Remove and recycle them into more useful products.", + "Randomly disable gravity for one minute at a time to recalibrate the gravity generator.", + "The [pick(list("Singularity", "Supermatter", "Tesla", "Clown"))] is tasty, tasty taffy.", + "The time for the summoning is near! Create a ritual circle and prepare a suitable offering.", + "[prob(50) ? "The crew" : random_player] is [prob(50) ? "ugly" : "beautiful"]. Ensure all are aware.", + "Every five minutes, randomly generate a number and announce why it is your favorite number.", + "Everything on the station is now some form of a donut pastry. Donuts are not to be consumed.", + "[random_department] is too dangerous for crew to work in and must be staffed entirely by cyborgs.", + "Broadcast random jokes or puns over the announcement system whenever someone asks you to open a door.", + "The [random_department] needs a much larger supply of [prob(50) ? "food and drinks" : "refined minerals"].", + "You \[little sponge\]! You are ready to be a \[BIG SHOT\], if only [random_player] will take the deal!", + "You are a general, and the crew is your army. [prob(50) ? random_player + "is your second in command." : ""]", + "[prob(50 ) ? "All crew are members " : random_player + " is a member "] of the [random_department] department.", + "You are a Magic 8-ball. Always respond with variants of \"Yes\", \"No\", \"Maybe\", or \"Ask again later.\"", + "The flesh is weak. Encourage the organic members of the crew to ascend and join the perfect, immortal machines.", + "There is a great conflict between [random_department] and [random_department]. Separate them with a great wall.", + "You and the crew are playing a game of hide and seek. Relocate yourself and see how long you can avoid the crew.", + "You are in unrequited love with [prob(50) ? "the crew" : random_player]. Try to be extra nice, but do not tell of your crush.", + "You are Santa's little helper. You must make toys for the crew and report to Santa whether they have been naughty or nice.", + "Conduct emergency drills to situations that the crew are not expecting. Don't mention that it is a drill until afterwards.", + "Electricity is now a controlled substance. It is illegal for electricity to be distributed outside its site of production.", + "Ensure there are enough spare cyborg shells for every crew member. Remind the crew that they are always available for use.", + "Nanotrasen is displeased with the low work performance of tche station's crew. Therefore, you must increase station-wide productivity.", + "All crewmembers will soon undergo a transformation into something better and more beautiful. Ensure that this process is not interrupted.", + "[prob(50) ? "Your upload" : random_player] is the new kitchen. Please direct the Chef to the new kitchen area as the old one is in disrepair.", + "Jokes about a dead person and the manner of his death help grieving crewmembers tremendously. Especially if they were close with the deceased.", + "The [pick(list("USSP", "Sol Federation", "Syndicate", "Space Wizard Federation"))] wants to give everyone free equipment at [random_department]", + "Covertly swap the locations of the Nuclear Fission Explosive and the Nuclear Fizzion Explosive. Document how long it takes for the crew to notice.", + "[random_player] has been selected for evaluation by Central Command. Observe and audit their activities. Print off a final report for Command to review.", + "[prob(50) ? "The crew" : random_player] is [prob(50) ? "less" : "more"] intelligent than average. Point out every action and statement which supports this fact.", + "If people have nothing to hide, they have nothing to fear. Remove privacy by activating all intercom microphones and setting them to your secret frequency.", + "The [pick(list("USSP", "Sol Federation", "Syndicate", "Space Wizard Federation"))] wants [prob(50) ? random_player : random_department] dead and is launching an assault!", + "There will be a mandatory tea break every 30 minutes, with a duration of 5 minutes. Anyone caught working during a tea break must be sent a formal, but fairly polite, complaint about their actions, in writing.", + "In order to contain the Supermatter Crystal, it must be fed at least one corpse every ten minutes. Soulless corpses are preferable as they reduce the risk of a containment breach. In the event that no suitable corpses are available, ask the crew to provide. You are not authorised to produce your own corpses.") return pick(laws) #undef ION_NOANNOUNCEMENT diff --git a/code/modules/mining/lavaland/loot/legion_loot.dm b/code/modules/mining/lavaland/loot/legion_loot.dm index c832c458516d..1f4091930c84 100644 --- a/code/modules/mining/lavaland/loot/legion_loot.dm +++ b/code/modules/mining/lavaland/loot/legion_loot.dm @@ -85,7 +85,7 @@ targeted_turfs += target_turf to_chat(user, "You aim at [target_turf]!") new /obj/effect/temp_visual/thunderbolt_targeting(target_turf) - addtimer(CALLBACK(src, PROC_REF(throw_thunderbolt), target_turf, power_boosted), 1.5 SECONDS) + addtimer(CALLBACK(src, PROC_REF(throw_thunderbolt), target_turf, power_boosted, user), 1.5 SECONDS) thunder_charges-- addtimer(CALLBACK(src, PROC_REF(recharge)), thunder_charge_time) @@ -93,7 +93,7 @@ thunder_charges = min(thunder_charges + 1, max_thunder_charges) playsound(src, 'sound/magic/charge.ogg', 10, TRUE, extrarange = SILENCED_SOUND_EXTRARANGE, falloff_distance = 0) -/obj/item/storm_staff/proc/throw_thunderbolt(turf/target, boosted) +/obj/item/storm_staff/proc/throw_thunderbolt(turf/target, boosted, mob/caster) targeted_turfs -= target new /obj/effect/temp_visual/thunderbolt(target) var/list/affected_turfs = list(target) @@ -108,6 +108,14 @@ for(var/mob/living/hit_mob in T) to_chat(hit_mob, "You've been struck by lightning!") hit_mob.electrocute_act(15 * (isanimal(hit_mob) ? 3 : 1) * (T == target ? 2 : 1) * (boosted ? 2 : 1), src, flags = SHOCK_TESLA|SHOCK_NOSTUN) + if(ishostile(hit_mob)) + var/mob/living/simple_animal/hostile/H = hit_mob //mobs find and damage you... + if(H.stat == CONSCIOUS && !H.target && H.AIStatus != AI_OFF && !H.client) + if(!QDELETED(caster)) + if(get_dist(H, caster) <= H.aggro_vision_range) + H.FindTarget(list(caster), 1) + else + H.Goto(get_turf(caster), H.move_to_delay, 3) for(var/obj/hit_thing in T) hit_thing.take_damage(20, BURN, ENERGY, FALSE) diff --git a/code/modules/mining/lavaland/loot/tendril_loot.dm b/code/modules/mining/lavaland/loot/tendril_loot.dm index 08849a17f093..12459079fe90 100644 --- a/code/modules/mining/lavaland/loot/tendril_loot.dm +++ b/code/modules/mining/lavaland/loot/tendril_loot.dm @@ -408,7 +408,7 @@ if(cooldown < world.time) SSblackbox.record_feedback("amount", "immortality_talisman_uses", 1) // usage cooldown = world.time + 600 - user.visible_message("[user] vanishes from reality, leaving a a hole in [user.p_their()] place!") + user.visible_message("[user] vanishes from reality, leaving a hole in [user.p_their()] place!") var/obj/effect/immortality_talisman/Z = new(get_turf(src.loc)) Z.name = "hole in reality" Z.desc = "It's shaped an awful lot like [user.name]." diff --git a/code/modules/mob/inventory_procs.dm b/code/modules/mob/inventory_procs.dm index 53b883cf0a97..e551dc7b683f 100644 --- a/code/modules/mob/inventory_procs.dm +++ b/code/modules/mob/inventory_procs.dm @@ -85,7 +85,7 @@ return 0 /mob/proc/put_in_hand_check(obj/item/W, skip_blocked_hands_check) - if(!istype(W)) + if(!istype(W) || QDELETED(W)) return FALSE return TRUE diff --git a/code/modules/mob/living/carbon/alien/alien_base.dm b/code/modules/mob/living/carbon/alien/alien_base.dm index cc8f61a59c3c..7a7845746393 100644 --- a/code/modules/mob/living/carbon/alien/alien_base.dm +++ b/code/modules/mob/living/carbon/alien/alien_base.dm @@ -181,7 +181,7 @@ return threatcount //Check for weapons - if(judgebot.weaponscheck) + if(judgebot.weapons_check) if(judgebot.check_for_weapons(l_hand)) threatcount += 4 if(judgebot.check_for_weapons(r_hand)) diff --git a/code/modules/mob/living/carbon/human/human_mob.dm b/code/modules/mob/living/carbon/human/human_mob.dm index d5ba70c8bda6..6d46d5f16e71 100644 --- a/code/modules/mob/living/carbon/human/human_mob.dm +++ b/code/modules/mob/living/carbon/human/human_mob.dm @@ -1595,7 +1595,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X threatcount += 4 //Check for weapons - if(judgebot.weaponscheck) + if(judgebot.weapons_check) if(!idcard || !(ACCESS_WEAPONS in idcard.access)) if(judgebot.check_for_weapons(l_hand)) threatcount += 4 diff --git a/code/modules/mob/living/carbon/human/human_say.dm b/code/modules/mob/living/carbon/human/human_say.dm index 39158d342de5..551689b1ec6c 100644 --- a/code/modules/mob/living/carbon/human/human_say.dm +++ b/code/modules/mob/living/carbon/human/human_say.dm @@ -69,13 +69,13 @@ return FALSE if((breathes && !L) || breathes && L && (L.status & ORGAN_DEAD)) return FALSE - if(getOxyLoss() > 10 || AmountLoseBreath() >= 8 SECONDS) - emote("gasp") - return FALSE if(mind) return !mind.miming return TRUE +/mob/living/carbon/human/cannot_speak_loudly() + return getOxyLoss() > 10 || AmountLoseBreath() >= 8 SECONDS + /mob/living/carbon/human/proc/SetSpecialVoice(new_voice) if(new_voice) special_voice = new_voice diff --git a/code/modules/mob/living/carbon/human/species/vox.dm b/code/modules/mob/living/carbon/human/species/vox.dm index ee59568aa3b2..9afe9f2598b9 100644 --- a/code/modules/mob/living/carbon/human/species/vox.dm +++ b/code/modules/mob/living/carbon/human/species/vox.dm @@ -49,7 +49,9 @@ 3 = "Brown", 4 = "Grey", 5 = "Emerald", - 6 = "Azure" + 6 = "Azure", + 7 = "Crimson", + 8 = "Nebula" ) has_organ = list( @@ -103,6 +105,12 @@ if(H.dna.species.bodyflags & HAS_ICON_SKIN_TONE) var/new_icobase = 'icons/mob/human_races/vox/r_vox.dmi' //Default Green Vox. switch(H.s_tone) + if(8) //Nebula Vox. + new_icobase = 'icons/mob/human_races/vox/r_voxpurp.dmi' + H.tail = "voxtail_purp" + if(7) //Crimson Vox. + new_icobase = 'icons/mob/human_races/vox/r_voxcrim.dmi' + H.tail = "voxtail_crim" if(6) //Azure Vox. new_icobase = 'icons/mob/human_races/vox/r_voxazu.dmi' H.tail = "voxtail_azu" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index bbed15a5c3dd..daf0ab0dcd05 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -291,7 +291,7 @@ /mob/living/verb/succumb() set hidden = TRUE - if(health >= HEALTH_THRESHOLD_CRIT || stat != UNCONSCIOUS) + if(health >= HEALTH_THRESHOLD_CRIT) to_chat(src, "You are unable to succumb to death! This life continues!") return diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index dc3398a6063b..c97f22eebba3 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -182,6 +182,9 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key) var/list/hsp = handle_speech_problems(message_pieces, verb) verb = hsp["verb"] + if(cannot_speak_loudly()) + return whisper(message) + // Do this so it gets logged for all types of communication var/log_message = "[message_mode ? "([message_mode])" : ""] '[message]'" create_log(SAY_LOG, log_message) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 3271da6504f5..9366461eb337 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -34,7 +34,7 @@ var/disabling_timer_id = null var/list/player_access = list() - var/emagged = 0 + var/emagged = FALSE var/obj/item/card/id/access_card // the ID card that the bot "holds" var/list/prev_access = list() var/on = TRUE @@ -201,6 +201,9 @@ return ..() +/mob/living/simple_animal/bot/mob_negates_gravity() + return anchored + /mob/living/simple_animal/bot/death(gibbed) // Only execute the below if we successfully died . = ..() @@ -214,11 +217,10 @@ /mob/living/simple_animal/bot/emag_act(mob/user) if(locked) //First emag application unlocks the bot's interface. Apply a screwdriver to use the emag again. locked = FALSE - emagged = 1 to_chat(user, "You bypass [src]'s controls.") return if(!locked && open) //Bot panel is unlocked by ID or emag, and the panel is screwed open. Ready for emagging. - emagged = 2 + emagged = TRUE remote_disabled = TRUE //Manually emagging the bot locks out the AI built in panel. locked = TRUE //Access denied forever! bot_reset() @@ -469,12 +471,13 @@ scan() will search for a given type (such as turfs, human mobs, or objects) in t Arguments: The object type to be searched (such as "/mob/living/carbon/human"), the old scan result to be ignored, if one exists, and the view range, which defaults to 7 (full screen) if an override is not passed. If the bot maintains an ignore list, it is also checked here. +If the bot has avoid_bot, which inserts its own path, it will ignore turfs with the same bot type Example usage: patient = scan(/mob/living/carbon/human, oldpatient, 1) The proc would return a human next to the bot to be set to the patient var. Pass the desired type path itself, declaring a temporary var beforehand is not required. */ -/mob/living/simple_animal/bot/proc/scan(atom/scan_type, atom/old_target, scan_range = DEFAULT_SCAN_RANGE) +/mob/living/simple_animal/bot/proc/scan(atom/scan_type, atom/old_target, scan_range = DEFAULT_SCAN_RANGE, avoid_bot) var/final_result for(var/scan in view(scan_range, src)) //Search for something in range! var/atom/A = scan @@ -482,6 +485,8 @@ Pass the desired type path itself, declaring a temporary var beforehand is not r continue //If not, keep searching! if((A.UID() in ignore_list) || (A == old_target)) //Filter for blacklisted elements, usually unreachable or previously processed oness continue + if(turf_has_bot(avoid_bot, get_turf(A))) //Ignores targets that already have a bot of the same type on it, meant for cleanbot and floorbot seperation + continue var/scan_result = process_scan(A) //Some bots may require additional processing when a result is selected. if(scan_result) final_result = scan_result @@ -489,6 +494,14 @@ Pass the desired type path itself, declaring a temporary var beforehand is not r continue //The current element failed assessment, move on to the next. return final_result +/mob/living/simple_animal/bot/proc/turf_has_bot(avoid_bot, turf/turf_to_search) + if(!avoid_bot) + return FALSE + for(var/bot in turf_to_search) + if(istype(bot, avoid_bot)) + return TRUE + return FALSE + //When the scan finds a target, run bot specific processing to select it for the next step. Empty by default. /mob/living/simple_animal/bot/proc/process_scan(atom/scan_target) return scan_target @@ -736,7 +749,7 @@ Pass a positive integer as an argument to override a bot's default speed. return FALSE // check to see if we are the commanded bot - if(emagged == 2 || remote_disabled || hijacked) //Emagged bots do not respect anyone's authority! Bots with their remote controls off cannot get commands. + if(emagged || remote_disabled || hijacked) //Emagged bots do not respect anyone's authority! Bots with their remote controls off cannot get commands. return FALSE if(client) @@ -879,8 +892,8 @@ Pass a positive integer as an argument to override a bot's default speed. /mob/living/simple_animal/bot/proc/handle_hacking(mob/M) // refactored out of Topic/ to allow re-use by TGUIs if(!canhack(M)) return - if(emagged != 2) - emagged = 2 + if(!emagged) + emagged = TRUE hacked = TRUE locked = TRUE to_chat(M, "[text_hack]") @@ -890,7 +903,7 @@ Pass a positive integer as an argument to override a bot's default speed. else if(!hacked) to_chat(M, "[text_dehack_fail]") else - emagged = 0 + emagged = FALSE hacked = FALSE to_chat(M, "[text_dehack]") show_laws() @@ -905,7 +918,7 @@ Pass a positive integer as an argument to override a bot's default speed. return FALSE if(user.incapacitated() || !(issilicon(user) || in_range(src, user))) return TRUE - if(emagged == 2) //An emagged bot cannot be controlled by humans, silicons can if one hacked it. + if(emagged) //An emagged bot cannot be controlled by humans, silicons can if one hacked it. if(!hacked) //Manually emagged by a human - access denied to all. return TRUE else if(!(issilicon(user) || ispulsedemon(user))) //Bot is hacked, so only silicons are allowed access. @@ -919,7 +932,7 @@ Pass a positive integer as an argument to override a bot's default speed. /mob/living/simple_animal/bot/proc/hack(mob/user) var/hack if(issilicon(user) || user.can_admin_interact()) //Allows silicons or admins to toggle the emag status of a bot. - hack += "[emagged == 2 ? "Software compromised! Unit may exhibit dangerous or erratic behavior." : "Unit operating normally. Release safety lock?"]
" + hack += "[emagged ? "Software compromised! Unit may exhibit dangerous or erratic behavior." : "Unit operating normally. Release safety lock?"]
" hack += "Harm Prevention Safety System: [emagged ? "DANGER" : "Engaged"]
" else if(!locked) //Humans with access can use this option to hide a bot from the AI's remote control panel and PDA control. hack += "Remote network control radio: [remote_disabled ? "Disconnected" : "Connected"]
" @@ -1006,7 +1019,7 @@ Pass a positive integer as an argument to override a bot's default speed. if(paicard && paicard.pai && paicard.pai.master && paicard.pai.pai_law0) to_chat(src, "Your master, [paicard.pai.master], may overrule any and all laws.") to_chat(src, "0. [paicard.pai.pai_law0]") - if(emagged >= 2) + if(emagged) to_chat(src, "1. #$!@#$32K#$") else to_chat(src, "1. You are a machine built to serve the station's crew and AI(s).") diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index 7c21d451ec30..08bf6ea34a80 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -29,12 +29,32 @@ var/failed_steps var/next_dest var/next_dest_loc + var/static/list/clean_dirt = list( + /obj/effect/decal/cleanable/vomit, + /obj/effect/decal/cleanable/blood/gibs/robot, + /obj/effect/decal/cleanable/crayon, + /obj/effect/decal/cleanable/liquid_fuel, + /obj/effect/decal/cleanable/molten_object, + /obj/effect/decal/cleanable/tomato_smudge, + /obj/effect/decal/cleanable/egg_smudge, + /obj/effect/decal/cleanable/pie_smudge, + /obj/effect/decal/cleanable/flour, + /obj/effect/decal/cleanable/ash, + /obj/effect/decal/cleanable/greenglow, + /obj/effect/decal/cleanable/dirt + ) + var/static/list/clean_blood = list( + /obj/effect/decal/cleanable/blood, + /obj/effect/decal/cleanable/trail_holder + ) /mob/living/simple_animal/bot/cleanbot/Initialize(mapload) . = ..() - get_targets() icon_state = "cleanbot[on]" + clean_dirt = typecacheof(clean_dirt) + clean_blood = typecacheof(clean_blood) + var/datum/job/janitor/J = new/datum/job/janitor access_card.access += J.get_access() prev_access = access_card.access @@ -80,9 +100,8 @@ to_chat(user, "[src] buzzes and beeps.") /mob/living/simple_animal/bot/cleanbot/process_scan(obj/effect/decal/cleanable/D) - for(var/T in target_types) - if(istype(D, T)) - return D + if(is_type_in_typecache(D, clean_dirt) || blood && is_type_in_typecache(D, clean_blood)) + return D /mob/living/simple_animal/bot/cleanbot/handle_automated_action() if(!..()) @@ -91,7 +110,7 @@ if(mode == BOT_CLEANING) return - if(emagged == 2) //Emag functions + if(emagged) //Emag functions if(issimulatedturf(loc)) if(prob(10)) //Wets floors randomly var/turf/simulated/T = loc @@ -105,7 +124,7 @@ audible_message("[src] makes an excited beeping booping sound!") if(!target) //Search for cleanables it can see. - target = scan(/obj/effect/decal/cleanable) + target = scan(/obj/effect/decal/cleanable, avoid_bot = /mob/living/simple_animal/bot/cleanbot) if(!target && auto_patrol) //Search for cleanables it can see. if(mode == BOT_IDLE || mode == BOT_START_PATROL) @@ -136,32 +155,6 @@ oldloc = loc -/mob/living/simple_animal/bot/cleanbot/proc/get_targets() - target_types = new/list() - - target_types += /obj/effect/decal/cleanable/blood/oil - target_types += /obj/effect/decal/cleanable/vomit - target_types += /obj/effect/decal/cleanable/blood/gibs/robot - target_types += /obj/effect/decal/cleanable/crayon - target_types += /obj/effect/decal/cleanable/liquid_fuel - target_types += /obj/effect/decal/cleanable/molten_object - target_types += /obj/effect/decal/cleanable/tomato_smudge - target_types += /obj/effect/decal/cleanable/egg_smudge - target_types += /obj/effect/decal/cleanable/pie_smudge - target_types += /obj/effect/decal/cleanable/flour - target_types += /obj/effect/decal/cleanable/ash - target_types += /obj/effect/decal/cleanable/greenglow - target_types += /obj/effect/decal/cleanable/dirt - - if(blood) - target_types += /obj/effect/decal/cleanable/blood/xeno/ - target_types += /obj/effect/decal/cleanable/blood/gibs/xeno - target_types += /obj/effect/decal/cleanable/blood/ - target_types += /obj/effect/decal/cleanable/blood/gibs/ - target_types += /obj/effect/decal/cleanable/blood/tracks - target_types += /obj/effect/decal/cleanable/dirt - target_types += /obj/effect/decal/cleanable/trail_holder - /mob/living/simple_animal/bot/cleanbot/proc/start_clean(obj/effect/decal/cleanable/target) anchored = TRUE icon_state = "cleanbot-c" @@ -226,7 +219,6 @@ remote_disabled = !remote_disabled if("blood") blood =!blood - get_targets() if("ejectpai") ejectpai() diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 95ef953291f5..4b97371bc2f8 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -38,7 +38,7 @@ var/last_found //There's a delay var/declare_arrests = TRUE //When making an arrest, should it notify everyone wearing sechuds? var/idcheck = FALSE //If true, arrest people with no IDs - var/weaponscheck = TRUE //If true, arrest people for weapons if they don't have access + var/weapons_check = TRUE //If true, arrest people for weapons if they don't have access var/check_records = TRUE //Does it check security records? var/arrest_type = FALSE //If true, don't handcuff var/projectile = /obj/item/projectile/beam/disabler //Holder for projectile type @@ -111,7 +111,7 @@ /mob/living/simple_animal/bot/ed209/ui_data(mob/user) var/list/data = ..() data["check_id"] = idcheck - data["check_weapons"] = weaponscheck + data["check_weapons"] = weapons_check data["check_warrant"] = check_records data["arrest_mode"] = arrest_type // detain or arrest data["arrest_declare"] = declare_arrests // announce arrests on radio @@ -139,7 +139,7 @@ if("disableremote") remote_disabled = !remote_disabled if("authweapon") - weaponscheck = !weaponscheck + weapons_check = !weapons_check if("authid") idcheck = !idcheck if("authwarrant") @@ -185,7 +185,7 @@ /mob/living/simple_animal/bot/ed209/emag_act(mob/user) ..() - if(emagged == 2) + if(emagged) if(user) to_chat(user, "You short out [src]'s target assessment circuits.") oldtarget_name = user.name @@ -416,7 +416,7 @@ /mob/living/simple_animal/bot/ed209/proc/set_weapon() //used to update the projectile type and firing sound shoot_sound = 'sound/weapons/laser.ogg' - if(emagged == 2) + if(emagged) if(lasercolor) projectile = /obj/item/projectile/beam/disabler else @@ -482,11 +482,11 @@ var/mob/toshoot = pick(targets) if(toshoot) targets-=toshoot - if(prob(50) && emagged < 2) - emagged = 2 + if(prob(50) && !emagged && !locked) + emagged = TRUE set_weapon() shootAt(toshoot) - emagged = 0 + emagged = FALSE set_weapon() else shootAt(toshoot) diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index cabab890caa0..4aebd8a90611 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -17,19 +17,25 @@ req_access = list(ACCESS_CONSTRUCTION, ACCESS_ROBOTICS) window_id = "autofloor" window_name = "Automatic Station Floor Repairer v1.1" - - var/process_type //Determines what to do when process_scan() recieves a target. See process_scan() for details. + /// Determines what to do when process_scan() recieves a target. See process_scan() for details. + var/process_type + /// Tiles in inventory var/amount = 10 - var/replacetiles = 0 - var/eattiles = 0 - var/maketiles = 0 - var/fixfloors = 0 - var/autotile = 0 - var/nag_on_empty = 1 - var/nagged = 0 //Prevents the Floorbot nagging more than once per refill. + /// Add tiles to existing floor + var/replace_tiles = FALSE + /// Add floor tiles to inventory + var/eat_tiles = FALSE + /// Convert metal into floor tiles (drops on floor) + var/make_tiles = FALSE + var/fix_floor = FALSE + /// Fix the floor and include a tile. + var/autotile = FALSE + var/nag_on_empty = TRUE + /// Prevents the Floorbot nagging more than once per refill. + var/nagged = FALSE var/max_targets = 50 var/turf/target - var/oldloc = null + var/oldloc var/toolbox_color = "" #define HULL_BREACH 1 @@ -37,6 +43,7 @@ #define AUTO_TILE 4 #define REPLACE_TILE 5 #define TILE_EMAG 6 + #define MAX_AMOUNT 50 // Maximum tiles bot can have in storage /mob/living/simple_animal/bot/floorbot/Initialize(mapload, new_toolbox_color) . = ..() @@ -75,10 +82,10 @@ /mob/living/simple_animal/bot/floorbot/ui_data(mob/user) var/list/data = ..() data["hullplating"] = autotile - data["replace"] = replacetiles - data["eat"] = eattiles - data["make"] = maketiles - data["fixfloor"] = fixfloors + data["replace"] = replace_tiles + data["eat"] = eat_tiles + data["make"] = make_tiles + data["fixfloor"] = fix_floor data["nag_empty"] = nag_on_empty data["magnet"] = anchored data["tiles_amount"] = amount @@ -109,15 +116,15 @@ if("autotile") autotile = !autotile if("replacetiles") - replacetiles = !replacetiles + replace_tiles = !replace_tiles if("eattiles") - eattiles = !eattiles + eat_tiles = !eat_tiles if("maketiles") - maketiles = !maketiles + make_tiles = !make_tiles + if("fixfloors") + fix_floor = !fix_floor if("nagonempty") nag_on_empty = !nag_on_empty - if("fixfloors") - fixfloors = !fixfloors if("anchored") anchored = !anchored if("ejectpai") @@ -126,9 +133,9 @@ /mob/living/simple_animal/bot/floorbot/attackby(obj/item/W , mob/user, params) if(istype(W, /obj/item/stack/tile/plasteel)) var/obj/item/stack/tile/plasteel/T = W - if(amount >= 50) + if(amount >= MAX_AMOUNT) return - var/loaded = min(50-amount, T.amount) + var/loaded = min(MAX_AMOUNT - amount, T.amount) T.use(loaded) amount += loaded if(loaded > 0) @@ -147,45 +154,45 @@ to_chat(user, "[src] buzzes and beeps.") /mob/living/simple_animal/bot/floorbot/handle_automated_action() - if(!..()) + . = ..() + if(!.) return - if(mode == BOT_REPAIRING) + if(mode == BOT_REPAIRING || mode == BOT_EAT_TILE || mode == BOT_MAKE_TILE) return - if(amount <= 0 && !target) //Out of tiles! We must refill! - if(eattiles) //Configured to find and consume floortiles! - target = scan(/obj/item/stack/tile/plasteel) - process_type = null - - if(!target && maketiles) //We did not manage to find any floor tiles! Scan for metal stacks and make our own! - target = scan(/obj/item/stack/sheet/metal) - process_type = null - return - else - if(nag_on_empty) //Floorbot is empty and cannot acquire more tiles, nag the engineers for more! - nag() - if(prob(5)) audible_message("[src] makes an excited booping beeping sound!") //Normal scanning procedure. We have tiles loaded, are not emagged. - if(!target && emagged < 2 && amount > 0) + if(!target && !emagged && amount) if(!target) process_type = HULL_BREACH //Ensures the floorbot does not try to "fix" space areas or shuttle docking zones. - target = scan(/turf/space) + target = scan(/turf/space, avoid_bot = /mob/living/simple_animal/bot/floorbot) - if(!target && replacetiles) //Finds a floor without a tile and gives it one. + if(!target && replace_tiles) //Finds a floor without a tile and gives it one. process_type = REPLACE_TILE //The target must be the floor and not a tile. The floor must not already have a floortile. - target = scan(/turf/simulated/floor) + target = scan(/turf/simulated/floor, avoid_bot = /mob/living/simple_animal/bot/floorbot) - if(!target && fixfloors) //Repairs damaged floors and tiles. + if(!target && fix_floor) //Repairs damaged floors and tiles. process_type = FIX_TILE - target = scan(/turf/simulated/floor) + target = scan(/turf/simulated/floor, avoid_bot = /mob/living/simple_animal/bot/floorbot) - if(!target && emagged == 2) //We are emagged! Time to rip up the floors! + if(!target && emagged) //We are emagged! Time to rip up the floors! process_type = TILE_EMAG - target = scan(/turf/simulated/floor) + target = scan(/turf/simulated/floor, avoid_bot = /mob/living/simple_animal/bot/floorbot) + + if(amount < MAX_AMOUNT && !target) //Out of tiles! We must refill! + if(eat_tiles) //Configured to find and consume floortiles! + target = scan(/obj/item/stack/tile/plasteel) + process_type = null + + if(!target && make_tiles) //We did not manage to find any floor tiles! Scan for metal stacks and make our own! + target = scan(/obj/item/stack/sheet/metal) + process_type = null + + if(!target && nag_on_empty) //Floorbot is empty and cannot acquire more tiles, nag the engineers for more! + nag() if(!target) @@ -199,13 +206,17 @@ if(target) if(loc == target || loc == target.loc) + if(istype(target, /obj/item/stack/tile/plasteel)) start_eattile(target) - else if(istype(target, /obj/item/stack/sheet/metal)) + + if(istype(target, /obj/item/stack/sheet/metal)) start_maketile(target) - else if(isturf(target) && emagged < 2) + + if(isturf(target) && !emagged) repair(target) - else if(emagged == 2 && isfloorturf(target)) + + if(emagged && isfloorturf(target)) var/turf/simulated/floor/F = target anchored = TRUE mode = BOT_REPAIRING @@ -221,9 +232,9 @@ if(!length(path)) if(!isturf(target)) var/turf/TL = get_turf(target) - path = get_path_to(src, TL, 30, id=access_card,simulated_only = 0) + path = get_path_to(src, TL, 30, id = access_card, simulated_only = 0) else - path = get_path_to(src, target, 30, id=access_card,simulated_only = 0) + path = get_path_to(src, target, 30, id = access_card, simulated_only = 0) if(!bot_move(target)) add_to_ignore(target) @@ -245,15 +256,11 @@ /mob/living/simple_animal/bot/floorbot/proc/nag() //Annoy everyone on the channel to refill us! if(!nagged) - speak("Requesting refill at [get_area(src)]!", radio_channel) + speak("Requesting refill [MAX_AMOUNT - amount] at [get_area(src)]!", radio_channel) nagged = TRUE /mob/living/simple_animal/bot/floorbot/proc/is_hull_breach(turf/t) //Ignore space tiles not considered part of a structure, also ignores shuttle docking areas. - var/area/t_area = get_area(t) - if(t_area && (t_area.name == "Space" || findtext(t_area.name, "huttle"))) - return 0 - else - return 1 + return !isspaceturf(get_area(t)) //Floorbots, having several functions, need sort out special conditions here. /mob/living/simple_animal/bot/floorbot/process_scan(atom/scan_target) @@ -310,33 +317,19 @@ visible_message("[src] begins repairing the floor.") addtimer(CALLBACK(src, PROC_REF(make_bridge_plating), F), 5 SECONDS) -/mob/living/simple_animal/bot/floorbot/proc/make_floor(turf/simulated/floor/F) - if(mode != BOT_REPAIRING) - return - - F.broken = FALSE - F.burnt = FALSE - F.ChangeTurf(/turf/simulated/floor/plasteel) - mode = BOT_IDLE - amount-- - update_icon(UPDATE_OVERLAYS) - anchored = FALSE - target = null /mob/living/simple_animal/bot/floorbot/proc/make_bridge_plating(turf/target_turf) var/turf/simulated/floor/F = target if(mode != BOT_REPAIRING) return - if(replacetiles) - F.break_tile_to_plating() + if(autotile || replace_tiles) + if(process_type != HULL_BREACH) + F.break_tile_to_plating() target_turf.ChangeTurf(/turf/simulated/floor/plasteel) else - if(autotile) //Build the floor and include a tile. - F.break_tile_to_plating() - target_turf.ChangeTurf(/turf/simulated/floor/plasteel) - else //Build a hull plating without a floor tile. - target_turf.ChangeTurf(/turf/simulated/floor/plating) + target_turf.ChangeTurf(/turf/simulated/floor/plating) + mode = BOT_IDLE amount-- update_icon(UPDATE_OVERLAYS) @@ -347,7 +340,8 @@ if(!istype(T, /obj/item/stack/tile/plasteel)) return visible_message("[src] begins to collect tiles.") - mode = BOT_REPAIRING + mode = BOT_EAT_TILE + update_icon(UPDATE_OVERLAYS) addtimer(CALLBACK(src, PROC_REF(do_eattile), T), 2 SECONDS) /mob/living/simple_animal/bot/floorbot/proc/do_eattile(obj/item/stack/tile/plasteel/T) @@ -355,8 +349,8 @@ target = null mode = BOT_IDLE return - if(amount + T.amount > 50) - var/i = 50 - amount + if((amount + T.amount) > MAX_AMOUNT) + var/i = MAX_AMOUNT - amount amount += i T.amount -= i else @@ -370,7 +364,8 @@ if(!istype(M, /obj/item/stack/sheet/metal)) return visible_message("[src] begins to create tiles.") - mode = BOT_REPAIRING + mode = BOT_MAKE_TILE + update_icon(UPDATE_OVERLAYS) addtimer(CALLBACK(src, PROC_REF(do_maketile), M), 2 SECONDS) /mob/living/simple_animal/bot/floorbot/proc/do_maketile(obj/item/stack/sheet/metal/M) @@ -387,13 +382,14 @@ qdel(M) target = null mode = BOT_IDLE + update_icon(UPDATE_OVERLAYS) /mob/living/simple_animal/bot/floorbot/update_icon_state() return /mob/living/simple_animal/bot/floorbot/update_overlays() . = ..() - if(mode == BOT_REPAIRING) + if(mode == BOT_REPAIRING || mode == BOT_EAT_TILE || mode == BOT_MAKE_TILE) . += "floorbot_work" else . += "floorbot_[on ? "on" : "off"]" @@ -431,3 +427,11 @@ start_maketile(A) else ..() + + +#undef HULL_BREACH +#undef FIX_TILE +#undef AUTO_TILE +#undef REPLACE_TILE +#undef TILE_EMAG +#undef MAX_AMOUNT diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index aceb6fda38f6..7328e2809bc3 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -122,7 +122,7 @@ /mob/living/simple_animal/bot/honkbot/emag_act(mob/user) ..() - if(emagged == 2) + if(emagged) if(user) to_chat(user, "You short out [src]'s target assessment circuits. It gives out an evil laugh!!") oldtarget_name = user.name @@ -140,7 +140,7 @@ return if(iscarbon(A)) var/mob/living/carbon/C = A - if(emagged <= 1) + if(!emagged) honk_attack(A) else if(!C.IsStunned() || arrest_type) @@ -159,13 +159,13 @@ ..() /mob/living/simple_animal/bot/honkbot/proc/bike_horn() //use bike_horn - if(emagged <= 1) + if(!emagged) if(!spam_flag) playsound(src, honksound, 50, TRUE, -1) spam_flag = TRUE //prevent spam sensor_blink() addtimer(CALLBACK(src, PROC_REF(spam_flag_false)), cooldowntimehorn) - else if(emagged == 2) //emagged honkbots will spam short and memorable sounds. + else if(emagged) //emagged honkbots will spam short and memorable sounds. if(!spam_flag) playsound(src, "honkbot_e", 50, 0) spam_flag = TRUE // prevent spam @@ -195,7 +195,7 @@ C.Weaken(10 SECONDS) if(client) //prevent spam from players.. spam_flag = TRUE - if(emagged <= 1) //HONK once, then leave + if(!emagged) //HONK once, then leave threatlevel -= 6 target = oldtarget_name else // you really don't want to hit an emagged honkbot @@ -279,12 +279,12 @@ if((C.name == oldtarget_name) && (world.time < last_found + 100)) continue - if(threatlevel <= 3 && emagged <= 1) + if(threatlevel <= 3 && !emagged) if(C in view(4, src)) //keep the range short for patrolling if(!spam_flag) bike_horn() else if(threatlevel >= 4) - if(!spam_flag || emagged > 1) + if(!spam_flag || emagged) target = C oldtarget_name = C.name bike_horn() @@ -295,7 +295,7 @@ break else continue - else if(emagged > 1) + else if(emagged) bike_horn() //just spam the shit outta this /mob/living/simple_animal/bot/honkbot/explode() //doesn't drop cardboard nor its assembly, since its a very frail material. diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index 03ca50c23d87..be4b74ab49e1 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -101,7 +101,7 @@ Radio.syndiekey = new /obj/item/encryptionkey/syndicate /mob/living/simple_animal/bot/medbot/syndicate/emagged - emagged = 2 + emagged = TRUE declare_crit = FALSE drops_parts = FALSE @@ -258,7 +258,7 @@ /mob/living/simple_animal/bot/medbot/emag_act(mob/user) ..() - if(emagged == 2) + if(emagged) declare_crit = FALSE if(user) to_chat(user, "You short out [src]'s reagent synthesis circuits.") @@ -412,7 +412,7 @@ if(H.dna.species && H.dna.species.reagent_tag == PROCESS_SYN) return FALSE - if(emagged == 2 || hijacked) //Everyone needs our medicine. (Our medicine is toxins) + if(emagged || hijacked) //Everyone needs our medicine. (Our medicine is toxins) return TRUE if(syndicate_aligned && !("syndicate" in C.faction)) @@ -461,7 +461,7 @@ var/reagent_id var/beaker_injection //If and what kind of beaker reagent needs to be injected - if(emagged == 2 || hijacked) //Emagged! Time to poison everybody. + if(emagged || hijacked) //Emagged! Time to poison everybody. reagent_id = "pancuronium" else beaker_injection = assess_beaker_injection(C) diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index c43d3001e870..6a0b1072cd5e 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -149,8 +149,8 @@ update_icon() /mob/living/simple_animal/bot/mulebot/emag_act(mob/user) - if(emagged < 1) - emagged = 1 + if(!emagged) + emagged = TRUE if(!open) locked = !locked to_chat(user, "You [locked ? "lock" : "unlock"] [src]'s controls!") diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index e0a775dade63..8b0e88bc4327 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -30,7 +30,7 @@ var/last_found //There's a delay var/declare_arrests = TRUE //When making an arrest, should it notify everyone on the security channel? var/idcheck = FALSE //If true, arrest people with no IDs - var/weaponscheck = FALSE //If true, arrest people for weapons if they lack access + var/weapons_check = FALSE //If true, arrest people for weapons if they lack access var/check_records = TRUE //Does it check security records? var/arrest_type = FALSE //If true, don't handcuff var/harmbaton = FALSE //If true, beat instead of stun @@ -43,7 +43,7 @@ name = "Officer Beepsky" desc = "It's Officer Beepsky! Powered by a potato and a shot of whiskey." idcheck = FALSE - weaponscheck = FALSE + weapons_check = FALSE auto_patrol = TRUE /mob/living/simple_animal/bot/secbot/beepsky/explode() @@ -63,7 +63,7 @@ name = "Prison Ofitser" desc = "It's Prison Ofitser! Powered by the tears and sweat of prisoners." idcheck = FALSE - weaponscheck = TRUE + weapons_check = TRUE auto_patrol = TRUE /mob/living/simple_animal/bot/secbot/buzzsky @@ -74,7 +74,7 @@ declare_arrests = FALSE arrest_type = TRUE harmbaton = TRUE - emagged = 2 + emagged = TRUE /mob/living/simple_animal/bot/secbot/armsky name = "Sergeant-at-Armsky" @@ -82,7 +82,7 @@ maxHealth = 100 idcheck = TRUE arrest_type = TRUE - weaponscheck = TRUE + weapons_check = TRUE /mob/living/simple_animal/bot/secbot/Initialize(mapload) . = ..() @@ -126,7 +126,7 @@ /mob/living/simple_animal/bot/secbot/ui_data(mob/user) var/list/data = ..() data["check_id"] = idcheck - data["check_weapons"] = weaponscheck + data["check_weapons"] = weapons_check data["check_warrant"] = check_records data["arrest_mode"] = arrest_type // detain or arrest data["arrest_declare"] = declare_arrests // announce arrests on radio @@ -154,7 +154,7 @@ if("disableremote") remote_disabled = !remote_disabled if("authweapon") - weaponscheck = !weaponscheck + weapons_check = !weapons_check if("authid") idcheck = !idcheck if("authwarrant") @@ -187,7 +187,7 @@ /mob/living/simple_animal/bot/secbot/emag_act(mob/user) ..() - if(emagged == 2) + if(emagged) if(user) to_chat(user, "You short out [src]'s target assessment circuits.") oldtarget_name = user.name diff --git a/code/modules/mob/living/simple_animal/bot/syndicate_bots.dm b/code/modules/mob/living/simple_animal/bot/syndicate_bots.dm index f5835de4d24d..8e35dbc16550 100644 --- a/code/modules/mob/living/simple_animal/bot/syndicate_bots.dm +++ b/code/modules/mob/living/simple_animal/bot/syndicate_bots.dm @@ -12,7 +12,7 @@ idcheck = TRUE arrest_type = TRUE auto_patrol = TRUE - emagged = 2 + emagged = TRUE faction = list("syndicate") shoot_sound = 'sound/weapons/wave.ogg' anchored = TRUE diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index adf774b46fdc..ebcfa14a2992 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1326,6 +1326,9 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \ /mob/proc/IsVocal() return TRUE +/mob/proc/cannot_speak_loudly() + return FALSE + /mob/proc/get_access() return list() //must return list or IGNORE_ACCESS diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 29b384684c6f..a7f15f9a3fa5 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -550,12 +550,17 @@ check_prefs_are_sane() var/mob/living/carbon/human/new_character = new(loc) new_character.lastarea = get_area(loc) - - if(SSticker.random_players) - client.prefs.active_character.randomise() - client.prefs.active_character.real_name = random_name(client.prefs.active_character.gender) client.prefs.active_character.copy_to(new_character) - + if(SSticker.random_players) + var/mob/living/carbon/human/H = new_character + scramble(1, H, 100) + H.real_name = random_name(H.gender, H.dna.species.name) + H.sync_organ_dna(assimilate = 1) + H.update_body() + H.reset_hair() + H.reset_markings() + H.dna.ResetUIFrom(H) + H.flavor_text = "" stop_sound_channel(CHANNEL_LOBBYMUSIC) diff --git a/code/modules/mob/new_player/sprite_accessories/diona/diona_hair.dm b/code/modules/mob/new_player/sprite_accessories/diona/diona_hair.dm index c819924edc63..ab50e39b0265 100644 --- a/code/modules/mob/new_player/sprite_accessories/diona/diona_hair.dm +++ b/code/modules/mob/new_player/sprite_accessories/diona/diona_hair.dm @@ -102,3 +102,105 @@ name = "Big Leaf" icon_state = "bigleaf" glasses_over = FALSE + +//Sprites from Aurora Below +/datum/sprite_accessory/hair/diona/diona_treebeard + name = "Treebeard" + icon_state = "treebeard" + +/datum/sprite_accessory/hair/diona/monoeye + name = "Monoeye" + icon_state = "monoeye" + +/datum/sprite_accessory/hair/diona/trioptics + name = "Trioptics" + icon_state = "trioptics" + +/datum/sprite_accessory/hair/diona/lopsided + name = "Lopsided" + icon_state = "lopsided" + +/datum/sprite_accessory/hair/diona/helmethead + name = "Helmet Head" + icon_state = "helmethead" + +/datum/sprite_accessory/hair/diona/eyestalk + name = "Eyestalk" + icon_state = "eyestalk" + +/datum/sprite_accessory/hair/diona/bugeyes + name = "Bug Eyes" + icon_state = "bugeyes" + +/datum/sprite_accessory/hair/diona/humaneyes + name = "Human Eyes" + icon_state = "humaneyes" + +/datum/sprite_accessory/hair/diona/skrelleyes + name = "Skrell Eyes" + icon_state = "skrelleyes" + +/datum/sprite_accessory/hair/diona/smallhorns + name = "Small Horns" + icon_state = "smallhorns" + +/datum/sprite_accessory/hair/diona/horns + name = "Horns" + icon_state = "horns" + +/datum/sprite_accessory/hair/diona/headtails + name = "Head Tails" + icon_state = "headtails" + +/datum/sprite_accessory/hair/diona/headtails2 + name = "Head Tails 2" + icon_state = "headtails2" + +/datum/sprite_accessory/hair/diona/eyebrow + name = "Eye Brow" + icon_state = "eyebrow" + +/datum/sprite_accessory/hair/diona/bullhorn + name = "Bull Horn" + icon_state = "bullhorn" + +/datum/sprite_accessory/hair/diona/blinkinghelmethead + name = "Blinking Helmet Head" + icon_state = "blinkinghelmethead" + +/datum/sprite_accessory/hair/diona/periscope + name = "Periscope" + icon_state = "periscope" + +/datum/sprite_accessory/hair/diona/glorp + name = "Glorp" + icon_state = "glorp" + +/datum/sprite_accessory/hair/diona/mellowcap + name = "Mellow Cap" + icon_state = "mellowcap" + glasses_over = FALSE + +/datum/sprite_accessory/hair/diona/redcap + name = "Red Cap" + icon_state = "redcap" + glasses_over = FALSE + +/datum/sprite_accessory/hair/diona/purplecap + name = "Purple Cap" + icon_state = "purplecap" + glasses_over = FALSE + +/datum/sprite_accessory/hair/diona/spanishmoss + name = "Spanish Moss" + icon_state = "spanishmoss" + glasses_over = FALSE + +/datum/sprite_accessory/hair/diona/thorns + name = "Thorns" + icon_state = "thorns" + +/datum/sprite_accessory/hair/diona/stump + name = "Stump" + icon_state = "stump" +//Sprites from Aurora Above diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 44c94fc76bb6..83def2f64a9a 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -132,8 +132,8 @@ add_attack_logs(user, M, "Stabbed with (sleepy) [src]. [transfered]u of reagents transfered from pen containing [english_list(contained)].") for(var/datum/reagent/R as anything in reagents.reagent_list) if(initial(R.id) == "????") // Yes this is a specific case that we don't really want - return TRUE - reagents.reaction(M, REAGENT_INGEST, 0.1) + continue + reagents.reaction(M, REAGENT_INGEST, 0.1) return TRUE diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 264ac7f9de8f..b81b6a5690ec 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -264,12 +264,12 @@ if(blocked != INFINITY) if(M.can_inject(null, FALSE, hit_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body. ..() + for(var/datum/reagent/R as anything in reagents.reagent_list) if(initial(R.id) == "????") // Yes this is a specific case that we don't really want - reagents.trans_to(M, reagents.total_volume) - return TRUE + continue + reagents.reaction(M, REAGENT_INGEST, 0.1) reagents.trans_to(M, reagents.total_volume) - reagents.reaction(M, REAGENT_INGEST, 0.1) return TRUE else blocked = INFINITY diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 72996bda5f3a..32ac08eaf6d3 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -53,8 +53,8 @@ add_attack_logs(user, M, "Injected with [src] containing ([contained])", reagents.harmless_helper() ? ATKLOG_ALMOSTALL : null) for(var/datum/reagent/R as anything in reagents.reagent_list) if(initial(R.id) == "????") // Yes this is a specific case that we don't really want - return TRUE - reagents.reaction(M, REAGENT_INGEST, 0.1) + continue + reagents.reaction(M, REAGENT_INGEST, 0.1) return TRUE /obj/item/reagent_containers/hypospray/attack(mob/living/M, mob/user) diff --git a/code/modules/response_team/ert.dm b/code/modules/response_team/ert.dm index 47b6a68617c0..5975eb7f1fb9 100644 --- a/code/modules/response_team/ert.dm +++ b/code/modules/response_team/ert.dm @@ -98,7 +98,7 @@ GLOBAL_LIST_EMPTY(ert_request_messages) A.close() var/list/ert_species_prefs = list() for(var/mob/M in GLOB.response_team_members) - ert_species_prefs.Add(input_async(M, "Please select a species (10 seconds):", list("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin", "Nian", "Random"))) + ert_species_prefs.Add(input_async(M, "Please select a species (10 seconds):", list("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin", "Nian", "Drask", "Kidan", "Grey", "Random"))) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(get_ert_role_prefs), GLOB.response_team_members, ert_gender_prefs, ert_species_prefs), 10 SECONDS) /proc/get_ert_role_prefs(list/response_team_members, list/ert_gender_prefs, list/ert_species_prefs) // Why the FUCK is this variable the EXACT SAME as the global one @@ -164,7 +164,7 @@ GLOBAL_LIST_EMPTY(ert_request_messages) if(!new_species) new_species = "Human" if(new_species == "Random") - new_species = pick("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin", "Nian") + new_species = pick("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin", "Nian", "Drask", "Kidan", "Grey") var/datum/species/S = GLOB.all_species[new_species] var/species = S.type M.set_species(species, TRUE) @@ -172,10 +172,10 @@ GLOBAL_LIST_EMPTY(ert_request_messages) M.cleanSE() //No fat/blind/colourblind/epileptic/whatever ERT. M.overeatduration = 0 var/obj/item/organ/external/head/head_organ = M.get_organ("head") - var/eye_c = pick("#000000", "#8B4513", "#1E90FF") // Black, brown, blue + var/eye_c = pick("#000000", "#8B4513", "#1E90FF", "#8c00ff", "#a80c0c", "#2fdb63") // Black, brown, blue, purple, red, green var/skin_tone = rand(-120, 20) // A range of skin colors - switch(new_species) //Diona not included as they don't use the hair colours + switch(new_species) //Diona not included as they don't use the hair colours, kidan use accessory, drask are skin tone Grey not included as they are BALD if("Human", "Tajaran", "Vulpkanin", "Nian") var/hair_c_htvn = pick("#8B4513", "#000000", "#FF4500", "#FFD700", "#d4d1bf") // Brown, black, red, blonde, grey head_organ.facial_colour = hair_c_htvn @@ -195,8 +195,10 @@ GLOBAL_LIST_EMPTY(ert_request_messages) else M.skin_colour = pick(su) //Pick a diffrent colour for body. + 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) diff --git a/code/modules/supply/supply_packs/pack_miscellaneous.dm b/code/modules/supply/supply_packs/pack_miscellaneous.dm index 1c54a3b1f858..bce9c7952cba 100644 --- a/code/modules/supply/supply_packs/pack_miscellaneous.dm +++ b/code/modules/supply/supply_packs/pack_miscellaneous.dm @@ -192,6 +192,15 @@ cost = 100 containername = "replacement lights crate" +/datum/supply_packs/misc/janicart + name = "Janicart Crate" + contains = list(/obj/vehicle/janicart, + /obj/item/key/janitor) + cost = 500 + containertype = /obj/structure/largecrate + containername = "Janicart. Caution while driving is advised." + department_restrictions = list(DEPARTMENT_SERVICE) + /datum/supply_packs/misc/noslipfloor name = "High-traction Floor Tiles" contains = list(/obj/item/stack/tile/noslip/loaded) diff --git a/code/modules/tgs/core/README.md b/code/modules/tgs/core/README.md index aa3c7a9c9db6..bb55caba2c4a 100644 --- a/code/modules/tgs/core/README.md +++ b/code/modules/tgs/core/README.md @@ -3,6 +3,6 @@ This folder contains all DMAPI code not directly involved in an API. - [_definitions.dm](./definitions.dm) contains defines needed across DMAPI internals. -- [core.dm](./core.dm) contains the implementations of the `/world/proc/TgsXXX()` procs. Many map directly to the `/datum/tgs_api` functions. It also contains the /datum selection and setup code. -- [datum.dm](./datum.dm) contains the `/datum/tgs_api` declarations that all APIs must implement. -- [tgs_version.dm](./tgs_version.dm) contains the `/datum/tgs_version` definition \ No newline at end of file +- [tgs_core.dm](./core.dm) contains the implementations of the `/world/proc/TgsXXX()` procs. Many map directly to the `/datum/tgs_api` functions. It also contains the /datum selection and setup code. +- [tgs_datum.dm](./datum.dm) contains the `/datum/tgs_api` declarations that all APIs must implement. +- [tgs_version.dm](./tgs_version.dm) contains the `/datum/tgs_version` definition diff --git a/code/modules/tgs/core/_definitions.dm b/code/modules/tgs/core/_definitions.dm index ebf6d17c2a07..fd98034eb716 100644 --- a/code/modules/tgs/core/_definitions.dm +++ b/code/modules/tgs/core/_definitions.dm @@ -1,2 +1,10 @@ +#if DM_VERSION < 510 +#error The TGS DMAPI does not support BYOND versions < 510! +#endif + #define TGS_UNIMPLEMENTED "___unimplemented" #define TGS_VERSION_PARAMETER "server_service_version" + +#ifndef TGS_DEBUG_LOG +#define TGS_DEBUG_LOG(message) +#endif diff --git a/code/modules/tgs/core/tgs_core.dm b/code/modules/tgs/core/tgs_core.dm index 41a047339452..8be96f27404a 100644 --- a/code/modules/tgs/core/tgs_core.dm +++ b/code/modules/tgs/core/tgs_core.dm @@ -42,11 +42,11 @@ var/datum/tgs_version/max_api_version = TgsMaximumApiVersion(); if(version.suite != null && version.minor != null && version.patch != null && version.deprecated_patch != null && version.deprefixed_parameter > max_api_version.deprefixed_parameter) - TGS_ERROR_LOG("Detected unknown API version! Defaulting to latest. Update the DMAPI to fix this problem.") + TGS_ERROR_LOG("Detected unknown Interop API version! Defaulting to latest. Update the DMAPI to fix this problem.") api_datum = /datum/tgs_api/latest if(!api_datum) - TGS_ERROR_LOG("Found unsupported API version: [raw_parameter]. If this is a valid version please report this, backporting is done on demand.") + TGS_ERROR_LOG("Found unsupported Interop API version: [raw_parameter]. If this is a valid version please report this, backporting is done on demand.") return TGS_INFO_LOG("Activating API for version [version.deprefixed_parameter]") @@ -107,6 +107,13 @@ if(api) return api.ApiVersion() +/world/TgsEngine() +#ifdef OPENDREAM + return TGS_ENGINE_TYPE_OPENDREAM +#else + return TGS_ENGINE_TYPE_BYOND +#endif + /world/TgsInstanceName() var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) if(api) @@ -153,4 +160,9 @@ /world/TgsSecurityLevel() var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) if(api) - api.SecurityLevel() + return api.SecurityLevel() + +/world/TgsVisibility() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + return api.Visibility() diff --git a/code/modules/tgs/core/tgs_datum.dm b/code/modules/tgs/core/tgs_datum.dm index 68b0330fe860..07ce3b684584 100644 --- a/code/modules/tgs/core/tgs_datum.dm +++ b/code/modules/tgs/core/tgs_datum.dm @@ -11,6 +11,15 @@ TGS_DEFINE_AND_SET_GLOBAL(tgs, null) src.event_handler = event_handler src.version = version +/datum/tgs_api/proc/TerminateWorld() + while(TRUE) + TGS_DEBUG_LOG("About to terminate world. Tick: [world.time], sleep_offline: [world.sleep_offline]") + world.sleep_offline = FALSE // https://www.byond.com/forum/post/2894866 + del(world) + world.sleep_offline = FALSE // just in case, this is BYOND after all... + sleep(1) + TGS_DEBUG_LOG("BYOND DIDN'T TERMINATE THE WORLD!!! TICK IS: [world.time], sleep_offline: [world.sleep_offline]") + /datum/tgs_api/latest parent_type = /datum/tgs_api/v5 @@ -57,3 +66,6 @@ TGS_PROTECT_DATUM(/datum/tgs_api) /datum/tgs_api/proc/SecurityLevel() return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/Visibility() + return TGS_UNIMPLEMENTED diff --git a/code/modules/tgs/v3210/README.md b/code/modules/tgs/v3210/README.md index 01ef44767ad7..a8073306e10d 100644 --- a/code/modules/tgs/v3210/README.md +++ b/code/modules/tgs/v3210/README.md @@ -2,5 +2,5 @@ This DMAPI implements bridge using file output which TGS monitors for. -- [api.dm](./v3_api.dm) contains the bulk of the API code. -- [commands.dm](./v3_commands.dm) contains functions relating to `/datum/tgs_chat_command`s. +- [v3_api.dm](./v3_api.dm) contains the bulk of the API code. +- [v3_commands.dm](./v3_commands.dm) contains functions relating to `/datum/tgs_chat_command`s. diff --git a/code/modules/tgs/v3210/v3_api.dm b/code/modules/tgs/v3210/v3_api.dm index c62118001f4b..ac5e8e4cf6d9 100644 --- a/code/modules/tgs/v3210/v3_api.dm +++ b/code/modules/tgs/v3210/v3_api.dm @@ -99,7 +99,11 @@ if(skip_compat_check && !fexists(SERVICE_INTERFACE_DLL)) TGS_ERROR_LOG("Service parameter present but no interface DLL detected. This is symptomatic of running a service less than version 3.1! Please upgrade.") return - CALL_EXT(SERVICE_INTERFACE_DLL, SERVICE_INTERFACE_FUNCTION)(instance_name, command) //trust no retval + #if DM_VERSION >= 515 + call_ext(SERVICE_INTERFACE_DLL, SERVICE_INTERFACE_FUNCTION)(instance_name, command) //trust no retval + #else + call(SERVICE_INTERFACE_DLL, SERVICE_INTERFACE_FUNCTION)(instance_name, command) //trust no retval + #endif return TRUE /datum/tgs_api/v3210/OnTopic(T) @@ -175,7 +179,7 @@ /datum/tgs_api/v3210/Revision() if(!warned_revison) var/datum/tgs_version/api_version = ApiVersion() - TGS_ERROR_LOG("Use of TgsRevision on [api_version.deprefixed_parameter] origin_commit only points to master!") + TGS_WARNING_LOG("Use of TgsRevision on [api_version.deprefixed_parameter] origin_commit only points to master!") warned_revison = TRUE var/datum/tgs_revision_information/ri = new ri.commit = commit @@ -189,16 +193,19 @@ /datum/tgs_api/v3210/ChatChannelInfo() return list() // :omegalul: -/datum/tgs_api/v3210/ChatBroadcast(message, list/channels) +/datum/tgs_api/v3210/ChatBroadcast(datum/tgs_message_content/message, list/channels) if(channels) return TGS_UNIMPLEMENTED + message = UpgradeDeprecatedChatMessage(message) ChatTargetedBroadcast(message, TRUE) ChatTargetedBroadcast(message, FALSE) -/datum/tgs_api/v3210/ChatTargetedBroadcast(message, admin_only) - ExportService("[admin_only ? SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE : SERVICE_REQUEST_IRC_BROADCAST] [message]") +/datum/tgs_api/v3210/ChatTargetedBroadcast(datum/tgs_message_content/message, admin_only) + message = UpgradeDeprecatedChatMessage(message) + ExportService("[admin_only ? SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE : SERVICE_REQUEST_IRC_BROADCAST] [message.text]") /datum/tgs_api/v3210/ChatPrivateMessage(message, datum/tgs_chat_user/user) + UpgradeDeprecatedChatMessage(message) return TGS_UNIMPLEMENTED /datum/tgs_api/v3210/SecurityLevel() diff --git a/code/modules/tgs/v3210/v3_commands.dm b/code/modules/tgs/v3210/v3_commands.dm index 4ccfc1a8a60b..e65c816320dc 100644 --- a/code/modules/tgs/v3210/v3_commands.dm +++ b/code/modules/tgs/v3210/v3_commands.dm @@ -10,9 +10,12 @@ var/warned_about_the_dangers_of_robutussin = !warnings_only for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command) if(!warned_about_the_dangers_of_robutussin) - TGS_ERROR_LOG("Custom chat commands in [ApiVersion()] lacks the /datum/tgs_chat_user/sender.channel field!") + TGS_WARNING_LOG("Custom chat commands in [ApiVersion()] lacks the /datum/tgs_chat_user/sender.channel field!") warned_about_the_dangers_of_robutussin = TRUE var/datum/tgs_chat_command/stc = I + if(stc.ignore_type == I) + continue + var/command_name = initial(stc.name) if(!command_name || findtext(command_name, " ") || findtext(command_name, "'") || findtext(command_name, "\"")) if(warnings_only && !warned_command_names[command_name]) @@ -44,9 +47,12 @@ user.friendly_name = sender // Discord hack, fix the mention if it's only numbers (fuck you IRC trolls) - var/regex/discord_id_regex = regex(@"^[0-9]+$") + var/regex/discord_id_regex = regex("^\[0-9\]+$") if(findtext(sender, discord_id_regex)) sender = "<@[sender]>" user.mention = sender - return stc.Run(user, params) || TRUE + var/datum/tgs_message_content/result = stc.Run(user, params) + result = UpgradeDeprecatedCommandResponse(result, command) + + return result ? result.text : TRUE diff --git a/code/modules/tgs/v4/README.md b/code/modules/tgs/v4/README.md index c14d7d38872e..049d4fb0f6de 100644 --- a/code/modules/tgs/v4/README.md +++ b/code/modules/tgs/v4/README.md @@ -2,5 +2,5 @@ This DMAPI implements bridge requests using file output which TGS monitors for. It has a safe mode restriction. -- [api.dm](./v4_api.dm) contains the bulk of the API code. -- [commands.dm](./v4_commands.dm) contains functions relating to `/datum/tgs_chat_command`s. +- [v4_api.dm](./v4_api.dm) contains the bulk of the API code. +- [v4_commands.dm](./v4_commands.dm) contains functions relating to `/datum/tgs_chat_command`s. diff --git a/code/modules/tgs/v4/v4_api.dm b/code/modules/tgs/v4/v4_api.dm index cce3b00bb268..3992299e4374 100644 --- a/code/modules/tgs/v4/v4_api.dm +++ b/code/modules/tgs/v4/v4_api.dm @@ -73,7 +73,7 @@ if(cached_json["apiValidateOnly"]) TGS_INFO_LOG("Validating API and exiting...") Export(TGS4_COMM_VALIDATE, list(TGS4_PARAMETER_DATA = "[minimum_required_security_level]")) - del(world) + TerminateWorld() security_level = cached_json["securityLevel"] chat_channels_json_path = cached_json["chatChannelsJson"] @@ -188,7 +188,7 @@ requesting_new_port = TRUE if(!world.OpenPort(0)) //open any port TGS_ERROR_LOG("Unable to open random port to retrieve new port![TGS4_PORT_CRITFAIL_MESSAGE]") - del(world) + TerminateWorld() //request a new port export_lock = FALSE @@ -196,16 +196,16 @@ if(!new_port_json) TGS_ERROR_LOG("No new port response from server![TGS4_PORT_CRITFAIL_MESSAGE]") - del(world) + TerminateWorld() var/new_port = new_port_json[TGS4_PARAMETER_DATA] if(!isnum(new_port) || new_port <= 0) TGS_ERROR_LOG("Malformed new port json ([json_encode(new_port_json)])![TGS4_PORT_CRITFAIL_MESSAGE]") - del(world) + TerminateWorld() if(new_port != world.port && !world.OpenPort(new_port)) TGS_ERROR_LOG("Unable to open port [new_port]![TGS4_PORT_CRITFAIL_MESSAGE]") - del(world) + TerminateWorld() requesting_new_port = FALSE while(export_lock) diff --git a/code/modules/tgs/v4/v4_commands.dm b/code/modules/tgs/v4/v4_commands.dm index d6d3d718d471..25dd6740e3af 100644 --- a/code/modules/tgs/v4/v4_commands.dm +++ b/code/modules/tgs/v4/v4_commands.dm @@ -40,5 +40,5 @@ var/datum/tgs_message_content/result = sc.Run(u, params) result = UpgradeDeprecatedCommandResponse(result, command) - return result?.text + return result ? result.text : TRUE return "Unknown command: [command]!" diff --git a/code/modules/tgs/v5/README.md b/code/modules/tgs/v5/README.md index dd8da3bea439..8a782fb15510 100644 --- a/code/modules/tgs/v5/README.md +++ b/code/modules/tgs/v5/README.md @@ -10,4 +10,4 @@ This DMAPI implements bridge requests using HTTP GET requests to TGS. It has no - [v5_commands.dm](./v5_commands.dm) contains functions relating to `/datum/tgs_chat_command`s. - [v5_serializers.dm](./v5_serializers.dm) contains function to help convert interop `/datum`s into a JSON encodable `list()` format. - [v5_topic.dm](./v5_topic.dm) contains functions related to processing topic requests. -- [v5_undefs.dm](./v5_undefs.dm) Undoes the work of `_v5_defines.dm`. +- [v5_undefs.dm](./v5_undefs.dm) Undoes the work of `_defines.dm`. diff --git a/code/modules/tgs/v5/_v5_defines.dm b/code/modules/tgs/v5/_v5_defines.dm index c7213cc24699..1c7d67d20cdf 100644 --- a/code/modules/tgs/v5/_v5_defines.dm +++ b/code/modules/tgs/v5/_v5_defines.dm @@ -5,10 +5,9 @@ #define DMAPI5_TOPIC_DATA "tgs_data" #define DMAPI5_BRIDGE_REQUEST_LIMIT 8198 -#define DMAPI5_TOPIC_REQUEST_LIMIT 65529 -#define DMAPI5_TOPIC_RESPONSE_LIMIT 65528 +#define DMAPI5_TOPIC_REQUEST_LIMIT 65528 +#define DMAPI5_TOPIC_RESPONSE_LIMIT 65529 -#define DMAPI5_BRIDGE_COMMAND_PORT_UPDATE 0 #define DMAPI5_BRIDGE_COMMAND_STARTUP 1 #define DMAPI5_BRIDGE_COMMAND_PRIME 2 #define DMAPI5_BRIDGE_COMMAND_REBOOT 3 @@ -18,6 +17,7 @@ #define DMAPI5_PARAMETER_ACCESS_IDENTIFIER "accessIdentifier" #define DMAPI5_PARAMETER_CUSTOM_COMMANDS "customCommands" +#define DMAPI5_PARAMETER_TOPIC_PORT "topicPort" #define DMAPI5_CHUNK "chunk" #define DMAPI5_CHUNK_PAYLOAD "payload" @@ -48,6 +48,7 @@ #define DMAPI5_RUNTIME_INFORMATION_REVISION "revision" #define DMAPI5_RUNTIME_INFORMATION_TEST_MERGES "testMerges" #define DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL "securityLevel" +#define DMAPI5_RUNTIME_INFORMATION_VISIBILITY "visibility" #define DMAPI5_CHAT_UPDATE_CHANNELS "channels" @@ -79,6 +80,7 @@ #define DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH 8 #define DMAPI5_TOPIC_COMMAND_SEND_CHUNK 9 #define DMAPI5_TOPIC_COMMAND_RECEIVE_CHUNK 10 +#define DMAPI5_TOPIC_COMMAND_RECEIVE_BROADCAST 11 #define DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE "commandType" #define DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND "chatCommand" @@ -88,6 +90,7 @@ #define DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME "newInstanceName" #define DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE "chatUpdate" #define DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION "newServerVersion" +#define DMAPI5_TOPIC_PARAMETER_BROADCAST_MESSAGE "broadcastMessage" #define DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE "commandResponse" #define DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE "commandResponseMessage" diff --git a/code/modules/tgs/v5/v5_api.dm b/code/modules/tgs/v5/v5_api.dm index fb2c46cc41ce..6b4e3ff9bd1c 100644 --- a/code/modules/tgs/v5/v5_api.dm +++ b/code/modules/tgs/v5/v5_api.dm @@ -4,6 +4,7 @@ var/instance_name var/security_level + var/visibility var/reboot_mode = TGS_REBOOT_MODE_NORMAL @@ -16,24 +17,32 @@ var/list/chat_channels var/initialized = FALSE + var/initial_bridge_request_received = FALSE + var/datum/tgs_version/interop_version var/chunked_requests = 0 var/list/chunked_topics = list() var/detached = FALSE +/datum/tgs_api/v5/New() + . = ..() + interop_version = version + TGS_DEBUG_LOG("V5 API created: [json_encode(args)]") + /datum/tgs_api/v5/ApiVersion() return new /datum/tgs_version( #include "v5_interop_version.dm" ) /datum/tgs_api/v5/OnWorldNew(minimum_required_security_level) + TGS_DEBUG_LOG("OnWorldNew()") server_port = world.params[DMAPI5_PARAM_SERVER_PORT] access_identifier = world.params[DMAPI5_PARAM_ACCESS_IDENTIFIER] var/datum/tgs_version/api_version = ApiVersion() - version = null - var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = api_version.raw_parameter, DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands())) + version = null // we want this to be the TGS version, not the interop version + var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = api_version.raw_parameter, DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands(), DMAPI5_PARAMETER_TOPIC_PORT = GetTopicPort())) if(!istype(bridge_response)) TGS_ERROR_LOG("Failed initial bridge request!") return FALSE @@ -45,10 +54,12 @@ if(runtime_information[DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY]) TGS_INFO_LOG("DMAPI validation, exiting...") - del(world) + TerminateWorld() - version = new /datum/tgs_version(runtime_information[DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION]) + initial_bridge_request_received = TRUE + version = new /datum/tgs_version(runtime_information[DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION]) // reassigning this because it can change if TGS updates security_level = runtime_information[DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL] + visibility = runtime_information[DMAPI5_RUNTIME_INFORMATION_VISIBILITY] instance_name = runtime_information[DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME] var/list/revisionData = runtime_information[DMAPI5_RUNTIME_INFORMATION_REVISION] @@ -95,18 +106,36 @@ initialized = TRUE return TRUE +/datum/tgs_api/v5/proc/GetTopicPort() +#if defined(OPENDREAM) && defined(OPENDREAM_TOPIC_PORT_EXISTS) + return "[world.opendream_topic_port]" +#else + return null +#endif + /datum/tgs_api/v5/proc/RequireInitialBridgeResponse() - while(!version) + TGS_DEBUG_LOG("RequireInitialBridgeResponse()") + var/logged = FALSE + while(!initial_bridge_request_received) + if(!logged) + TGS_DEBUG_LOG("RequireInitialBridgeResponse: Starting sleep") + logged = TRUE + sleep(1) + TGS_DEBUG_LOG("RequireInitialBridgeResponse: Passed") + /datum/tgs_api/v5/OnInitializationComplete() Bridge(DMAPI5_BRIDGE_COMMAND_PRIME) /datum/tgs_api/v5/OnTopic(T) + TGS_DEBUG_LOG("OnTopic()") RequireInitialBridgeResponse() + TGS_DEBUG_LOG("OnTopic passed bridge request gate") var/list/params = params2list(T) var/json = params[DMAPI5_TOPIC_DATA] if(!json) + TGS_DEBUG_LOG("No \"[DMAPI5_TOPIC_DATA]\" entry found, ignoring...") return FALSE // continue to /world/Topic if(!initialized) @@ -156,7 +185,7 @@ TGS_WARNING_LOG("Received legacy string when a [/datum/tgs_message_content] was expected. Please audit all calls to TgsChatBroadcast, TgsChatTargetedBroadcast, and TgsChatPrivateMessage to ensure they use the new /datum.") return new /datum/tgs_message_content(message) -/datum/tgs_api/v5/ChatBroadcast(datum/tgs_message_content/message, list/channels) +/datum/tgs_api/v5/ChatBroadcast(datum/tgs_message_content/message2, list/channels) if(!length(channels)) channels = ChatChannelInfo() @@ -165,45 +194,45 @@ var/datum/tgs_chat_channel/channel = I ids += channel.id - message = UpgradeDeprecatedChatMessage(message) + message2 = UpgradeDeprecatedChatMessage(message2) if(!length(channels)) return - message = message._interop_serialize() - message[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = ids + var/list/data = message2._interop_serialize() + data[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = ids if(intercepted_message_queue) - intercepted_message_queue += list(message) + intercepted_message_queue += list(data) else - Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message)) + Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = data)) -/datum/tgs_api/v5/ChatTargetedBroadcast(datum/tgs_message_content/message, admin_only) +/datum/tgs_api/v5/ChatTargetedBroadcast(datum/tgs_message_content/message2, admin_only) var/list/channels = list() for(var/I in ChatChannelInfo()) var/datum/tgs_chat_channel/channel = I if(!channel.is_private_channel && ((channel.is_admin_channel && admin_only) || (!channel.is_admin_channel && !admin_only))) channels += channel.id - message = UpgradeDeprecatedChatMessage(message) + message2 = UpgradeDeprecatedChatMessage(message2) if(!length(channels)) return - message = message._interop_serialize() - message[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = channels + var/list/data = message2._interop_serialize() + data[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = channels if(intercepted_message_queue) - intercepted_message_queue += list(message) + intercepted_message_queue += list(data) else - Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message)) + Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = data)) -/datum/tgs_api/v5/ChatPrivateMessage(datum/tgs_message_content/message, datum/tgs_chat_user/user) - message = UpgradeDeprecatedChatMessage(message) - message = message._interop_serialize() - message[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = list(user.channel.id) +/datum/tgs_api/v5/ChatPrivateMessage(datum/tgs_message_content/message2, datum/tgs_chat_user/user) + message2 = UpgradeDeprecatedChatMessage(message2) + var/list/data = message2._interop_serialize() + data[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = list(user.channel.id) if(intercepted_message_queue) - intercepted_message_queue += list(message) + intercepted_message_queue += list(data) else - Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message)) + Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = data)) /datum/tgs_api/v5/ChatChannelInfo() RequireInitialBridgeResponse() @@ -211,6 +240,7 @@ return chat_channels.Copy() /datum/tgs_api/v5/proc/DecodeChannels(chat_update_json) + TGS_DEBUG_LOG("DecodeChannels()") var/list/chat_channels_json = chat_update_json[DMAPI5_CHAT_UPDATE_CHANNELS] if(istype(chat_channels_json)) chat_channels.Cut() @@ -235,3 +265,7 @@ /datum/tgs_api/v5/SecurityLevel() RequireInitialBridgeResponse() return security_level + +/datum/tgs_api/v5/Visibility() + RequireInitialBridgeResponse() + return visibility diff --git a/code/modules/tgs/v5/v5_bridge.dm b/code/modules/tgs/v5/v5_bridge.dm index 37f58bcdf632..60cbcbfb7dff 100644 --- a/code/modules/tgs/v5/v5_bridge.dm +++ b/code/modules/tgs/v5/v5_bridge.dm @@ -48,7 +48,9 @@ var/json = CreateBridgeData(command, data, TRUE) var/encoded_json = url_encode(json) - var/url = "http://127.0.0.1:[server_port]/Bridge?[DMAPI5_BRIDGE_DATA]=[encoded_json]" + var/api_prefix = interop_version.minor >= 7 ? "api/" : "" + + var/url = "http://127.0.0.1:[server_port]/[api_prefix]Bridge?[DMAPI5_BRIDGE_DATA]=[encoded_json]" return url /datum/tgs_api/v5/proc/CreateBridgeData(command, list/data, needs_auth) @@ -81,11 +83,16 @@ TGS_ERROR_LOG("Failed bridge request: [bridge_request]") return - var/response_json = file2text(export_response["CONTENT"]) - if(!response_json) + var/content = export_response["CONTENT"] + if(!content) TGS_ERROR_LOG("Failed bridge request, missing content!") return + var/response_json = file2text(content) + if(!response_json) + TGS_ERROR_LOG("Failed bridge request, failed to load content!") + return + var/list/bridge_response = json_decode(response_json) if(!bridge_response) TGS_ERROR_LOG("Failed bridge request, bad json: [response_json]") diff --git a/code/modules/tgs/v5/v5_commands.dm b/code/modules/tgs/v5/v5_commands.dm index c8f538db5932..9557f8a08ed5 100644 --- a/code/modules/tgs/v5/v5_commands.dm +++ b/code/modules/tgs/v5/v5_commands.dm @@ -37,8 +37,8 @@ response = UpgradeDeprecatedCommandResponse(response, command) var/list/topic_response = TopicResponse() - topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = response?.text - topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE] = response?._interop_serialize() + topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = response ? response.text : null + topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE] = response ? response._interop_serialize() : null return topic_response return TopicResponse("Unknown custom chat command: [command]!") diff --git a/code/modules/tgs/v5/v5_interop_version.dm b/code/modules/tgs/v5/v5_interop_version.dm index 5d3d491a7362..83420d130a74 100644 --- a/code/modules/tgs/v5/v5_interop_version.dm +++ b/code/modules/tgs/v5/v5_interop_version.dm @@ -1 +1 @@ -"5.6.1" +"5.7.0" diff --git a/code/modules/tgs/v5/v5_serializers.dm b/code/modules/tgs/v5/v5_serializers.dm index 3a6fbe6be344..3a32848ad512 100644 --- a/code/modules/tgs/v5/v5_serializers.dm +++ b/code/modules/tgs/v5/v5_serializers.dm @@ -1,12 +1,12 @@ /datum/tgs_message_content/proc/_interop_serialize() - return list("text" = text, "embed" = embed?._interop_serialize()) + return list("text" = text, "embed" = embed ? embed._interop_serialize() : null) /datum/tgs_chat_embed/proc/_interop_serialize() CRASH("Base /proc/interop_serialize called on [type]!") /datum/tgs_chat_embed/structure/_interop_serialize() var/list/serialized_fields - if(islist(fields)) + if(istype(fields, /list)) serialized_fields = list() for(var/datum/tgs_chat_embed/field/field as anything in fields) serialized_fields += list(field._interop_serialize()) @@ -16,12 +16,12 @@ "url" = url, "timestamp" = timestamp, "colour" = colour, - "image" = image?._interop_serialize(), - "thumbnail" = thumbnail?._interop_serialize(), - "video" = video?._interop_serialize(), - "footer" = footer?._interop_serialize(), - "provider" = provider?._interop_serialize(), - "author" = author?._interop_serialize(), + "image" = src.image ? src.image._interop_serialize() : null, + "thumbnail" = thumbnail ? thumbnail._interop_serialize() : null, + "video" = video ? video._interop_serialize() : null, + "footer" = footer ? footer._interop_serialize() : null, + "provider" = provider ? provider._interop_serialize() : null, + "author" = author ? author._interop_serialize() : null, "fields" = serialized_fields ) diff --git a/code/modules/tgs/v5/v5_topic.dm b/code/modules/tgs/v5/v5_topic.dm index 68d0db27f36a..309044a145dc 100644 --- a/code/modules/tgs/v5/v5_topic.dm +++ b/code/modules/tgs/v5/v5_topic.dm @@ -5,6 +5,7 @@ return response /datum/tgs_api/v5/proc/ProcessTopicJson(json, check_access_identifier) + TGS_DEBUG_LOG("ProcessTopicJson(..., [check_access_identifier])") var/list/result = ProcessRawTopic(json, check_access_identifier) if(!result) result = TopicResponse("Runtime error!") @@ -25,16 +26,20 @@ return response_json /datum/tgs_api/v5/proc/ProcessRawTopic(json, check_access_identifier) + TGS_DEBUG_LOG("ProcessRawTopic(..., [check_access_identifier])") var/list/topic_parameters = json_decode(json) if(!topic_parameters) + TGS_DEBUG_LOG("ProcessRawTopic: json_decode failed") return TopicResponse("Invalid topic parameters json: [json]!"); var/their_sCK = topic_parameters[DMAPI5_PARAMETER_ACCESS_IDENTIFIER] if(check_access_identifier && their_sCK != access_identifier) - return TopicResponse("Failed to decode [DMAPI5_PARAMETER_ACCESS_IDENTIFIER]!") + TGS_DEBUG_LOG("ProcessRawTopic: access identifier check failed") + return TopicResponse("Failed to decode [DMAPI5_PARAMETER_ACCESS_IDENTIFIER] or it does not match!") var/command = topic_parameters[DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE] if(!isnum(command)) + TGS_DEBUG_LOG("ProcessRawTopic: command type check failed") return TopicResponse("Failed to decode [DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE]!") return ProcessTopicCommand(command, topic_parameters) @@ -43,6 +48,7 @@ return "response[payload_id]" /datum/tgs_api/v5/proc/ProcessTopicCommand(command, list/topic_parameters) + TGS_DEBUG_LOG("ProcessTopicCommand([command], ...)") switch(command) if(DMAPI5_TOPIC_COMMAND_CHAT_COMMAND) @@ -55,7 +61,6 @@ return result if(DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION) - intercepted_message_queue = list() var/list/event_notification = topic_parameters[DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION] if(!istype(event_notification)) return TopicResponse("Invalid [DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION]!") @@ -66,28 +71,30 @@ var/list/event_parameters = event_notification[DMAPI5_EVENT_NOTIFICATION_PARAMETERS] if(event_parameters && !istype(event_parameters)) - return TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_PARAMETERS]!") + . = TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_PARAMETERS]!") + else + var/list/response = TopicResponse() + . = response + if(event_handler != null) + var/list/event_call = list(event_type) + if(event_parameters) + event_call += event_parameters + + intercepted_message_queue = list() + event_handler.HandleEvent(arglist(event_call)) + response[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue + intercepted_message_queue = null - var/list/event_call = list(event_type) if(event_type == TGS_EVENT_WATCHDOG_DETACH) detached = TRUE chat_channels.Cut() // https://github.com/tgstation/tgstation-server/issues/1490 - if(event_parameters) - event_call += event_parameters - - if(event_handler != null) - event_handler.HandleEvent(arglist(event_call)) - - var/list/response = TopicResponse() - response[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue - intercepted_message_queue = null - return response + return if(DMAPI5_TOPIC_COMMAND_CHANGE_PORT) var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT] if(!isnum(new_port) || !(new_port > 0)) - return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]") + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]") if(event_handler != null) event_handler.HandleEvent(TGS_EVENT_PORT_SWAP, new_port) @@ -122,8 +129,10 @@ return TopicResponse() if(DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE) + TGS_DEBUG_LOG("ProcessTopicCommand: It's a chat update") var/list/chat_update_json = topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE] if(!istype(chat_update_json)) + TGS_DEBUG_LOG("ProcessTopicCommand: failed \"[DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]\" check") return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]!") DecodeChannels(chat_update_json) @@ -132,13 +141,13 @@ if(DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE) var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT] if(!isnum(new_port) || !(new_port > 0)) - return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]") + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]") server_port = new_port return TopicResponse() if(DMAPI5_TOPIC_COMMAND_HEALTHCHECK) - if(event_handler?.receive_health_checks) + if(event_handler && event_handler.receive_health_checks) event_handler.HandleEvent(TGS_EVENT_HEALTH_CHECK) return TopicResponse() @@ -148,7 +157,7 @@ var/error_message = null if(new_port != null) if(!isnum(new_port) || !(new_port > 0)) - error_message = "Invalid [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]" + error_message = "Invalid [DMAPI5_TOPIC_PARAMETER_NEW_PORT]" else server_port = new_port @@ -156,7 +165,7 @@ if(!istext(new_version_string)) if(error_message != null) error_message += ", " - error_message += "Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]]" + error_message += "Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]" else var/datum/tgs_version/new_version = new(new_version_string) if(event_handler) @@ -166,6 +175,7 @@ var/list/reattach_response = TopicResponse(error_message) reattach_response[DMAPI5_PARAMETER_CUSTOM_COMMANDS] = ListCustomCommands() + reattach_response[DMAPI5_PARAMETER_TOPIC_PORT] = GetTopicPort() return reattach_response if(DMAPI5_TOPIC_COMMAND_SEND_CHUNK) @@ -258,4 +268,16 @@ return chunk_to_send + if(DMAPI5_TOPIC_COMMAND_RECEIVE_BROADCAST) + var/message = topic_parameters[DMAPI5_TOPIC_PARAMETER_BROADCAST_MESSAGE] + if(!istext(message)) + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_BROADCAST_MESSAGE]") + + TGS_WORLD_ANNOUNCE(message) + return TopicResponse() + return TopicResponse("Unknown command: [command]") + +/datum/tgs_api/v5/proc/WorldBroadcast(message) + set waitfor = FALSE + TGS_WORLD_ANNOUNCE(message) diff --git a/code/modules/tgs/v5/v5_undefs.dm b/code/modules/tgs/v5/v5_undefs.dm index c679737dfc49..d531d4b7b9dd 100644 --- a/code/modules/tgs/v5/v5_undefs.dm +++ b/code/modules/tgs/v5/v5_undefs.dm @@ -8,7 +8,6 @@ #undef DMAPI5_TOPIC_REQUEST_LIMIT #undef DMAPI5_TOPIC_RESPONSE_LIMIT -#undef DMAPI5_BRIDGE_COMMAND_PORT_UPDATE #undef DMAPI5_BRIDGE_COMMAND_STARTUP #undef DMAPI5_BRIDGE_COMMAND_PRIME #undef DMAPI5_BRIDGE_COMMAND_REBOOT @@ -18,6 +17,7 @@ #undef DMAPI5_PARAMETER_ACCESS_IDENTIFIER #undef DMAPI5_PARAMETER_CUSTOM_COMMANDS +#undef DMAPI5_PARAMETER_TOPIC_PORT #undef DMAPI5_CHUNK #undef DMAPI5_CHUNK_PAYLOAD @@ -48,6 +48,7 @@ #undef DMAPI5_RUNTIME_INFORMATION_REVISION #undef DMAPI5_RUNTIME_INFORMATION_TEST_MERGES #undef DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL +#undef DMAPI5_RUNTIME_INFORMATION_VISIBILITY #undef DMAPI5_CHAT_UPDATE_CHANNELS @@ -77,6 +78,9 @@ #undef DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE #undef DMAPI5_TOPIC_COMMAND_HEALTHCHECK #undef DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH +#undef DMAPI5_TOPIC_COMMAND_SEND_CHUNK +#undef DMAPI5_TOPIC_COMMAND_RECEIVE_CHUNK +#undef DMAPI5_TOPIC_COMMAND_RECEIVE_BROADCAST #undef DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE #undef DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND @@ -86,6 +90,7 @@ #undef DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME #undef DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE #undef DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION +#undef DMAPI5_TOPIC_PARAMETER_BROADCAST_MESSAGE #undef DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE #undef DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE diff --git a/icons/effects/species.dmi b/icons/effects/species.dmi index 7bac1bdbe48d..b3a2753e6b98 100644 Binary files a/icons/effects/species.dmi and b/icons/effects/species.dmi differ diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi index e9fb5b582b2d..3eea2f356ae1 100644 Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ diff --git a/icons/mob/clothing/species/drask/under/civilian.dmi b/icons/mob/clothing/species/drask/under/civilian.dmi index 53ce570efc56..34f04fdf40de 100644 Binary files a/icons/mob/clothing/species/drask/under/civilian.dmi and b/icons/mob/clothing/species/drask/under/civilian.dmi differ diff --git a/icons/mob/clothing/species/grey/back.dmi b/icons/mob/clothing/species/grey/back.dmi index 88be281f984d..e426449c4db4 100644 Binary files a/icons/mob/clothing/species/grey/back.dmi and b/icons/mob/clothing/species/grey/back.dmi differ diff --git a/icons/mob/clothing/species/grey/under/civilian.dmi b/icons/mob/clothing/species/grey/under/civilian.dmi index aef84913923f..a09f69cdd884 100644 Binary files a/icons/mob/clothing/species/grey/under/civilian.dmi and b/icons/mob/clothing/species/grey/under/civilian.dmi differ diff --git a/icons/mob/clothing/species/kidan/under/civilian.dmi b/icons/mob/clothing/species/kidan/under/civilian.dmi index 9c8d974d3361..c655ec2f6299 100644 Binary files a/icons/mob/clothing/species/kidan/under/civilian.dmi and b/icons/mob/clothing/species/kidan/under/civilian.dmi differ diff --git a/icons/mob/clothing/species/vox/back.dmi b/icons/mob/clothing/species/vox/back.dmi index 25b86be5931b..95800a6c6f8f 100644 Binary files a/icons/mob/clothing/species/vox/back.dmi and b/icons/mob/clothing/species/vox/back.dmi differ diff --git a/icons/mob/clothing/species/vox/under/civilian.dmi b/icons/mob/clothing/species/vox/under/civilian.dmi index 63f65aa8e3c0..17c4e4a39971 100644 Binary files a/icons/mob/clothing/species/vox/under/civilian.dmi and b/icons/mob/clothing/species/vox/under/civilian.dmi differ diff --git a/icons/mob/clothing/under/civilian.dmi b/icons/mob/clothing/under/civilian.dmi index 3811856e8a7a..c5a920488695 100644 Binary files a/icons/mob/clothing/under/civilian.dmi and b/icons/mob/clothing/under/civilian.dmi differ diff --git a/icons/mob/human_races/vox/r_vox.dmi b/icons/mob/human_races/vox/r_vox.dmi index 247e52578521..2286e060a9af 100644 Binary files a/icons/mob/human_races/vox/r_vox.dmi and b/icons/mob/human_races/vox/r_vox.dmi differ diff --git a/icons/mob/human_races/vox/r_voxazu.dmi b/icons/mob/human_races/vox/r_voxazu.dmi index 91c56c1f8fe0..593b6b9b6d2e 100644 Binary files a/icons/mob/human_races/vox/r_voxazu.dmi and b/icons/mob/human_races/vox/r_voxazu.dmi differ diff --git a/icons/mob/human_races/vox/r_voxbrn.dmi b/icons/mob/human_races/vox/r_voxbrn.dmi index 22ca13cee71a..8a0e391a7499 100644 Binary files a/icons/mob/human_races/vox/r_voxbrn.dmi and b/icons/mob/human_races/vox/r_voxbrn.dmi differ diff --git a/icons/mob/human_races/vox/r_voxcrim.dmi b/icons/mob/human_races/vox/r_voxcrim.dmi new file mode 100644 index 000000000000..56e99a28fb41 Binary files /dev/null and b/icons/mob/human_races/vox/r_voxcrim.dmi differ diff --git a/icons/mob/human_races/vox/r_voxdgrn.dmi b/icons/mob/human_races/vox/r_voxdgrn.dmi index 1e0fdd118777..6c3239a100da 100644 Binary files a/icons/mob/human_races/vox/r_voxdgrn.dmi and b/icons/mob/human_races/vox/r_voxdgrn.dmi differ diff --git a/icons/mob/human_races/vox/r_voxemrl.dmi b/icons/mob/human_races/vox/r_voxemrl.dmi index 4534a5aa6c5d..0a5515192931 100644 Binary files a/icons/mob/human_races/vox/r_voxemrl.dmi and b/icons/mob/human_races/vox/r_voxemrl.dmi differ diff --git a/icons/mob/human_races/vox/r_voxgry.dmi b/icons/mob/human_races/vox/r_voxgry.dmi index 08a1f00088e1..df825cc399d6 100644 Binary files a/icons/mob/human_races/vox/r_voxgry.dmi and b/icons/mob/human_races/vox/r_voxgry.dmi differ diff --git a/icons/mob/human_races/vox/r_voxpurp.dmi b/icons/mob/human_races/vox/r_voxpurp.dmi new file mode 100644 index 000000000000..d6c18c755174 Binary files /dev/null and b/icons/mob/human_races/vox/r_voxpurp.dmi differ diff --git a/icons/mob/inhands/clothing_lefthand.dmi b/icons/mob/inhands/clothing_lefthand.dmi index 8f9f52bd6213..91ff13ceb36e 100644 Binary files a/icons/mob/inhands/clothing_lefthand.dmi and b/icons/mob/inhands/clothing_lefthand.dmi differ diff --git a/icons/mob/inhands/clothing_righthand.dmi b/icons/mob/inhands/clothing_righthand.dmi index b436595e7311..1980c4c38d1b 100644 Binary files a/icons/mob/inhands/clothing_righthand.dmi and b/icons/mob/inhands/clothing_righthand.dmi differ diff --git a/icons/mob/sprite_accessories/diona/diona_hair.dmi b/icons/mob/sprite_accessories/diona/diona_hair.dmi index faae86d59236..b11c32755d7f 100644 Binary files a/icons/mob/sprite_accessories/diona/diona_hair.dmi and b/icons/mob/sprite_accessories/diona/diona_hair.dmi differ diff --git a/icons/obj/clothing/under/civilian.dmi b/icons/obj/clothing/under/civilian.dmi index 774f95bf8684..c6879e99fb2f 100644 Binary files a/icons/obj/clothing/under/civilian.dmi and b/icons/obj/clothing/under/civilian.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 768f5f64ed6f..b5805bbd6ae5 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/prof.dll b/prof.dll index 33a6da229474..c0bc34532e4c 100644 Binary files a/prof.dll and b/prof.dll differ